1

Similar to: Java3d: Texture is not applied to OBJ model properly

Except that i generate the IndexedTriangleArray myself and map the texture.

The geometry is fine but it takes the colour of the bottom left corner of the texture image instead of stretching it over the entire image. Testure.jpg is a 256*256 image.

Edit: Strangely, The non-indexed TriangleArray works fine. So i assume it's a problem with the way i'm setting the texture coordinates?

( To switch between IndexedTriangleArray and TriangleArray, Just comment out the line in the main function )

import com.sun.j3d.utils.universe.*;
import javax.vecmath.*;
import javax.media.j3d.*;
import java.awt.*;
import org.j3d.geom.*;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.image.*;

import java.io.*;


public class SEMVCE{


public static IndexedTriangleArray getITA(int gridSize, float h) {  //Creates a terrain using indexedTriangleArray geometry
     int    rows = gridSize,
            cols = gridSize;
     int vertexCount = gridSize*gridSize;  

    int cols_1 = cols-1,
        rows_1 = rows-1;

    IndexedTriangleArray ta = new IndexedTriangleArray( vertexCount, IndexedTriangleArray.COORDINATES  | IndexedTriangleArray.TEXTURE_COORDINATE_2, 6*rows_1*cols_1);

     Point3f coords[] = new Point3f[vertexCount];
     TexCoord2f texCo[] = new TexCoord2f[cols*rows];

     //Set the vertices
     for(int i=0;i<cols;i++){
        for(int j=0;j<rows;j++){
            if(i%2==1 && j%2==1 )
                coords[i*rows+j] = new Point3f(i,h,j);
            else
                coords[i*rows+j] = new Point3f(i,0,j);

            //texCo[i*rows+j] = new TexCoord2f((float)i/(gridSize-1),(float)j/(gridSize-1) );
        }
    }


    for (int i=0;i<vertexCount;i++){
        texCo[i] = new TexCoord2f(coords[i].x /(gridSize-1), coords[i].z /(gridSize-1));
    }


    ta.setCoordinates(0,coords);
    ta.setTextureCoordinates(0,0, texCo);

    //Do the indexes
    int offset = 0;
    for(int i=0;i<cols_1;i++){
        for(int j=0;j<rows_1;j++){
            offset = (i*rows_1+j)*6;
            ta.setCoordinateIndex(offset+0, (i*rows + j));              
            ta.setCoordinateIndex(offset+1, (i*rows+ j+1 ));            
            ta.setCoordinateIndex(offset+2, ((i+1)*rows + j));

            ta.setCoordinateIndex(offset+3, ((i+1)*rows + j));
            ta.setCoordinateIndex(offset+4, (i*rows+ j+1 ));
            ta.setCoordinateIndex(offset+5, ((i+1)*rows + j+1));
        }
    }

    return ta;
}

public static TriangleArray getTriangleArray(int gridSize, float h){ //Creates a terrain using TriangleArray geometry
     int    rows = gridSize,
            cols = gridSize;

    int cols_1 = cols-1,
        rows_1 = rows-1;


    int vertexCount = 6*rows_1*cols_1;  

    TriangleArray ta = new TriangleArray( vertexCount, IndexedTriangleArray.COORDINATES  | IndexedTriangleArray.TEXTURE_COORDINATE_2);

     Point3f coords[] = new Point3f[vertexCount];
     TexCoord2f texCo[] = new TexCoord2f[vertexCount];



    //Do the vertices
    int offset = 0;
    float height = 0;
    for(int i=0;i<cols_1;i++){
        for(int j=0;j<rows_1;j++){
            if(i%3==1 && j%3==1)
                height= h;
            else
                height = 0;

            offset = (i*rows_1+j)*6;
            coords[offset+0] = new Point3f(i,0, j);
            coords[offset+1] = new Point3f((i+1), 0,j);
            coords[offset+2] = new Point3f(i, 0, j+1);

            coords[offset+3] =  new Point3f( (i+1), 0, j);
            coords[offset+4] = new Point3f((i+1), 0,j+1);
            coords[offset+5] = new Point3f(i,0, j+1);

            if(i%2==1 && j%2==1)
                coords[offset+0] = new Point3f(i,h, j);
            else if(i%2==0 && j%2==0)
                coords[offset+4] = new Point3f((i+1), h,j+1);
            else if( (i+1)%2==1 && j%2==1){
                coords[offset+1] = new Point3f(i+1,h,j);
                coords[offset+3] = new Point3f(i+1,h,j);
            }
            else if( i%2==1 && (j+1)%2==1){
                coords[offset+2] = new Point3f(i,h, j+1);
                coords[offset+5] = new Point3f(i,h, j+1);
            }
        }
    }

    int gridSize_1 = gridSize-1;
    for (int i=0;i<vertexCount;i++){
        texCo[i] = new TexCoord2f(coords[i].x / gridSize_1, coords[i].z / gridSize_1);
    }

    ta.setCoordinates(0,coords);
    ta.setTextureCoordinates(0,0, texCo);

    return ta;
}

public static Texture2D loadTexture(String filename){
    //ImageObserver iObserve = new ImageObserver();
    TextureLoader loader = new TextureLoader(filename, new Container());
    ImageComponent2D image = loader.getImage();
    Texture2D texture = new Texture2D(Texture2D.BASE_LEVEL, Texture2D.RGBA, image.getWidth(), image.getHeight() );
    texture.setImage(0, image);
    texture.setEnable( true );
    texture.setBoundaryModeS(Texture.WRAP);

    texture.setBoundaryModeT(Texture.WRAP);
    return texture;
}

public static Appearance getAppearance(){
    Appearance appear = new Appearance();
    Texture2D texture = loadTexture("texture.jpg");
    appear.setTexture(texture);
    PolygonAttributes polygonAttributes = new PolygonAttributes();
    polygonAttributes.setCullFace(PolygonAttributes.CULL_NONE);
    //appear.setTexCoordGeneration(new TexCoordGeneration());
    appear.setPolygonAttributes(polygonAttributes);

    return appear;
}

public static void main(String args[]){
    SimpleUniverse world = new SimpleUniverse();
    int gridSize=11;

    //Comment out according to which you want to test
    //GeometryArray geometry = getTriangleArray(gridSize,2);
    GeometryArray geometry = getITA(gridSize,2);

    Shape3D shape= new Shape3D(geometry,getAppearance());

    BranchGroup bg = new BranchGroup();
    bg.addChild(shape);

    world.addBranchGraph(bg);
    setCameraPosition(world.getViewingPlatform(), new Point3d(gridSize/2,5,-10), new Point3d(gridSize/2,0,gridSize/2), new Vector3d(0,1,0));//new Point3d(gridSize/2,gridSize/2,gridSize/2), new Point3d(gridSize/2,0,gridSize/2), new Vector3d(0,1,0));

}


public static void setCameraPosition(ViewingPlatform VP,Point3d from, Point3d to, Vector3d v){
    TransformGroup viewTransform = VP.getViewPlatformTransform();
    Transform3D t3d = new Transform3D();

    t3d.lookAt(from,to,v);
    t3d.invert();
    viewTransform.setTransform(t3d);

}


}
Community
  • 1
  • 1
