我正在用Java 3D API编写一个小游戏,我使用javax.media.j3d.BoundingBox的对象来存储模型的边界。
边界框的构造函数如下:
public BoundingBox(Point3d lower, Point3d upper) {
boundId = BOUNDING_BOX;
this.lower = new Point3d(lower);
this.upper = new Point3d(upper);
updateBoundsStates();
}
现在我想平移和旋转边界框,因为模型本身确实如此,我使用以下边界框方法:
/**
* 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;
}
}
但是:如果使用此方法旋转边界框,则会生成一个新的边界框,其体积可能大于旧边界框。只有当您精确旋转 90、180、270 或 360 度时,它才能提供相同的音量。
附加信息:我必须手动计算边界框,因为我通过在模型上调用 setAutoComputeBounds(false) 和 setBounds(XYZ) 来使用手动边界(而不是太大的自动计算边界)(在这种情况下,它实际上是指向 javax.media.j3d.SharedGroup 的 javax.media.j3d 的实例),并且似乎 Java 3d 引擎(至少在这种情况下)不会在平移/旋转的情况下自动重新计算您的手动边界相应的模型。
我的问题是:我必须如何(重新)实现上面显示的方法 transform() 才能获得始终具有相同体积的边界框?
BoundingBox 实际上始终与轴保持对齐,无论它的两点在哪里。两个点不能定义任意立方体。无论您如何重写转换函数,它都不起作用。
您可以考虑边界多面体类。它提供了由平面形成的更一般的边界,尽管它确实有一个接受另一个 Bounds 对象的构造函数,因此您实际上不需要自己定义平面。