VCRA-SZCZERBACKI-PointBasedRendering/lwo6.cpp

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++;    //if size is odd, add 1 padding
00054 
00055                 switch(chunkname)
00056                 {
00057                 case 'PNTS':
00058                         svPrint("PNTS %d vertices\n",chunklen/12);
00059                         if( PNTS == 0 ) //consider only the first PNTS chunk
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 ) //consider only VMAPS associated to the first PNTS chunk
00085                         {
00086                                 UINT32 type = readID4();        //PICK,WGHT,MNVW,TXUV,RGB,RGBA,MORF,SPOT
00087                                 UINT32 dimension = readU2();
00088                                 const char *name = readS0();    //VMAD needs to be associated with the VMAP with the same name
00089                                 vmaps.push_back( name );
00090                                 static float val[16];   //we assume max dimension to be 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 )    //just in case..
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 ) //VMADS associated to the first PNTS and POLS
00121                         {
00122                                 UINT32 type = readID4();        //PICK,WGHT,MNVW,TXUV,RGB,RGBA,MORF,SPOT
00123                                 UINT32 dimension = readU2();
00124                                 const char *name = readS0();    //VMAD needs to be associated with the VMAP with the same name
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 )        //corresponding VMAP found
00136                                 {
00137                                         static float val[16];   //we assume max dimension to be 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 //                                              svPrint(" %d/%f",vi,val[0]);
00146 
00147                                                 //create new vertex
00148                                                 if( type == 'TXUV' || type == 'RGB ' || type == 'RGBA' )
00149                                                 {
00150                                                         //check whether there's already new vertex with the same attributes
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                                                         {       //vertex doesn't exist yet
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 )    //just in case..
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                                                         //remap polygons using the old vertex
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                                 //else: each polygon has discontinuous mapping
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 ) //POLS associated only with the first PNTS
00212                         {
00213                                 UINT32 type = readID4();        //FACE,CURV,PTCH,MBAL,BONE
00214                                 int read = 0;
00215                                 static int vtable[1023];        //max number of vertices is 1023
00216                                 while( m_readptr < chunkend )
00217                                 {
00218                                         ++read;
00219                                         UINT32 vert = readU2() & 0x3f;  //6 msb are flags, we don't need them
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                                                 //normal is cross product of the first and the last edges
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 ) //consider only the first TAGS chunk
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 ) //PTAGs associated with the first TAGS and POLS chunk
00290                         {
00291                                 UINT32 type = readID4();        //SURF,PART,SMGP
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();       //read the name
00331                                 readS0();       //read the source surface (we're not going to support that)
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++;      //if size is odd, add 1 padding
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         //calculate how many triangles are using each surface
00362         //set triangle using info
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         //normalize vertex normals and calculate initial tangent spaces
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;   //file length + terminating 0
00440         if( l & 1 ) ++m_readptr;        //if odd, add 1 padding
00441         m_readptr += l;
00442         return (const char*)ptr;
00443 }
00444 UINT32 Mesh::readVX()
00445 {
00446         UINT8 a = *m_readptr++;
00447         if( a == 0xff ) //if first is 0xff, 4 byte index is used, otherwise 2 bytes
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 //=======================================================================

Generated on Thu Feb 15 09:09:20 2007 for Surface Splating by  doxygen 1.5.1-p1