2bigpigs
  • 452
  • 3
  • 12
  • Can't test this at the moment, but from the description, a crazy guess: What happens when you use `new TexCoord2f((float)i/(gridSize-1)*256, (float)j/(gridSize-1)*256);` (this should **NOT** be right... maybe I can try it out in the next few days if nobody else does it) – Marco13 Jun 27 '14 at 20:45
  • @Marco13 That's true. I've changed my code a little bit since. It now looks like new TexCoord2f((float)i/(gridSize-1), (float)j/(gridSize-1) ); And i've updated the question accordingly. Same result THe strange thing is, I can get a triangleArray to be textured properly but not an indexedTriangleArray – 2bigpigs Jun 28 '14 at 10:20
  • Just an aside, I tried this now, but it (apart from being not compilable due to "MyUniverse" missing) it does not show anything at all with the TriangleArray. – Marco13 Jul 03 '14 at 20:35
  • Do you get anything with the IndexedTriangleArray? IT might be because it's outside your field of vision. Flip the coordinates ( multiply x,z coordinates while building the coords array ) and it should show up properly. Or just flip the z coord. THat's the important one – 2bigpigs Jul 07 '14 at 11:48
  • Maybe I'll try this later, but why not post a http://stackoverflow.com/help/mcve in the first place? – Marco13 Jul 07 '14 at 12:17
  • Yes. I should have posted that. Done now. Thanks for the input :) – 2bigpigs Jul 08 '14 at 19:30

1 Answers1

0

Admittedly, I could/should have noticed this earlier, but ... it has been a while since I have actively been using Java3D - and since then, I've mainly been squeezing out my meager knowledge and memories to answer forum and stackoverfow questions about it ;-)

