我已经查看了Glui包中的示例,但我需要有关加载(.m)文件的帮助,这是3D模型 这是示例代码....
#include <iostream>
#include <GL/glut.h>
#include <cstdlib>
using namespace std;
void createMenu(void);
void menu(int value);
void disp(void);
static int win;
static int menid;
static int submenid;
static int primitive = 0; // global variable for the geometric primitive
int main(int argc, char **argv){
// normal initialisation
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE);
glutInitWindowSize(500,500);
glutInitWindowPosition(100,100);
win = glutCreateWindow("GLUT MENU");
// put all the menu functions in one nice procedure
createMenu();
// set the clearcolor and the callback
glClearColor(0.0,0.0,0.0,0.0);
// register your drawing function
glutDisplayFunc(disp);
// enter the main loop
glutMainLoop();
return 1;
}
//#define USE_SUB_MENU
void createMenu(void){
//#ifdef USE_SUB_MENU
// step 1: Create a submenu, this has to be done first.
submenid = glutCreateMenu(menu); // pass the function "menu" to glutCreateMenu
// Add sub menu entry
glutAddMenuEntry("Teapot", 2);
glutAddMenuEntry("Cube", 3);
glutAddMenuEntry("Torus", 4);
// step 2: Create the main menu, this menu becomes the current menu
menid = glutCreateMenu(menu);
// Create an entry
glutAddMenuEntry("Clear", 1);
glutAddSubMenu("Draw", submenid);
// Create an entry
glutAddMenuEntry("Quit", 0);
// Let the menu respond on the right mouse button
glutAttachMenu(GLUT_RIGHT_BUTTON);
//#else
menid = glutCreateMenu(menu);
// Create an entry
glutAddMenuEntry("Clear", 1);
glutAddMenuEntry("Teapot", 2);
glutAddMenuEntry("Cube", 3);
glutAddMenuEntry("Torus", 4);
// Create an entry
glutAddMenuEntry("Quit", 0);
// Let the menu respond on the right mouse button
glutAttachMenu(GLUT_RIGHT_BUTTON);
//#endif
}
void disp(void){
// Just clean the screen
// this has to be called everytime when you draw sth
glClear(GL_COLOR_BUFFER_BIT);
// draw what the user asked
if(primitive == 1){ // clear the screen
glutPostRedisplay();
}else if(primitive == 2){ // draw the teapot
glutWireTeapot(0.5);
}else if(primitive == 3){ // draw the cube
glutWireCube(0.5);
}else if(primitive == 4){ // draw the torus
glutWireTorus(0.3,0.6,100,100);
}
glFlush();
}
void menu(int value){
if(value == 0){ // the user clicks 'quit'
glutDestroyWindow(win);
exit(0);
}else{
primitive=value; // set the geometric primitive
}
// you would want to redraw now
glutPostRedisplay();
}
我真的不知道如何做T_T,要求是使用opengl,glut,glui加载.m文件....所以,我需要帮助才能用opengl加载它而不会崩溃然后完成。
答案 0 :(得分:1)
你需要一个.M文件的解析器。
我无法在任何地方找到规格,所以我对格式进行了猜测:
#include <glm/glm.hpp>
using namespace glm;
struct Vertex
{
vec3 position;
vec3 normal;
};
vector< Vertex > LoadM( istream& in )
{
vector< Vertex > verts;
map< int, vec3 > positions;
map< int, vec3 > normals;
string lineStr;
while( getline( in, lineStr ) )
{
istringstream lineSS( lineStr );
string lineType;
lineSS >> lineType;
// vertex
if( lineType == "Vertex" )
{
int idx;
float x = 0, y = 0, z = 0;
lineSS >> idx >> x >> y >> z;
positions[ idx ] = vec3( x, y, z );
}
// face
if( lineType == "Face" )
{
int indexes[ 3 ];
int idx;
lineSS >> idx >> indexes[0] >> indexes[1] >> indexes[2];
// http://www.opengl.org/wiki/Calculating_a_Surface_Normal
vec3 U( positions[ indexes[1] ] - positions[ indexes[0] ] );
vec3 V( positions[ indexes[2] ] - positions[ indexes[0] ] );
vec3 faceNormal = normalize( cross( U, V ) );
for( size_t j = 0; j < 3; ++j )
{
Vertex vert;
vert.position = vec3( positions[ indexes[j] ] );
vert.normal = faceNormal;
verts.push_back( vert );
}
}
}
return verts;
}
在上下文中使用:
#include <GL/glut.h>
#include <glm/glm.hpp>
#include <glm/gtx/component_wise.hpp>
#include <vector>
#include <map>
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
using namespace glm;
struct Vertex
{
vec3 position;
vec3 normal;
};
vector< Vertex > LoadM( istream& in )
{
vector< Vertex > verts;
map< int, vec3 > positions;
string lineStr;
while( getline( in, lineStr ) )
{
istringstream lineSS( lineStr );
string lineType;
lineSS >> lineType;
// parse vertex line
if( lineType == "Vertex" )
{
int idx = 0;
float x = 0, y = 0, z = 0;
lineSS >> idx >> x >> y >> z;
positions.insert( make_pair( idx, vec3( x, y, z ) ) );
}
// parse face line
if( lineType == "Face" )
{
int indexes[ 3 ] = { 0 };
int idx = 0;
lineSS >> idx >> indexes[0] >> indexes[1] >> indexes[2];
// http://www.opengl.org/wiki/Calculating_a_Surface_Normal
vec3 U( positions[ indexes[1] ] - positions[ indexes[0] ] );
vec3 V( positions[ indexes[2] ] - positions[ indexes[0] ] );
vec3 faceNormal = normalize( cross( U, V ) );
for( size_t j = 0; j < 3; ++j )
{
Vertex vert;
vert.position = vec3( positions[ indexes[j] ] );
vert.normal = faceNormal;
verts.push_back( vert );
}
}
}
return verts;
}
// mouse state
int btn;
ivec2 startMouse;
ivec2 startRot, curRot;
ivec2 startTrans, curTrans;
void mouse(int button, int state, int x, int y )
{
y = glutGet( GLUT_WINDOW_HEIGHT ) - y;
if( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN )
{
btn = button;
startMouse = ivec2( x, y );
startRot = curRot;
}
if( button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN )
{
btn = button;
startMouse = ivec2( x, y );
startTrans = curTrans;
}
}
void motion( int x, int y )
{
y = glutGet( GLUT_WINDOW_HEIGHT ) - y;
ivec2 curMouse( x, y );
if( btn == GLUT_LEFT_BUTTON )
{
curRot = startRot + ( curMouse - startMouse );
}
else if( btn == GLUT_RIGHT_BUTTON )
{
curTrans = startTrans + ( curMouse - startMouse );
}
glutPostRedisplay();
}
vector< Vertex > model;
void display()
{
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;
// "pan"
glTranslatef( curTrans.x / w * 2, curTrans.y / h * 2, 0 );
gluPerspective( 60, ar, 0.1, 20 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glTranslatef( 0, 0, -10 );
glPushMatrix();
// apply mouse rotation
glRotatef( curRot.x % 360, 0, 1, 0 );
glRotatef( -curRot.y % 360, 1, 0, 0 );
glColor3ub( 255, 0, 0 );
// draw model
glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_NORMAL_ARRAY );
glVertexPointer( 3, GL_FLOAT, sizeof(Vertex), &model[0].position );
glNormalPointer( GL_FLOAT, sizeof(Vertex), &model[0].normal );
glDrawArrays( GL_TRIANGLES, 0, model.size() );
glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_NORMAL_ARRAY );
// draw bounding cube
glDisable( GL_LIGHTING );
glColor3ub( 255, 255, 255 );
glutWireCube( 7 );
glEnable( GL_LIGHTING );
glPopMatrix();
glutSwapBuffers();
}
// return the x/y/z min/max of some geometry
template< typename Vec >
pair< Vec, Vec > GetExtents
(
const Vec* pts,
size_t stride,
size_t count
)
{
typedef typename Vec::value_type Scalar;
Vec pmin( std::numeric_limits< Scalar >::max() );
Vec pmax( std::min( std::numeric_limits< Scalar >::min(),
(Scalar)-std::numeric_limits< Scalar >::max() ) );
// find extents
unsigned char* base = (unsigned char*)pts;
for( size_t i = 0; i < count; ++i )
{
const Vec& pt = *(Vec*)base;
pmin = glm::min( pmin, pt );
pmax = glm::max( pmax, pt );
base += stride;
}
return 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
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 )
{
Vec& pt = *(Vec*)base;
pt = ((pt - center) * factor);
base += stride;
}
}
int main( int argc, char **argv )
{
ifstream ifile( "bunny.m" );
model = LoadM( ifile );
if( model.empty() )
{
cerr << "Empty model!" << endl;
return -1;
}
CenterAndScale( &model[0].position, sizeof( Vertex ), model.size(), 7 );
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
glutInitWindowSize( 640, 480 );
glutCreateWindow( "GLUT" );
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;
}