Java 3d API:旋转边界框提供了一个体积更大的新盒子



我正在用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 对象的构造函数,因此您实际上不需要自己定义平面。

最新更新