However: You did set the indices for the vertices, using the

ta.setCoordinateIndex(...);

calls. But you additionally have to set the indices for the texture coordinates, using

ta.setTextureCoordinateIndex(0, ...);

The 0 refers to the texture coordinate set (there may be multiple textures, with different coordinate sets). Apart from that, the indices are the same as for the vertices here.

Here again, as a MCVE. (The image name was changed. Lena rules!)

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.GraphicsConfiguration;

import javax.media.j3d.Appearance;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.GeometryArray;
import javax.media.j3d.ImageComponent2D;
import javax.media.j3d.IndexedTriangleArray;
import javax.media.j3d.PolygonAttributes;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Texture;
import javax.media.j3d.Texture2D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.TriangleArray;
import javax.swing.JFrame;
import javax.vecmath.Point3d;
import javax.vecmath.Point3f;
import javax.vecmath.TexCoord2f;
import javax.vecmath.Vector3d;

import com.sun.j3d.utils.image.TextureLoader;
import com.sun.j3d.utils.universe.SimpleUniverse;
import com.sun.j3d.utils.universe.ViewingPlatform;

public class SEMVCE
{
    public static IndexedTriangleArray getITA(int gridSize, float h)
    {
        int rows = gridSize, cols = gridSize;
        int vertexCount = gridSize * gridSize;

        int cols_1 = cols - 1, rows_1 = rows - 1;

        IndexedTriangleArray ta =
            new IndexedTriangleArray(vertexCount,
                IndexedTriangleArray.COORDINATES | 
                IndexedTriangleArray.TEXTURE_COORDINATE_2, 
                6 * rows_1 * cols_1);

        Point3f coords[] = new Point3f[vertexCount];
        TexCoord2f texCo[] = new TexCoord2f[cols * rows];

        // Set the vertices
        for (int i = 0; i < cols; i++)
        {
            for (int j = 0; j < rows; j++)
            {
                if (i % 2 == 1 && j % 2 == 1)
                    coords[i * rows + j] = new Point3f(i, h, j);
                else
                    coords[i * rows + j] = new Point3f(i, 0, j);
            }
        }
        for (int i = 0; i < vertexCount; i++)
        {
            texCo[i] =
                new TexCoord2f(
                    coords[i].x / (gridSize - 1), 
                    coords[i].z / (gridSize - 1));
        }

        ta.setCoordinates(0, coords);
        ta.setTextureCoordinates(0, 0, texCo);

        // Do the indexes
        int offset = 0;
        for (int i = 0; i < cols_1; i++)
        {
            for (int j = 0; j < rows_1; j++)
            {
                offset = (i * rows_1 + j) * 6;
                ta.setCoordinateIndex(offset + 0, (i * rows + j));
                ta.setCoordinateIndex(offset + 1, (i * rows + j + 1));
                ta.setCoordinateIndex(offset + 2, ((i + 1) * rows + j));

                ta.setCoordinateIndex(offset + 3, ((i + 1) * rows + j));
                ta.setCoordinateIndex(offset + 4, (i * rows + j + 1));
                ta.setCoordinateIndex(offset + 5, ((i + 1) * rows + j + 1));

                ta.setTextureCoordinateIndex(0, offset + 0, (i * rows + j));
                ta.setTextureCoordinateIndex(0, offset + 1, (i * rows + j + 1));
                ta.setTextureCoordinateIndex(0, offset + 2, ((i + 1) * rows + j));

                ta.setTextureCoordinateIndex(0, offset + 3, ((i + 1) * rows + j));
                ta.setTextureCoordinateIndex(0, offset + 4, (i * rows + j + 1));
                ta.setTextureCoordinateIndex(0, offset + 5, ((i + 1) * rows + j + 1));

            }
        }

        return ta;
    }

