首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >无法正确转换OBJ或OpenGL无法正确绘制对象

无法正确转换OBJ或OpenGL无法正确绘制对象
EN

Stack Overflow用户
提问于 2018-05-30 02:05:11
回答 1查看 285关注 0票数 1

我花了几个小时尝试用OpenGL绘制我的.obj模型。我想可能是我的Python脚本(将obj模型转换为C++文件)出了问题。或者是.obj文件有问题。我不知道如何让它正常工作。OpenGL绘制一个对象,但它与我在SketchUp中创建的对象完全不同。

简而言之:我的脚本正确地转换了.obj (除非我不知道其他规则)。首先,我将具有顶点的线收集在一个线列表中,vn和vt也是如此。我还收集了有关人脸的数据。然后,我将适当的v,vn和vt与人脸进行匹配。最后,它使用数据生成.h和.cpp文件。会出什么问题呢?

这是.obj文件:https://pastebin.com/g0HwpRqB

代码语言:javascript
复制
    # Alias OBJ Model File
# Exported from SketchUp, (c) 2000-2012 Trimble Navigation Limited
# File units = meters

mtllib sciany1.mtl

g Mesh1 Model

usemtl Brick_Tumbled
v 2.06118 0 0.0146645
vt -2.25413 -0.0320745
vn 0 -1 -0
v -3.02882 0 0.0146645
vt 3.31236 -0.0320745
v -3.02882 0 -9.68534
vt 3.31236 21.184
v 2.06118 0 -9.68534
vt -2.25413 21.184
f 1/1/1 2/2/1 3/3/1 4/4/1 

usemtl FrontColor
vt -119.245 0
vn 0 0 1
vt 81.1487 0
v 2.06118 2.76 0.0146645
vt 81.1487 108.661
v -3.02882 2.76 0.0146645
vt -119.245 108.661
f 2/5/2 1/6/2 5/7/2 6/8/2 

usemtl Brick_Tumbled
vt -0.0160372 0
vn 1 0 -0
vt 10.592 0
v 2.06118 2.76 -9.68534
vt 10.592 6.03675
vt -0.0160372 6.03675
f 1/9/3 4/10/3 7/11/3 5/12/3 

usemtl FrontColor
vt -81.1487 0
vn 0 0 -1
vt 119.245 0
v -3.02882 2.76 -9.68534
vt 119.245 108.661
vt -81.1487 108.661
f 4/13/4 3/14/4 8/15/4 7/16/4 

usemtl Brick_Tumbled
vt -10.592 0
vn -1 0 -0
vt 0.0160372 0
vt 0.0160372 6.03675
vt -10.592 6.03675
f 3/17/5 2/18/5 6/19/5 8/20/5 

vt -3.31236 -0.0320745
vn 0 1 -0
vt 2.25413 -0.0320745
vt 2.25413 21.184
vt -3.31236 21.184
f 6/21/6 5/22/6 7/23/6 8/24/6

下面是生成的.cpp文件:https://pastebin.com/YPXnuuzP

代码语言:javascript
复制
            #include "sciany1.h"

            namespace Models {

                Sciany1 sciany1;

                Sciany1::Sciany1() {
                    vertices=Sciany1Internal::vertices;
                    normals=Sciany1Internal::normals;
                    vertexNormals=Sciany1Internal::vertexNormals;
                    texCoords=Sciany1Internal::texCoords;
                    colors=Sciany1Internal::colors;
                    vertexCount=Sciany1Internal::vertexCount;
                }

                Sciany1::~Sciany1() {
                }

                void Sciany1::drawSolid() {
                    glEnable(GL_NORMALIZE);

                    glEnableClientState(GL_VERTEX_ARRAY);
                    //glEnableClientState(GL_COLOR_ARRAY);
                    //glEnableClientState(GL_NORMAL_ARRAY);
                    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

                    glVertexPointer(4,GL_FLOAT,0,vertices);
                    //glColorPointer(4,GL_FLOAT,0,colors);
                    glNormalPointer(GL_FLOAT,sizeof(float)*4,vertexNormals);
                    glTexCoordPointer(2,GL_FLOAT,0,texCoords);

                    glDrawArrays(GL_TRIANGLES,0,vertexCount);

                    glDisableClientState(GL_VERTEX_ARRAY);
                    //glDisableClientState(GL_COLOR_ARRAY);
                    //glDisableClientState(GL_NORMAL_ARRAY);
                    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
                }

                namespace Sciany1Internal {
                        unsigned int vertexCount=18;

                        float vertices[]={
                            2.06,0,0.01,
-3.02,0,0.01,
-3.02,0,-9.68,
-3.02,0,0.01,
2.06,0,0.01,
2.06,2.76,0.01,
2.06,0,0.01,
2.06,0,-9.68,
2.06,2.76,-9.68,
2.06,0,-9.68,
-3.02,0,-9.68,
-3.02,2.76,-9.68,
-3.02,0,-9.68,
-3.02,0,0.01,
-3.02,2.76,0.01,
-3.02,2.76,0.01,
2.06,2.76,0.01,
2.06,2.76,-9.68,


                        };

                        float colors[]={
                        };

                        float normals[]={
                            0,-1,-0,
0,-1,-0,
0,-1,-0,
0,0,1,
0,0,1,
0,0,1,
1,0,-0,
1,0,-0,
1,0,-0,
0,0,-1,
0,0,-1,
0,0,-1,
-1,0,-0,
-1,0,-0,
-1,0,-0,
0,1,-0,
0,1,-0,
0,1,-0,

                        };

                        float vertexNormals[]={

                        };

                        float texCoords[]={
                            -2.25,-0.03,
3.31,-0.03,
3.31,21.18,
-119.24,0,
81.14,0,
81.14,108.66,
-0.01,0,
10.59,0,
10.59,6.03,
-81.14,0,
119.24,0,
119.24,108.66,
-10.59,0,
0.01,0,
0.01,6.03,
-3.31,-0.03,
2.25,-0.03,
2.25,21.18,

                        };
                }
            }

下面是生成的.h文件:https://pastebin.com/jaf73yf2

代码语言:javascript
复制
#ifndef SCIANY1_H
#define SCIANY1_H

//Sciany1 model made out of triangles
//Contains arrays:
//vertices - vertex positions in homogenous coordinates
//normals - vertex normals in homogenous coordinates
//texCoords - texturing coordinates
//colors - vertex colors (rgba)
//Culling GL_CW
//TBN friendly

#include "model.h"

namespace Models {
    namespace Sciany1Internal {
        extern float vertices[];
        extern float normals[];
        extern float vertexNormals[];
        extern float texCoords[];
        extern float colors[];
        extern unsigned int vertexCount;
    }

    class Sciany1: public Model {
        public:
            Sciany1();
            virtual ~Sciany1();
            virtual void drawSolid();
    };

    extern Sciany1 sciany1;
}




#endif

这是我的Python脚本:https://pastebin.com/LivefwgY

代码语言:javascript
复制
def round_number(string_number):
    if "\n" in string_number:
        string_number = string_number.replace("\n", "")
    if "." in string_number:
        parts = string_number.split(".")
        if len(parts[1]) > 2:
            return parts[0] + "." + parts[1][:2]
    return string_number


def line_to_good_line(line):
    processed_numbers=[]
    numbers=line.split(" ")
    for number in numbers:
        if number and number != "\n":
            processed_numbers.append(round_number(number))
    output = str.join(",", processed_numbers) + ",\n"
    return output

def add_numbers_in_the_end(lines, additional_number):
    new_lines=[]
    for line in lines:
        new_lines.append(line[:-1]+","+additional_number+",\n")
    return new_lines


def prepare_output_from_faces(data, faces):
    ready_list = []
    for face in faces:
        for number in face:
            ready_list.append(data[int(number)-1])
    return str.join("", ready_list)


def convert_to_cpp(filename):
    model_name = filename[0].upper() + filename[1:-4]
    upper_model_name = model_name.upper()
    lower_model_name = model_name.lower()

    vertices_lines = []
    normals_lines = []
    tex_coords_lines = []

    vertices_faces = []
    normals_faces = []
    tex_coords_faces = []

    vertices="" # final string output
    normals="" # final string output
    tex_coords="" # final string output

    with open(filename, "r") as file:
        lines = file.readlines()
    for line in lines:
        if line[0:2] == "v ":
            line = line_to_good_line(line[2:])
            vertices_lines.append(line)
        elif line[0:3] == "vn ":
            line = line_to_good_line(line[3:])
            normals_lines.append(line);
        elif line[0:3] == "vt ":
            line = line_to_good_line(line[3:])
            tex_coords_lines.append(line)
        elif line[0:2] == "f ":
            face = line[2:].replace("\n", "").split(" ")
            face[0] = face[0].split("/")
            face[1] = face[1].split("/")
            face[2] = face[2].split("/")
            vertex_face = [face[0][0], face[1][0], face[2][0]]
            tex_coord_face = [face[0][1], face[1][1], face[2][1]]
            normals_face = [face[0][2], face[1][2], face[2][2]]
            vertices_faces.append(vertex_face)
            tex_coords_faces.append(tex_coord_face)
            normals_faces.append(normals_face)

    vertices = prepare_output_from_faces(vertices_lines, vertices_faces)
    normals = prepare_output_from_faces(normals_lines, normals_faces)
    tex_coords = prepare_output_from_faces(tex_coords_lines, tex_coords_faces)
    vertices_number = vertices.count("\n")

    with open(lower_model_name + ".h", "w") as header_file:
        data = """
        /*
        Niniejszy program jest wolnym oprogramowaniem; możesz go
        rozprowadzać dalej i / lub modyfikować na warunkach Powszechnej
        Licencji Publicznej GNU, wydanej przez Fundację Wolnego
        Oprogramowania - według wersji 2 tej Licencji lub(według twojego
        wyboru) którejś z późniejszych wersji.

        Niniejszy program rozpowszechniany jest z nadzieją, iż będzie on
        użyteczny - jednak BEZ JAKIEJKOLWIEK GWARANCJI, nawet domyślnej
        gwarancji PRZYDATNOŚCI HANDLOWEJ albo PRZYDATNOŚCI DO OKREŚLONYCH
        ZASTOSOWAŃ.W celu uzyskania bliższych informacji sięgnij do
        Powszechnej Licencji Publicznej GNU.

        Z pewnością wraz z niniejszym programem otrzymałeś też egzemplarz
        Powszechnej Licencji Publicznej GNU(GNU General Public License);
        jeśli nie - napisz do Free Software Foundation, Inc., 59 Temple
        Place, Fifth face, Boston, MA  02110 - 1301  USA
        */

        #ifndef {}_H
        #define {}_H

        //{} model made out of triangles
        //Contains arrays:
        //vertices - vertex positions in homogenous coordinates
        //normals - vertex normals in homogenous coordinates
        //texCoords - texturing coordinates
        //colors - vertex colors (rgba)
        //Culling GL_CW
        //TBN friendly

        #include "model.h"

        namespace Models {{
            namespace {}Internal {{
                extern float vertices[];
                extern float normals[];
                extern float vertexNormals[];
                extern float texCoords[];
                extern float colors[];
                extern unsigned int vertexCount;
            }}

            class {}: public Model {{
                public:
                    {}();
                    virtual ~{}();
                    virtual void drawSolid();
            }};

            extern {} {};
        }}




        #endif
        """.format(upper_model_name, upper_model_name,
         model_name, model_name, model_name, model_name,
         model_name, model_name, lower_model_name)
        header_file.write(data)

        with open(model_name + ".cpp", "w") as cpp_file:
            data = """
            /*
            Niniejszy program jest wolnym oprogramowaniem; możesz go
            rozprowadzać dalej i / lub modyfikować na warunkach Powszechnej
            Licencji Publicznej GNU, wydanej przez Fundację Wolnego
            Oprogramowania - według wersji 2 tej Licencji lub(według twojego
            wyboru) którejś z późniejszych wersji.

            Niniejszy program rozpowszechniany jest z nadzieją, iż będzie on
            użyteczny - jednak BEZ JAKIEJKOLWIEK GWARANCJI, nawet domyślnej
            gwarancji PRZYDATNOŚCI HANDLOWEJ albo PRZYDATNOŚCI DO OKREŚLONYCH
            ZASTOSOWAŃ.W celu uzyskania bliższych informacji sięgnij do
            Powszechnej Licencji Publicznej GNU.

            Z pewnością wraz z niniejszym programem otrzymałeś też egzemplarz
            Powszechnej Licencji Publicznej GNU(GNU General Public License);
            jeśli nie - napisz do Free Software Foundation, Inc., 59 Temple
            Place, Fifth face, Boston, MA  02110 - 1301  USA
            */

            #include "{}.h"

            namespace Models {{

                {} {};

                {}::{}() {{
                    vertices={}Internal::vertices;
                    normals={}Internal::normals;
                    vertexNormals={}Internal::vertexNormals;
                    texCoords={}Internal::texCoords;
                    colors={}Internal::colors;
                    vertexCount={}Internal::vertexCount;
                }}

                {}::~{}() {{
                }}

                void {}::drawSolid() {{
                    glEnable(GL_NORMALIZE);

                    glEnableClientState(GL_VERTEX_ARRAY);
                    //glEnableClientState(GL_COLOR_ARRAY);
                    //glEnableClientState(GL_NORMAL_ARRAY);
                    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

                    glVertexPointer(4,GL_FLOAT,0,vertices);
                    //glColorPointer(4,GL_FLOAT,0,colors);
                    glNormalPointer(GL_FLOAT,sizeof(float)*4,vertexNormals);
                    glTexCoordPointer(2,GL_FLOAT,0,texCoords);

                    glDrawArrays(GL_TRIANGLES,0,vertexCount);

                    glDisableClientState(GL_VERTEX_ARRAY);
                    //glDisableClientState(GL_COLOR_ARRAY);
                    //glDisableClientState(GL_NORMAL_ARRAY);
                    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
                }}

                namespace {}Internal {{
                        unsigned int vertexCount={};

                        float vertices[]={{
                            {}

                        }};

                        float colors[]={{
                        }};

                        float normals[]={{
                            {}
                        }};

                        float vertexNormals[]={{

                        }};

                        float texCoords[]={{
                            {}
                        }};
                }}
            }}

            """.format(lower_model_name, model_name, lower_model_name, model_name,
            model_name, model_name, model_name, model_name, model_name, model_name,
            model_name, model_name, model_name, model_name, model_name, vertices_number,
            vertices, normals, tex_coords)
            cpp_file.write(data)


filename = input("Input the name of the obj file: ")
convert_to_cpp(filename)
EN

回答 1

Stack Overflow用户

发布于 2018-05-30 04:00:38

obj文件由具有3个分量(x,y,z)的顶点坐标、具有3个分量(x,y,z)的法向量和具有2个分量(u,v)的纹理坐标组成。

glVertexPointer的第一个参数指定每个顶点的坐标(组件)数,glTexCoordPointer的第一个参数指定每个纹理属性的坐标(组件)数。

您很好地完成了纹理坐标的规范,但在顶点坐标的定义中,您指定了4个分量而不是3个分量。

更改顶点坐标数组的定义:

代码语言:javascript
复制
glVertexPointer(3, GL_FLOAT, 0, vertices);

请注意,由于顶点数组定义了4个组件,而不是3个组件,因此对顶点坐标的访问未对齐,并且超出了末尾的界限。这会导致渲染网格的顶点坐标看起来是任意的。

glNormalPointer的第二个参数指定连续法线之间的字节偏移量。如果stride为0,则认为法线紧密堆积在数组中。

法线向量由3个分量组成(正如glNormalPointer所预期的那样),并且它们紧密堆叠在一起。

步幅参数之一必须为0:

代码语言:javascript
复制
glNormalPointer(GL_FLOAT, 0, vertexNormals);

或者它必须是3*sizeof(float)

代码语言:javascript
复制
glNormalPointer(GL_FLOAT, sizeof(float)*3, vertexNormals);

在函数round number中,属性坐标被四舍五入为2位小数,但在obj文件中,顶点坐标的提交精度高达5位小数。

将数字的四舍五入从2位小数更改为5位小数:

代码语言:javascript
复制
def round_number(string_number):
    if "\n" in string_number:
        string_number = string_number.replace("\n", "")
    if "." in string_number:
        parts = string_number.split(".")
        if len(parts[1]) > 5: # <---------------- 5 instead of 2
            return parts[0] + "." + parts[1][:2]
    return string_number 
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50590377

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档