Displaying a ModelOnce a model is loaded, it's displayed inside the scene. This simple task is complicated by the need to make sure that the model is positioned, oriented, and scaled so the user can see all of it. I've simplified the problem by making some assumptions about how the model should be reoriented and scaled: a loaded model is always rotated clockwise around the x-axis by 90 degrees and scaled to be no bigger than 10 world units across. I don't bother repositioning the model since all the examples I tested were located close to the origin after they'd been scaled. Why the rotation? Most of the models I'm using were created with 3D Studio Max, which uses a different axis system from Java 3D. The axes in 3D Studio Max use the XY plane as the floor, with the z-axis as the vertical; Java 3D treats the XZ plane as the floor and the y-axis as the vertical. The difference can be seen by considering a vector displayed in the two systems. The vertical vector (0, 0, 1) in 3D Studio Max will point forward in Java 3D (see Figure 16-5). Figure 16-5. The vector (0,0,1) in 3D Studio Max and Java 3DA model that's upright in 3D Studio Max will be displayed face down when loaded into a Java 3D scene. The solution? Rotate the model clockwise around the x-axis by 90 degrees to bring it back upright. The rotation and the scaling operations are applied to the model via a transformGroup node placed between the model's BranchGroup node (loadedBG in Figure 16-6) and the sceneBG BranchGroup node (the top-level node of the scene). Figure 16-6 shows the scene graph fragment for the model. In practice, the model subgraph below loadedBG will be more complex than the one shown here. Figure 16-6. Scene graph fragment for the loaded modelThe code that creates this graph is located inloadModel( ) and executed just after the model has been loaded: loadedBG = loadedScene.getSceneGroup( ); // model's BG Transform3D t3d = new Transform3D( ); t3d.rotX( -Math.PI/2.0 ); // rotate Vector3d scaleVec = calcScaleFactor(loadedBG); // scale t3d.setScale( scaleVec ); TransformGroup tg = new TransformGroup(t3d); tg.addChild(loadedBG); sceneBG.addChild(tg); // add (tg->loadedBG) to scene The code is simple since it applies a rotation to every loaded model, even those that are correctly oriented. The rotation operation is t3d.rotX(-Math.PI/2.0); This specifies a negative rotation of 90 degrees about the x-axis according to Java 3D's righthand rule for rotations: place your closed right hand with its thumb pointing in the direction of the positive axis of interest, (the x-axis in this case) and your fingers will be bent in the direction of a positive rotation (see Figure 16-7). Figure 16-7. Righthand, positive rotation for the x-axisIn this case, I want the model to rotate clockwise around the x-axis, which is a negative angle according to the righthand rule. Scaling the ModelA model may become large when loaded into Java 3D's coordinate space. This can be corrected by using the object's bounding box to calculate a suitable scaling factor. This approach is employed in calcScaleFactor( ): private Vector3d calcScaleFactor(BranchGroup loadedBG) { BoundingBox boundbox = new BoundingBox( loadedBG.getBounds( ) ); // obtain the upper and lower coordinates of the box Point3d lower = new Point3d( ); boundbox.getLower( lower ); Point3d upper = new Point3d( ); boundbox.getUpper( upper ); // calculate the maximum dimension double max = 0.0; if( (upper.x - lower.x ) > max ) max = (upper.x - lower.x ); if( (upper.y - lower.y ) > max ) max = (upper.y - lower.y ); if( (upper.z - lower.z ) > max ) max = (upper.z - lower.z ); double scaleFactor = 10.0/max; // limit the scaling so that a big model isn't scaled too much if( scaleFactor < 0.0005 ) scaleFactor = 0.0005; return new Vector3d(scaleFactor, scaleFactor, scaleFactor); } // end of calcScaleFactor( ) The scaling factor will leave the model at most 10 units wide, high, or deep, which is comparable to the size of the floor (20 units square). The scale factor reduction is constrained so a large model isn't shrunk too much. This problem occurs when one dimension of the model is large (for example, its height), but the other dimensions are small. An unconstrained reduction applied to the height will leave the width and depth so small that the model will be almost invisible. |