2009-08-25 111 views
3

我有一個圓錐我的Java 3D畫了下面的代碼:如何在Java 3D中旋轉對象?

Cone cone = new Cone(2f, 3f); 

Transform3D t3d = new Transform3D(); 
TransformGroup coneTransform = new TransformGroup(t3d); 
coneTransform.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); 

t3d.setTranslation(new Vector3f(0f,0f,0f); 
coneTransform.setTransform(t3d); 
coneTransform.addChild(cone); 

this.addChild(coneTransform); 

假設我有錐坐在點(1,1,1)和我想要的錐尖指向下一個假想線穿過(0,0,0)和(1,1,1)......我該怎麼做?

這裏是什麼,我一直想一個例子:

Transform3D t3d = new Transform3D(); 

Vector3f direction = new Vector3f(1,2,1);  

final double angleX = direction.angle(new Vector3f(1,0,0)); 
final double angleY = direction.angle(new Vector3f(0,1,0)); 
final double angleZ = direction.angle(new Vector3f(0,0,1)); 

t3d.rotX(angleX); 
t3d.rotY(angleY); 
t3d.rotZ(angleZ); 

t3d.setTranslation(direction); 

coneTransform.setTransform(t3d); 

預先感謝所有幫助!

回答

1

我終於想通過使用Quaternion來了解我想要做什麼,我在這裏瞭解到了這些:http://www.cs.uic.edu/~jbell/Courses/Eng591_F1999/outline_2.html這是我的解決方案。

創建錐體:

private void attachCone(float size) { 
     Cone cone = new Cone(size, size* 2); 

     // The group for rotation 
     arrowheadRotationGroup = new TransformGroup(); 
     arrowheadRotationGroup. 
      setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); 
     arrowheadRotationGroup.addChild(cone); 

     // The group for positioning the cone 
     arrowheadPositionGroup = new TransformGroup(); 
     arrowheadPositionGroup. 
       setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); 
     arrowheadPositionGroup.addChild(arrowheadRotationGroup); 

     super.addChild(arrowheadPositionGroup); 
    } 

現在,當我要旋轉的錐體中指定爲從點(0,0,0)的向量某一方向到點(direction.x, direction.y,direction.z),我用:

private final Vector3f yAxis = new Vector3f(0f, 1f, 0f); 
private Vector3f direction; 

private void rotateCone() { 
     // Get the normalized axis perpendicular to the direction 
     Vector3f axis = new Vector3f(); 
     axis.cross(yAxis, direction); 
     axis.normalize(); 

     // When the intended direction is a point on the yAxis, rotate on x 
     if (Float.isNaN(axis.x) && Float.isNaN(axis.y) && Float.isNaN(axis.z)) 
     { 
      axis.x = 1f; 
      axis.y = 0f; 
      axis.z = 0f; 
     } 
     // Compute the quaternion transformations 
     final float angleX = yAxis.angle(direction); 
     final float a = axis.x * (float) Math.sin(angleX/2f); 
     final float b = axis.y * (float) Math.sin(angleX/2f); 
     final float c = axis.z * (float) Math.sin(angleX/2f); 
     final float d = (float) Math.cos(angleX/2f); 

     Transform3D t3d = new Transform3D(); 
     Quat4f quat = new Quat4f(a, b, c, d); 
     t3d.set(quat); 
     arrowheadRotationGroup.setTransform(t3d); 

     Transform3D translateToTarget = new Transform3D(); 
     translateToTarget.setTranslation(this.direction); 
     arrowheadPositionGroup.setTransform(translateToTarget); 
    } 
0

我想這應該這樣做:

coneTransform.rotX(Math.PI/4); 
coneTransform.rotY(Math.PI/4); 
+0

謝謝。 t3d.rotX(Math.PI/2);和Y類似,Z將旋轉錐體。你能描述一下如何計算旋轉X和Y的角度?例如,如果我從(0,0,0)到(1,1,1)繪製一條線,如何計算旋轉量? – Cuga 2009-08-25 20:50:44

+1

旋轉函數將弧度值作爲輸入。有2 * PI一個完整的旋轉,或垂直線之間的PI/2度(這意味着我錯了,你只需要旋轉PI/4)。 一般而言,您不需要沿着所有三個角度旋轉,因爲您可以通過沿着兩個軸旋轉來描述任何旋轉。 – Zed 2009-08-26 06:28:49

+0

哈哈 - 我*只是*意識到我不需要所有3輪。現在我正在紙上寫出如何計算我需要的角度。謝謝你的幫助。 – Cuga 2009-08-26 13:07:32

2

這不是一個Java3D的具體的答案。

通常可以建立一個矩陣,使得有4個向量來描述它。

1)側(或橫向)載體
2)向上矢量
3)的方向矢量
4)位置

的4×4矩陣的每一行。因此,對於一個簡單的單位矩陣,我們有以下矩陣(我將定義一個列主矩陣,對於一個行主矩陣,所有您需要做的就是交換矩陣索引,使得第2行第3列變爲第3行整個矩陣中的第2列)。

