如何分别纹理化(使用不同的纹理文件)3D模型?

时间:2014-09-26 19:18:02

标签: java opengl 3d lwjgl

我有一个在Blender中制作并导出到java(.OBJ文件)的3D文件,它的纹理被分成了一些文件。在这个.obj文件中,它有一些字段用于修改USEMTL及其部件的名称(纹理文件)。但是,当我在屏幕上绘制它时,他只显示最后一个USEMTL名称。 我的问题是:我怎样才能让他以正确的方式阅读和纹理化?没有研磨其他纹理?

这是具有.obj加载程序

的类
    public MLoader(String path, Model m) throws IOException {
            @SuppressWarnings("resource")
            BufferedReader reader = new BufferedReader(new FileReader(new File(path)));
            String line;

    while ((line = reader.readLine()) != null) {
        if (line.startsWith("v ")) {
            float 
            v1 = Float.valueOf(line.split(" ")[1]), 
            v2 = Float.valueOf(line.split(" ")[2]), 
            v3 = Float.valueOf(line.split(" ")[3]);

            Vector3f v = new Vector3f (v1, v2, v3);

            m.vertex.add(v);
        } if (line.startsWith("usemtl ")){
            String name = String.valueOf(line.split(" ")[1]);
            m.nameTexture.add(name);
            continue;
        } if (line.startsWith("f ")) {
            float 
            v1 = Float.valueOf(line.split(" ")[1].split("/")[0]),
            v2 = Float.valueOf(line.split(" ")[2].split("/")[0]),
            v3 = Float.valueOf(line.split(" ")[3].split("/")[0]),

            n1 = Float.valueOf(line.split(" ")[1].split("/")[1]),
            n2 = Float.valueOf(line.split(" ")[2].split("/")[1]),
            n3 = Float.valueOf(line.split(" ")[3].split("/")[1]);

            Vector3f
            v = new Vector3f (v1, v2, v3),
            n = new Vector3f (n1, n2, n3);

            m.face.add(new Faces(v, n));
        }if (line.startsWith("vt ")) {
            float 
            vt1 = Float.valueOf(line.split(" ")[1]), 
            vt2 = Float.valueOf(line.split(" ")[2]);

            Vector2f vt = new Vector2f (vt1, vt2);

            m.vertexTexture.add(vt);
        } 
    }
}

正如你所看到的,我创建了一个IF语句,只是为了得到这个usemtl的东西(在.obj文件里面) - 纹理名称(它们分成单独的文件)只是为了看看我是否可以单独绑定它们。但是我很难做到这一点(也许,逻辑不在我身边)。怎么办?

其他课程:

纹理类

public class Textures {
    public Texture[] tx;

    public void setNumTex(int i) {
        tx = new Texture[i];
    }

    public void setTexture(String format, String name, int i) {
        try {
            tx[i] = TextureLoader.getTexture(format, new FileInputStream(new File("res/Textures/" + name + format)));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void texturing(Vector2f ft1, Vector2f ft2, int indexx) {
        for (int i=0; i<indexx; i++) {
            tx[i].bind();
        }
        glTexCoord2f(ft1.x, ft1.y);
        glTexCoord2f(ft2.x, ft2.y);
    }
}

渲染类

public class Renderer {
    Model m;

    public void loadContent(String objPath) {
        //Everithing that is loading is been putting here
        m = Model.getModel("res/Models/" + objPath);

        m.loadTex();
    }

    public void render() {
        glEnable(GL_SMOOTH);

        m.renderModel();
    }
}

模型类

public class Model {
    Textures tx;

    List<Vector3f> vertex, norms;
    List<Vector2f> vertexTexture;
    List<Faces> face;
    List<String> nameTexture;
    String name[];

    private int numTex = 0;

    Vector2f 
    t1 = new Vector2f(), t2 = new Vector2f();

    Vector3f
    v1 = new Vector3f(), v2 = new Vector3f(), v3 = new Vector3f(),
    n1 = new Vector3f(), n2 = new Vector3f(), n3 = new Vector3f(),

    public Model(String path)throws 
    LWJGLException, FileNotFoundException, IOException {
        vertex = new ArrayList<Vector3f>();
        norms = new ArrayList<Vector3f>();
        vertexTexture = new ArrayList<Vector2f>();
        face = new ArrayList<Faces>();
        nameTexture = new ArrayList<String>();

        tx = new Textures();

        new MLoader(path, this);
    }

    public static Model getModel(String path, Vector3f position, Vector3f rotation) {
        try {
            return new Model(path, position, rotation);
        } catch (LWJGLException | IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public void loadTex() {
        name = new String[nameTexture.toArray().length];
        tx.setNumTex(nameTexture.toArray().length);

        for (int i=0; i<name.length; i++) {
            name[i] = nameTexture.get(i);
            numTex += 1;

            tx.setTexture(".TGA", name[i], i);
        }
    }

    public void renderModel() {
        glPushMatrix();
        glPolygonMode(GL_FRONT_AND_BACK, GL_DEPTH_BUFFER_BIT);
        glEnable(GL_TEXTURE_2D);
        glBegin(GL_TRIANGLES);
        {
            for (Faces f : face) {
                v1 = vertex.get((int) f.v.x - 1);
                v2 = vertex.get((int) f.v.y - 1);
                v3 = vertex.get((int) f.v.z - 1);
                n1 = vertex.get((int) f.n.x - 1);
                n2 = vertex.get((int) f.n.y - 1);
                n3 = vertex.get((int) f.n.z - 1);
                t1 = vertexTexture.get((int) f.n.x - 1); //
                t2 = vertexTexture.get((int) f.n.y - 1); // 

                //Vertexes
                glVertex3f(v1.x, v1.y-3.4f, v1.z-0.53f);
                glVertex3f(v2.x, v2.y-3.4f, v2.z-0.53f);
                glVertex3f(v3.x, v3.y-3.4f, v3.z-0.53f);

                //Normals
                glNormal3f(n1.x, n1.y-3.4f, n1.z-0.53f);
                glNormal3f(n2.x, n2.y-3.4f, n2.z-0.53f);
                glNormal3f(n3.x, n3.y-3.4f, n3.z-0.53f);

                //Texture
                tx.texturing(t1, t2, numTex);
                //tx.texturing(n1, n2, n3);             
            }
        }
        glEnd();
        glDisable(GL_TEXTURE_2D);
        glPopMatrix();
    }
}

2 个答案:

答案 0 :(得分:0)

我不会放任何代码,因为你的问题对于2行解决方案来说相当复杂。但是这里它通常如何在一个简单的3D引擎中工作。网格的多个纹理意味着网格被分成2个或更多个子-meshes。我不是搅拌器专家,但我确信它能够像Autodesk 3D studio max.Now一样导出网状物与其子网格树,当你将这样的网格导入你的程序时,你应该能够解析所有那些子网格成为单独的实体。每个这样的子网格都有自己的顶点,纹理坐标和法线。在发出绘制调用时,您将逐个遍历所有子网格,并在其自己的绘制调用中绘制每个子网格。因此,在每次绘制调用时,您还应该能够附加用于该特定绘制的唯一纹理。 sub-mesh。这就是全部。现在由你来决定如何设计这样一个系统。 希望它有所帮助。

答案 1 :(得分:0)

好的,我发现了什么问题。 这是解决方案:在MLoader类中,我只需要在“usemtl”部分放置一个“区分器”。有了它,当他在“F SECTION”时,当他回来并将“faceArray”添加到脸上时,他只需要增加他需要的东西。

例:
face.add(1, 2, 3);
faceArray.add(face); //Assuming that the face has his 1, 2, 3 thing
当他再次去“f”的时候,他补充道,

face.add(4, 5, 6);
faceArray.add(face); //But, this time, when he adds the face, it already had 1, 2, 3, 

//so, he's with '1, 2, 3, 4, 5, 6' into him
这是我所做的改变(只是改变):

班级MLoader:

public MLoader(String path, Model m) throws IOException {
...
        while ((line = reader.readLine()) != null) {
            ...
            } if (line.contains("g ")) {
                index = 0;
            } if (line.startsWith("usemtl ") && index == 0){
                String name = String.valueOf(line.split(" ")[1]);   
                m.nameTexture.add(name);
                m.faceArray.add(m.face);

                m.face = new ArrayList<Faces>();
                index = 1;
            } if (line.contains("f ") && index == 1) {
                ...
            }

班级模型:

int numTex = 0;
List<List <Faces>> faceArray;
...

public void loadTex() {
    for (String n : nameTexture) {
        tx.loadTexture("TGA", n);
        numTex ++;
    }
}
...

public void renderModel() {
...
glEnable(GL_TEXTURE_2D);
        for (int i = 0; i < numTex; i++) {
            tx.tx.get(i).bind();

            glBegin(GL_TRIANGLES);
            {
                for (Faces f : faceArray.get(i)) {              
                    ...
                    }
                }
                glEnd();
            }
            glDisable(GL_TEXTURE_2D);
            ...
    }