我遇到了各种各样的心理障碍,并且正在寻找一些建议或建议。我的问题是:
我有一个WebGL场景(我没有使用第三方库,除了gl-matrix),用户可以上下左右旋转摄像机(绕X / Y轴旋转)。它们也可以旋转模型(偏航/俯仰)。
要查看问题,假设模型在场景中有两个块A和B,A位于中心,B位于右侧(在视口中),旋转中心位于A的中心。用户旋转模型,它围绕块A的中心旋转。但是如果用户点击对象B,我需要能够将旋转中心更改为B的中心,但仍然保持当前的摄像机方向。目前,当旋转中心切换到B时,块B移动到屏幕的中心,块A移动到左侧。基本上,代码总是以当前中心或旋转为中心。
我使用以下代码进行模型视图矩阵更新:
var mvMatrix = this.mvMatrix;
mat4.identity(mvMatrix);
mat4.translate(mvMatrix, mvMatrix, this.orbit);
mat4.rotateY(mvMatrix, mvMatrix, this.orbitYaw);
mat4.rotateX(mvMatrix, mvMatrix, this.orbitPitch);
mat4.translate(mvMatrix, mvMatrix, this.eye);
mat4.rotateY(mvMatrix, mvMatrix, this.eyeYaw);
mat4.rotateX(mvMatrix, mvMatrix, this.eyePitch);
我正在试图找出轨道和眼睛的正确偏航和俯仰值,以便向后移动当前位置并实现当前相机/眼睛方向以避免来自一个物体的“反弹”当旋转中心移动时,到另一个。
我搜索了很多,似乎无法找到最好的方法(我目前的尝试有问题)。任何示例代码,或只是良好的描述将不胜感激。
修改
我遵循了gman的建议并尝试了以下代码,但切换轨道只是跳了起来。我的模型由多个物体组成,轨道中心可以改变,但是在改变轨道后,摄像机的方向需要保持稳定,这就是我必须计算轨道偏航/俯仰和眼睛偏航/俯仰的校正的原因。在改变轨道后将眼睛放回同一个位置并指向相同的方向。顺便说一句,根据当前轨道的位置,我只有一个轨道偏航和俯仰,所以这与gman的样本有点不同:
Camera.prototype.changeOrbit = function (newOrbit) {
var matA = mat4.create();
var matB = mat4.create();
mat4.translate(matA, matA, this.orbit);
mat4.rotateY(matA, matA, this.orbitYaw);
mat4.rotateX(matA, matA, this.orbitPitch);
mat4.translate(matB, matB, newOrbit);
mat4.rotateY(matB, matB, this.orbitYaw);
mat4.rotateX(matB, matB, this.orbitPitch);
var matInverseNewOrbit = mat4.create();
var matNewOrbitToCamera = mat4.create();
mat4.invert(matInverseNewOrbit, matB);
mat4.multiply(matNewOrbitToCamera, matInverseNewOrbit, matA);
var m = matNewOrbitToCamera;
this.eye[0] = m[12];
this.eye[1] = m[13];
this.eye[2] = m[14];
this.eyePitch = ExtractPitch(m);
this.eyeYaw = ExtractYaw(m);
this.update();
};
ExtractPitch和ExtractYaw按照gman指定的方式工作,但我确实围绕不同的轴旋转,因为音高通常围绕Y轴定义,依此类推。谢谢你的建议。
答案 0 :(得分:0)
我不确定我能解释一下,但基本上是这样:
在切换时从A
切换到B
,
A
(上面的代码)。 (camera
)B
(matB
)B
矩阵的倒数。 (inverseMatB
) camera
乘以inverseMatB
。 (matBtoCamera
)
现在你有一个从B
到相机的矩阵。
将此矩阵(matBToCamera
)分解为平移和旋转。
不幸的是我不知道一个好的分解矩阵函数指向你。我很久没需要了。翻译基本上是矩阵的元素12,13,14。 (假设您使用的是16个元素矩阵,我认为这是glMatrix使用的)。
var translation = [m[12], m[13], m[14]];
对于旋转,矩阵的上/左3x3部分表示旋转。只要不涉及缩放或倾斜,根据此页面(http://nghiaho.com/?page_id=846),它就是
var rotXInRadians = Math.atan2(m[9], m[10]);
var rotYInRadians = Math.atan2(-m[8], Math.sqrt(m[9] * m[9] + m[10] * m[10]));
var rotZInRadians = Math.atan2(m[4], m[0]);
这是一个例子
http://jsfiddle.net/greggman/q7Bsy/
我会将此处的代码专门粘贴到glMatrix
// first let's make 3 nodes, 'a', 'b', and 'camera
var degToRad = function(v) {
return v * Math.PI / 180;
}
var a = {
name: "a",
translation: [0, -50, -75],
pitch: 0,
yaw: degToRad(30),
};
var b = {
name: "b",
translation: [0, 100, 50],
pitch: 0,
yaw: degToRad(-75),
}
var camera = {
name: "cam",
translation: [0, 15, 10],
pitch: 0,
yaw: degToRad(16),
parent: a,
};
这是计算每个
矩阵的代码var matA = mat4.create();
mat4.identity(matA);
mat4.translate(matA, matA, a.translation);
mat4.rotateY(matA, matA, a.pitch);
mat4.rotateX(matA, matA, a.yaw);
a.mat = matA;
var matB = mat4.create();
mat4.identity(matB);
mat4.translate(matB, matB, b.translation);
mat4.rotateY(matB, matB, b.pitch);
mat4.rotateX(matB, matB, b.yaw);
b.mat = matB;
var matCamera = mat4.create();
mat4.identity(matCamera);
var parent = camera.parent;
mat4.translate(matCamera, matCamera, parent.translation);
mat4.rotateY(matCamera, matCamera, parent.pitch);
mat4.rotateX(matCamera, matCamera, parent.yaw);
mat4.translate(matCamera, matCamera, camera.translation);
mat4.rotateY(matCamera, matCamera, camera.pitch);
mat4.rotateX(matCamera, matCamera, camera.yaw);
camera.mat = matCamera;
这是交换相机的代码
// Note: Assumes matrices on objects are updated.
var reparentObject = function(obj, newParent) {
var matInverseNewParent = mat4.create();
var matNewParentToObject = mat4.create();
mat4.invert(matInverseNewParent, newParent.mat);
mat4.multiply(matNewParentToObject, matInverseNewParent, obj.mat);
var m = matNewParentToObject;
obj.translation[0] = m[12];
obj.translation[1] = m[13];
obj.translation[2] = m[14];
var rotXInRadians = Math.atan2(m[9], m[10]);
var rotYInRadians = Math.atan2(-m[8], Math.sqrt(m[9] * m[9] + m[10] * m[10]));
var rotZInRadians = Math.atan2(m[4], m[0]);
obj.pitch = rotYInRadians;
obj.yaw = rotXInRadians;
obj.parent = newParent;
};
var newParent = camera.parent == a ? b : a;
reparentObject(camera, newParent);