Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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
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
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
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
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
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
00197 file->close();
00198
00199
00200
00201 std::vector< ref<ArrayFloat3> > vertex_frames;
00202 std::vector< ref<ArrayFloat3> > normal_frames;
00203
00204
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
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
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
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
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
00249 geometry->setVertexArray( vertex_frames[0].get() );
00250 geometry->setNormalArray( NULL );
00251 geometry->setTexCoordArray( 0, tex_coords.get() );
00252
00253
00254 DoubleVertexRemover remover;
00255 remover.removeDoubles( geometry.get() );
00256
00257
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
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
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
00303
00304
00305
00306
00307
00308
00309