java - 纹理在 java3d 中无法正确显示

标签 java texture-mapping java-3d texture2d

类似于:Java3d: Texture is not applied to OBJ model properly

除了我自己生成 IndexedTriangleArray 并映射纹理。

几何形状很好,但它采用纹理图像左下角的颜色,而不是将其拉伸(stretch)到整个图像。 Testure.jpg是一张256*256的图片。

编辑:奇怪的是,非索引 TriangleArray 工作正常。 所以我认为这是我设置纹理坐标的方式的问题?

(要在 IndexedTriangleArray 和 TriangleArray 之间切换,只需注释掉主函数中的该行即可)

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);

}


}

最佳答案

诚然,我可以/应该早点注意到这一点,但是......自从我积极使用Java3D以来已经有一段时间了 - 从那时起,我主要是在挤出我的时间知识和内存微薄,无法回答论坛和 stackoverfow 相关问题;-)

但是:您确实使用

设置了顶点的索引
ta.setCoordinateIndex(...);

通话。但是您另外必须设置纹理坐标的索引,使用

ta.setTextureCoordinateIndex(0, ...);

0指纹理坐标集(可能有多个纹理,具有不同的坐标集)。除此之外,索引与此处的顶点相同。

再次以 MCVE 身份。 (图像名称已更改。莉娜规则!)

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);

    }

}

关于java - 纹理在 java3d 中无法正确显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24458276/

相关文章:

java - Java 3D 中表面的每一面是否可以有不同的颜色?

java - Java3D:逐步旋转Universe

java - 如何创建回调(添加为动态参数,一个函数)?

java - Android fragment oncreateview 被调用,但 View 未膨胀并且没有错误

java - 如何从 shaded jar 中排除 *.DSA 和 *.SF 文件?

java - UV 和 ST 纹理坐标之间的差异

java - Maven tomcat 插件不接受路径

Android OpenGLES 2.0 纹理映射不工作

ios - 使用 isgl3D 未正确进行 3D 对象 (.pod) 中的纹理映射

java - 将对象附加到 Java3D 中的 View 平台