obj文件的理解请参考:http://foolog.net/?p=941
要注意一点,obj文件中面的保存,有的是按照三角形(也就是只有三个点),有的是按照空间四边形保存(包含四个点),这里是按照四个点来的,注释中已经给出。
#ifndef GLUT_DISABLE_ATEXIT_HACK #define GLUT_DISABLE_ATEXIT_HACK #endif #define GLEW_STATIC #include <GL/glew.h> #include <GL/wglew.h> #include <GL/freeglut.h> #include <vector> #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> //for matrices #include <glm/gtc/type_ptr.hpp> //undefine if u want to use the default bending constraint of pbd #include<sstream> #include <fstream> #include<iostream> using namespace std; GLfloat rtx = 0.0f, rty = 0.0f, rtz = 0.0; GLfloat step = 0.1; //float exp1 = 1e-3; const int GRID_SIZE = 10; GLint viewport[4]; GLdouble PP[16]; int v_num; //记录点的数量 int vn_num;//记录法线的数量 int vt_num;// int f_num; //记录面的数量 GLfloat **vArr; //存放点的二维数组 GLfloat **vnArr;//存放法线的二维数组 int **fvArr; //存放面顶点的二维数组 int **fnArr; //存放面法线的二维数组 int readfile(string addrstr) //将文件内容读到数组中去 { int i; string s1; float f2,f3,f4; vArr=new GLfloat*[v_num]; for (i=0; i<v_num; i++) { vArr[i]=new GLfloat[3]; } vnArr=new GLfloat*[vn_num]; for (i=0; i<vn_num; i++) { vnArr[i]=new GLfloat[3]; } fvArr=new int*[f_num]; fnArr=new int*[f_num]; for (i=0; i<f_num; i++) { fvArr[i]=new int[4]; fnArr[i]=new int[3]; } ifstream infile(addrstr.c_str()); string sline;//每一行 int ii=0,jj=0,kk=0; while(getline(infile,sline)) { if(sline[0]=='v') { if(sline[1]=='n')//vn { istringstream sin(sline); sin>>s1>>f2>>f3>>f4; vnArr[ii][0]=f2; vnArr[ii][1]=f3; vnArr[ii][2]=f4; ii++; } else if(sline[1] == 't'){} else//v { istringstream sin(sline); sin>>s1>>f2>>f3>>f4; vArr[jj][0]=f2; vArr[jj][1]=f3; vArr[jj][2]=f4; jj++; } } if (sline[0]=='f') //读取面 { istringstream in(sline); GLfloat a; in>>s1;//去掉前缀f int i,k; //点数改这里 for(i=0; i<4; i++) { in>>s1; // cout<<s1<<endl; printf("%s\n",s1.c_str()); //取得顶点索引和法线索引 a=0; for(k=0; s1[k]!='/'; k++) { a=a*10+(s1[k]-48); } fvArr[kk][i]=a; a=0; for(k=k+2; s1[k]; k++) { a=a*10+(s1[k]-48);; } fnArr[kk][i]=a; } kk++; } } return 0; } void getLineNum(string addrstr){ //获取点数以及面数 // cout<<addrstr.c_str()<<endl; v_num = vn_num = f_num = vt_num = 0; ifstream infile(addrstr.c_str()); string sline;//每一行 while(getline(infile, sline)){ // cout<<sline<<endl; printf("%s\n",sline.c_str()); if(sline[0]=='v'){ if(sline[1] == 'n'){ vn_num ++; }else if(sline[1] =='t'){ //vt vt_num ++; }else{ v_num ++; } }else{ if(sline[0] == 'f'){ f_num ++; } } } } string s1; GLfloat f2,f3,f4; void DrawGrid() { glBegin(GL_LINES); glColor3f(0.5f, 0.5f, 0.5f); for(int i=-GRID_SIZE;i<=GRID_SIZE;i++) { glVertex3f((float)i,0,(float)-GRID_SIZE); glVertex3f((float)i,0,(float)GRID_SIZE); glVertex3f((float)-GRID_SIZE,0,(float)i); glVertex3f((float)GRID_SIZE,0,(float)i); } glEnd(); } void draw(void) { cout<<f_num; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glTranslatef(0,0,-10); glRotatef(15,1,0,0); DrawGrid(); glBegin(GL_LINES); glColor3f(1, 1, 1); for(int i = 0; i < f_num; i++){ int a0,a1,a2,a3; a0 = fvArr[i][0]-1; a1 = fvArr[i][1]-1; a2 = fvArr[i][2]-1; //点数改这里 a3 = fvArr[i][3]-1; glVertex3f(vArr[a0][0],vArr[a0][1],vArr[a0][2]); glVertex3f(vArr[a1][0],vArr[a1][1],vArr[a1][2]); cout<<vArr[a0][0]<<" line "<<vArr[a1][0]<<endl; glVertex3f(vArr[a1][0],vArr[a1][1],vArr[a1][2]); glVertex3f(vArr[a2][0],vArr[a2][1],vArr[a2][2]); cout<<vArr[a1][0]<<" line "<<vArr[a2][0]<<endl; glVertex3f(vArr[a2][0],vArr[a2][1],vArr[a2][2]); //点数改这里 glVertex3f(vArr[a3][0],vArr[a3][1],vArr[a3][2]); glVertex3f(vArr[a3][0],vArr[a3][1],vArr[a3][2]); cout<<vArr[a2][0]<<" line "<<vArr[a0][0]<<endl; glVertex3f(vArr[a0][0],vArr[a0][1],vArr[a0][2]); } glEnd(); glutSwapBuffers(); } void OnReshape(int nw, int nh) { glViewport(0,0,nw, nh); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60, (GLfloat)nw / (GLfloat)nh, 1.f, 100.0f); glGetIntegerv(GL_VIEWPORT, viewport); glGetDoublev(GL_PROJECTION_MATRIX, PP); glMatrixMode(GL_MODELVIEW); } //float step = 0.001; int main(int argc, char * argv[]) { getLineNum("yifu.obj"); readfile("yifu.obj"); glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); glutInitWindowPosition(100, 100); glutInitWindowSize(1024, 1024); glutCreateWindow("Hello OpenGL"); // init(); glutDisplayFunc(draw); // glutIdleFunc(draw); //指定程序空闲时调用函数 glutReshapeFunc(OnReshape); //指定窗口形状变化时的回调函数 glEnable(GL_DEPTH_TEST); glutMainLoop(); return 0; }
相关推荐
在处理OBJ模型时,可以加载并应用对应的Mtl材质文件,以获取模型的材质属性,包括颜色、透明度、反射率等,从而实现更加精细的渲染效果。 总之,OBJ格式作为一种通用且易于处理的3D模型格式,在OpenGL中具有广泛的...
`city.mtl` 文件就提供了`city.obj` 模型的材质信息,使3D渲染器能够正确显示模型的外观。 3. **gltf格式**: GL Transmission Format(gltf)是Khronos Group开发的一种开放标准的3D资产交换格式,旨在成为WebGL...
一篇详解OBJ格式以及实现读入的文章,可以参考参考(介绍了当今流行的三维作图工具Maya,阐述了Maya 生成的OBJ 三维格式,如何将OBJ 格式文件在OpenGL(Open Graphic Library)中进行输入和处理。重点介绍了OBJ 文件的...
本教程“OpenGL-Learn18(加载外部模型)”聚焦于如何使用OpenGL加载和渲染外部3D模型,例如从.obj文件中加载圣诞熊模型(christmas_bear_obj)。 首先,我们要了解.obj文件格式。.obj是Wavefront公司创建的一种...
对于提供的“三维模型.obj格式”文件,你可以使用各种3D建模软件(如Blender、3ds Max、Maya等)或编程库(如Assimp、OpenGL、Direct3D等)来打开、查看和编辑这个模型。通过研究这个模型,你可以更深入地理解OBJ...
这些模型通常以OBJ、FBX或其他格式导出,并通过OpenGL加载。模型的几何信息(顶点、法线、纹理坐标)和材质属性是实现光照效果的关键。 5. **贴图技术**:在3D模型上应用贴图可以增强其视觉效果。常见的贴图类型有...
4. **模型导入OpenGL**:将处理好的模型以特定格式(如.md3、.3ds、.obj或.smd)导出后,可以通过OpenGL的API将模型数据加载进内存,准备渲染。这里特别提到了smd格式,它是Source引擎使用的动画格式,通过专门的...
obj2opengl脚本就承担了这个角色,它可以解析.obj文件,并将其转换为OpenGL可理解的数据结构,从而方便地在iOS设备上渲染3D模型。 使用obj2opengl,开发者可以避免手动处理复杂的3D模型数据,节省大量时间。只需...
其中,obj格式是一种广泛使用的3D模型交换格式,它由Wavefront Technologies公司为他们的OpenGL编程接口开发。本篇文章将深入探讨obj格式的特点、结构以及它在不同场景中的应用。 1. **obj格式概述** - obj文件...
OpenGL加载Obj文件 obj文件是3D模型文件格式。由Alias|Wavefront公司为3D建模和动画软件"Advanced Visualizer"开发的一种标准,适合用于3D软件模型之间的互导,也可以通过Maya读写。
在地图建模方面,开发者可能使用了某种3D建模软件(如Blender或Maya)来创建原始模型,然后导出为如OBJ或OBJ+MTL格式的文件,再在程序中读取并解析这些文件,将模型数据转换为OpenGL能理解的形式。纹理信息可能存储...
总之,"Obj.rar_java obj"文件是一个关于使用Java 3D加载和显示OBJ模型的实例,涵盖了3D图形编程的核心概念,包括文件解析、几何构建、材质和纹理应用,以及最终的渲染。这对于希望在Java环境中进行3D图形开发的...
4. **文件支持**:可能支持多种3D格式的导入和导出,如OBJ、3DS、FBX等,方便与其他软件(如Blender、Maya等)进行数据交换。 5. **资源管理**:编辑器可能包含资源管理功能,如纹理、模型、动画的组织和管理,便于...
Obj文件格式的主要优点在于它的简单性和通用性,使得它能被多种3D建模软件所支持,如Blender、Maya、3DS Max等。 Obj文件主要包括以下几部分: 1. **顶点(Vertices)**:Obj文件用`v`关键字定义顶点,每个顶点由...
看到这个需求,直接React是用OpenGLES加载一个.obj(顶点数据)与.mtl(颜色材质信息)文件 就搞定了( .obj与.mtl文件由设计师用3dmax、Maya等工具导出)。 本以为是一个简单需求,但做起来发现困难点并不少: OpenGLES...
为了构建这个模型,开发者首先需要对人体肺部的解剖学有深入理解,然后使用建模软件(如Blender、Maya或3DS Max)创建3D模型,并将其导出为WebGL可读的格式,如OBJ或GLTF。模型可能包含多个部件,如左肺、右肺、...
接下来,Obj文件格式是一种常见的3D模型文件格式,由Wavefront Technologies开发,常用于3D建模软件如Blender或Maya中导出模型。Obj文件包含顶点坐标、纹理坐标和面信息等,使用ASCII编码,易于阅读和编写。解析Obj...
接着,我们可以实例化GLTFLoader,并在load方法中传入模型文件URL,加载完成后,loader会调用回调函数,其中包含解析后的模型数据。 ```javascript var loader = new THREE.GLTFLoader(); loader.load('model.gltf'...
开发者可能使用专门的3D建模软件如Blender或Maya来设计模型,然后将其导出为OBJ、GLTF或FBX等格式,再在程序中加载并解析这些模型。此外,纹理映射则允许我们在3D模型表面添加色彩和细节,增强视觉效果,这通常涉及...
角色有蒙皮,你可以根据自己需要选择自己的蒙皮,但需要自己提供Obj格式的三维模型,为了使骨骼驱动皮肤,你还需要提供皮肤与骨骼绑定的权重数据,我提供了maya插件可以将你的模型和骨骼的权重数据在maya中导出,...