-2

我查看了 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,glu加载.m文件......所以,我需要帮助才能用opengl加载它而不会崩溃然后完成。

4

1 回答 1

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;
}
于 2013-11-13T18:49:30.780 回答