worldsim/src/wmesh.cpp

00001 /********************************************************************************
00002  *  WorldSim -- library for robot simulations                                   *
00003  *  Copyright (C) 2008-2011 Gianluca Massera <emmegian@yahoo.it>                *
00004  *                                                                              *
00005  *  This program is free software; you can redistribute it and/or modify        *
00006  *  it under the terms of the GNU General Public License as published by        *
00007  *  the Free Software Foundation; either version 2 of the License, or           *
00008  *  (at your option) any later version.                                         *
00009  *                                                                              *
00010  *  This program is distributed in the hope that it will be useful,             *
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of              *
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               *
00013  *  GNU General Public License for more details.                                *
00014  *                                                                              *
00015  *  You should have received a copy of the GNU General Public License           *
00016  *  along with this program; if not, write to the Free Software                 *
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA  *
00018  ********************************************************************************/
00019 // Thanks to Brett Porter and Mete Ciragan for help with this MS3D model loading code
00020 // Thanks to Ronny A. Reierstad and Vadim Tikhanoff
00021 // www.morrowland.com
00022 // apron@morrowland.com
00023 
00024 #include "wmesh.h"
00025 
00026 //----------------------------------
00027 //--- MS3D STRUCTURES --------------
00028 // PACK_STRUCT : byte-align structures
00029 #ifdef _MSC_VER
00030     #pragma pack( push, packing )
00031     #pragma pack( 1 )
00032     #define PACK_STRUCT
00033     #ifndef PATH_MAX
00034         #define PATH_MAX _MAX_PATH
00035     #endif
00036 #elif defined( __GNUC__ )
00037     #define PACK_STRUCT __attribute__((packed))
00038     #include <limits.h>
00039 #else
00040     #error you must byte-align these structures with the appropriate compiler directives
00041 #endif
00042 
00043 namespace farsa {
00044 
00045 typedef unsigned char byte;
00046 typedef unsigned short word;
00047 // File Header
00048 struct MS3DHeader {
00049     char m_ID[10];
00050     int m_version;
00051 } PACK_STRUCT;
00052 // Vertex info
00053 struct MS3DVertex {
00054     byte m_flags;
00055     float m_vertex[3];
00056     char m_boneID;
00057     byte m_refCount;
00058 } PACK_STRUCT;
00059 // Triangle info
00060 struct MS3DTriangle {
00061     word m_flags;
00062     word m_vertexIndices[3];
00063     float m_vertexNormals[3][3];
00064     float m_s[3], m_t[3];
00065     byte m_smoothingGroup;
00066     byte m_groupIndex;
00067 } PACK_STRUCT;
00068 // Material info
00069 struct MS3DMaterial {
00070     static unsigned int Texture[15];
00071     char m_name[32];
00072     float m_ambient[4];
00073     float m_diffuse[4];
00074     float m_specular[4];
00075     float m_emissive[4];
00076     float m_shininess;                  // 0.0f - 128.0f
00077     float m_transparency;               // 0.0f - 1.0f
00078     byte m_mode;                        // 0, 1, 2 (unused now)
00079     char m_texture[128];
00080     char m_alphamap[128];
00081 } PACK_STRUCT;
00082 // back to Default alignment
00083 #ifdef _MSC_VER                         
00084     #pragma pack( pop, packing )
00085 #endif
00086 #undef PACK_STRUCT
00087 //--- MS3D STRUCTURES ENDS ---------
00088 //----------------------------------
00089 
00090 } // end namespace farsa
00091 
00092 #include "string.h"
00093 #include <QString>
00094 #include <QFile>
00095 #include <QImage>
00096 
00097 namespace farsa {
00098 
00099 WMesh::WMesh( World* world, QString name, const wMatrix& tm)
00100     : WObject( world, name, tm, false ) {
00101     m_numMeshes = 0;
00102     m_pMeshes = NULL;
00103     m_numMaterials = 0;
00104     m_pMaterials = NULL;
00105     m_numTriangles = 0;
00106     m_pTriangles = NULL;
00107     m_numVertices = 0;
00108     m_pVertices = NULL;
00109     attacho = NULL;
00110     world->pushObject( this );
00111 }
00112 
00113 WMesh::~WMesh() {
00114     int i;
00115     for ( i = 0; i < m_numMeshes; i++ ) {
00116         delete[] m_pMeshes[i].m_pTriangleIndices;
00117     }
00118     m_numMeshes = 0;
00119     if ( m_pMeshes != NULL ) {
00120         delete[] m_pMeshes;
00121         m_pMeshes = NULL;
00122     }
00123     m_numMaterials = 0;
00124     if ( m_pMaterials != NULL ) {
00125         delete[] m_pMaterials;
00126         m_pMaterials = NULL;
00127     }
00128     m_numTriangles = 0;
00129     if ( m_pTriangles != NULL ) {
00130         delete[] m_pTriangles;
00131         m_pTriangles = NULL;
00132     }
00133     m_numVertices = 0;
00134     if ( m_pVertices != NULL ) {
00135         delete[] m_pVertices;
00136         m_pVertices = NULL;
00137     }
00138 }
00139 
00140 void WMesh::attachTo( WObject* obj ) {
00141     this->attacho = obj;
00142 }
00143 
00144 bool WMesh::loadMS3DModel( QString filename ) {
00145     QFile inputFile( filename );
00146     if ( !inputFile.open( QIODevice::ReadOnly ) ) {
00147         return false;
00148     }
00149     QByteArray bBuffer = inputFile.readAll();
00150     const char *pPtr = bBuffer.data();
00151     MS3DHeader *pHeader = ( MS3DHeader* )pPtr;
00152     pPtr += sizeof( MS3DHeader );
00153     if ( strncmp( pHeader->m_ID, "MS3D000000", 10 ) != 0 ) {
00154          // "Not a valid Milkshape3D model file."
00155         return false;
00156     }
00157     if ( pHeader->m_version < 3 ) {
00158          // "Unhandled file version. Only Milkshape3D Version 1.3 and 1.4 is supported."
00159         return false;
00160     }
00161     int nVertices = *( word* )pPtr;
00162     m_numVertices = nVertices;
00163     m_pVertices = new Vertex[nVertices];
00164     pPtr += sizeof( word );
00165     int i;
00166     for ( i = 0; i < nVertices; i++ ) {
00167         MS3DVertex *pVertex = ( MS3DVertex* )pPtr;
00168         m_pVertices[i].m_boneID = pVertex->m_boneID;
00169         memcpy( m_pVertices[i].m_location, pVertex->m_vertex, sizeof( float )*3 );
00170         pPtr += sizeof( MS3DVertex );
00171     }
00172     int nTriangles = *( word* )pPtr;
00173     m_numTriangles = nTriangles;
00174     m_pTriangles = new Triangle[nTriangles];
00175     pPtr += sizeof( word );
00176     for ( i = 0; i < nTriangles; i++ ) {
00177         MS3DTriangle *pTriangle = ( MS3DTriangle* )pPtr;
00178         int vertexIndices[3] = { pTriangle->m_vertexIndices[0], pTriangle->m_vertexIndices[1], pTriangle->m_vertexIndices[2] };
00179         float t[3] = { 1.0f-pTriangle->m_t[0], 1.0f-pTriangle->m_t[1], 1.0f-pTriangle->m_t[2] };
00180         memcpy( m_pTriangles[i].m_vertexNormals, pTriangle->m_vertexNormals, sizeof( float )*3*3 );
00181         memcpy( m_pTriangles[i].m_s, pTriangle->m_s, sizeof( float )*3 );
00182         memcpy( m_pTriangles[i].m_t, t, sizeof( float )*3 );
00183         memcpy( m_pTriangles[i].m_vertexIndices, vertexIndices, sizeof( int )*3 );
00184         pPtr += sizeof( MS3DTriangle );
00185     }
00186     int nGroups = *( word* )pPtr;
00187     m_numMeshes = nGroups;
00188     m_pMeshes = new Mesh[nGroups];
00189     pPtr += sizeof( word );
00190     for ( i = 0; i < nGroups; i++ ) {
00191         pPtr += sizeof( byte ); // flags
00192         pPtr += 32;             // name
00193         word nTriangles = *( word* )pPtr;
00194         pPtr += sizeof( word );
00195         int *pTriangleIndices = new int[nTriangles];
00196         for ( int j = 0; j < nTriangles; j++ ) {
00197             pTriangleIndices[j] = *( word* )pPtr;
00198             pPtr += sizeof( word );
00199         }
00200         char materialIndex = *( char* )pPtr;
00201         pPtr += sizeof( char );
00202         m_pMeshes[i].m_materialIndex = materialIndex;
00203         m_pMeshes[i].m_numTriangles = nTriangles;
00204         m_pMeshes[i].m_pTriangleIndices = pTriangleIndices;
00205     }
00206     int nMaterials = *( word* )pPtr;
00207     m_numMaterials = nMaterials;
00208     m_pMaterials = new Material[nMaterials];
00209     pPtr += sizeof( word );
00210     for ( i = 0; i < nMaterials; i++ ) {
00211         MS3DMaterial *pMaterial = ( MS3DMaterial* )pPtr;
00212         memcpy( m_pMaterials[i].m_ambient, pMaterial->m_ambient, sizeof( float )*4 );
00213         memcpy( m_pMaterials[i].m_diffuse, pMaterial->m_diffuse, sizeof( float )*4 );
00214         memcpy( m_pMaterials[i].m_specular, pMaterial->m_specular, sizeof( float )*4 );
00215         memcpy( m_pMaterials[i].m_emissive, pMaterial->m_emissive, sizeof( float )*4 );
00216         m_pMaterials[i].m_shininess = pMaterial->m_shininess;
00217         m_pMaterials[i].m_pTextureFilename = QString( pMaterial->m_texture );
00218         pPtr += sizeof( MS3DMaterial );
00219     }
00220     return true;
00221 }
00222 
00223 } // end namespace farsa