1 0 0 0 
0 1 0 0 
0 0 1 0 
0 0 0 1 

在這第一列是側向量。第二列向上的向量。第三個方向和第四個位置。

邏輯上我們可以看到矢量(1,0,0,0)指向x軸(因此是側矢量)。向量(0,1,0,0)沿着y軸指向(因此是向上向量)。第三個(0,0,1,0)指向Z軸(因此是方向矢量)。第四個(0,0,0,1)表示對象完全不移動。

現在讓我們說我們想要沿着X軸面對。

很明顯,這意味着我們有一個矢量(1,0,0,0)用於我們的方向矢量。 Up仍然是(0,1,0,0),位置仍然是0,0,0 1.那麼我們的側向矢量是什麼?那麼,邏輯上它會沿着z軸指向。但是,哪種方式?那麼握住你的手指,讓一個手指指向前方,一個側面,一個向上。現在旋轉,使正向手指朝向與手指側面相同的方向。側面指向哪一側?與指向手指的原始方向相反的方向。因此矩陣是

0 0 1 0 
0 1 0 0 
-1 0 0 0 
0 0 0 1 

在這一點上看起來事情似乎稍微複雜一點。採用任意位置和任意點來查看(我將稱它們爲vPos和vFocus)非常簡單。通過從vFocus減去vPos(vFocus.x - vPos.x,vFocus.y - vPos.y,vFocus.z - vPos.z,vFocus.w - vPos.w),從vPos到vFocus形成矢量非常簡單。 。請記住,所有位置都應在w位置以'1'定義,其中所有方向應該爲'0'。當你做上述減法時,這是自動處理的,因爲兩個ws中的1都會取消並保留0。無論如何,我們現在有一個矢量指向vFocus的位置,我們稱之爲vDir。不幸的是,它具有vPos和vFocus之間區別的長度。然而,如果我們將vDir矢量除以其長度(vDir.x /長度,vDir.y /長度,vDir.z /長度,vDir.w /長度),那麼我們將其規格化爲它,並且我們有一個總長度方向爲1.

在這個ponit我們現在有我們矩陣的第3和第4列。現在,讓我們依然是(0,1,0,0)或vUp。我們可以假設方向和vUp的交叉乘積會產生一個向量,該向量垂直於vDir和vUp形成的平面(也是單位長度)。這給了我們我們的側面向量或vLat。現在..我們確實承擔了向上的向量,所以它不是嚴格正確的。現在我們可以精確計算vLat和vDir的交叉乘積,並且我們有4個向量。

最終的矩陣因此定義如下

vLat.x vUp.x vDir.x vPos.x 
vLat.y vUp.y vDir.y vPos.y 
vLat.z vUp.z vDir.z vPos.z 
vLat.w vUp.w vDir.w vPos.w 

這不是嚴格完整的答案,你對一個點看接近你會得到你的問題(0,1,0,0)載體,但這應該適用於大多數個案。

3

我現在剛剛學習Java 3D,並且從我目前的知識來看,旋轉方法將變換設置爲僅關於該軸的旋轉。 因此,如果您希望執行關於多個軸的旋轉,那麼您將需要使用第二個Transform3D。
即:

Transform3D rotation = new Transform3D(); 
Transform3D temp = new Transform3D(); 

rotation.rotX(Math.PI/2); 
temp.rotZ(Math.PI/2); 
rotation.mul(temp); // multiply the 2 transformation matrices together. 

至於Math.PI的原因,這是因爲它使用弧度,而不是度,其中Math.PI相當於180度。

找到你當前的方向和你想要的方向之間的角度並不難 - 你可以使用Vector3fs和angle()方法。矢量將以初始方向設置,另一個在預期中。 但是,這並不能告訴你角度在哪個軸上。這樣做需要檢查矢量以查看設置了哪些段。 [當然,可能有些東西我目前在API中沒有意識到]

+0

啊...所以我需要爲每個我想旋轉的軸單獨的Transform3D?我試圖使用相同的Transform3D實例並對其執行rotX(),rotY(),rotZ()。我會試一試。 – Cuga 2009-08-26 02:46:12

+0

我用四元數進行旋轉。圍繞x和y旋轉只是不斷給我提供不可靠的問題。顯然,它們不是100%可以避免的。四元數可以避免這種情況。 – Cuga 2009-08-31 15:13:16

0

你可以給你的Transform3D一個旋轉矩陣。你可以使用旋轉矩陣計算器在線獲得旋轉矩陣:http://toolserver.org/~dschwen/tools/rotationmatrix.html這裏是我的示例:

Matrix3f mat = new Matrix3f(0.492403876506104f, 0.586824088833465f, 
      -0.642787609686539f, 0.413175911166535f, 0.492403876506104f, 
      0.766044443118978f, 0.766044443118978f, -0.642787609686539f, 0f); 

    Transform3D trans = new Transform3D(); 

    trans.set(mat);