[英]Need rotation matrix for opengl 3D transformation
問題是我在3D空間中有兩個點,其中y +是向上的,x +是向右的,而z +是朝向你的。 我想在它們之間定位一個圓柱體,它是兩個點之間距離的長度,因此它的兩個中心端都接觸這兩個點。 我將氣缸轉換到兩點中心的位置,我需要幫助提出一個旋轉矩陣應用於氣缸,以便它以正確的方式定向。 我對整個事物的轉換矩陣如下所示:
平移(中心點)* rotateX(有些X度)* rotateZ(有些Z度)
翻譯最后應用,這樣我可以在翻譯之前將其轉換為正確的方向。
以下是我迄今為止所做的事情:
mat4 getTransformation(vec3 point, vec3 parent)
{
float deltaX = point.x - parent.x;
float deltaY = point.y - parent.y;
float deltaZ = point.z - parent.z;
float yRotation = atan2f(deltaZ, deltaX) * (180.0 / M_PI);
float xRotation = atan2f(deltaZ, deltaY) * (180.0 / M_PI);
float zRotation = atan2f(deltaX, deltaY) * (-180.0 / M_PI);
if(point.y < parent.y)
{
zRotation = atan2f(deltaX, deltaY) * (180.0 / M_PI);
}
vec3 center = vec3((point.x + parent.x)/2.0, (point.y + parent.y)/2.0, (point.z + parent.z)/2.0);
mat4 translation = Translate(center);
return translation * RotateX(xRotation) * RotateZ(zRotation) * Scale(radius, 1, radius) * Scale(0.1, 0.1, 0.1);
}
我嘗試了下面給出的解決方案,但它似乎根本不起作用
mat4 getTransformation(vec3 parent, vec3 point)
{
// moves base of cylinder to origin and gives it unit scaling
mat4 scaleFactor = Translate(0, 0.5, 0) * Scale(radius/2.0, 1/2.0, radius/2.0) * cylinderModel;
float length = sqrtf(pow((point.x - parent.x), 2) + pow((point.y - parent.y), 2) + pow((point.z - parent.z), 2));
vec3 direction = normalize(point - parent);
float pitch = acos(direction.y);
float yaw = atan2(direction.z, direction.x);
return Translate(parent) * Scale(length, length, length) * RotateX(pitch) * RotateY(yaw) * scaleFactor;
}
運行上面的代碼后,我得到了這個:
每個黑點都是一個點,其父級是產生它的點(前面的那個)我希望分支適合點。 基本上我正在嘗試為隨機樹生成實現空間定殖算法。 我得到了大部分,但我想將樹枝映射到它,所以看起來不錯。 我可以使用GL_LINES來建立一個通用的連接,但如果我得到這個工作,它看起來會更漂亮。 這里解釋了算法。
這是我想要做的事情的圖像(原諒我的繪畫技巧)
嗯,有任意數量的旋轉矩陣滿足您的約束。 但任何人都會這樣做。 我們不是試圖找出特定的旋轉,而是直接寫下矩陣。 假設您的圓柱體在未應用變換時,其軸線沿Z軸。 因此,您必須將局部空間Z軸轉換為這兩個點之間的方向。 即z_t = normalize(p_1 - p_2)
,其中normalize(a) = a / length(a)
。
現在我們只需要使它成為一個完整的三維坐標基礎。 我們從一個與z_t不平行的任意向量開始。 比如,(1,0,0)或(0,1,0)或(0,0,1)之一; 用標產品·
(也稱為內部,或內積)與z_t並使用其絕對值最小的向量,我們稱之為載體u
。 在偽代碼中:
# Start with (1,0,0)
mindotabs = abs( z_t · (1,0,0) )
minvec = (1,0,0)
for u_ in (0,1,0), (0,0,1):
dotabs = z_t · u_
if dotabs < mindotabs:
mindotabs = dotabs
minvec = u_
u = minvec_
然后,您正交化該向量,產生局部y變換y_t = normalize(u - z_t · u)
。
最后通過乘以叉積x_t = z_t × y_t
創建x變換
要將圓柱體移動到位,請將其與匹配的平移矩陣組合。
轉換矩陣實際上只是你從“來自”空間的軸,就像從另一個空間看到的那樣。 因此,得到的矩陣,即您正在尋找的旋轉矩陣,只是矢量x_t,y_t和z_t並排作為矩陣。 OpenGL使用所謂的均勻矩陣,因此您必須使用0,0,0,1最底行和最右列將其填充為4×4形式。
你可以加載到OpenGL; 如果使用固定功能使用glMultMatrix來應用旋轉,或者如果使用着色器乘以矩陣,則最終會傳遞給glUniform。
用具有其兩端,我稱之為一個單位長度的圓筒開始C1
,在原點(請注意,您的圖片表明了你的汽缸都有它的起源中心 ,但你可以很容易地變換一下我開頭)。 另一端,我稱之為C2
,然后是(0,1,0)
。
我想打電話給你的兩個點在世界坐標P1
和P2
,我們要找到C1
上的P1
和C2
至P2
。
首先將圓柱體轉換為P1
,然后將C1
成功定位到P1
。
然后按distance(P1, P2)
縮放圓柱體,因為它最初的長度為1
。
可以使用球面坐標計算剩余旋轉。 如果您不熟悉這種類型的坐標系:它就像GPS坐標:兩個角度; 一個圍繞極軸(在你的情況下是世界的Y軸),我們通常稱之為偏航 ,另一個是俯仰角(在你的情況下是模型空間中的X軸)。 可以通過將P2-P1
(即, P2
的局部偏移相對於P1
)轉換為球面坐標來計算這兩個角度。 首先以俯仰角圍繞X旋轉物體,然后繞Y偏航。
像這樣的東西會這樣做(偽代碼):
Matrix getTransformation(Point P1, Point P2) {
float length = distance(P1, P2);
Point direction = normalize(P2 - P1);
float pitch = acos(direction.y);
float yaw = atan2(direction.z, direction.x);
return translate(P1) * scaleY(length) * rotateX(pitch) * rotateY(yaw);
}
調用氣缸A的軸。 第二次旋轉(大約X )不能改變A和X之間的角度,所以我們必須在第一次旋轉(大約Z )時獲得該角度。
調用目標矢量(兩點之間的矢量) B 。 拿-acos(B X / B Y ),這是第一次旋轉的角度。
再次取B ,忽略X分量,並查看其在(Y,Z)平面中的投影。 取acos(B Z / B Y ),這就是第二次旋轉的角度。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.