- Main Page
- Namespaces
- Classes
- Files

# 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 //=======================================================================