Hi, all: I think that I sent wrong file in the previous mail. here are the test files. Just run java Tree3ele2, you will see the white ground. I also attached two screen shots in a word file, first one was using j2sdk1.3.0_02 with j3d1.2.1_03 and the second shot was using j2sdk1.3.1_04 with j3d1.3 running the same code. And I noticed that this appearance problem only occurs with the IndexedTriangleStripArray. I wondered that anyone using this type of geometry having the similar problem.
Any help is appreciated. Thanks! >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. > > > > > >Lan Wu-Cavener >Dept. of Landscape Architecture
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;
}
}
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
