3Dワイヤフレーム球をHTML5キャンバスにプロットするためのJSコードを記述しました。HTML5 Canvas + JavaScriptワイヤフレーム球体変換の問題
私はthis postから開始し、Qt3D vertices generationを球形メッシュに使用して改良しました。 JSコードは、最初にリングを表示し、2番目にスライスを表示するために頂点上を2回通過します。通常、OpenGLはすべての頂点を自動的に三角形で接続します。
私はスライス/リングを設定可能にしていましたが、例えばX軸に沿って球を回転させるときなど、変換コードに問題があります。
だから、基本から始めて。
がすべて良いと思われる:ここでは1パス、4輪、4つのスライス、無変換です。今、2回のパス、10個のリング、10個のスライス、変換なし:私は(唯一明らかにY位置)をX軸、上部と下部の頂点にそれを30°回転させた場合
まだ良いが、取得しますうんざりする
私はそこに何かが間違って回転機能である、または投影機能に疑いがあります。
ここで何が起こっているのか理解してもらえますか?
(私は私の目標は、QMLアプリケーションでポートにこれです原因Three.jsを使用したくない注)
ここでは完全なコードです。
var sphere = new Sphere3D();
var rotation = new Point3D();
var distance = 1000;
var lastX = -1;
var lastY = -1;
function Point3D() {
this.x = 0;
this.y = 0;
this.z = 0;
}
function Sphere3D(radius) {
this.vertices = new Array();
this.radius = (typeof(radius) == "undefined" || typeof(radius) != "number") ? 20.0 : radius;
this.rings = 10;
this.slices = 10;
this.numberOfVertices = 0;
var M_PI_2 = Math.PI/2;
var dTheta = (Math.PI * 2)/this.slices;
var dPhi = Math.PI/this.rings;
// Iterate over latitudes (rings)
for (var lat = 0; lat < this.rings + 1; ++lat) {
var phi = M_PI_2 - lat * dPhi;
var cosPhi = Math.cos(phi);
var sinPhi = Math.sin(phi);
// Iterate over longitudes (slices)
for (var lon = 0; lon < this.slices + 1; ++lon) {
var theta = lon * dTheta;
var cosTheta = Math.cos(theta);
var sinTheta = Math.sin(theta);
p = this.vertices[this.numberOfVertices] = new Point3D();
p.x = this.radius * cosTheta * cosPhi;
p.y = this.radius * sinPhi;
p.z = this.radius * sinTheta * cosPhi;
this.numberOfVertices++;
}
}
}
function rotateX(point, radians) {
var y = point.y;
point.y = (y * Math.cos(radians)) + (point.z * Math.sin(radians) * -1.0);
point.z = (y * Math.sin(radians)) + (point.z * Math.cos(radians));
}
function rotateY(point, radians) {
var x = point.x;
point.x = (x * Math.cos(radians)) + (point.z * Math.sin(radians) * -1.0);
point.z = (x * Math.sin(radians)) + (point.z * Math.cos(radians));
}
function rotateZ(point, radians) {
var x = point.x;
point.x = (x * Math.cos(radians)) + (point.y * Math.sin(radians) * -1.0);
point.y = (x * Math.sin(radians)) + (point.y * Math.cos(radians));
}
function projection(xy, z, xyOffset, zOffset, distance) {
return ((distance * xy)/(z - zOffset)) + xyOffset;
}
function strokeSegment(index, ctx, width, height) {
var x, y;
var p = sphere.vertices[index];
rotateX(p, rotation.x);
rotateY(p, rotation.y);
rotateZ(p, rotation.z);
x = projection(p.x, p.z, width/2.0, 100.0, distance);
y = projection(p.y, p.z, height/2.0, 100.0, distance);
if (lastX == -1 && lastY == -1) {
lastX = x;
lastY = y;
return;
}
if (x >= 0 && x < width && y >= 0 && y < height) {
if (p.z < 0) {
ctx.strokeStyle = "gray";
} else {
ctx.strokeStyle = "white";
}
ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(x, y);
ctx.stroke();
ctx.closePath();
lastX = x;
lastY = y;
}
}
function render() {
var canvas = document.getElementById("sphere3d");
var width = canvas.getAttribute("width");
var height = canvas.getAttribute("height");
var ctx = canvas.getContext('2d');
var p = new Point3D();
ctx.fillStyle = "black";
ctx.clearRect(0, 0, width, height);
ctx.fillRect(0, 0, width, height);
// draw each vertex to get the first sphere skeleton
for (i = 0; i < sphere.numberOfVertices; i++) {
strokeSegment(i, ctx, width, height);
}
// now walk through rings to draw the slices
for (i = 0; i < sphere.slices + 1; i++) {
for (var j = 0; j < sphere.rings + 1; j++) {
strokeSegment(i + (j * (sphere.slices + 1)), ctx, width, height);
}
}
}
function init() {
rotation.x = Math.PI/6;
render();
}
canvas {
background: black;
display: block;
}
<body onLoad="init();">
<canvas id="sphere3d" width="500" height="500">
Your browser does not support HTML5 canvas.
</canvas>
</body>
すばらしい答え、ありがとう。私はC/C++開発者であることを認めなければなりません。ポインタと参照の概念はJavaScriptではあまり明確ではありません。このコードは、私のQt/QMLプロジェクトのQML Canvasに描画するためのショートカットです。 –
@MassimoCallegari、JavaScriptではすべてが値渡されますが(これは非常に重要な "but"です)、プリミティブ型を除くすべてが参照であり、それらの "スタック"バージョンを取得できません。したがって、オブジェクトまたは配列をあるメソッドに渡して引数を変更すると、値が変更されます。 http://stackoverflow.com/questions/6605640/javascript-by-reference-vs-by-valueも参照してください。これらのルールは、QWidgetをポインタとして作成するQtルールと実際に似ています – SergGr