00001 #include "Mesh.h"
00002
00003
00004
00005
00006 struct PolyToTri
00007 {
00008 int m_firstTri;
00009 int m_triCount;
00010 };
00011
00012 struct VMADStruct
00013 {
00014 void operator=(const VMADStruct &v)
00015 {
00016 m_oldVertex = v.m_oldVertex;
00017 m_newVertex = v.m_newVertex;
00018 memcpy(m_value,v.m_value,sizeof(float)*16);
00019 }
00020 int m_oldVertex;
00021 int m_newVertex;
00022 float m_value[16];
00023 };
00024
00025 void Mesh::loadLW6( )
00026 {
00027 int chunklen,chunkname,subchunkname,subchunklen;
00028 int i;
00029 Vector3 p;
00030 float r;
00031 Color color,spec;
00032 UINT8 *chunks, *chunkend,*subchunkend,*vertexPointer = NULL;
00033 int PNTS = 0, POLS = 0, VMAP = 0, TAGS = 0, PTAG = 0, VMAD = 0, SURF = 0;
00034 std::vector<const char *> tags;
00035 std::vector<const char *> vmaps;
00036 std::vector<PolyToTri> polygons;
00037 std::vector<VMADStruct> vmads;
00038
00039 m_boundingBoxMin.set(FLT_MAX,FLT_MAX,FLT_MAX);
00040 m_boundingBoxMax.set(-FLT_MAX,-FLT_MAX,-FLT_MAX);
00041 m_boundingRadius = 0.0f;
00042
00043 chunks = m_readptr;
00044
00045 m_nextchunkptr = chunks;
00046 while(m_nextchunkptr < m_fileend)
00047 {
00048 m_readptr = m_nextchunkptr;
00049 chunkname = readID4();
00050 chunklen = readU4();
00051 chunkend = m_readptr + chunklen;
00052 m_nextchunkptr = chunkend;
00053 if( chunklen & 1 ) m_nextchunkptr++;
00054
00055 switch(chunkname)
00056 {
00057 case 'PNTS':
00058 svPrint("PNTS %d vertices\n",chunklen/12);
00059 if( PNTS == 0 )
00060 {
00061 m_vertices.resize( chunklen / 12 );
00062 for(i=0;i<m_vertices.size();++i)
00063 {
00064 p = readVEC12();
00065 m_vertices[i].m_position = p;
00066 m_vertices[i].m_normal.set(0,0,0);
00067 m_vertices[i].m_triangleUsing = -1;
00068 if( p.x > m_boundingBoxMax.x ) m_boundingBoxMax.x = p.x;
00069 if( p.x < m_boundingBoxMin.x ) m_boundingBoxMin.x = p.x;
00070 if( p.y > m_boundingBoxMax.y ) m_boundingBoxMax.y = p.y;
00071 if( p.y < m_boundingBoxMin.y ) m_boundingBoxMin.y = p.y;
00072 if( p.z > m_boundingBoxMax.z ) m_boundingBoxMax.z = p.z;
00073 if( p.z < m_boundingBoxMin.z ) m_boundingBoxMin.z = p.z;
00074
00075 r = dot(p, p);
00076 if(r > m_boundingRadius) m_boundingRadius = r;
00077 }
00078 }
00079 PNTS++;
00080 break;
00081 case 'VMAP':
00082 svPrint("VMAP");
00083 if( PNTS == 0 ) svError("invalid LWO2 file: VMAP chunk before PNTS");
00084 if( PNTS == 1 )
00085 {
00086 UINT32 type = readID4();
00087 UINT32 dimension = readU2();
00088 const char *name = readS0();
00089 vmaps.push_back( name );
00090 static float val[16];
00091 int read = 0;
00092 while( m_readptr < chunkend )
00093 {
00094 ++read;
00095 int vi = readVX();
00096 for(i=0;i<dimension;++i)
00097 val[i] = readF4();
00098 switch( type )
00099 {
00100 case 'TXUV':
00101 if( dimension == 2 )
00102 m_vertices[vi].m_uv = Vector2(val[0],1.0f-val[1]);
00103 break;
00104 case 'RGB ':
00105 m_vertices[vi].m_diffuse.set( val[0],val[1],val[2], 1 );
00106 break;
00107 case 'RGBA':
00108 m_vertices[vi].m_diffuse.set( val[0],val[1],val[2],val[3] );
00109 break;
00110 }
00111 }
00112 svPrint(" %c%c%c%c %s %d",((type>>24)&0xff),((type>>16)&0xff),((type>>8)&0xff),(type&0xff),name,read);
00113 }
00114 svPrint("\n");
00115 VMAP++;
00116 break;
00117 case 'VMAD':
00118 svPrint("VMAD");
00119 if( PNTS == 0 || POLS == 0 ) svError("invalid LWO2 file: VMAD chunk before PNTS or POLS");
00120 if( PNTS == 1 && POLS == 1 )
00121 {
00122 UINT32 type = readID4();
00123 UINT32 dimension = readU2();
00124 const char *name = readS0();
00125 int vmap = -1;
00126 int read = 0;
00127 for(i=0;i<vmaps.size();++i)
00128 {
00129 if( !strcmp(name,vmaps[i]) )
00130 {
00131 vmap = i;
00132 break;
00133 }
00134 }
00135 if( vmap != -1 )
00136 {
00137 static float val[16];
00138 while( m_readptr < chunkend )
00139 {
00140 ++read;
00141 int vi = readVX();
00142 int pi = readVX();
00143 for(i=0;i<dimension;++i)
00144 val[i] = readF4();
00145
00146
00147
00148 if( type == 'TXUV' || type == 'RGB ' || type == 'RGBA' )
00149 {
00150
00151 int nv = -1;
00152 for(i=0;i<vmads.size();++i)
00153 {
00154 if( vmads[i].m_oldVertex == vi && !memcmp(val,vmads[i].m_value,dimension*sizeof(float)) )
00155 {
00156 nv = vmads[i].m_newVertex;
00157 break;
00158 }
00159 }
00160 if( nv == -1 )
00161 {
00162 static Vertex ver;
00163 ver = m_vertices[vi];
00164 ver.m_triangleUsing = -1;
00165 switch( type )
00166 {
00167 case 'TXUV':
00168 if( dimension == 2 )
00169 ver.m_uv = Vector2(val[0],1.0f-val[1]);
00170 break;
00171 case 'RGB ':
00172 ver.m_diffuse.set( val[0],val[1],val[2], 1 );
00173 break;
00174 case 'RGBA':
00175 ver.m_diffuse.set( val[0],val[1],val[2],val[3] );
00176 break;
00177 }
00178
00179 nv = m_vertices.size();
00180 m_vertices.push_back( ver );
00181
00182 static VMADStruct vmad;
00183 vmad.m_oldVertex = vi;
00184 vmad.m_newVertex = nv;
00185 memcpy( vmad.m_value, val, dimension*sizeof(float) );
00186 vmads.push_back( vmad );
00187 }
00188
00189
00190 int base = polygons[pi].m_firstTri;
00191 for(i=0;i<polygons[pi].m_triCount;++i)
00192 {
00193 for(int j=0;j<3;++j)
00194 {
00195 if( m_triangles[base + i].m_v[j] == vi )
00196 m_triangles[base + i].m_v[j] = nv;
00197 }
00198 }
00199 }
00200 }
00201 }
00202
00203 svPrint(" %c%c%c%c %s %d",((type>>24)&0xff),((type>>16)&0xff),((type>>8)&0xff),(type&0xff),name,read);
00204 }
00205 svPrint("\n");
00206 VMAD++;
00207 break;
00208 case 'POLS':
00209 svPrint("POLS");
00210 if( PNTS == 0 ) svError("invalid LWO2 file: POLS chunk before PNTS");
00211 if( PNTS == 1 )
00212 {
00213 UINT32 type = readID4();
00214 int read = 0;
00215 static int vtable[1023];
00216 while( m_readptr < chunkend )
00217 {
00218 ++read;
00219 UINT32 vert = readU2() & 0x3f;
00220 for(i=0;i<vert;++i)
00221 {
00222 vtable[i] = readVX();
00223 }
00224 if( type == 'FACE' )
00225 {
00226 static PolyToTri poly;
00227 poly.m_firstTri = m_triangles.size();
00228 poly.m_triCount = vert - 2;
00229 polygons.push_back( poly );
00230
00231 static Triangle t;
00232 static Vector3 n,e1,e2;
00233 t.m_surface = -1;
00234 t.m_n[0] = -1;
00235 t.m_n[1] = -1;
00236 t.m_n[2] = -1;
00237
00238
00239 e1 = m_vertices[vtable[1]].m_position;
00240 e1 -= m_vertices[vtable[0]].m_position;
00241 e2 = m_vertices[vtable[vert-1]].m_position;
00242 e2 -= m_vertices[vtable[0]].m_position;
00243 n = cross(e1, e2);
00244 n.normalize();
00245
00246 for(i=0;i<vert-2;i++)
00247 {
00248 t.m_v[0] = vtable[0];
00249 t.m_v[1] = vtable[i+1];
00250 t.m_v[2] = vtable[i+2];
00251 t.m_normal = n;
00252
00253 e1 = m_vertices[t.m_v[1]].m_position;
00254 e1 -= m_vertices[t.m_v[0]].m_position;
00255 e2 = m_vertices[t.m_v[2]].m_position;
00256 e2 -= m_vertices[t.m_v[0]].m_position;
00257 e1 = cross(e1, e2);
00258 t.m_area = 0.5f * e1.length();
00259 m_triangles.push_back( t );
00260 }
00261 for(i=0;i<vert;i++)
00262 {
00263 m_vertices[vtable[i]].m_normal += n;
00264 }
00265 }
00266 }
00267 svPrint(" %c%c%c%c %d",((type>>24)&0xff),((type>>16)&0xff),((type>>8)&0xff),(type&0xff),read);
00268 }
00269 svPrint("\n");
00270 POLS++;
00271 break;
00272 case 'TAGS':
00273 svPrint("TAGS");
00274 if( TAGS == 0 )
00275 {
00276 while( m_readptr < chunkend )
00277 {
00278 svPrint(" %s",m_readptr);
00279 tags.push_back( (const char *)m_readptr );
00280 readS0();
00281 }
00282 }
00283 svPrint("\n");
00284 TAGS++;
00285 break;
00286 case 'PTAG':
00287 svPrint("PTAG");
00288 if( TAGS == 0 || POLS == 0 ) svError("invalid LWO2 file: PTAG chunk before TAGS or POLS");
00289 if( TAGS == 1 && POLS == 1 )
00290 {
00291 UINT32 type = readID4();
00292 int read = 0;
00293 while( m_readptr < chunkend )
00294 {
00295 ++read;
00296 int polyindex = readVX();
00297 if( polyindex < 0 || polyindex > polygons.size() - 1 )
00298 svError("invalid LWO2 file: PTAG polygon index invalid (%d)",polyindex);
00299 int tagindex = readU2();
00300 if( tagindex < 0 || tagindex > tags.size() - 1 )
00301 svError("invalid LWO2 file: PTAG polygon tag invalid (%d)",tagindex);
00302 int base = polygons[polyindex].m_firstTri;
00303 for(i=0;i<polygons[polyindex].m_triCount;++i)
00304 {
00305 if( m_triangles[base + i].m_surface != -1 )
00306 svPrint(" duplicate PTAG %d", polyindex);
00307 m_triangles[base + i].m_surface = tagindex;
00308 }
00309 }
00310 svPrint(" %c%c%c%c %d",((type>>24)&0xff),((type>>16)&0xff),((type>>8)&0xff),(type&0xff),read);
00311 }
00312 svPrint("\n");
00313 PTAG++;
00314 break;
00315 case 'SURF':
00316 svPrint("SURF %s",m_readptr);
00317 {
00318 int tagindex = -1;
00319 for(i=0;i<tags.size();++i)
00320 {
00321 if( !strcmp((const char*)m_readptr, tags[i]) )
00322 {
00323 tagindex = i;
00324 break;
00325 }
00326 }
00327 if( tagindex == -1 ) svError("invalid LWO2 file: surface %s not found from the TAGS list",m_readptr);
00328 if( m_surfaces.size() < tagindex + 1 ) m_surfaces.resize( tagindex + 1 );
00329 m_surfaces[tagindex].m_name = (const char *)m_readptr;
00330 readS0();
00331 readS0();
00332
00333 m_nextsubchunkptr = m_readptr;
00334 while(m_nextsubchunkptr < chunkend)
00335 {
00336 m_readptr = m_nextsubchunkptr;
00337 subchunkname = readID4();
00338 subchunklen = readU2();
00339 subchunkend = m_readptr + subchunklen;
00340 m_nextsubchunkptr = subchunkend;
00341 if( subchunklen & 1 ) m_nextsubchunkptr++;
00342
00343 switch(subchunkname)
00344 {
00345 case 'COLR':
00346 m_surfaces[tagindex].m_color.set( readCOL12() );
00347 break;
00348 }
00349 }
00350 }
00351 svPrint("\n");
00352 SURF++;
00353 break;
00354 default:
00355 break;
00356 }
00357 }
00358
00359 m_boundingRadius = float(sqrt( m_boundingRadius ));
00360
00361
00362
00363 for(i=0;i<m_triangles.size();++i)
00364 {
00365 if( m_triangles[i].m_surface == -1 )
00366 svError("invalid LWO2 file: not every polygon has a surface");
00367 ++m_surfaces[m_triangles[i].m_surface].m_polygons;
00368
00369 m_vertices[m_triangles[i].m_v[0]].m_triangleUsing = (i<<2) | 0;
00370 m_vertices[m_triangles[i].m_v[1]].m_triangleUsing = (i<<2) | 1;
00371 m_vertices[m_triangles[i].m_v[2]].m_triangleUsing = (i<<2) | 2;
00372 }
00373
00374
00375 static Vector3 up(0,1,0);
00376 for(i=0;i<m_vertices.size();i++)
00377 {
00378 m_vertices[i].m_normal.normalize();
00379 m_vertices[i].m_t1 = cross(up, m_vertices[i].m_normal);
00380 m_vertices[i].m_t2 = cross(m_vertices[i].m_normal, m_vertices[i].m_t1);
00381 if( (float)SS::fabs(dot(up, m_vertices[i].m_normal)) > 0.999f ) m_vertices[i].m_reliable = false;
00382 else m_vertices[i].m_reliable = true;
00383 }
00384 }
00385
00386
00387
00388
00389 UINT32 Mesh::readID4()
00390 {
00391 return readU4();
00392 }
00393 int Mesh::readI1()
00394 {
00395 signed char a = readU1();
00396 return a;
00397 }
00398 int Mesh::readI2()
00399 {
00400 signed short a = readU2();
00401 return a;
00402 }
00403 int Mesh::readI4()
00404 {
00405 signed int a = readU4();
00406 return a;
00407 }
00408 UINT8 Mesh::readU1()
00409 {
00410 UINT8 a;
00411 a = *m_readptr++;
00412 return a;
00413 }
00414 UINT16 Mesh::readU2()
00415 {
00416 UINT8 a,b;
00417 a = *m_readptr++;
00418 b = *m_readptr++;
00419 return (a<<8) + b;
00420 }
00421 UINT32 Mesh::readU4()
00422 {
00423 UINT8 a,b,c,d;
00424 a = *m_readptr++;
00425 b = *m_readptr++;
00426 c = *m_readptr++;
00427 d = *m_readptr++;
00428 return (a<<24) + (b<<16) + (c<<8) + d;
00429 }
00430 float Mesh::readF4()
00431 {
00432 UINT32 a = readU4();
00433 float *b = (float *)&a;
00434 return *b;
00435 }
00436 const char *Mesh::readS0()
00437 {
00438 UINT8 *ptr = m_readptr;
00439 int l = strlen( (const char*)m_readptr ) + 1;
00440 if( l & 1 ) ++m_readptr;
00441 m_readptr += l;
00442 return (const char*)ptr;
00443 }
00444 UINT32 Mesh::readVX()
00445 {
00446 UINT8 a = *m_readptr++;
00447 if( a == 0xff )
00448 {
00449 UINT8 b = *m_readptr++;
00450 UINT8 c = *m_readptr++;
00451 UINT8 d = *m_readptr++;
00452 return (b<<16) + (c<<8) + d;
00453 }
00454 UINT8 b = *m_readptr++;
00455 return (a << 8 ) + b;
00456 }
00457 Vector3 Mesh::readCOL12()
00458 {
00459 return readVEC12();
00460 }
00461 Vector3 Mesh::readVEC12()
00462 {
00463 Vector3 a;
00464 a.x = readF4();
00465 a.y = readF4();
00466 a.z = readF4();
00467 return a;
00468 }
00469
00470
00471