Java 3D API を使用して小さなゲームを作成しており、モデルの境界を格納するために javax.media.j3d.BoundingBox のオブジェクトを使用しています。
BoundingBox のコンストラクタは次のとおりです。
public BoundingBox(Point3d lower, Point3d upper) {
boundId = BOUNDING_BOX;
this.lower = new Point3d(lower);
this.upper = new Point3d(upper);
updateBoundsStates();
}
モデル自体がそうするので、BoundingBox を変換して回転させたいと思います。BoundingBox の次のメソッドを使用します。
/**
* Transforms this bounding box by the given matrix.
* @param matrix a transformation matrix
*/
public void transform(Transform3D matrix) {
if(boundsIsInfinite)
return;
if (tmpP3d == null)
tmpP3d = new Point3d();
double ux, uy, uz, lx, ly, lz;
ux = upper.x;
uy = upper.y;
uz = upper.z;
lx = lower.x;
ly = lower.y;
lz = lower.z;
tmpP3d.set(ux, uy, uz);
matrix.transform( tmpP3d );
upper.x = tmpP3d.x;
upper.y = tmpP3d.y;
upper.z = tmpP3d.z;
lower.x = tmpP3d.x;
lower.y = tmpP3d.y;
lower.z = tmpP3d.z;
tmpP3d.set(lx, uy, uz);
matrix.transform( tmpP3d );
if ( tmpP3d.x > upper.x ) upper.x = tmpP3d.x;
if ( tmpP3d.y > upper.y ) upper.y = tmpP3d.y;
if ( tmpP3d.z > upper.z ) upper.z = tmpP3d.z;
if ( tmpP3d.x < lower.x ) lower.x = tmpP3d.x;
if ( tmpP3d.y < lower.y ) lower.y = tmpP3d.y;
if ( tmpP3d.z < lower.z ) lower.z = tmpP3d.z;
tmpP3d.set(lx, ly, uz);
matrix.transform( tmpP3d );
if ( tmpP3d.x > upper.x ) upper.x = tmpP3d.x;
if ( tmpP3d.y > upper.y ) upper.y = tmpP3d.y;
if ( tmpP3d.z > upper.z ) upper.z = tmpP3d.z;
if ( tmpP3d.x < lower.x ) lower.x = tmpP3d.x;
if ( tmpP3d.y < lower.y ) lower.y = tmpP3d.y;
if ( tmpP3d.z < lower.z ) lower.z = tmpP3d.z;
tmpP3d.set(ux, ly, uz);
matrix.transform( tmpP3d );
if ( tmpP3d.x > upper.x ) upper.x = tmpP3d.x;
if ( tmpP3d.y > upper.y ) upper.y = tmpP3d.y;
if ( tmpP3d.z > upper.z ) upper.z = tmpP3d.z;
if ( tmpP3d.x < lower.x ) lower.x = tmpP3d.x;
if ( tmpP3d.y < lower.y ) lower.y = tmpP3d.y;
if ( tmpP3d.z < lower.z ) lower.z = tmpP3d.z;
tmpP3d.set(lx, uy, lz);
matrix.transform( tmpP3d );
if ( tmpP3d.x > upper.x ) upper.x = tmpP3d.x;
if ( tmpP3d.y > upper.y ) upper.y = tmpP3d.y;
if ( tmpP3d.z > upper.z ) upper.z = tmpP3d.z;
if ( tmpP3d.x < lower.x ) lower.x = tmpP3d.x;
if ( tmpP3d.y < lower.y ) lower.y = tmpP3d.y;
if ( tmpP3d.z < lower.z ) lower.z = tmpP3d.z;
tmpP3d.set(ux, uy, lz);
matrix.transform( tmpP3d );
if ( tmpP3d.x > upper.x ) upper.x = tmpP3d.x;
if ( tmpP3d.y > upper.y ) upper.y = tmpP3d.y;
if ( tmpP3d.z > upper.z ) upper.z = tmpP3d.z;
if ( tmpP3d.x < lower.x ) lower.x = tmpP3d.x;
if ( tmpP3d.y < lower.y ) lower.y = tmpP3d.y;
if ( tmpP3d.z < lower.z ) lower.z = tmpP3d.z;
tmpP3d.set(lx, ly, lz);
matrix.transform( tmpP3d );
if ( tmpP3d.x > upper.x ) upper.x = tmpP3d.x;
if ( tmpP3d.y > upper.y ) upper.y = tmpP3d.y;
if ( tmpP3d.z > upper.z ) upper.z = tmpP3d.z;
if ( tmpP3d.x < lower.x ) lower.x = tmpP3d.x;
if ( tmpP3d.y < lower.y ) lower.y = tmpP3d.y;
if ( tmpP3d.z < lower.z ) lower.z = tmpP3d.z;
tmpP3d.set(ux, ly, lz);
matrix.transform( tmpP3d );
if ( tmpP3d.x > upper.x ) upper.x = tmpP3d.x;
if ( tmpP3d.y > upper.y ) upper.y = tmpP3d.y;
if ( tmpP3d.z > upper.z ) upper.z = tmpP3d.z;
if ( tmpP3d.x < lower.x ) lower.x = tmpP3d.x;
if ( tmpP3d.y < lower.y ) lower.y = tmpP3d.y;
if ( tmpP3d.z < lower.z ) lower.z = tmpP3d.z;
if (VirtualUniverse.mc.releaseBoundingBoxMemory) {
// Free memory
tmpP3d = null;
}
}
ただし、このメソッドを使用して BoundingBox を回転させると、新しい BoundingBox が生成され、古いものよりも体積が大きくなる場合があります。正確に 90 度、180 度、270 度、または 360 度回転させた場合にのみ、同じ音量が得られます。
追加情報: モデルで setAutoComputeBounds(false) および setBounds(XYZ) を呼び出して手動境界 (および自動計算された大きすぎる境界ではない) を使用するため、BoundingBox を手動で計算する必要があります (この場合、実際には javax. javax.media.j3d.SharedGroup を指す media.j3d) であり、Java 3d エンジン (少なくともこのシナリオでは) は、対応するモデルの移動/回転の場合に手動境界を自動的に再計算しないようです。
私の質問は、常に同じボリュームを持つ BoundingBoxes を取得するために、上記のメソッド transform() をどのように (再) 実装する必要があるかということです。