Opengl 绕轴旋转物体
我有一个圆形的物体,我想像风扇一样沿着它自己的轴旋转 我可以使用变换矩阵更改任意方向的旋转,即Opengl 绕轴旋转物体,opengl,matrix,graphics,rotation,Opengl,Matrix,Graphics,Rotation,我有一个圆形的物体,我想像风扇一样沿着它自己的轴旋转 我可以使用变换矩阵更改任意方向的旋转,即dx、dy、dz 以下是代码: Matrix4f matrix = new Matrix4f(); matrix.setIdentity(); Matrix4f.translate(translation, matrix, matrix); Matrix4f.rotate((float) Math.toRadians(rx), new Vector3f(1,0,0), matrix, matri
dx、dy、dz
以下是代码:
Matrix4f matrix = new Matrix4f();
matrix.setIdentity();
Matrix4f.translate(translation, matrix, matrix);
Matrix4f.rotate((float) Math.toRadians(rx), new Vector3f(1,0,0), matrix, matrix);
Matrix4f.rotate((float) Math.toRadians(ry), new Vector3f(0,1,0), matrix, matrix);
Matrix4f.rotate((float) Math.toRadians(rz), new Vector3f(0,0,1), matrix, matrix);
Matrix4f.scale(new Vector3f(scale,scale,scale), matrix, matrix);
我的顶点代码:
vec4 worldPosition = transformationMatrix * vec4(position,1.0);
vec4 positionRelativeToCam = viewMatrix*worldPosition;
gl_Position = projectionMatrix *positionRelativeToCam;
Main Game Loop:
Object.increaseRotation(dxf,dyf,dzf);
但是,它不是沿着自己的轴旋转的。我错过了什么?
我想要这样的东西。请帮忙
为此,您应该去掉欧拉角
z
。如果您的网格定义为旋转轴未与任何轴对齐(x,y
或z
),或者中心点不是(0,0,0)
,则会导致问题。补救方法是更改网格几何体或创建一个特殊的常量变换矩阵M0
,该矩阵将所有顶点从网格LCS(局部坐标系)变换为一个不同的顶点,该顶点与轴对齐,且旋转中心在轴(也是旋转轴)中为零
在后一种情况下,对对象矩阵M
的任何操作都将如下所示:
M'=M.M0.operation.Inverse(M0)
或反向或反向(取决于矩阵/顶点乘法和行/列顺序约定)。如果网格已居中且轴已对齐,则只需执行以下操作:
M'=M.operation
操作是变化增量的变换矩阵(例如旋转矩阵)。M
是来自#2的对象当前变换矩阵,M'
是应用操作后的新版本
M'=M*rotation_matrix
其中,M
是当前对象变换矩阵,M'
是旋转后的新版本。这就是你与众不同的地方。您使用的是Euler角度rx、ry、rz
,而不是增量累积旋转。你不能用任何理智和稳健的方式来处理欧拉角!即使许多现代游戏和应用程序仍在努力做到这一点(并失败多年)M
而不是每个渲染的本地实例,因此只需初始化它一次,而不是在每帧的基础上清除它angspeed
是风扇转速的[rad/second]
或[deg/second]
,而dt
是以[seconds]
为单位经过的时间。例如,如果在计时器中执行此操作,则dt
是计时器间隔。对于可变时间,您可以测量经过的时间(它取决于平台,我通常使用PerformanceTimes或RDTSC)
您可以在其顶部堆叠更多操作(例如,您的风扇还可以围绕y
轴前后转动,以覆盖更多区域
对于对象直接控制(通过键盘、鼠标或操纵杆),只需添加以下内容:
if (keys.get( 38)) { redraw=true; M*=translate_z(-pos_speed*dt); }
if (keys.get( 40)) { redraw=true; M*=translate_z(+pos_speed*dt); }
if (keys.get( 37)) { redraw=true; M*=rotation_around_y(-turn_speed*dt); }
if (keys.get( 39)) { redraw=true; M*=rotation_around_y(+turn_speed*dt); }
其中,keys
是我的键映射,为键盘中的每个键保持开/关状态(这样我可以一次使用更多键)。此代码仅使用箭头控制对象。有关主题的更多信息,请参阅相关QA:
X,Y,Z
必须与其他两个向量垂直,并且其大小必须为单位。我这样做:
M'=M.M0.operation.Inverse(M0)
Z
轴,因为它通常是我网格中的主轴(查看方向、旋转轴等)。所以只需将此向量单位设为Z=Z/| Z
X=(+/-)zxy
和Y=(+/-)zx
,并对它们进行规格化X=X/| X |
和Y=Y/| Y
之所以存在,是因为我不知道您的坐标系约定,而叉积可以生成与原始方向相反的向量,因此如果方向相反,请更改乘法顺序或对结果求反(这是在非运行时编码时间时完成的!)void repro::orto(int测试)
{
双x[3],y[3],z[3];
if((cnt>=_resu_max_cnt)| | |(test))//这里cnt是操作计数器和测试力标准化,不管它是什么
{
使用_rep();//您可以忽略此选项
_rep=1;_inv=0;//您可以忽略此项
axix_-get(x);
axisy_-get(y);
axisz_-get(z);
向量_-one(z,z);
向量_mul(x,y,z);//x垂直于y,z
向量_-one(x,x);
向量μmul(y,z)