2016-05-05 12 views
1

私はOpenGLで3dレーザービームをレンダリングしようとしています。私は2つの点(p1、p2)と、p1とp2の間の距離でスケーリングされた3面の円柱を持っています。問題は、シリンダーが正しく回転することができないということです。私はatan2を使って3つの軸の角度を計算し、これを行列に適用しようとしましたが、これまでのところ成功しませんでした。シリンダーはちょうどポイントに従っていません。これは、回転計算をどのようにしたかです。OpenGL 3dレーザービーム

p3 = p2 - p1 
rotX = atan2(p3.y, p3.z) 
rotY = atan2(p3.x, p3.z) 
rotZ = atan2(p3.x, p3.y) 

matrix.rotate(rotX, rotY, rotZ) 
+1

クォータニオンを使用して回転行列に変換してください –

+0

@willywonka_dailyblah:それは役に立たないでしょう。問題は角度の選択です。クォータニオンを使うことは、同じ答えを得るための別のテクニックです。 –

答えて

1

これは、線形代数が少し進んでいる状況の1つです。三角法はまったく必要ありません。三角法はすべて角度に関するもので、直角座標を角度に変換してから直角座標に戻すことです。 2つのコンバージョンは不要です。

v = p2 - p1を定義しましょう。

円筒が(0、0、0)から(0、0、1)までZ軸に沿って移動しているとします。それは、あなたがそのようにそれを書いた後、それは本当に簡単に見える、

A * (0, 0, 1) = v 

まあません。私たちは、私たちに次の変換を与える行列Aを作成しようとしています!行列に基底ベクトルを右乗算すると、列ベクトルの1つが得られます。したがって、vは行列の列の1つでなければなりません。

A = [ ? ? v.x ] 
    [ ? ? v.y ] 
    [ ? ? v.z ] 

ここで、レーザーの断面形状を保存するために、正規化されvに直交する2つの他の列ベクトルを選択します。これは簡単です。ここではGLSLで書かれているようなコードをいくつか紹介します(glmをC++やgl-matrixとJavaScriptで似た構文にすることもできます)。数学に拡大すること

mat3 create_laser_matrix(vec3 v) { 
    // Find a vector, ref, not parallel to v 
    vec3 vmag = abs(v); 
    vec3 ref; 
    if (vmag.x <= vmag.y && vmag.x <= vmag.z) { 
     ref = vec3(1.0, 0.0, 0.0); 
    } else if (vmag.y <= vmag.z) { 
     ref = vec3(0.0, 1.0, 0.0); 
    } else { 
     ref = vec3(0.0, 0.0, 1.0); 
    } 
    // Use ref to create two unit vectors, u1, u2, so {v, u1, u2} are orthogonal 
    vec3 utemp = cross(v, ref); 
    vec3 u1 = normalize(cross(v, utemp)); 
    vec3 u2 = normalize(cross(v, u1)); 
    return mat3(u1, u2, v); 
} 

:三角法は、私たちは角度や直交座標およびその逆の間で変換することができますが、それは我々がすべてでこれを実行する必要がないことが判明。 「回転行列」は、ちょうど一種の直交行列(1ではなく行列式1を持つもの)であり、直交行列は列ベクトルが直交する行列であり、任意の2つの列の内積ベクトルはゼロです。三角法は必要ありません。 2つの点を結ぶためにレーザーを「引き伸ばす」必要があるので、我々は直交行列の直後ではありませんが、同じ数学のほとんどが適用されます。

関連する問題