adding textures to Xith3DTerrainTest

I’m poking at alpha-8, and have gotten all of the demos to run. I figured out how to colorize the terrain in TerrainShape.initVert(). After a few hours of reading and trial-n-error, I haven’t figured out how to get a texture onto the IndexedTriangleArray.

For starters, I changed the constructor to include a texCoordSetCount of 1 and added TEXTURE_COORDINATE_2:

        geo =
            new IndexedTriangleArray(
                MAX_VERTICES,
                GeometryArray.COORDINATES
                    | GeometryArray.NORMALS
                    | GeometryArray.TEXTURE_COORDINATE_2
                    | GeometryArray.COLOR_3,
                1,
                null,
                MAX_INDICES);

and added the texture stuff to the Shape:

        TextureLoader tl = new TextureLoader();

        // load the textures
        Texture2D textureGrass =
            (Texture2D) tl.getMinMapTexture("grass.jpg");

        TextureAttributes textureAttrs0 = new TextureAttributes();
        textureAttrs0.setTextureMode(TextureAttributes.DECAL);

        textureUnitStates[0] =
            new TextureUnitState(textureGrass, textureAttrs0, null);

        a.setTextureUnitState(textureUnitStates);

        shape = new Shape3D(geo, a);

but that doesn’t seem to be sufficient.

I promise that if you give me enough info to solve this, I’ll write up a tutorial. :slight_smile:

thanks much

Unfortunately I can’t help - I am stuck at nearly the same problem…

For my lightweight Lightwave import I also use an IndexedTriangleArray. However I can’t get textures work with such an indexed array at all. There are so many geometry.setTexCoord(…) and geometry.setTextureCoordinates(…) method calls I’m really confused now.
The only way to make the models being textured is to use the nice TexCoordGeneration object, which looks nice, but it’s not what I want to do (at the mo). :slight_smile:
Java3d tutorials don’t help because they never use an IndexedTriangleArray for their texture examples.

Also I’m fighting with the IndexedTriangleArray. The geometry.setIndex(connector_array) I confused with Java3d’s setCoordinatesIndices(0, connector_array)… Unfortunately I can’t find any help/tutorial about the details of all the important IndexedTriangleArray methods.
Maybe David’s single comment in the GeomIndexedContainer class explains a few of the difference Xith3d’s IndexedTriangleArray compared to J3d’s?[quote]Builds indexed geometry. The vertex inforamtion is still stored the regular way, but the vertices drawn are those specified by the index. A single index is used for all color, tex, normal coords. So if you have a vertex with the same coordinate, but with different tex coords you need to build a new vertex and reference that via the index. This is so that the speed of using only one coordinate is used.
[/quote]
A tutorial on this could maybe also solve our texture problems with IndexedArrays. Just a guess. :slight_smile:

HI guys,
I had this same problem and it took me forever to figure it out but I got a textured indexedTriangleArray working. Let me throw the code together into a program and I’ll post it by the end of today.

[quote]HI guys,
I had this same problem and it took me forever to figure it out but I got a textured indexedTriangleArray working. Let me throw the code together into a program and I’ll post it by the end of today.
[/quote]
Good to hear. Help is near! :slight_smile: Many thanks.

Here’s a program that uses textured indexedTriangleArrays

Make sure you use setTextureCoordinates(int, int, texCoord2f) when you set the texture coordinates.

If you have any questions about parts of the code. Just let me know.

The program should display a textured plane which is an indexedTriangleArray along with a cube.


import javax.vecmath.*;

// Xith3D
import com.xith3d.scenegraph.*;
import com.xith3d.test.*;
import com.xith3d.loaders.texture.*;

// use Jogl
import com.xith3d.render.*;
import com.xith3d.render.jogl.*;

public class indexTest
{
      public Shape3D shape;
      IndexedTriangleArray geo;
      
      private Point3f[] coordinates; // = new int[];
      private Vector3f[] normals;
      private Color3f[] colors;
      
      private int[] indices;
      private TexCoord2f[] texCoords;
            
      private int MAX_INDICES;
      private int MAX_COORDINATES;
      
      public PolygonAttributes pa;
      private Texture2D texture;
      private ColoringAttributes ca;
      private Material mat;
      private Appearance app;
      
      
      public static void main(String[] args)
      {
            new indexTest();
      }
      
      public Shape3D createShape(){
            
            int size = 5; //Shape is a square with length 'size'
            MAX_COORDINATES = size * size; 
            MAX_INDICES = (size-1)*(size-1) * 6;
                              
            this.generateCoordinates(size);
            this.generateIndices(size);
            this.generateTextureCoordinates(size);
            this.generateGeometry();

//Create Shape based on above created geometry      
            shape = new Shape3D(geo);
            
//Load Texture
            TextureLoader.tf.registerPath(".");
            TextureLoader.tf.registerPath("..");
            texture = (Texture2D) TextureLoader.tf.getMinMapTexture("stone.jpg");
            
//Polygon Attributes                        
            pa = new PolygonAttributes(PolygonAttributes.POLYGON_LINE,PolygonAttributes.CULL_NONE,0);
                      
//Creating Appearance
            app = new Appearance();
            app.setTexture(texture);
            app.setPolygonAttributes(pa);
            shape.setAppearance(app);
            shape.setBoundsAutoCompute(false);
            shape.setBounds(new BoundingSphere(new Point3f(0,0,0),100000));
            
            return shape;
      }
      
