2

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() をどのように (再) 実装する必要があるかということです。

4

1 に答える 1

2

BoundingBox は、その 2 つのポイントがどこにあるかに関係なく、実際には常に軸に整列したままです。2 点で任意の立方体を定義することはできません。変換関数をいくら書き直しても機能しません。

BoundingPolytope クラスを検討することもできます。平面から形成されるより一般的な境界を提供しますが、別の Bounds オブジェクトを受け入れるコンストラクターがあるため、実際に平面を自分で定義する必要はありません。

于 2012-06-27T12:29:57.537 に答える