    public static TriangleArray getTriangleArray(int gridSize, float h)
    { // Creates a terrain using TriangleArray geometry
        int rows = gridSize, cols = gridSize;

        int cols_1 = cols - 1, rows_1 = rows - 1;

        int vertexCount = 6 * rows_1 * cols_1;

        TriangleArray ta =
            new TriangleArray(vertexCount, IndexedTriangleArray.COORDINATES
                | IndexedTriangleArray.TEXTURE_COORDINATE_2);

        Point3f coords[] = new Point3f[vertexCount];
        TexCoord2f texCo[] = new TexCoord2f[vertexCount];

        // Do the vertices
        int offset = 0;
        float height = 0;
        for (int i = 0; i < cols_1; i++)
        {
            for (int j = 0; j < rows_1; j++)
            {
                if (i % 3 == 1 && j % 3 == 1)
                    height = h;
                else
                    height = 0;

                offset = (i * rows_1 + j) * 6;
                coords[offset + 0] = new Point3f(i, 0, j);
                coords[offset + 1] = new Point3f((i + 1), 0, j);
                coords[offset + 2] = new Point3f(i, 0, j + 1);

                coords[offset + 3] = new Point3f((i + 1), 0, j);
                coords[offset + 4] = new Point3f((i + 1), 0, j + 1);
                coords[offset + 5] = new Point3f(i, 0, j + 1);

                if (i % 2 == 1 && j % 2 == 1)
                    coords[offset + 0] = new Point3f(i, h, j);
                else if (i % 2 == 0 && j % 2 == 0)
                    coords[offset + 4] = new Point3f((i + 1), h, j + 1);
                else if ((i + 1) % 2 == 1 && j % 2 == 1)
                {
                    coords[offset + 1] = new Point3f(i + 1, h, j);
                    coords[offset + 3] = new Point3f(i + 1, h, j);
                }
                else if (i % 2 == 1 && (j + 1) % 2 == 1)
                {
                    coords[offset + 2] = new Point3f(i, h, j + 1);
                    coords[offset + 5] = new Point3f(i, h, j + 1);
                }
            }
        }

        int gridSize_1 = gridSize - 1;
        for (int i = 0; i < vertexCount; i++)
        {
            texCo[i] =
                new TexCoord2f(coords[i].x / gridSize_1, coords[i].z
                    / gridSize_1);
        }

        ta.setCoordinates(0, coords);
        ta.setTextureCoordinates(0, 0, texCo);

        return ta;
    }

    public static Texture2D loadTexture(String filename)
    {
        // ImageObserver iObserve = new ImageObserver();
        TextureLoader loader = new TextureLoader(filename, new Container());
        ImageComponent2D image = loader.getImage();
        Texture2D texture =
            new Texture2D(Texture2D.BASE_LEVEL, Texture2D.RGBA,
                image.getWidth(), image.getHeight());
        texture.setImage(0, image);
        texture.setEnable(true);
        texture.setBoundaryModeS(Texture.WRAP);

        texture.setBoundaryModeT(Texture.WRAP);
        return texture;
    }

    public static Appearance getAppearance()
    {
        Appearance appear = new Appearance();
        Texture2D texture = loadTexture("lena512color.png");
        appear.setTexture(texture);
        PolygonAttributes polygonAttributes = new PolygonAttributes();
        polygonAttributes.setCullFace(PolygonAttributes.CULL_NONE);
        // appear.setTexCoordGeneration(new TexCoordGeneration());
        appear.setPolygonAttributes(polygonAttributes);

        return appear;
    }

    public static void main(String args[])
    {
        System.setProperty("sun.awt.noerasebackground","true");

        GraphicsConfiguration config =
            SimpleUniverse.getPreferredConfiguration();
        Canvas3D c = new Canvas3D(config);

        JFrame f = new JFrame();
        f.getContentPane().add(c, BorderLayout.CENTER);

        SimpleUniverse u = new SimpleUniverse(c);
        u.getViewingPlatform().setNominalViewingTransform();

        int gridSize=11;

        // Comment out according to which you want to test
        //GeometryArray geometry = getTriangleArray(gridSize,2);
        GeometryArray geometry = getITA(gridSize, 2);

        Shape3D shape = new Shape3D(geometry, getAppearance());

        BranchGroup bg = new BranchGroup();
        bg.addChild(shape);
        u.addBranchGraph(bg);

        setCameraPosition(u.getViewingPlatform(), 
            new Point3d(gridSize/2,5,-10), 
            new Point3d(gridSize/2,0,gridSize/2), 
            new Vector3d(0,1,0));


        f.setSize(600,600);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void setCameraPosition(ViewingPlatform VP, Point3d from,
        Point3d to, Vector3d v)
    {
        TransformGroup viewTransform = VP.getViewPlatformTransform();
        Transform3D t3d = new Transform3D();

        t3d.lookAt(from, to, v);
        t3d.invert();
        viewTransform.setTransform(t3d);

    }

}
Marco13
  • 53,703
  • 9
  • 80
  • 159