      /**
       * This function generates the Indices which are in the following format
       *       v1          v2
       *(x,0,z)    (x+1,0,z)
       *       0-----------0
       *       |                 |
       *       |                   |
       *       |           |
       *       |                |
       *       |             |
       *       0-----------0
       * v3                  v4
       * @param sizeX, Size of the Terrain in the X dimension
       * @param sizeZ, Size of the Terrain in the Z dimension
       */
      private void generateIndices(int size){
            indices = new int[MAX_INDICES];
            int index=0;
            for(int z = 0; z < size-1; z++){
                  for(int x = 0; x < size-1; x++){
                         indices[index++] = x +     ( z * size );                              //v1
                         indices[index++] = x + 1 + ( z * size);                              //v2
                          indices[index++] = x + 1 + ((z + 1) * (size));                  //v4

                          indices[index++] = x +     (z * size);                              //v1
                          indices[index++] = x + 1 + ((z + 1) * (size));                  //v4
                          indices[index++] = x +     ((z + 1) * (size));                  //v3
                   }
             }
      }
      
      private void generateTextureCoordinates(int size){
            texCoords = new TexCoord2f[MAX_COORDINATES];
            int index=0;
            for(int z = 0; z < size; z++)
                  for(int x = 0; x < size; x++)
                        texCoords[index++] =  new TexCoord2f((float)x / (float)(size-1), (float)z / (float)(size-1)); 
      }
            
      private void generateCoordinates(int size){
            coordinates = new Point3f[MAX_COORDINATES];
            int index=0;
            for(int z=0; z<size; z++)
                  for(int x=0; x<size; x++)
                        coordinates[index++] = new Point3f((float)x, 0.0f, (float)z);
      }      
      
      private void generateGeometry()      {
            geo = new IndexedTriangleArray(MAX_COORDINATES, TriangleArray.COORDINATES | 
                                                                                    TriangleArray.TEXTURE_COORDINATE_2,
                                                                                    MAX_INDICES);
            geo.setValidVertexCount(MAX_COORDINATES);
            geo.setCoordinates(0, coordinates);
            geo.setValidIndexCount(MAX_INDICES);
            geo.setIndex(indices);
            geo.setTextureCoordinates(0,0,texCoords);
      }


      public void start(View view) {
            while (true){
                  Transform3D viewT = new Transform3D();
                  viewT.lookAt(new Point3f(5,5,-5),new Point3f(5,0,0),new Point3f(0,1,0));
                  view.setTransform(viewT);
                  
                  view.renderOnce();
                  try      {
                        Thread.sleep(10L);
                  }
                  catch (Exception e)      {
                  }
            }
      }

      public indexTest() {
            // create the virtual univers
            VirtualUniverse universe = new VirtualUniverse();

            // add a view to the universe
            View view = new View();
            universe.addView(view);

            // add a locale
            Locale locale = new Locale();
            universe.addLocale(locale);

            // create a BranchGroup
            BranchGroup scene = new BranchGroup();
            locale.addBranchGraph(scene);
                  
            // create Cube
            Shape3D plane = createShape();
            Geometry geo = Cube.createCubeViaTriangles(0, 0, 0, 1, true);
            Shape3D sh = new Shape3D(geo, new Appearance());
            scene.addChild(sh);
            scene.addChild(plane);

            // create a canvas for our graphics
            RenderPeer rp = new RenderPeerImpl();
            CanvasPeer cp = rp.makeCanvas(null, 640, 480, 32, false);
            Canvas3D canvas = new Canvas3D();
            canvas.set3DPeer(cp);

            // modify our view so we can see the cube
            view.addCanvas3D(canvas);
            start(view);
      }
}




Thanks again! With your example I made my test to work, too. :slight_smile:

Most of the surfaces of my (imported) 3d models need to have unique TexCoord2f pairs, so I realize that the benefits of an IndexedTriangleArrays (the sharing vertices ability) decreases rapidly. For any vertex which can’t share its TexCoord pair for its associated surfaces you’ve to double that vertex (coordinate and normal) and fill a new TexCoord pair. Like David saiy in the mentioned class comment. Usually you’ll just benefit in the case of a rectangle consisting of two triangles: instead of 6 vertices you can use 4 vertices, so you save 1/3.

However for the TerrainTest in this topic the IndexTriangleArray’s sharing works fine.

[quote]Here’s a program that uses textured indexedTriangleArrays
[/quote]
Much appreciated!!