我在这里真的很苦恼,甚至不知道为什么做不对。我正在使用 WEBGL 模式下的
事实上,在 3D 空间中绘制球体,使用
经过数小时的漫游,我发现绕3轴旋转并不像我想象的那么简单,最终我使用了Quaternion.js。但是我仍然无法将3D世界中球体的视觉位置与我从2D平面上的原始点(150,0,[0])计算出的坐标相匹配。
例如,在这里,球体在3个轴上旋转。一开始坐标是正确的(如果我忽略Z被取反的事实),但在某个时刻它完全失去同步。球体的计算位置似乎完全不相关:
p5.js
,想要计算绕原点旋转在三个轴上的一个点的位置,以便通过 p5.js、平移, 以及 X轴旋转、Y轴 和 Z轴 给出对象的平移和旋转。事实上,在 3D 空间中绘制球体,使用
p5.js
是通过平移和旋转来完成的,因为球体是在原点中心创建的,并没有内部模型给出 3D 坐标。经过数小时的漫游,我发现绕3轴旋转并不像我想象的那么简单,最终我使用了Quaternion.js。但是我仍然无法将3D世界中球体的视觉位置与我从2D平面上的原始点(150,0,[0])计算出的坐标相匹配。
例如,在这里,球体在3个轴上旋转。一开始坐标是正确的(如果我忽略Z被取反的事实),但在某个时刻它完全失去同步。球体的计算位置似乎完全不相关:
我已经花了好几个小时尝试解决这个问题,但是没有任何结果,我错过了什么?
以下是我的代码:
//font for WEBGL
var robotoFont;
var dotId = 0;
var rotating = true;
var orbits = [];
var dotsData = [];
function preload() {
robotoFont = loadFont('./assets/Roboto-Regular.ttf');
}
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
textFont(robotoFont);
background(0);
let orbit1 = new Orbit(0, 0, 0, 0.5, 0.5, 0.5);
orbit1.obj.push(new Dot(0, 0));
orbits.push(orbit1);
// let orbit2 = new Orbit(90, 45, 0);
// orbit2.obj.push(new Dot(0, 0));
// orbits.push(orbit2);
}
function draw() {
angleMode(DEGREES);
background(0);
orbitControl();
let len = 200;
fill('white');
stroke('white');
sphere(2);
stroke('red');
line(0, 0, 0, len, 0, 0);
text('x', len, 0)
stroke('green');
line(0, 0, 0, 0, len, 0);
text('y', 0, len)
push();
rotateX(90);
stroke('yellow');
line(0, 0, 0, 0, len, 0);
text('z', 0, len)
pop();
dotsData = [];
orbits.forEach(o => o.draw());
textSize(14);
push();
for (let i = 0; i < 2; i++) {
let yPos = -(windowHeight / 2) + 15;
for (let i = 0; i < dotsData.length; i++) {
let [id, pos, pos3d] = dotsData[i];
let [x1, y1, z1] = [pos[0].toFixed(0), pos[1].toFixed(0), pos[2].toFixed(0)];
let [x2, y2, z2] = [pos3d.x.toFixed(0), pos3d.y.toFixed(0), pos3d.z.toFixed(0)];
text(`${id}: (${x1}, ${y1}, ${z1}) -> (${x2}, ${y2}, ${z2})`, -windowWidth / 2 + 5, yPos);
yPos += 18;
}
rotateX(-90);
}
pop();
}
function mouseClicked() {
// controls.mousePressed();
}
function keyPressed() {
// controls.keyPressed(keyCode);
if (keyCode === 32) {
rotating = !rotating;
}
}
class Orbit {
constructor(x, y, z, xr, yr, zr) {
this.obj = [];
this.currentRot = [
x ? x : 0,
y ? y : 0,
z ? z : 0
]
this.rot = [
xr ? xr : 0,
yr ? yr : 0,
zr ? zr : 0
]
}
draw() {
push();
if (rotating) {
this.currentRot[0] += this.rot[0];
this.currentRot[1] += this.rot[1];
this.currentRot[2] += this.rot[2];
}
rotateY(this.currentRot[1]);
rotateX(this.currentRot[0]);
rotateZ(this.currentRot[2]);
noFill();
stroke('white');
ellipse(0, 0, 300, 300);
for (let i = 0; i < this.obj.length; i++) {
let o = this.obj[i];
o.draw();
dotsData.push([o.id, o.getPosition(), this.#get3DPos(o)]);
}
pop();
}
#get3DPos(o) {
let [x, y, z] = o.getPosition();
let w = 0;
let rotX = this.currentRot[0] * PI / 180;
let rotY = this.currentRot[1] * PI / 180;
let rotZ = this.currentRot[2] * PI / 180;
let rotation = Quaternion.fromEuler(rotZ, rotX, rotY, 'ZXY').conjugate();
[x, y, z] = rotation.rotateVector([x, y, z]);
return createVector(x, y, z);
}
}
class Dot {
constructor(angle) {
this.id = ++dotId;
this.x = cos(angle) * 150;
this.y = sin(angle) * 150;
}
draw() {
push();
fill('gray');
translate(this.x, this.y);
noStroke();
sphere(15);
pop();
}
getPosition() {
return [this.x, this.y, 0];
}
}
在stackoverflow上它不起作用,因为我需要像字体这样的本地资源。