Visualization Library v1.0.3A lightweight C++ OpenGL middleware for 2D/3D graphics |
[Download] [Tutorials] [All Classes] [Grouped Classes] |
00001 /**************************************************************************************/ 00002 /* */ 00003 /* Visualization Library */ 00004 /* http://visualizationlibrary.org */ 00005 /* */ 00006 /* Copyright (c) 2005-2010, Michele Bosi */ 00007 /* All rights reserved. */ 00008 /* */ 00009 /* Redistribution and use in source and binary forms, with or without modification, */ 00010 /* are permitted provided that the following conditions are met: */ 00011 /* */ 00012 /* - Redistributions of source code must retain the above copyright notice, this */ 00013 /* list of conditions and the following disclaimer. */ 00014 /* */ 00015 /* - Redistributions in binary form must reproduce the above copyright notice, this */ 00016 /* list of conditions and the following disclaimer in the documentation and/or */ 00017 /* other materials provided with the distribution. */ 00018 /* */ 00019 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ 00020 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ 00021 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ 00022 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ 00023 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ 00024 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ 00025 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ 00026 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ 00027 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ 00028 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 00029 /* */ 00030 /**************************************************************************************/ 00031 00032 #include "ioMD2.hpp" 00033 #include <vlCore/Time.hpp> 00034 #include <vlCore/Log.hpp> 00035 #include <vlCore/Say.hpp> 00036 #include <vlCore/VisualizationLibrary.hpp> 00037 #include <vlCore/FileSystem.hpp> 00038 #include <vlCore/LoadWriterManager.hpp> 00039 #include <vlGraphics/DoubleVertexRemover.hpp> 00040 00041 using namespace vl; 00042 00043 namespace 00044 { 00045 // MD2 structures and defines 00046 class LoaderMD2 00047 { 00048 public: 00049 LoaderMD2(): verbose(false) {} 00050 00051 enum { 00052 MD2_MAX_TRIANGLES = 4096, 00053 MD2_MAX_VERTICES = 2048, 00054 MD2_MAX_TEXCOORDS = 2048, 00055 MD2_MAX_FRAMES = 512, 00056 MD2_MAX_SKINS = 32, 00057 MD2_MAX_FRAMESIZE = MD2_MAX_VERTICES * 4 + 128 00058 }; 00059 00060 class md2_header_info 00061 { 00062 public: 00063 int magic; 00064 int version; 00065 int skinWidth; 00066 int skinHeight; 00067 int frameSize; 00068 int numSkins; 00069 int numVertices; 00070 int numTexCoords; 00071 int numTriangles; 00072 int numGlCommands; 00073 int numFrames; 00074 int offsetSkins; 00075 int offsetTexCoords; 00076 int offsetTriangles; 00077 int offsetFrames; 00078 int offsetGlCommands; 00079 int offsetEnd; 00080 }; 00081 00082 class md2_vertex_info 00083 { 00084 public: 00085 unsigned char vertex[3]; 00086 unsigned char light_norm_index; 00087 }; 00088 00089 class md2_triangle_info 00090 { 00091 public: 00092 short vert_idx[3]; 00093 short uv_idx[3]; 00094 }; 00095 00096 class md2_uv_info 00097 { 00098 public: 00099 short u, v; 00100 }; 00101 00102 class md2_frame_info 00103 { 00104 public: 00105 float scale[3]; 00106 float translate[3]; 00107 char name[16]; 00108 md2_vertex_info vertices[1]; 00109 }; 00110 00111 class md2_skin_info 00112 { 00113 public: 00114 unsigned char name[64]; 00115 }; 00116 00117 md2_header_info header; 00118 std::vector<md2_frame_info*> md2_frame; 00119 std::vector<md2_uv_info> md2_uv; 00120 std::vector<md2_triangle_info> md2_triangle; 00121 std::vector<md2_skin_info> md2_skin; 00122 bool verbose; 00123 }; 00124 } 00125 //----------------------------------------------------------------------------- 00126 ref<ResourceDatabase> vl::loadMD2(const String& path) 00127 { 00128 ref<VirtualFile> file = defFileSystem()->locateFile(path); 00129 00130 if (file) 00131 return loadMD2( file.get() ); 00132 else 00133 { 00134 Log::error( Say("Could not locate '%s'.\n") << path ); 00135 return NULL; 00136 } 00137 } 00138 //----------------------------------------------------------------------------- 00139 ref<ResourceDatabase> vl::loadMD2(VirtualFile* file) 00140 { 00141 ref<ResourceDatabase> res_db = new ResourceDatabase; 00142 ref<Geometry> geometry = new Geometry; 00143 res_db->resources().push_back( geometry.get() ); 00144 00145 if (!file->open(OM_ReadOnly)) 00146 { 00147 Log::error( Say("Error opening '%s'\n") << file->path() ); 00148 return NULL; 00149 } 00150 00151 LoaderMD2 loader; 00152 file->read( &loader.header, sizeof(loader.header) ); 00153 00154 if (loader.verbose) 00155 { 00156 Log::print( Say("tris %n:\n") << loader.header.numTriangles); 00157 Log::print( Say("verts %n:\n") << loader.header.numVertices); 00158 Log::print( Say("uvs %n:\n") << loader.header.numTexCoords); 00159 Log::print( Say("offs skins %n:\n") << loader.header.offsetSkins); 00160 Log::print( Say("offs end %n:\n") << loader.header.offsetEnd); 00161 Log::print( Say("offs frames %n:\n") << loader.header.offsetFrames); 00162 Log::print( Say("offs gl comm %n:\n") << loader.header.offsetGlCommands); 00163 Log::print( Say("offs tex coor %n:\n") << loader.header.offsetTexCoords); 00164 Log::print( Say("offs tri %n:\n") << loader.header.offsetTriangles); 00165 Log::print( Say("skinh %n:\n") << loader.header.skinHeight); 00166 Log::print( Say("skinw %n:\n") << loader.header.skinWidth); 00167 } 00168 00169 // load data into memory 00170 file->seekSet(loader.header.offsetFrames); 00171 loader.md2_frame.resize(loader.header.numFrames); 00172 for(unsigned i=0; i<loader.md2_frame.size(); ++i) 00173 { 00174 loader.md2_frame[i] = (LoaderMD2::md2_frame_info*)malloc(loader.header.frameSize * sizeof(char) ); 00175 file->read(loader.md2_frame[i], loader.header.frameSize); 00176 } 00177 00178 // uv 00179 loader.md2_uv.resize(loader.header.numTexCoords); 00180 file->seekSet( loader.header.offsetTexCoords ); 00181 file->read(&loader.md2_uv[0], loader.header.numTexCoords*sizeof(LoaderMD2::md2_uv_info) ); 00182 00183 // triangles 00184 loader.md2_triangle.resize(loader.header.numTriangles); 00185 file->seekSet(loader.header.offsetTriangles ); 00186 file->read(&loader.md2_triangle[0], loader.header.numTriangles*sizeof(LoaderMD2::md2_triangle_info) ); 00187 00188 // textures 00189 if (loader.header.numSkins) 00190 { 00191 loader.md2_skin.resize(loader.header.numSkins); 00192 file->seekSet( loader.header.offsetSkins ); 00193 file->read(&loader.md2_skin[0], loader.header.numSkins*sizeof(LoaderMD2::md2_skin_info) ); 00194 } 00195 00196 // fclose(fin); 00197 file->close(); 00198 00199 // conversion 00200 00201 std::vector< ref<ArrayFloat3> > vertex_frames; 00202 std::vector< ref<ArrayFloat3> > normal_frames; 00203 00204 // allocate frames 00205 for(int i=0; i<loader.header.numFrames; ++i) 00206 { 00207 vertex_frames.push_back( new ArrayFloat3 ); 00208 vertex_frames[i]->resize( 3 * loader.header.numTriangles ); 00209 // normals are computed later 00210 } 00211 00212 ref<DrawElementsUInt> polygons = new DrawElementsUInt; 00213 ref<ArrayFloat2> tex_coords = new ArrayFloat2; 00214 tex_coords->resize( 3 * loader.header.numTriangles ); 00215 polygons->indexBuffer()->resize( 3 * loader.header.numTriangles ); 00216 geometry->setTexCoordArray(0, tex_coords.get()); 00217 geometry->drawCalls()->push_back( polygons.get() ); 00218 00219 int vert_idx = 0; 00220 VL_CHECK( (int)loader.md2_triangle.size() == loader.header.numTriangles ) 00221 for(int itri=0; itri<loader.header.numTriangles; itri++) 00222 { 00223 for( int ivert=3; ivert--; ++vert_idx ) 00224 { 00225 // add uv 00226 float u = (float)loader.md2_uv[ loader.md2_triangle[itri].uv_idx[ivert] ].u / loader.header.skinWidth; 00227 float v = 1.0f - (float)loader.md2_uv[ loader.md2_triangle[itri].uv_idx[ivert] ].v / loader.header.skinHeight; 00228 tex_coords->at(vert_idx) = fvec2(u, v); 00229 00230 // add vert 00231 for(int iframe=0; iframe<loader.header.numFrames; iframe++) 00232 { 00233 fvec3 vec; 00234 vec.x() = loader.md2_frame[iframe]->vertices[ loader.md2_triangle[itri].vert_idx[ivert] ].vertex[0] * loader.md2_frame[iframe]->scale[0] + loader.md2_frame[iframe]->translate[0]; 00235 vec.y() = loader.md2_frame[iframe]->vertices[ loader.md2_triangle[itri].vert_idx[ivert] ].vertex[2] * loader.md2_frame[iframe]->scale[2] + loader.md2_frame[iframe]->translate[2]; 00236 vec.z() = -1 *(loader.md2_frame[iframe]->vertices[ loader.md2_triangle[itri].vert_idx[ivert] ].vertex[1] * loader.md2_frame[iframe]->scale[1] + loader.md2_frame[iframe]->translate[1]); 00237 vertex_frames[iframe]->at( vert_idx ) = vec; 00238 } 00239 00240 // add index 00241 polygons->indexBuffer()->at( vert_idx ) = vert_idx; 00242 } 00243 } 00244 00245 for(int iframe=0; iframe<loader.header.numFrames; iframe++) 00246 free(loader.md2_frame[iframe]); 00247 00248 // remove double vertices using the first vertex frame 00249 geometry->setVertexArray( vertex_frames[0].get() ); 00250 geometry->setNormalArray( NULL ); // don't count the normals 00251 geometry->setTexCoordArray( 0, tex_coords.get() ); // count the texture coords 00252 00253 // this takes away the 66% of the vertices! 00254 DoubleVertexRemover remover; 00255 remover.removeDoubles( geometry.get() ); 00256 00257 // install the newly created and simplified arrays 00258 vertex_frames[0] = cast<ArrayFloat3>(geometry->vertexArray()); VL_CHECK(vertex_frames[0]); 00259 tex_coords = cast<ArrayFloat2>(geometry->texCoordArray(0)); VL_CHECK(tex_coords); 00260 polygons = cast<DrawElementsUInt>(geometry->drawCalls()->at(0)); VL_CHECK(polygons); 00261 00262 // simplify the remaining frames based on the translation table remover.oldToNewIndexMap() 00263 for(int iframe=1; iframe<loader.header.numFrames; ++iframe) 00264 { 00265 ArrayFloat3* new_vertex_frame = new ArrayFloat3; 00266 new_vertex_frame->resize( vertex_frames[0]->size() ); 00267 00268 for(size_t ivert=0; ivert<vertex_frames[iframe]->size(); ++ivert) 00269 { 00270 VL_CHECK( remover.mapOldToNew()[ivert] < new_vertex_frame->size() ) 00271 new_vertex_frame->at( remover.mapOldToNew()[ivert] ) = vertex_frames[iframe]->at(ivert); 00272 } 00273 vertex_frames[iframe] = new_vertex_frame; 00274 } 00275 00276 // compute normals 00277 normal_frames.resize( loader.header.numFrames ); 00278 for(int iframe=0; iframe<loader.header.numFrames; iframe++) 00279 { 00280 geometry->setVertexArray( vertex_frames[iframe].get() ); 00281 geometry->computeNormals(); 00282 normal_frames[iframe] = cast<ArrayFloat3>(geometry->normalArray()); VL_CHECK(normal_frames[iframe]); 00283 VL_CHECK( normal_frames[iframe] ) 00284 } 00285 00286 for(unsigned i=0; i<vertex_frames.size(); ++i) 00287 { 00288 vertex_frames[i]->setObjectName("vertex_frame"); 00289 res_db->resources().push_back(vertex_frames[i].get()); 00290 } 00291 00292 for(unsigned i=0; i<normal_frames.size(); ++i) 00293 { 00294 normal_frames[i]->setObjectName("normal_frame"); 00295 res_db->resources().push_back(normal_frames[i].get()); 00296 } 00297 00298 return res_db; 00299 } 00300 //----------------------------------------------------------------------------- 00301 00302 /* Quick MD2 Animation Map 00303 * stand 0,39 00304 * run 40,45 00305 * attack 46,53 00306 * wave 112, 122 00307 * die 190 197 00308 */ 00309