OpenSceneGraph实现的NeHe OpenGL教程 - 第三十一课

  • 简介

本节课实现了加载Milkshape3D建模生成的文件,本课的大部分内容主要是分析Milkshape3D的模型文件格式

  • 实现

本课中的读取文件的内容大部分来自NeHe课程中的代码:

主要加载文件的代码在以下函数之中:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. virtual bool loadModelData( const char *filename )  

其他的部分在前面课程中已经详细地介绍过了,具体读者可以查看代码:

编译运行程序:

附:本课源码(源码中可能存在错误和不足,仅供参考)


[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include "../osgNeHe.h"  
  2.   
  3. #include <iostream>  
  4. #include <fstream>  
  5.   
  6. #include <QtCore/QTimer>  
  7. #include <QtGui/QApplication>  
  8. #include <QtGui/QVBoxLayout>  
  9.   
  10. #include <osgViewer/Viewer>  
  11. #include <osgDB/ReadFile>  
  12. #include <osgQt/GraphicsWindowQt>  
  13.   
  14. #include <osg/MatrixTransform>  
  15. #include <osg/Texture2D>  
  16. #include <osg/Material>  
  17. #include <osg/AnimationPath>  
  18. using namespace std;  
  19.   
  20.   
  21. //  
  22. ///File From NeHe Tutorial//  
  23. //  
  24.   
  25. osg::Texture2D * LoadGLTexture( const char *filename )  
  26. {  
  27.     osg::Image *textureImage = osgDB::readImageFile(filename);  
  28.     osg::Texture2D *texture2D = new osg::Texture2D;  
  29.     texture2D->setImage(textureImage);  
  30.     texture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);  
  31.     texture2D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);  
  32.   
  33.     return texture2D;  
  34. }  
  35.   
  36. class Model  
  37. {  
  38.     public:  
  39.         struct Mesh  
  40.         {  
  41.             int m_materialIndex;  
  42.             int m_numTriangles;  
  43.             int *m_pTriangleIndices;  
  44.         };  
  45.         struct Material  
  46.         {  
  47.             float m_ambient[4], m_diffuse[4], m_specular[4], m_emissive[4];  
  48.             float m_shininess;  
  49.             osg::Texture2D *m_texture;  
  50.             char *m_pTextureFilename;  
  51.         };  
  52.         struct Triangle  
  53.         {  
  54.             float m_vertexNormals[3][3];  
  55.             float m_s[3], m_t[3];  
  56.             int m_vertexIndices[3];  
  57.         };  
  58.         struct Vertex  
  59.         {  
  60.             char m_boneID;  
  61.             float m_location[3];  
  62.         };  
  63.   
  64.     public:  
  65.         Model()  
  66.         {  
  67.             m_numMeshes = 0;  
  68.             m_pMeshes = NULL;  
  69.             m_numMaterials = 0;  
  70.             m_pMaterials = NULL;  
  71.             m_numTriangles = 0;  
  72.             m_pTriangles = NULL;  
  73.             m_numVertices = 0;  
  74.             m_pVertices = NULL;  
  75.         }  
  76.         virtual ~Model()  
  77.         {  
  78.             int i;  
  79.             for ( i = 0; i < m_numMeshes; i++ )  
  80.                 delete[] m_pMeshes[i].m_pTriangleIndices;  
  81.             for ( i = 0; i < m_numMaterials; i++ )  
  82.                 delete[] m_pMaterials[i].m_pTextureFilename;  
  83.   
  84.             m_numMeshes = 0;  
  85.             if ( m_pMeshes != NULL )  
  86.             {  
  87.                 delete[] m_pMeshes;  
  88.                 m_pMeshes = NULL;  
  89.             }  
  90.   
  91.             m_numMaterials = 0;  
  92.             if ( m_pMaterials != NULL )  
  93.             {  
  94.                 delete[] m_pMaterials;  
  95.                 m_pMaterials = NULL;  
  96.             }  
  97.   
  98.             m_numTriangles = 0;  
  99.             if ( m_pTriangles != NULL )  
  100.             {  
  101.                 delete[] m_pTriangles;  
  102.                 m_pTriangles = NULL;  
  103.             }  
  104.   
  105.             m_numVertices = 0;  
  106.             if ( m_pVertices != NULL )  
  107.             {  
  108.                 delete[] m_pVertices;  
  109.                 m_pVertices = NULL;  
  110.             }  
  111.         }  
  112.         virtual bool loadModelData( const char *filename ) = 0;  
  113.   
  114.         osg::Geode* drawGeode()  
  115.         {  
  116.             osg::Geode *geode = new osg::Geode;  
  117.             geode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);  
  118.   
  119.             for ( int i = 0; i < m_numMeshes; i++ )  
  120.             {  
  121.                 osg::Geometry *geometry = new osg::Geometry;  
  122.                 osg::Vec3Array *vertexArray = new osg::Vec3Array;  
  123.                 osg::Vec2Array *textureArray = new osg::Vec2Array;  
  124.                 osg::Vec3Array *normalArray = new osg::Vec3Array;  
  125.   
  126.                 int materialIndex = m_pMeshes[i].m_materialIndex;  
  127.                 if ( materialIndex >= 0 )  
  128.                 {  
  129.                     osg::Material *material = new osg::Material;  
  130.                     material->setAmbient(osg::Material::FRONT,osg::Vec4(m_pMaterials[materialIndex].m_ambient[0], m_pMaterials[materialIndex].m_ambient[1],m_pMaterials[materialIndex].m_ambient[2],m_pMaterials[materialIndex].m_ambient[3]));  
  131.                     material->setDiffuse(osg::Material::FRONT,osg::Vec4(m_pMaterials[materialIndex].m_diffuse[0],m_pMaterials[materialIndex].m_diffuse[1],m_pMaterials[materialIndex].m_diffuse[2],m_pMaterials[materialIndex].m_diffuse[3]));  
  132.                     material->setEmission(osg::Material::FRONT,osg::Vec4(m_pMaterials[materialIndex].m_emissive[0],m_pMaterials[materialIndex].m_emissive[1],m_pMaterials[materialIndex].m_emissive[2],m_pMaterials[materialIndex].m_emissive[3]));  
  133.                     material->setSpecular(osg::Material::FRONT,osg::Vec4(m_pMaterials[materialIndex].m_specular[0],m_pMaterials[materialIndex].m_specular[1],m_pMaterials[materialIndex].m_specular[2],m_pMaterials[materialIndex].m_specular[3]));  
  134.                     material->setShininess(osg::Material::FRONT, m_pMaterials[materialIndex].m_shininess);  
  135.                     geometry->getOrCreateStateSet()->setAttributeAndModes(material);  
  136.   
  137.                     if ( m_pMaterials[materialIndex].m_texture > 0 )  
  138.                     {  
  139.                         geometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, m_pMaterials[materialIndex].m_texture);  
  140.                     }  
  141.                 }  
  142.   
  143.                 for ( int j = 0; j < m_pMeshes[i].m_numTriangles; j++ )  
  144.                 {  
  145.                     int triangleIndex = m_pMeshes[i].m_pTriangleIndices[j];  
  146.                     const Triangle* pTri = &m_pTriangles[triangleIndex];  
  147.   
  148.                     for ( int k = 0; k < 3; k++ )  
  149.                     {  
  150.                         int index = pTri->m_vertexIndices[k];  
  151.                         normalArray->push_back(osg::Vec3(pTri->m_vertexNormals[k][0], pTri->m_vertexNormals[k][1], pTri->m_vertexNormals[k][2]));  
  152.                         textureArray->push_back(osg::Vec2(pTri->m_s[k], pTri->m_t[k]));  
  153.                         vertexArray->push_back(osg::Vec3(m_pVertices[index].m_location[0], m_pVertices[index].m_location[1], m_pVertices[index].m_location[2]));  
  154.                     }  
  155.                 }  
  156.   
  157.                 geometry->setVertexArray(vertexArray);  
  158.                 geometry->setNormalArray(normalArray, osg::Array::BIND_PER_VERTEX);  
  159.                 geometry->setTexCoordArray(0, textureArray, osg::Array::BIND_PER_VERTEX);  
  160.                 geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, 0, vertexArray->size()));  
  161.   
  162.                 geode->addDrawable(geometry);  
  163.             }  
  164.   
  165.             return geode;  
  166.         }  
  167.   
  168.         void reloadTextures()  
  169.         {  
  170.             for ( int i = 0; i < m_numMaterials; i++ )  
  171.                 if ( strlen( m_pMaterials[i].m_pTextureFilename ) > 0 )  
  172.                     m_pMaterials[i].m_texture = LoadGLTexture( m_pMaterials[i].m_pTextureFilename );  
  173.                 else  
  174.                     m_pMaterials[i].m_texture = 0;  
  175.         }  
  176.     protected:  
  177.         int m_numMeshes;  
  178.         Mesh *m_pMeshes;  
  179.         int m_numMaterials;  
  180.         Material *m_pMaterials;  
  181.         int m_numTriangles;  
  182.         Triangle *m_pTriangles;  
  183.         int m_numVertices;  
  184.         Vertex *m_pVertices;  
  185. };  
  186.   
  187.   
  188. //  
  189.   
  190. #ifdef _MSC_VER  
  191. #   pragma pack( push, packing )  
  192. #   pragma pack( 1 )  
  193. #   define PACK_STRUCT  
  194. #elif defined( __GNUC__ )  
  195. #   define PACK_STRUCT  __attribute__((packed))  
  196. #else  
  197. #   error you must byte-align these structures with the appropriate compiler directives  
  198. #endif  
  199.   
  200. typedef unsigned short word;  
  201.   
  202. // File header  
  203. struct MS3DHeader  
  204. {  
  205.     char m_ID[10];  
  206.     int m_version;  
  207. } PACK_STRUCT;  
  208.   
  209. // Vertex information  
  210. struct MS3DVertex  
  211. {  
  212.     char m_flags;  
  213.     float m_vertex[3];  
  214.     char m_boneID;  
  215.     char m_refCount;  
  216. } PACK_STRUCT;  
  217.   
  218. // Triangle information  
  219. struct MS3DTriangle  
  220. {  
  221.     word m_flags;  
  222.     word m_vertexIndices[3];  
  223.     float m_vertexNormals[3][3];  
  224.     float m_s[3], m_t[3];  
  225.     char m_smoothingGroup;  
  226.     char m_groupIndex;  
  227. } PACK_STRUCT;  
  228.   
  229. // Material information  
  230. struct MS3DMaterial  
  231. {  
  232.     char m_name[32];  
  233.     float m_ambient[4];  
  234.     float m_diffuse[4];  
  235.     float m_specular[4];  
  236.     float m_emissive[4];  
  237.     float m_shininess;  // 0.0f - 128.0f  
  238.     float m_transparency;   // 0.0f - 1.0f  
  239.     char m_mode;    // 0, 1, 2 is unused now  
  240.     char m_texture[128];  
  241.     char m_alphamap[128];  
  242. } PACK_STRUCT;  
  243.   
  244. //  Joint information  
  245. struct MS3DJoint  
  246. {  
  247.     char m_flags;  
  248.     char m_name[32];  
  249.     char m_parentName[32];  
  250.     float m_rotation[3];  
  251.     float m_translation[3];  
  252.     word m_numRotationKeyframes;  
  253.     word m_numTranslationKeyframes;  
  254. } PACK_STRUCT;  
  255.   
  256. // Keyframe data  
  257. struct MS3DKeyframe  
  258. {  
  259.     float m_time;  
  260.     float m_parameter[3];  
  261. } PACK_STRUCT;  
  262.   
  263. // Default alignment  
  264. #ifdef _MSC_VER  
  265. #   pragma pack( pop, packing )  
  266. #endif  
  267.   
  268. #undef PACK_STRUCT  
  269.   
  270.   
  271. class MilkshapeModel : public Model  
  272. {  
  273.     public:  
  274.         MilkshapeModel()  
  275.         {  
  276.         }  
  277.         virtual ~MilkshapeModel()  
  278.         {  
  279.         }  
  280.         virtual bool loadModelData( const char *filename )  
  281.         {  
  282.             ifstream inputFile( filename, ios::in | ios::binary | ios::_Nocreate );  
  283.             if ( inputFile.fail())  
  284.                 return false;  
  285.   
  286.             inputFile.seekg( 0, ios::end );  
  287.             long fileSize = inputFile.tellg();  
  288.             inputFile.seekg( 0, ios::beg );  
  289.   
  290.             char *pBuffer = new char[fileSize];  
  291.             inputFile.read( pBuffer, fileSize );  
  292.             inputFile.close();  
  293.   
  294.             const char *pPtr = pBuffer;  
  295.             MS3DHeader *pHeader = ( MS3DHeader* )pPtr;  
  296.             pPtr += sizeof( MS3DHeader );  
  297.   
  298.             if ( strncmp( pHeader->m_ID, "MS3D000000", 10 ) != 0 )  
  299.                 return false// "Not a valid Milkshape3D model file."  
  300.   
  301.             if ( pHeader->m_version < 3 || pHeader->m_version > 4 )  
  302.                 return false// "Unhandled file version. Only Milkshape3D Version 1.3 and 1.4 is supported." );  
  303.   
  304.             int nVertices = *( word* )pPtr;   
  305.             m_numVertices = nVertices;  
  306.             m_pVertices = new Vertex[nVertices];  
  307.             pPtr += sizeof( word );  
  308.   
  309.             int i;  
  310.             for ( i = 0; i < nVertices; i++ )  
  311.             {  
  312.                 MS3DVertex *pVertex = ( MS3DVertex* )pPtr;  
  313.                 m_pVertices[i].m_boneID = pVertex->m_boneID;  
  314.                 memcpy( m_pVertices[i].m_location, pVertex->m_vertex, sizeoffloat )*3 );  
  315.                 pPtr += sizeof( MS3DVertex );  
  316.             }  
  317.   
  318.             int nTriangles = *( word* )pPtr;  
  319.             m_numTriangles = nTriangles;  
  320.             m_pTriangles = new Triangle[nTriangles];  
  321.             pPtr += sizeof( word );  
  322.   
  323.             for ( i = 0; i < nTriangles; i++ )  
  324.             {  
  325.                 MS3DTriangle *pTriangle = ( MS3DTriangle* )pPtr;  
  326.                 int vertexIndices[3] = { pTriangle->m_vertexIndices[0], pTriangle->m_vertexIndices[1], pTriangle->m_vertexIndices[2] };  
  327.                 float t[3] = { 1.0f-pTriangle->m_t[0], 1.0f-pTriangle->m_t[1], 1.0f-pTriangle->m_t[2] };  
  328.                 memcpy( m_pTriangles[i].m_vertexNormals, pTriangle->m_vertexNormals, sizeoffloat )*3*3 );  
  329.                 memcpy( m_pTriangles[i].m_s, pTriangle->m_s, sizeoffloat )*3 );  
  330.                 memcpy( m_pTriangles[i].m_t, t, sizeoffloat )*3 );  
  331.                 memcpy( m_pTriangles[i].m_vertexIndices, vertexIndices, sizeofint )*3 );  
  332.                 pPtr += sizeof( MS3DTriangle );  
  333.             }  
  334.   
  335.             int nGroups = *( word* )pPtr;  
  336.             m_numMeshes = nGroups;  
  337.             m_pMeshes = new Mesh[nGroups];  
  338.             pPtr += sizeof( word );  
  339.             for ( i = 0; i < nGroups; i++ )  
  340.             {  
  341.                 pPtr += sizeofchar ); // flags  
  342.                 pPtr += 32;             // name  
  343.   
  344.                 word nTriangles = *( word* )pPtr;  
  345.                 pPtr += sizeof( word );  
  346.                 int *pTriangleIndices = new int[nTriangles];  
  347.                 for ( int j = 0; j < nTriangles; j++ )  
  348.                 {  
  349.                     pTriangleIndices[j] = *( word* )pPtr;  
  350.                     pPtr += sizeof( word );  
  351.                 }  
  352.   
  353.                 char materialIndex = *( char* )pPtr;  
  354.                 pPtr += sizeofchar );  
  355.   
  356.                 m_pMeshes[i].m_materialIndex = materialIndex;  
  357.                 m_pMeshes[i].m_numTriangles = nTriangles;  
  358.                 m_pMeshes[i].m_pTriangleIndices = pTriangleIndices;  
  359.             }  
  360.   
  361.             int nMaterials = *( word* )pPtr;  
  362.             m_numMaterials = nMaterials;  
  363.             m_pMaterials = new Material[nMaterials];  
  364.             pPtr += sizeof( word );  
  365.             for ( i = 0; i < nMaterials; i++ )  
  366.             {  
  367.                 MS3DMaterial *pMaterial = ( MS3DMaterial* )pPtr;  
  368.                 memcpy( m_pMaterials[i].m_ambient, pMaterial->m_ambient, sizeoffloat )*4 );  
  369.                 memcpy( m_pMaterials[i].m_diffuse, pMaterial->m_diffuse, sizeoffloat )*4 );  
  370.                 memcpy( m_pMaterials[i].m_specular, pMaterial->m_specular, sizeoffloat )*4 );  
  371.                 memcpy( m_pMaterials[i].m_emissive, pMaterial->m_emissive, sizeoffloat )*4 );  
  372.                 m_pMaterials[i].m_shininess = pMaterial->m_shininess;  
  373.                 m_pMaterials[i].m_pTextureFilename = new char[strlen( pMaterial->m_texture )+1];  
  374.                 strcpy( m_pMaterials[i].m_pTextureFilename, pMaterial->m_texture );  
  375.                 pPtr += sizeof( MS3DMaterial );  
  376.             }  
  377.   
  378.             reloadTextures();  
  379.   
  380.             delete[] pBuffer;  
  381.   
  382.             return true;  
  383.         }  
  384. };  
  385.   
  386.   
  387. class ViewerWidget : public QWidget, public osgViewer::Viewer  
  388. {  
  389. public:  
  390.     ViewerWidget(osg::Node *scene = NULL)  
  391.     {  
  392.         QWidget* renderWidget = getRenderWidget( createGraphicsWindow(0,0,100,100), scene);  
  393.   
  394.         QVBoxLayout* layout = new QVBoxLayout;  
  395.         layout->addWidget(renderWidget);  
  396.         layout->setContentsMargins(0, 0, 0, 1);  
  397.         setLayout( layout );  
  398.   
  399.         connect( &_timer, SIGNAL(timeout()), this, SLOT(update()) );  
  400.         _timer.start( 10 );  
  401.     }  
  402.   
  403.     QWidget* getRenderWidget( osgQt::GraphicsWindowQt* gw, osg::Node* scene )  
  404.     {  
  405.         osg::Camera* camera = this->getCamera();  
  406.         camera->setGraphicsContext( gw );  
  407.   
  408.         const osg::GraphicsContext::Traits* traits = gw->getTraits();  
  409.   
  410.         camera->setClearColor( osg::Vec4(0.0, 0.0, 0.0, 1.0) );  
  411.         camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) );  
  412.         camera->setProjectionMatrixAsPerspective(45.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 0.1f, 100.0f );  
  413.         camera->setViewMatrixAsLookAt(osg::Vec3d(75, 75, 75), osg::Vec3d(0, 0, 0), osg::Vec3d(0, 1, 0));  
  414.   
  415.         this->setSceneData( scene );  
  416.   
  417.         return gw->getGLWidget();  
  418.     }  
  419.   
  420.     osgQt::GraphicsWindowQt* createGraphicsWindow( int x, int y, int w, int h, const std::string& name=""bool windowDecoration=false )  
  421.     {  
  422.         osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();  
  423.         osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;  
  424.         traits->windowName = name;  
  425.         traits->windowDecoration = windowDecoration;  
  426.         traits->x = x;  
  427.         traits->y = y;  
  428.         traits->width = w;  
  429.         traits->height = h;  
  430.         traits->doubleBuffer = true;  
  431.         traits->alpha = ds->getMinimumNumAlphaBits();  
  432.         traits->stencil = ds->getMinimumNumStencilBits();  
  433.         traits->sampleBuffers = ds->getMultiSamples();  
  434.         traits->samples = ds->getNumMultiSamples();  
  435.   
  436.         return new osgQt::GraphicsWindowQt(traits.get());  
  437.     }  
  438.   
  439.     virtual void paintEvent( QPaintEvent* event )  
  440.     {   
  441.         frame();   
  442.     }  
  443.   
  444. protected:  
  445.   
  446.     QTimer _timer;  
  447. };  
  448.   
  449.   
  450. osg::Node*  buildScene()  
  451. {  
  452.     Model *pModel = new MilkshapeModel();                     
  453.     pModel->loadModelData( "Data/model.ms3d");  
  454.     pModel->reloadTextures();  
  455.   
  456.     osg::Group *root = new osg::Group;  
  457.     osg::MatrixTransform *rotYMT = new osg::MatrixTransform;  
  458.     rotYMT->addUpdateCallback(new osg::AnimationPathCallback(osg::Vec3(), osg::Y_AXIS, 2.5));  
  459.     rotYMT->addChild(pModel->drawGeode());  
  460.     root->addChild(rotYMT);  
  461.   
  462.     return root;  
  463. }  
  464.   
  465.   
  466. int main( int argc, char** argv )  
  467. {  
  468.     QApplication app(argc, argv);  
  469.     ViewerWidget* viewWidget = new ViewerWidget(buildScene());  
  470.     viewWidget->setGeometry( 100, 100, 640, 480 );  
  471.     viewWidget->show();  
  472.     return app.exec();  
  473. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值