簡體   English   中英

圍繞World Axis OpenGL旋轉對象

[英]Rotation of object around World Axis OpenGL

我正在嘗試在OpenGL中制作一個可控的球。 我正在使用自己的矩陣類來轉換對象矩陣,但似乎無法正確實現“旋轉”。 我總是以球繞局部軸旋轉而告終。 這就是現在的樣子https://gfycat.com/LongKindBassethound 長線是局部軸。

因此,當球向前移動時,下一個側向移動將是錯誤的。 矩陣類中有一個函數可以繞任何軸旋轉:

Matrix& Matrix::rotationAxis(const Vector& Axis, float Angle) {
const float Si = sin(Angle);
const float Co = cos(Angle);
const float OMCo = 1 - Co;
Vector Ax = Axis;
Ax.normalize();

m00= (Ax.X * Ax.X) * OMCo + Co;
m01= (Ax.X * Ax.Y) * OMCo - (Ax.Z * Si);
m02= (Ax.X * Ax.Z) * OMCo + (Ax.Y * Si);
m03= 0;

m10= (Ax.Y * Ax.X) * OMCo + (Ax.Z * Si);
m11= (Ax.Y * Ax.Y) * OMCo + Co;
m12= (Ax.Y * Ax.Z) * OMCo - (Ax.X * Si);
m13= 0;

m20= (Ax.Z * Ax.X) * OMCo - (Ax.Y * Si);
m21= (Ax.Z * Ax.Y) * OMCo + (Ax.X * Si);
m22= (Ax.Z * Ax.Z) * OMCo + Co;
m23= 0;

m30= 0;
m31= 0;
m32= 0;
m33= 1;

return *this;
}

我認為,我可以采用世界方向矢量並將其轉換為對象的局部空間,然后圍繞結果旋轉。 我真的不知道該怎么做(球的矩陣*世界向量?那是行不通的)。 我真的很想避免四元數,但是如果我不能這樣做,我也很樂意朝這個方向提出建議。

編輯:更多信息

轉換代碼。 如您所見,我嘗試了不同的方法,所有這些方法都執行相同的操作...因此,這並不起作用並不奇怪。

Matrix transM, rotX, rotZ;
rotationX = straight;
rotationZ = side;
if (velocity != Vector(0, 0, 0)) {
    velocity.X = -0.0005 * DeltaTime;
    velocity.X = clamp(velocity.X, 0, FLT_MAX);

    velocity.Z = -0.0005 * DeltaTime;
    velocity.Z = clamp(velocity.Z, 0, FLT_MAX);
}

velocity.X += speed * -side * DeltaTime;
velocity.Z += speed * straight * DeltaTime;
transM.translation(velocity.X, 0, velocity.Z);

if (velocity.Z != 0 || velocity.X != 0) {
    //http://mathworld.wolfram.com/EulerAngles.html
    //http://gamedev.stackexchange.com/questions/67199/how-to-rotate-an-object-around-world-aligned-axes

    Vector localAxisX =  m_Ball * Vector(1, 0, 0);
    Vector localAxisZ = m_Ball * Vector(0, 0, 1);
    rotX.rotationAxis(Vector(1, 0, 0), 0.5* M_PI * straight * DeltaTime);
    rotZ.rotationAxis(Vector(0, 0, 1), 0.5* M_PI * side * DeltaTime);
    //rotX.rotationX(0.5* M_PI * straight * DeltaTime * 3);
    //rotZ.rotationZ(0.5* M_PI * side * DeltaTime * 3);
    //Matrix fullRotation.rotationYawPitchRoll(Vector(0,  0.5* M_PI * straight * DeltaTime, 0.5* M_PI * side * DeltaTime));
    m_Ball = transM * m_Ball * (rotX*rotZ);
}
else {
    m_Ball = transM * m_Ball;
}

我以前嘗試使用glRotatef的嘗試繪制代碼(現在已明顯注釋掉)

void Ball::draw(float DeltaTime) {
  glPushMatrix();
  glMultMatrixf(m_Ball);
  if(rotationX)
    glRotatef(0.5* M_PI * rotationX * DeltaTime, 1.0, 0.0, 0.0);
  if(rotationZ)
    glRotatef(0.5* M_PI * rotationZ * DeltaTime, 0.0, 0.0, 1.0);
  g_Model_ball.drawTriangles();
  glPopMatrix();
  drawAxis();
}

我強烈建議使用四元數來輕松處理復合旋轉並避免雲台鎖定。

https://zh.wikipedia.org/wiki/雲台鎖定

關於您的評論和視頻,您想繞球的中心旋轉。 看來您在m_Ball累積了旋轉,但是做了一個怪異的transM乘法。 另外,您可能正在transM積累翻譯。

盡量不要混合使用平移和旋轉,並避免將它們累積在m_Ball 你可以做這樣的事情。

//transformation matrix
transM.translation(velocity.X, 0, velocity.Z);

//accumulate translations in m_BallT
m_BallT = transM * m_BallT;

//final Rotation
Matrix rotation = rotX * rotZ;

//accumulate rotations in m_BallR
m_BallR = rotation * m_BallR;

//now compute your final transformation matrix from accumulated rotations and translation
m_Ball = m_BallT * m_BallR;

請注意m_BallR只是如何累積旋轉。 乘法后將確保在m_BallR累積旋轉后應用新的rotation 最后轉換為m_BallT累積的最終位置。 您的球將繞其中心旋轉並根據m_BallT移動。

您也可以簡單地替換m_BallR上的轉換組件,以避免額外的矩陣乘法。

Vector newPos(m_Ball.translation().X + velocity.X, terrainNoise.GetHeight(m_Ball.translation().X, m_Ball.translation().Z) + 0.5, m_Ball.translation().Z + velocity.Z);

rotX.rotationAxis(Vector(1, 0, 0), 0.5* M_PI * straight * DeltaTime * abs(velocity.Z) * 100);
rotZ.rotationAxis(Vector(0, 0, 1), 0.5* M_PI * side * DeltaTime * abs(velocity.X) * 100);

m_Rotation = (rotX*rotZ);

m_Ball = (m_Ball.invert() * m_Rotation).invert();


m_Ball.m03 = newPos.X;
m_Ball.m13 = newPos.Y;
m_Ball.m23 = newPos.Z;

這是我想出了閱讀后的溶液這個由@Spektre提供的鏈接。 基本上,您只需要反轉球的ModelMatrix即可將其置於世界位置,進行旋轉,然后將其轉換回局部空間。

旋轉之前必須設置newPos Vector,否則它將影響以后的轉換。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM