opengl 中的对象加载器
我在 C++ 中创建了一个程序,它也包含 opengl,我还想创建一个 obj 加载器以加载我拥有的 obj 文件!我已经创建了两个函数,它们是:
void ReadFile(model *md){//打开文件读取OBJINFO.TXTifstream obj_file("tree.obj");如果(obj_file.fail())退出(1);//获取顶点数obj_file >>md->顶点;//获取人脸数量obj_file >>md->faces;//获取顶点坐标for (int i = 0; i vertices; i++){obj_file >>md->obj_points[i].x;obj_file >>md->obj_points[i].y;obj_file >>md->obj_points[i].z;}//获取人脸结构for (int i = 0; i faces; i++){obj_file >>md->obj_faces[i].vn[0];obj_file >>md->obj_faces[i].vn[1];obj_file >>md->obj_faces[i].vn[2];obj_file >>md->obj_faces[i].vn[3];}obj_file.close();}void DisplayModel(model md){glPushMatrix();glBegin(GL_TRIANGLES);for (int i = 0; i
主要问题是当我编译项目并运行它时,viewport 中什么也没有出现.我还增加了视口的尺寸,以防它变小以显示对象,但情况保持不变!所以我得出的结果是我在这些功能上做错了!有人可以帮我吗?!
我还给出了我的 obj 文件的一些值:
v 0.158000 0.975000 0.151491 1.000000v 0.188743 0.025000 0.173826 1.000000v 0.196000 0.025000 0.151491 1.000000v 0.158000 0.025000 0.151491 1.000000v 0.169743 0.025000 0.187631 1.000000v 0.146257 0.025000 0.187631 1.000000v 0.127257 0.025000 0.173826 1.000000vn 0.950370 0.038015 0.308791vn 0.950370 0.038015 0.308791vn 0.950370 0.038015 0.308791vn 0.000000 -1.000000 0.000000vn 0.000000 -1.000000 0.000000vn 0.000000 -1.000000 -0.000000vn 0.587380 0.038015 0.808418f 1//1 2//2 3//3f 4//4 3//5 2//61//7 5//8 2//9f 4//10 2//11 5//12f 1//13 6//14 5//15f 4//16 5//17 6//18f 1//19 7//20 6//21
解决方案 //获取顶点数obj_file >>md->顶点;//获取人脸数量obj_file >>md->faces;
再次阅读规范.这不是 OBJ 的工作方式.在进行过程中,您必须解析出顶点/纹理坐标/法线/面.
使用这样的东西:
#include #include #define GLM_ENABLE_EXPERIMENTAL#include #include <向量>#include <fstream>#include 结构顶点{glm::vec3 位置;glm::vec2 texcoord;glm::vec3 正常;};结构体 VertRef{VertRef( int v, int vt, int vn ) : v(v), vt(vt), vn(vn) { }int v, vt, vn;};std::vector<顶点LoadOBJ( std::istream& in ){std::vector<顶点顶点;std::vector位置( 1, glm::vec4( 0, 0, 0, 0 ) );std::vectortexcoords(1, glm::vec3(0, 0, 0));std::vector法线(1,glm::vec3(0,0,0));std::string lineStr;while( std::getline( in, lineStr ) ){std::istringstream lineSS( lineStr );std::string lineType;lineSS>>线型;//顶点if( lineType == "v" ){浮动 x = 0, y = 0, z = 0, w = 1;lineSS>>x>>y>>>>;position.push_back(glm::vec4(x,y,z,w));}//质地if( lineType == "vt" ){浮动u = 0,v = 0,w = 0;lineSS>>你>>>>;texcoords.push_back(glm::vec3(u, v, w));}//普通的if( lineType == "vn" ){浮点 i = 0, j = 0, k = 0;lineSS>>我>>>>k;normals.push_back( glm::normalize( glm::vec3( i, j, k ) ) );}//多边形if( lineType == "f" ){std::vector参考文献;std::string refStr;而(行SS>> refStr){std::istringstream ref(refStr);std::string vStr, vtStr, vnStr;std::getline( ref, vStr, '/' );std::getline( ref, vtStr, '/' );std::getline( ref, vnStr, '/' );int v = atoi( vStr.c_str() );int vt = atoi( vtStr.c_str() );int vn = atoi( vnStr.c_str() );v = ( v >= 0 ? v : position.size() + v );vt = ( vt >= 0 ? vt : texcoords.size() + vt );vn = ( vn >= 0 ? vn : normals.size() + vn );refs.push_back( VertRef( v, vt, vn ) );}//三角测量,假设 n>3-gons 是凸面和共面的for( size_t i = 1; i+1 v]-positions[p[0]->v]);glm::vec3 V(positions[p[2]->v]-positions[p[0]->v]);glm::vec3 faceNormal = glm::normalize(glm::cross(U, V));for( size_t j = 0; j <3; ++j ){顶点垂直;vert.position = glm::vec3(positions[p[j]->v]);vert.texcoord = glm::vec2(texcoords[p[j]->vt]);vert.normal = ( p[j]->vn != 0 ? normals[ p[j]->vn ] : faceNormal );verts.push_back(vert);}}}}返回顶点;}国际btn;glm::ivec2 startMouse;glm::ivec2 startRot, curRot;glm::ivec2 startTrans, curTrans;void mouse(int button, int state, int x, int y ){if( 按钮 == GLUT_LEFT_BUTTON && 状态 == GLUT_DOWN ){btn = 按钮;startMouse = glm::ivec2( x, glutGet( GLUT_WINDOW_HEIGHT ) - y );startRot = curRot;}if( 按钮 == GLUT_RIGHT_BUTTON && 状态 == GLUT_DOWN ){btn = 按钮;startMouse = glm::ivec2( x, glutGet( GLUT_WINDOW_HEIGHT ) - y );startTrans = curTrans;}}无效运动(int x,int y){glm::ivec2 curMouse( x, glutGet( GLUT_WINDOW_HEIGHT ) - y );如果( btn == GLUT_LEFT_BUTTON ){curRot = startRot + ( curMouse - startMouse );}否则如果( btn == GLUT_RIGHT_BUTTON ){curTrans = startTrans + ( curMouse - startMouse );}glutPostRedisplay();}std::vector<顶点模型;无效显示(){glClearColor( 0.2f, 0.2f, 0.2f, 1.0f );glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glMatrixMode(GL_PROJECTION);glLoadIdentity();双 w = glutGet( GLUT_WINDOW_WIDTH );双 h = glutGet( GLUT_WINDOW_HEIGHT );双 ar = w/h;glTranslatef( curTrans.x/w * 2, curTrans.y/h * 2, 0 );gluPerspective( 60, ar, 0.1, 100 );glMatrixMode(GL_MODELVIEW);glLoadIdentity();glTranslatef( 0, 0, -10 );glPushMatrix();{glRotatef( curRot.x % 360, 0, 1, 0 );glRotatef(-curRot.y % 360, 1, 0, 0);//目的glColor3ub( 255, 0, 0 );glEnableClientState( GL_VERTEX_ARRAY );glEnableClientState( GL_TEXTURE_COORD_ARRAY );glEnableClientState( GL_NORMAL_ARRAY );glVertexPointer(3, GL_FLOAT, sizeof(Vertex), &model[0].position);glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &model[0].texcoord);glNormalPointer( GL_FLOAT, sizeof(Vertex), &model[0].normal );glDrawArrays(GL_TRIANGLES, 0, model.size());glDisableClientState( GL_VERTEX_ARRAY );glDisableClientState( GL_TEXTURE_COORD_ARRAY );glDisableClientState( GL_NORMAL_ARRAY );//边界立方体glDisable(GL_LIGHTING);glColor3ub( 255, 255, 255 );glutWireCube(7);glEnable(GL_LIGHTING);}glPopMatrix();glutSwapBuffers();}//返回 pts 的最小/最大点数模板<类型名称 Vec >std::pairGetExtents(const Vec* pts, size_t stride, size_t count){unsigned char* base = (unsigned char*)pts;Vec pmin( *(Vec*)base );Vec pmax( *(Vec*)base );for( size_t i = 0; i < count; ++i, base += stride ){const Vec&pt = *(vec*)base;pmin = glm::min( pmin, pt );pmax = glm::max(pmax, pt);}返回 std::make_pair( pmin, pmax );}//以原点为中心的几何图形//并将其缩放以适合大小 ^3 的框模板<类型名称 Vec >void CenterAndScale( Vec* pts, size_t stride, size_t count, const typename Vec::value_type& size ){typedef typename Vec::value_type 标量;//获取最小/最大范围std::pairexts = GetExtents( pts, stride, count );//居中和缩放const Vec center = ( exts.first * Scalar( 0.5 ) ) + ( exts.second * Scalar( 0.5f ) );const 标量因子 = 大小/glm::compMax( exts.second - exts.first );unsigned char* base = (unsigned char*)pts;for( size_t i = 0; i < count; ++i, base += stride ){维克&pt = *(vec*)base;pt = ( ( pt - 中心 ) * 因子 );}}int main( int argc, char **argv ){//https://en.wikipedia.org/wiki/Stanford_bunnystd::ifstream ifile( "bunny.obj" );模型 = LoadOBJ(文件);CenterAndScale( &model[0].position, sizeof( Vertex ), model.size(), 7 );glutInit( &argc, argv );glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);glutInitWindowSize(640, 480);glutCreateWindow("OBJ");glutDisplayFunc( 显示 );glutMouseFunc(鼠标);glutMotionFunc(运动);glEnable(GL_DEPTH_TEST);//设置类似头灯"的灯glShadeModel(GL_SMOOTH);glEnable(GL_COLOR_MATERIAL);glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);glEnable(GL_LIGHTING);glEnable(GL_LIGHT0);glMatrixMode(GL_MODELVIEW);glLoadIdentity();GLfloat 位置[] = { 0, 0, 1, 0 };glLightfv( GL_LIGHT0, GL_POSITION, 位置);glPolygonMode(GL_FRONT, GL_FILL);glPolygonMode(GL_BACK, GL_LINE);glutMainLoop();返回0;}
LMB-拖动旋转,RMB-拖动平移".
并使用这个:
v 0.000000 2.000000 2.000000v 0.000000 0.000000 2.000000v 2.000000 0.000000 2.000000v 2.000000 2.000000 2.000000f -4 -3 -2 -1v 2.000000 2.000000 0.000000v 2.000000 0.000000 0.000000v 0.000000 0.000000 0.000000v 0.000000 2.000000 0.000000f -4 -3 -2 -1v 2.000000 2.000000 2.000000v 2.000000 0.000000 2.000000v 2.000000 0.000000 0.000000v 2.000000 2.000000 0.000000f -4 -3 -2 -1v 0.000000 2.000000 0.000000v 0.000000 2.000000 2.000000v 2.000000 2.000000 2.000000v 2.000000 2.000000 0.000000f -4 -3 -2 -1v 0.000000 2.000000 0.000000v 0.000000 0.000000 0.000000v 0.000000 0.000000 2.000000v 0.000000 2.000000 2.000000f -4 -3 -2 -1v 0.000000 0.000000 2.000000v 0.000000 0.000000 0.000000v 2.000000 0.000000 0.000000v 2.000000 0.000000 2.000000f -4 -3 -2 -1
或者这个:
v 0.000000 2.000000 0.000000v 0.000000 0.000000 0.000000v 2.000000 0.000000 0.000000v 2.000000 2.000000 0.000000v 4.000000 0.000000 -1.255298v 4.000000 2.000000 -1.255298vn 0.000000 0.000000 1.000000vn 0.000000 0.000000 1.000000vn 0.276597 0.000000 0.960986vn 0.276597 0.000000 0.960986vn 0.531611 0.000000 0.846988vn 0.531611 0.000000 0.846988# 6 个顶点# 6 法线全部1f 1//1 2//2 3//3 4//4f 4//4 3//3 5//5 6//6# 2 个元素
对于test.obj
.
glm.hpp
来自 GLM 库.>
I have create a program in C++ that contains also opengl and I want to create also an obj loader in order to load an obj file I have ! I have already created two functions which are :
void ReadFile(model *md)
{
// Open the file for reading OBJINFO.TXT
ifstream obj_file("tree.obj");
if (obj_file.fail())
exit(1);
// Get the number of vertices
obj_file >> md->vertices;
// Get the number of faces
obj_file >> md->faces;
// Get the vertex coordinates
for (int i = 0; i < md->vertices; i++)
{
obj_file >> md->obj_points[i].x;
obj_file >> md->obj_points[i].y;
obj_file >> md->obj_points[i].z;
}
// Get the face structure
for (int i = 0; i < md->faces; i++)
{
obj_file >> md->obj_faces[i].vn[0];
obj_file >> md->obj_faces[i].vn[1];
obj_file >> md->obj_faces[i].vn[2];
obj_file >> md->obj_faces[i].vn[3];
}
obj_file.close();
}
void DisplayModel(model md)
{
glPushMatrix();
glBegin(GL_TRIANGLES);
for (int i = 0; i < md.faces; i++)
{
glVertex3f(md.obj_points[md.obj_faces[i].vn[0]-1].x, md.obj_points[md.obj_faces[i].vn[0]-1].y, md.obj_points[md.obj_faces[i].vn[0]-1].z);
glVertex3f(md.obj_points[md.obj_faces[i].vn[1]-1].x, md.obj_points[md.obj_faces[i].vn[1]-1].y, md.obj_points[md.obj_faces[i].vn[1]-1].z);
glVertex3f(md.obj_points[md.obj_faces[i].vn[2]-1].x, md.obj_points[md.obj_faces[i].vn[2]-1].y, md.obj_points[md.obj_faces[i].vn[2]-1].z);
glVertex3f(md.obj_points[md.obj_faces[i].vn[2]-1].x, md.obj_points[md.obj_faces[i].vn[2]-1].y, md.obj_points[md.obj_faces[i].vn[3]-1].z);
}
glEnd();
glPopMatrix();
}
The main problem is that when I compile the project and run it , nothing appears in viewport . I increased also the dimensions of viewport in case it is small in order to appear the object , but the situation remains the same ! So I reach the result that I have done something wrong in these functions ! Could anyone help me ?!
Also I give some values of my obj file :
v 0.158000 0.975000 0.151491 1.000000
v 0.188743 0.025000 0.173826 1.000000
v 0.196000 0.025000 0.151491 1.000000
v 0.158000 0.025000 0.151491 1.000000
v 0.169743 0.025000 0.187631 1.000000
v 0.146257 0.025000 0.187631 1.000000
v 0.127257 0.025000 0.173826 1.000000
vn 0.950370 0.038015 0.308791
vn 0.950370 0.038015 0.308791
vn 0.950370 0.038015 0.308791
vn 0.000000 -1.000000 0.000000
vn 0.000000 -1.000000 0.000000
vn 0.000000 -1.000000 -0.000000
vn 0.587380 0.038015 0.808418
f 1//1 2//2 3//3
f 4//4 3//5 2//6
f 1//7 5//8 2//9
f 4//10 2//11 5//12
f 1//13 6//14 5//15
f 4//16 5//17 6//18
f 1//19 7//20 6//21
解决方案
// Get the number of vertices
obj_file >> md->vertices;
// Get the number of faces
obj_file >> md->faces;
Read the spec again. That's not how OBJs work. You have to parse out the vertexes/texture coordinates/normals/faces as you go along.
Use something like this:
#include <GL/glut.h>
#include <glm/glm.hpp>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/component_wise.hpp>
#include <vector>
#include <fstream>
#include <sstream>
struct Vertex
{
glm::vec3 position;
glm::vec2 texcoord;
glm::vec3 normal;
};
struct VertRef
{
VertRef( int v, int vt, int vn ) : v(v), vt(vt), vn(vn) { }
int v, vt, vn;
};
std::vector< Vertex > LoadOBJ( std::istream& in )
{
std::vector< Vertex > verts;
std::vector< glm::vec4 > positions( 1, glm::vec4( 0, 0, 0, 0 ) );
std::vector< glm::vec3 > texcoords( 1, glm::vec3( 0, 0, 0 ) );
std::vector< glm::vec3 > normals( 1, glm::vec3( 0, 0, 0 ) );
std::string lineStr;
while( std::getline( in, lineStr ) )
{
std::istringstream lineSS( lineStr );
std::string lineType;
lineSS >> lineType;
// vertex
if( lineType == "v" )
{
float x = 0, y = 0, z = 0, w = 1;
lineSS >> x >> y >> z >> w;
positions.push_back( glm::vec4( x, y, z, w ) );
}
// texture
if( lineType == "vt" )
{
float u = 0, v = 0, w = 0;
lineSS >> u >> v >> w;
texcoords.push_back( glm::vec3( u, v, w ) );
}
// normal
if( lineType == "vn" )
{
float i = 0, j = 0, k = 0;
lineSS >> i >> j >> k;
normals.push_back( glm::normalize( glm::vec3( i, j, k ) ) );
}
// polygon
if( lineType == "f" )
{
std::vector< VertRef > refs;
std::string refStr;
while( lineSS >> refStr )
{
std::istringstream ref( refStr );
std::string vStr, vtStr, vnStr;
std::getline( ref, vStr, '/' );
std::getline( ref, vtStr, '/' );
std::getline( ref, vnStr, '/' );
int v = atoi( vStr.c_str() );
int vt = atoi( vtStr.c_str() );
int vn = atoi( vnStr.c_str() );
v = ( v >= 0 ? v : positions.size() + v );
vt = ( vt >= 0 ? vt : texcoords.size() + vt );
vn = ( vn >= 0 ? vn : normals.size() + vn );
refs.push_back( VertRef( v, vt, vn ) );
}
// triangulate, assuming n>3-gons are convex and coplanar
for( size_t i = 1; i+1 < refs.size(); ++i )
{
const VertRef* p[3] = { &refs[0], &refs[i], &refs[i+1] };
// http://www.opengl.org/wiki/Calculating_a_Surface_Normal
glm::vec3 U( positions[ p[1]->v ] - positions[ p[0]->v ] );
glm::vec3 V( positions[ p[2]->v ] - positions[ p[0]->v ] );
glm::vec3 faceNormal = glm::normalize( glm::cross( U, V ) );
for( size_t j = 0; j < 3; ++j )
{
Vertex vert;
vert.position = glm::vec3( positions[ p[j]->v ] );
vert.texcoord = glm::vec2( texcoords[ p[j]->vt ] );
vert.normal = ( p[j]->vn != 0 ? normals[ p[j]->vn ] : faceNormal );
verts.push_back( vert );
}
}
}
}
return verts;
}
int btn;
glm::ivec2 startMouse;
glm::ivec2 startRot, curRot;
glm::ivec2 startTrans, curTrans;
void mouse(int button, int state, int x, int y )
{
if( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN )
{
btn = button;
startMouse = glm::ivec2( x, glutGet( GLUT_WINDOW_HEIGHT ) - y );
startRot = curRot;
}
if( button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN )
{
btn = button;
startMouse = glm::ivec2( x, glutGet( GLUT_WINDOW_HEIGHT ) - y );
startTrans = curTrans;
}
}
void motion( int x, int y )
{
glm::ivec2 curMouse( x, glutGet( GLUT_WINDOW_HEIGHT ) - y );
if( btn == GLUT_LEFT_BUTTON )
{
curRot = startRot + ( curMouse - startMouse );
}
else if( btn == GLUT_RIGHT_BUTTON )
{
curTrans = startTrans + ( curMouse - startMouse );
}
glutPostRedisplay();
}
std::vector< Vertex > model;
void display()
{
glClearColor( 0.2f, 0.2f, 0.2f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
double ar = w / h;
glTranslatef( curTrans.x / w * 2, curTrans.y / h * 2, 0 );
gluPerspective( 60, ar, 0.1, 100 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glTranslatef( 0, 0, -10 );
glPushMatrix();
{
glRotatef( curRot.x % 360, 0, 1, 0 );
glRotatef( -curRot.y % 360, 1, 0, 0 );
// object
glColor3ub( 255, 0, 0 );
glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glEnableClientState( GL_NORMAL_ARRAY );
glVertexPointer( 3, GL_FLOAT, sizeof(Vertex), &model[0].position );
glTexCoordPointer( 2, GL_FLOAT, sizeof(Vertex), &model[0].texcoord );
glNormalPointer( GL_FLOAT, sizeof(Vertex), &model[0].normal );
glDrawArrays( GL_TRIANGLES, 0, model.size() );
glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
glDisableClientState( GL_NORMAL_ARRAY );
// bounding cube
glDisable( GL_LIGHTING );
glColor3ub( 255, 255, 255 );
glutWireCube( 7 );
glEnable( GL_LIGHTING );
}
glPopMatrix();
glutSwapBuffers();
}
// return the min/max points of pts
template< typename Vec >
std::pair< Vec, Vec > GetExtents( const Vec* pts, size_t stride, size_t count )
{
unsigned char* base = (unsigned char*)pts;
Vec pmin( *(Vec*)base );
Vec pmax( *(Vec*)base );
for( size_t i = 0; i < count; ++i, base += stride )
{
const Vec& pt = *(Vec*)base;
pmin = glm::min( pmin, pt );
pmax = glm::max( pmax, pt );
}
return std::make_pair( pmin, pmax );
}
// centers geometry around the origin
// and scales it to fit in a size^3 box
template< typename Vec >
void CenterAndScale( Vec* pts, size_t stride, size_t count, const typename Vec::value_type& size )
{
typedef typename Vec::value_type Scalar;
// get min/max extents
std::pair< Vec, Vec > exts = GetExtents( pts, stride, count );
// center and scale
const Vec center = ( exts.first * Scalar( 0.5 ) ) + ( exts.second * Scalar( 0.5f ) );
const Scalar factor = size / glm::compMax( exts.second - exts.first );
unsigned char* base = (unsigned char*)pts;
for( size_t i = 0; i < count; ++i, base += stride )
{
Vec& pt = *(Vec*)base;
pt = ( ( pt - center ) * factor );
}
}
int main( int argc, char **argv )
{
// https://en.wikipedia.org/wiki/Stanford_bunny
std::ifstream ifile( "bunny.obj" );
model = LoadOBJ( ifile );
CenterAndScale( &model[0].position, sizeof( Vertex ), model.size(), 7 );
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
glutInitWindowSize( 640, 480 );
glutCreateWindow( "OBJ" );
glutDisplayFunc( display );
glutMouseFunc( mouse );
glutMotionFunc( motion );
glEnable( GL_DEPTH_TEST );
// set up "headlamp"-like light
glShadeModel( GL_SMOOTH );
glEnable( GL_COLOR_MATERIAL );
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ) ;
glEnable( GL_LIGHTING );
glEnable( GL_LIGHT0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
GLfloat position[] = { 0, 0, 1, 0 };
glLightfv( GL_LIGHT0, GL_POSITION, position );
glPolygonMode( GL_FRONT, GL_FILL );
glPolygonMode( GL_BACK, GL_LINE );
glutMainLoop();
return 0;
}
LMB-drag rotates, RMB-drag "pans".
And use this:
v 0.000000 2.000000 2.000000
v 0.000000 0.000000 2.000000
v 2.000000 0.000000 2.000000
v 2.000000 2.000000 2.000000
f -4 -3 -2 -1
v 2.000000 2.000000 0.000000
v 2.000000 0.000000 0.000000
v 0.000000 0.000000 0.000000
v 0.000000 2.000000 0.000000
f -4 -3 -2 -1
v 2.000000 2.000000 2.000000
v 2.000000 0.000000 2.000000
v 2.000000 0.000000 0.000000
v 2.000000 2.000000 0.000000
f -4 -3 -2 -1
v 0.000000 2.000000 0.000000
v 0.000000 2.000000 2.000000
v 2.000000 2.000000 2.000000
v 2.000000 2.000000 0.000000
f -4 -3 -2 -1
v 0.000000 2.000000 0.000000
v 0.000000 0.000000 0.000000
v 0.000000 0.000000 2.000000
v 0.000000 2.000000 2.000000
f -4 -3 -2 -1
v 0.000000 0.000000 2.000000
v 0.000000 0.000000 0.000000
v 2.000000 0.000000 0.000000
v 2.000000 0.000000 2.000000
f -4 -3 -2 -1
Or this:
v 0.000000 2.000000 0.000000
v 0.000000 0.000000 0.000000
v 2.000000 0.000000 0.000000
v 2.000000 2.000000 0.000000
v 4.000000 0.000000 -1.255298
v 4.000000 2.000000 -1.255298
vn 0.000000 0.000000 1.000000
vn 0.000000 0.000000 1.000000
vn 0.276597 0.000000 0.960986
vn 0.276597 0.000000 0.960986
vn 0.531611 0.000000 0.846988
vn 0.531611 0.000000 0.846988
# 6 vertices
# 6 normals
g all
s 1
f 1//1 2//2 3//3 4//4
f 4//4 3//3 5//5 6//6
# 2 elements
for test.obj
.
glm.hpp
is from the GLM library.
相关文章