我的3D模型围绕错误的轴旋转。除X轴外的所有东西都可以。当我将Y和Z的角度设置为0时,X工作正常,但如果旋转它,例如。绕Z轴旋转90度,然后围绕Z旋转,它也绕Z旋转。因此,当使用Y或Z时,X围绕Z旋转。因此,如果我使模型绕Z旋转90度,绕X旋转-90度,则完全静止。
我的转换矩阵函数。如果我将public static Matrix4f createTransformationMatrix(Vector3f position, Vector3f rotation, Vector3f scale) {
Matrix4f matrix = new Matrix4f();
matrix.scale(scale);
matrix.translate(position);
matrix.rotate((float) Math.toRadians(rotation.x), new Vector3f(1, 0, 0));
matrix.rotate((float) Math.toRadians(rotation.y), new Vector3f(0, 1, 0));
matrix.rotate((float) Math.toRadians(rotation.z), new Vector3f(0, 0, 1));
return matrix;
}
移动到旋转状态下,我的模型会以巨大的圆圈旋转(可能在世界原点附近)。
public static FloatBuffer toFloatBuffer(Matrix4f matrix) {
FloatBuffer buffer = BufferUtils.createFloatBuffer(16);
buffer.put(matrix.m00());
buffer.put(matrix.m01());
buffer.put(matrix.m02());
buffer.put(matrix.m03());
buffer.put(matrix.m10());
buffer.put(matrix.m11());
buffer.put(matrix.m12());
buffer.put(matrix.m13());
buffer.put(matrix.m20());
buffer.put(matrix.m21());
buffer.put(matrix.m22());
buffer.put(matrix.m23());
buffer.put(matrix.m30());
buffer.put(matrix.m31());
buffer.put(matrix.m32());
buffer.put(matrix.m33());
buffer.flip();
return buffer;
}
将矩阵转换为floatbuffer,以便将其传递给着色器:
gl_Position = transformationMatrix * vec4(position, 1.0) * viewMatrix * projectionMatrix;
着色器中的用法:
with tmp as (
select 'Oracle' as field_name , 1 as data from dual union all
select 'Oracle' as field_name , null as data from dual union all
select NULL as field_name , null as data from dual union all
select 'Test' as field_name , null as data from dual )
Select * from tmp
Where 1 = case when field_name = 'Oracle' and data is null
then 0
else 1
end
模特'零点已设置为其原点,我确信发送到这些功能的所有数据都是正确的。我一直在调试这个。我正在使用LWJGL 3。
答案 0 :(得分:2)
我认为你正面对Gimbal Lock。 这意味着,重要的是旋转应用的顺序,然后您可能会得到奇怪的结果,例如您所经历的结果。
要解决此问题,您必须使用Quaternions。
基本上,你必须:
您必须创建一个表示X轴旋转的旋转四元数,依此类推Y轴和Z轴
你将它们相乘
最后,您必须将生成的四元数转换为矩阵。
请在此处阅读how to implement Rotation Quaternions in OpenGL?
编辑:
请在此处阅读有关如何将四元数转换为矩阵的信息:Convert Quaternion rotation to rotation matrix?
这是我的Camera类(不幸的是,它使用像Quaternion这样的JOGL库,但是应该可以移植到LWJGL。它以Euler或Quaternion的方式提供缩放,移动,围绕中心的旋转,以及检索指向的方法方向等。
public class Camera {
public Matrix4 matrix;
public Quaternion rotation;
public Vector3 position;
public Vector3 scale;
public Vector3 center;
public Vector2 frictionx;
public Vector2 frictiony;
public Vector2 frictionz;
public Camera() {
matrix=new Matrix4();
rotation=new Quaternion();
position=new Vector3(0f,0f,0f);
scale=new Vector3(1f,1f,1f);
center=new Vector3(0f,0f,0f);
frictionx=new Vector2(0,0);
frictiony=new Vector2(0,0);
frictionz=new Vector2(0,0);
}
public float tryFric(float a, float b) {
try {
float r=a/b;
if (r == Float.NaN) {
return 0;
}
return r;
}
catch (Exception e) {
return 0;
}
}
public void getFrictions(Vector3 pointing) {
frictionx.x=tryFric(pointing.y,pointing.x);
frictionx.y=tryFric(pointing.z,pointing.x);
frictiony.x=tryFric(pointing.x,pointing.y);
frictiony.y=tryFric(pointing.z,pointing.y);
frictionz.x=tryFric(pointing.x,pointing.z);
frictionz.y=tryFric(pointing.y,pointing.z);
}
public Vector3 getPointing(Vector3 vec) {
float[] in=new float[] {vec.x,vec.y,vec.z};
float[] out=new float[3];
rotation.conjugate();
rotation.rotateVector(out, 0, in, 0);
rotation.conjugate();
Vector3 p=new Vector3(out[0],out[1],out[2]);
getFrictions(p);
return p;
}
public void move(float x, float y, float z) {
position.x+=x;
position.y+=y;
position.z+=z;
}
public void setPosition(float x, float y, float z) {
position.x=x;
position.y=y;
position.z=z;
}
public void moveCenter(float x, float y, float z) {
center.x+=x;
center.y+=y;
center.z+=z;
}
public void setCenter(float x, float y, float z) {
center.x=x;
center.y=y;
center.z=z;
}
public void scale(float x, float y, float z) {
scale.x*=x;
scale.y*=y;
scale.z*=z;
}
public void setScale(float x, float y, float z) {
scale.x=x;
scale.y=y;
scale.z=z;
}
public void rotateQuaternion(float angle, float x, float y, float z) {
Quaternion rotationy=new Quaternion();
rotationy.rotateByAngleY(angle*y);
rotation.mult(rotationy);
Quaternion rotationx=new Quaternion();
rotationx.rotateByAngleX(angle*x);
rotation.mult(rotationx);
Quaternion rotationz=new Quaternion();
rotationz.rotateByAngleZ(angle*z);
rotation.mult(rotationz);
rotation.normalize();
}
public void rotateEuler(float angle, float x, float y, float z) {
rotation.rotateByEuler(angle*x, angle*y, angle*z);
}
public Vector3 getPointing() {
Matrix4 as_matrix=new Matrix4();
as_matrix.loadIdentity();
as_matrix.rotate(rotation);
float[] out=new float[3];
float[] in=new float[] {0,0,-1};
as_matrix.multVec(in, out);
Vector3 pointing=new Vector3(out[0],out[1],out[2]);
return pointing;
}
public Matrix4 getMatrix() {
Matrix4 rot_as_mat=new Matrix4();
rot_as_mat.loadIdentity();
rot_as_mat.translate(center.x, center.y, center.z);
rot_as_mat.rotate(rotation);
Matrix4 result=new Matrix4();
result.loadIdentity();
result.scale(scale.x, scale.y, scale.z);
result.multMatrix(rot_as_mat);
result.translate(position.x,position.y,position.z);
matrix=result;
return result;
}
}
希望它有所帮助!
注意: