Hi, everyone:

I have been fiddling with this problem for a while but still fail to find
out the reason. I have a class Elevation to generate the ground Shape3D
using IndexedTriangleStripArray without vertex color. I have tried to
assign it with ground color through Appearance object. It worked fine until
I updated to the new j3d version. Could someone be kind enough to check my
test code? Thank you in advance!

By the way, the Elevation.java is borrowed from the web just for
constructing test case. I's like to acknowledge the author whoever he/she is.

Attachment: Elevation.class
Description: Binary data

//
//  CLASS
//    ElevationGrid     -  a 3D terrain grid built from a list of heights
//
//  DESCRIPTION
//    This class creates a 3D terrain on a grid whose X and Z dimensions,
//    and row/column spacing are parameters, along with a list of heights
//    (elevations), one per grid row/column pair.
//

//package mip.ivt.demo;

import java.awt.*;
import java.awt.event.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.geometry.*;

class Elevation extends Object
{
    // Parameters
    protected int xDimension = 0, zDimension = 0;
    protected double xSpacing = 0.0, zSpacing = 0.0;
    protected double[] heights = null;

    // 3D nodes
//    private Appearance mainAppearance = null;
    private Appearance mainAppearance = new Appearance();
    private Shape3D shape = null;
    private IndexedTriangleStripArray tristrip = null;


     //
     //  Construct an elevation grid
    public Elevation( )
 {
        xDimension = 2;
        zDimension = 2;
        xSpacing = 1.0;
        zSpacing = 1.0;
        mainAppearance = null;
        zeroHeights( );
        rebuild( );
    }

    public Elevation( int xDim, int zDim )
{
        xDimension = xDim;
        zDimension = zDim;
        xSpacing = 1.0;
        zSpacing = 1.0;
        mainAppearance = null;
        zeroHeights( );
        rebuild( );
    }

    public Elevation( int xDim, int zDim,
    Appearance app )
 {
         xDimension = xDim;
        zDimension = zDim;
        xSpacing = 1.0;
        zSpacing = 1.0;
        mainAppearance = app;
        zeroHeights( );
        rebuild( );
    }

     public Elevation( int xDim, int zDim,
                                     double xSpace, double zSpace )
 {
         xDimension = xDim;
         zDimension = zDim;
         xSpacing = xSpace;
         zSpacing = zSpace;
         mainAppearance = null;
         zeroHeights( );
         rebuild( );
     }

     public Elevation( int xDim, int zDim,
     double xSpace, double zSpace,
     Appearance app )
 {
         xDimension = xDim;
         zDimension = zDim;
         xSpacing = xSpace;
         zSpacing = zSpace;
         mainAppearance = app;
         zeroHeights( );
         rebuild( );
     }

     public Elevation( int xDim, int zDim,
     double[] h )
 {
         this( xDim, zDim, 1.0, 1.0, h, null );
     }

     public Elevation( int xDim, int zDim,
     double[] h,
     Appearance app )
 {
         this( xDim, zDim, 1.0, 1.0, h, app );
     }

     public Elevation( int xDim, int zDim,
     double xSpace, double zSpace,
     double[] h )
 {
         this( xDim, zDim, xSpace, zSpace, h, new Appearance() );
     }

     public Elevation( int xDim, int zDim,
     double xSpace, double zSpace,
     double[] h,
     Appearance app )
 {
         xDimension = xDim;
         zDimension = zDim;
         xSpacing   = xSpace;
         zSpacing   = zSpace;
         mainAppearance = app;
         if ( h == null )
             zeroHeights( );
         else
         {
             heights = new double[h.length];
             for ( int i = 0; i < h.length; i++ )
                 heights[i] = h[i];
         }
         rebuild( );
     }


     private void zeroHeights( )
 {
         int n = xDimension * zDimension;
         heights = new double[n];
         for ( int i = 0; i < n; i++ )
             heights[i] = 0.0;
     }



     private void rebuild( )
 {
         // Build a shape
         if ( shape == null )
         {
             shape = new Shape3D( );
             shape.setCapability( Shape3D.ALLOW_APPEARANCE_WRITE );
             shape.setCapability( Shape3D.ALLOW_GEOMETRY_WRITE );
             shape.setAppearance( mainAppearance );
//             addChild( shape );
         }
         else
         {
             shape.setAppearance( mainAppearance );
         }

         if ( xDimension < 2 || zDimension < 2 ||
         heights == null || heights.length < 4 )
         {
             tristrip = null;
             shape.setGeometry( null );
             return;
         }


         // Create a list of coordinates, one per grid row/column
         double[] coordinates = new double[xDimension*zDimension*3];
         double x, z;
         int n = 0, k = 0;
         z = ((double)(zDimension-1)) * zSpacing / 2.0;  // start at front edge
         for ( int i = 0; i < zDimension; i++ )
         {
             x = -((double)(xDimension-1)) * xSpacing / 2.0;// start at left edge
             for ( int j = 0; j < xDimension; j++ )
             {
                 coordinates[n++] = x;
                 coordinates[n++] = heights[k++];
                 coordinates[n++] = z;
                 x += xSpacing;
             }
             z -= zSpacing;
         }

         // Create a list of normals, one per grid row/column
         float[] normals = new float[xDimension*zDimension*3];
         Vector3f one = new Vector3f( 0.0f, 0.0f, 0.0f );
         Vector3f two = new Vector3f( 0.0f, 0.0f, 0.0f );
         Vector3f norm = new Vector3f( 0.0f, 0.0f, 0.0f );
         n = 0;
         k = 0;
         for ( int i = 0; i < zDimension-1; i++ )
         {
             for ( int j = 0; j < xDimension-1; j++ )
             {
                 // Vector to right in X
                 one.set( (float)xSpacing, (float)(heights[k+1] - heights[k]), 0.0f );

                 // Vector back in Z
                 two.set( 0.0f, (float)(heights[k+xDimension] - heights[k]), 
(float)-zSpacing );

                 // Cross them to get the normal
                 norm.cross( one, two );
                 normals[n++] = norm.x;
                 normals[n++] = norm.y;
                 normals[n++] = norm.z;
                 k++;
             }

             // Last normal in row is a copy of the previous one
             normals[n]   = normals[n-3]; // X
             normals[n+1] = normals[n-2]; // Y
             normals[n+2] = normals[n-1]; // Z
             n += 3;
             k++;
         }

         // Last row of normals is a copy of the previous row
         for ( int j = 0; j < xDimension; j++ )
         {
             normals[n]   = normals[n-xDimension*3];   // X
             normals[n+1] = normals[n-xDimension*3+1]; // Y
             normals[n+2] = normals[n-xDimension*3+2]; // Z
             n += 3;
         }

         // Create a list of texture coordinates, one per grid row/column
         float[] texcoordinates = new float[xDimension*zDimension*2];
         float deltaS = 1.0f / (float)(xDimension-1);
         float deltaT = 1.0f / (float)(zDimension-1);
         float s = 0.0f;
         float t = 0.0f;
         n = 0;
         for ( int i = 0; i < zDimension; i++ )
         {
             s = 0.0f;
             for ( int j = 0; j < xDimension; j++ )
             {
                 texcoordinates[n++] = s;
                 texcoordinates[n++] = t;
                 s += deltaS;
             }
             t += deltaT;
         }

         // Create a list of triangle strip indexes.  Each strip goes
         // down one row (X direction) of the elevation grid.
         int[] indexes = new int[xDimension*(zDimension-1)*2];
         int[] stripCounts = new int[zDimension-1];
         n = 0;
         k = 0;
         for ( int i = 0; i < zDimension-1; i++ )
         {
             stripCounts[i] = xDimension*2;
             for ( int j = 0; j < xDimension; j++ )
             {
                 indexes[n++] = k+xDimension;
                 indexes[n++] = k;
                 k++;
             }
         }


         // Create geometry for collection of triangle strips, one
         // strip per row of the elevation grid
         tristrip = new IndexedTriangleStripArray(
         coordinates.length,
         GeometryArray.COORDINATES |
         GeometryArray.NORMALS |
         GeometryArray.TEXTURE_COORDINATE_2,
         indexes.length,
         stripCounts );
         tristrip.setCoordinates( 0, coordinates );
         tristrip.setNormals( 0, normals );
         tristrip.setTextureCoordinates( 0, texcoordinates );
         tristrip.setCoordinateIndices( 0, indexes );
         tristrip.setNormalIndices( 0, indexes );
         tristrip.setTextureCoordinateIndices( 0, indexes );

         // Set the geometry for the shape
         shape.setGeometry( tristrip );
     }


     //
     //  Control the appearance
     //
     public void setAppearance( Appearance app )
 {
         mainAppearance = app;
         if ( shape != null )
             shape.setAppearance( mainAppearance );
     }


     //
     //  Control grid parameters
     //
     public void setHeights( double[] h )
 {
         if ( h == null )
             zeroHeights( );
         else
         {
             heights = new double[h.length];
             for ( int i = 0; i < h.length; i++ )
                 heights[i] = h[i];
         }
         rebuild( );
     }
     public double[] getHeights( )
 {
         return heights;
     }

     public void setXDimension( int xDim )
 {
         xDimension = xDim;
         rebuild( );
     }
     public int getXDimension( )
 {
         return xDimension;
     }

     public void setZDimension( int zDim )
 {
         zDimension = zDim;
         rebuild( );
     }
     public int getZDimension( )
 {
         return zDimension;
     }

     public void setXSpacing( double xSpace )
 {
         xSpacing = xSpace;
         rebuild( );
     }
     public double getXSpacing( )
 {
         return xSpacing;
     }

     public void setZSpacing( double zSpace )
 {
         zSpacing = zSpace;
         rebuild( );
     }
     public double getZSpacing( )
 {
         return zSpacing;
     }


     //
     //  Provide info on the shape and geometry
     //
     public Shape3D getShape( int partid )
 {
         return shape;
     }

     public int getNumTriangles( )
 {
         return xDimension * zDimension * 2;
     }

     public int getNumVertices( )
 {
         return xDimension * zDimension;
     }
 }


Attachment: Tree3ele2.class
Description: Binary data

import java.applet.Applet;
import com.sun.j3d.utils.applet.MainFrame;
import java.awt.*;

import java.awt.event.*;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
import com.sun.j3d.utils.behaviors.vp.*;
import com.sun.j3d.utils.behaviors.mouse.*;
import com.sun.j3d.utils.image.TextureLoader;
import java.io.*;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.geom.AffineTransform;

public class Tree3ele2 extends Applet implements ActionListener
{
        protected final static Color3f White    = new Color3f( 1.0f, 1.0f, 1.0f );
        protected final static Color3f Green    = new Color3f( 0.0f, 1.0f, 0.0f );
        protected static final Color3f brown  = new Color3f( 0.78f, 0.2f, 0.1f );
        protected static final Color3f bkground = new Color3f(.761f, .973f, .969f);
        private final static Color3f groundAmbient = new Color3f( 0.6f, 0.4f, 0.3f );
        private final static Color3f groundEmissive = new Color3f( 0.2f, 0.1f, 0.05f );
        private final static Color3f groundDiffuse = new Color3f( 0.7f, 0.5f, 0.4f );
        private final static Color3f groundSpecular = new Color3f( 0.8f, 0.6f, 0.6f );

        private SimpleUniverse u;
        private Canvas3D vFstCanvas3D;
        private BoundingSphere bounds;
        ViewingPlatform viewingPlatform;

        public static TransformGroup vpTransformGroup, joyTransformGroup;

    public void init() {
                BranchGroup bg = new BranchGroup();
        GraphicsConfiguration config =
                                                 
SimpleUniverse.getPreferredConfiguration();
                vFstCanvas3D = new Canvas3D( config )
                {
                                Dimension canvasPrefSize = new Dimension( 600, 800 );
                                public Dimension getPreferredSize() { return 
canvasPrefSize; }
                };

                u = new SimpleUniverse(vFstCanvas3D,2);
                setLayout( new BorderLayout() );
                add( vFstCanvas3D, BorderLayout.CENTER );

                viewingPlatform = u.getViewingPlatform();
                MultiTransformGroup multi = viewingPlatform.getMultiTransformGroup();
        joyTransformGroup = multi.getTransformGroup(0);
        vpTransformGroup = multi.getTransformGroup(1);

                viewingPlatform.setNominalViewingTransform();

        long initTime = System.currentTimeMillis();
                bg = createSceneGraph();
        System.out.println("Time taken to create 
BranchGroup:"+(System.currentTimeMillis() - initTime));

                u.addBranchGraph( bg );

        }


    public void actionPerformed(ActionEvent e) {

        }

    public BranchGroup createSceneGraph() {

                BranchGroup objRoot = new BranchGroup();


        // ground

        Appearance app = new Appearance();
        Material groundMa = new Material( groundAmbient,
                groundEmissive, new Color3f(0.6f, 0.6f, 0.6f), groundSpecular, 30.0f );
        groundMa.setLightingEnable( true );
        RenderingAttributes ra1 = new RenderingAttributes();
        ra1.setIgnoreVertexColors(true);
        app.setRenderingAttributes(ra1);
        app.setMaterial(groundMa);


        double height[] = new double[126];
        for (int i=0; i<63; i++)
                height[i]=0.d;
        for (int i=63; i<70; i++)
                height[i]=.5d;
        for (int i=70; i<74; i++)
                height[i]=.5d;
        for (int i=74; i<77; i++)
                height[i]=.2d;
        for (int i=77; i<81; i++)
                height[i]=.0d;
        for (int i=81; i<126; i++)
                height[i]=.2d;

        Elevation ele = new Elevation( 7, 18, 2, 3, height, app);

        Transform3D t = new Transform3D();
                // move the object upwards
        t.set(new Vector3f(0.0f, -.50f, 0.f));
    t.setScale(0.1);
        TransformGroup trans = new TransformGroup(t);
        trans.addChild(ele.getShape(0));
        objRoot.addChild(trans);


        OrbitBehavior orbit = new OrbitBehavior(vFstCanvas3D, 
OrbitBehavior.REVERSE_ALL);
        BoundingSphere bounds =
            new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0);
        orbit.setSchedulingBounds(bounds);
        viewingPlatform.setViewPlatformBehavior(orbit);


        //      add light
        Vector3f LightDirection = new Vector3f( -.70f, -.70f, -.50f );
        DirectionalLight dirLight = new DirectionalLight(
                new Color3f(1.f, 1.f, 1.f), LightDirection );
        dirLight.setInfluencingBounds( bounds );
        objRoot.addChild( dirLight );

        BoundingLeaf boundingLeaf = new BoundingLeaf( bounds );
        objRoot.addChild( boundingLeaf );

        // add backgroud
        Background background = new Background();
        background.setColor( bkground );
        background.setCapability( Background.ALLOW_COLOR_WRITE );
        background.setApplicationBoundingLeaf(boundingLeaf);
        objRoot.addChild( background );

        objRoot.compile();

        return objRoot;
    }


    public static void main(String[] args) {
        Tree3ele2 treeTest = new Tree3ele2();
                new MainFrame(treeTest, 1024, 512);

    }

}
Lan Wu-Cavener
Dept. of Landscape Architecture

Reply via email to