Esempio n. 1
0
void LWOReader::ReadPTAG( UInt32 pChunkSize )
{
    UInt32      dataRead = 0;
    LWIndex     index;
    LWIndex     val;
    UInt32      tagType;

    dataRead += ReadID4( tagType );

    if( tagType != ID_SURF && tagType != ID_PART && tagType != ID_SMGP )
    {
        Skip( pChunkSize - dataRead );
        return;
    }

    while( dataRead < pChunkSize ) 
    {
        dataRead += ReadVX( index );
        dataRead += ReadVX( val );
                
        switch( tagType )
        {
        case ID_SURF:  GetCurrentLayer()->mPolygonList.mPolygons[index]->mSurfaceIndex        = val;  break;
        case ID_PART:  GetCurrentLayer()->mPolygonList.mPolygons[index]->mPartIndex           = val;  break;
        case ID_SMGP:  GetCurrentLayer()->mPolygonList.mPolygons[index]->mSmoothingGroupIndex = val;  break;
        }
    }
}
Esempio n. 2
0
bool LWOFile::LoadVMAP(unsigned int iChunkSize)
{
  Layer *pLayer=GetLastLayer();
  if(pLayer==NULL)
  {
    AddError("No LAYR before VMAP");
    return false;
  }

  // VMAP { type[ID4], dimension[U2], name[S0],
  //  ( vert[VX], value[F4] # dimension )* }
  unsigned int iType=0;
  if(!ReadID4(iType))
  {
    return false;
  }

  // uvmap
  if(iType==ID4("TXUV"))
  {
    return LoadUVMap(iChunkSize);
  }
  // weightmap
  else if(iType==ID4("WGHT"))
  {
    return LoadWeightMap(iChunkSize);
  }

  // unknown type - skip
  m_pData+=iChunkSize-4;
  AddError("Warning: Unknown vertex map type "+ID4ToString(iType));
  return true;
}
Esempio n. 3
0
bool LWOFile::LoadPOLS(unsigned int iChunkSize)
{
  Layer *pLayer=GetLastLayer();
  if(pLayer==NULL)
  {
    AddError("No LAYR before POLS");
    return false;
  }

  const char *pChunkEndPos=m_pData+iChunkSize;

  // POLS { type[ID4], ( numvert+flags[U2], vert[VX] # numvert )* }
  unsigned int iType=0;
  if(!ReadID4(iType)) return false;

  // only faces supported (but patches control cage can be loaded as well)
  if(iType!=ID4("FACE") && iType!=ID4("PTCH"))
  {
    AddError("Warning: POLS has unsupported type "+ID4ToString(iType));
    // skip
    m_pData=pChunkEndPos;
    return true;
  }

  unsigned int iBytesLeft=iChunkSize-4;

  // allocate for worst case polygon count
  unsigned int iPolysNeeded=iBytesLeft/(2+2);
  unsigned int iExistingPolys=(unsigned int)pLayer->m_Polygons.size();
  pLayer->m_Polygons.resize(iExistingPolys+iPolysNeeded);

  unsigned int iPolygon=0;
  while(m_pData<pChunkEndPos)
  {
    // read vertex count
    unsigned short iVertexCount;
    if(!ReadU2(iVertexCount)) return false;

    // quote: The 6 high-order bits of the vertex count are flag
    //        bits with different meanings for each polygon type.
    //
    // let's just mask them out
    iVertexCount &= 0x03FF;

    pLayer->m_Polygons[iExistingPolys+iPolygon].m_iSurface=0xffff;
    pLayer->m_Polygons[iExistingPolys+iPolygon].m_Vertices.resize(iVertexCount);

    unsigned int *pVertices=&pLayer->m_Polygons[iExistingPolys+iPolygon].m_Vertices[0];
    for(unsigned short j=0;j<iVertexCount;j++)
    {
      if(!ReadVX(pVertices[j])) return false;
    }
    iPolygon++;
  }

  // make array size match the actual polygon count
  pLayer->m_Polygons.resize(iExistingPolys+iPolygon);

  return true;
}
Esempio n. 4
0
void LWOReader::ReadPOLS( UInt32 pChunkSize )
{
    UInt32      dataRead = 0;
    UInt16      numVertex;
    UInt32      polygonType;
    LWPolygon*  newPolygon;
    
    dataRead += ReadID4( polygonType );

    while( dataRead < pChunkSize )
    {   
        newPolygon = GD_NEW(LWPolygon, this, "Polygon");

        dataRead += ReadU2( numVertex );

        newPolygon->mFlags       = (0xFC00 & numVertex) >> 10;                		
		numVertex                = 0x03FF & numVertex;
		        
        newPolygon->mType        = polygonType;
        newPolygon->mVertex      = GD_NEW_ARRAY(LWPolygonVertex, numVertex, this, "Polygon::Vertex");
        newPolygon->mVertexCount = numVertex;

        // Read indices and assign them to each vertex
		for( UInt32 iIndex = 0; iIndex < newPolygon->mVertexCount; iIndex++ )
            dataRead += ReadVX( newPolygon->mVertex[iIndex].mIndex );
        
        GetCurrentLayer()->mPolygonList.mPolygons.push_back( newPolygon );
    }
}
Esempio n. 5
0
bool LWOFile::LoadSURF(unsigned int iChunkSize)
{
  Surface surf;
  surf.m_vBaseColor[0] = 1.0f;
  surf.m_vBaseColor[1] = 1.0f;
  surf.m_vBaseColor[2] = 1.0f;

  // SURF { name[S0], source[S0], attributes[SUB-CHUNK] * }
  const char *pChunkEndPos=m_pData+iChunkSize;

  // name
  unsigned int iStrBytes=0;
  if(!ReadS0(surf.m_strName,iStrBytes))
  {
    return false;
  }

  // source
  if(!ReadS0(surf.m_strSource,iStrBytes))
  {
    return false;
  }
  
  // while there's data left
  while(m_pData<pChunkEndPos)
  {
    // get chunk ID
    unsigned int iID=0;
    if(!ReadID4(iID)) return false;

    // get chunk size
    unsigned short iChunkSize=0;
    if(!ReadU2(iChunkSize)) return false;

    const char *pSubChunkEndPos=m_pData+iChunkSize;

    // color
    if(iID == ID4("COLR"))
    {
      // COLR { base-color[COL12], envelope[VX]  }

      // read values
      if(!ReadF4(surf.m_vBaseColor[0])) return false;
      if(!ReadF4(surf.m_vBaseColor[1])) return false;
      if(!ReadF4(surf.m_vBaseColor[2])) return false;
    }

    // skip to end of sub-chunk
    m_pData = pSubChunkEndPos;
    if(iChunkSize%2==1) m_pData+=1;
  }

  m_Surfaces.push_back(surf);

  return true;
}
Esempio n. 6
0
bool LWOFile::LoadPTAG(unsigned int iChunkSize)
{
  Layer *pLayer=GetLastLayer();
  if(pLayer==NULL)
  {
    AddError("No LAYR before PTAG");
    return false;
  }

  if(pLayer->m_Polygons.size()==0)
  {
    AddError("No POLS before PTAG");
    return false;
  }

  const char *pChunkEndPos=m_pData+iChunkSize;

  // read type
  unsigned int iType=0;
  if(!ReadID4(iType))
  {
    return false;
  }

  if(iType!=ID4("SURF"))
  {
    // unknown type - skip
    m_pData+=iChunkSize-4;
    AddError("Warning: Unknown PTAG type "+ID4ToString(iType));
    return true;
  }

  while(m_pData<pChunkEndPos)
  {
    // read poly id
    unsigned int iPolyID;
    if(!ReadVX(iPolyID)) return false;

    // read tag
    unsigned short iTag;
    if(!ReadU2(iTag)) return false;

    if(iPolyID>=pLayer->m_Polygons.size()) return false;
    pLayer->m_Polygons[iPolyID].m_iSurface=iTag;
  }

  return true;
}
Esempio n. 7
0
void LWOReader::ReadHEAD( LWSurfaceBlock* pSurfaceBlock, UInt32 pChunkSize )
{
    UInt32      dataRead = 0;
    UInt16      subChunkSize;
    UInt32      subChunkTag;
    UInt32      bytesHold;
    LWIndex     env;

    dataRead += ReadS0( pSurfaceBlock->mOrdinalString );

    while( dataRead < pChunkSize )
    {
        subChunkTag = ReadSubChunk(subChunkSize,2);
        dataRead += sizeof(subChunkTag);   // Subchunk tag.
        dataRead += sizeof(subChunkSize);  // Subchunk size.

        bytesHold = dataRead;

        switch( subChunkTag )
        {
        case ID_CHAN:
            dataRead += ReadID4( pSurfaceBlock->mTextureChannel );
            break;

        case ID_ENAB:
            dataRead += ReadU2( pSurfaceBlock->mEnableState );
            break;

        case ID_OPAC:
            dataRead += ReadU2( pSurfaceBlock->mOpacityType );
            dataRead += ReadFP4( pSurfaceBlock->mOpacity );
            dataRead += ReadVX( env );
            break;

        default:
            dataRead += Skip( subChunkSize );
            break;
        }

        // Make sure we've read all subchunk bytes (given by the size).
        if( (subChunkSize - dataRead + bytesHold) > 0 ) 
            dataRead += Skip( subChunkSize - dataRead + bytesHold );
    }
}
Esempio n. 8
0
bool LWOFile::LoadVMAD(unsigned int iChunkSize)
{
  Layer *pLayer=GetLastLayer();
  if(pLayer==NULL)
  {
    AddError("No LAYR before VMAD");
    return false;
  }

  const char *pChunkEndPos=m_pData+iChunkSize;

  // VMAD { type[ID4], dimension[U2], name[S0],
  // ( vert[VX], poly[VX], value[F4] # dimension )* }
  unsigned int iType=0;
  if(!ReadID4(iType)) return false;

  // type must be uvmap
  if(iType!=ID4("TXUV"))
  {
    AddError("Warning: Unknown discontinuous vertex map type "+ID4ToString(iType));
    m_pData+=iChunkSize-4;
    return true;
  }

  // dimension
  unsigned short iDimension=0;
  if(!ReadU2(iDimension))
  {
    return false;
  }

  // not 2 floats per vertex
  if(iDimension!=2)
  {
    AddError("Warning: Discontinuous UVMap has "+ConvertToString(iDimension)+" floats per vertex (2 expected)");
    // skip
    m_pData+=iChunkSize-4-2;
    return true;
  }

  // name
  unsigned int iStrBytes=0;
  std::string strName;
  if(!ReadS0(strName,iStrBytes))
  {
    return false;
  }

  // for each uvmap
  UVMap *pUV=NULL;
  for(unsigned int iUV=0;iUV<pLayer->m_UVMaps.size();iUV++)
  {
    if(pLayer->m_UVMaps[iUV]->m_strName==strName)
    {
      pUV=pLayer->m_UVMaps[iUV];
    }
  }

  if(pUV==NULL)
  {
    AddError("No matching UVMap for discontinuous UVMap \""+strName+"\"");
    return false;
  }


  // read rest of chunk to memory
  //
  unsigned int iBytesLeft=iChunkSize-4-2-iStrBytes;

  UVMapD *pUVMap=new UVMapD();
  pUVMap->m_strName=strName;
  pUVMap->m_pUVMap=pUV;
  // worst case estimate
  pUVMap->m_Entries.reserve(iBytesLeft/(2+2+4+4));
  pLayer->m_UVMapDs.push_back(pUVMap);

  while(m_pData<pChunkEndPos)
  {
    unsigned int iVertexID=0;
    if(!ReadVX(iVertexID)) return false;

    unsigned int iPolyID=0;
    if(!ReadVX(iPolyID)) return false;

    UVMapD::Entry e;
    e.iVertex=iVertexID;
    e.iPolygon=iPolyID;
    if(!ReadF4(e.u)) return false;
    if(!ReadF4(e.v)) return false;
    // flip v coordinate
    e.v=1-e.v;
    pUVMap->m_Entries.push_back(e);
  }

  return true;
}
Esempio n. 9
0
bool LWOFile::LoadFromMemory(const void *pData, unsigned int iFileSize)
{
  if(pData==NULL || iFileSize==0)
  {
    AddError("Loading from memory failed: no data");
    return false;
  }
  m_pData=(const char*)pData;
  m_pDataEnd=m_pData+iFileSize;

  // read main chunk id
  //
  unsigned int iID=0;
  if(!ReadID4(iID) || iID!=ID4("FORM"))
  {
    AddError("Main chunk FORM not found!");
    return false;
  }

  // read main chunk size
  //
  unsigned int iMainSize=0;
  if(!ReadU4(iMainSize)) return false;

  // read file format
  //
  if(!ReadID4(iID)) return false;
  if(iID!=ID4("LWO2"))
  {
    AddError("Format "+ID4ToString(iID)+" is not supported!");
    return false;
  }

  unsigned int iLayerID=ID4("LAYR");
  unsigned int iPointsID=ID4("PNTS");
  unsigned int iPolygonsID=ID4("POLS");
  unsigned int iVertexMapID=ID4("VMAP");
  unsigned int iVertexMapDID=ID4("VMAD");
  unsigned int iTagsID=ID4("TAGS");
  unsigned int iPTagsID=ID4("PTAG");
  unsigned int iSurfID=ID4("SURF");

  // while we have data left
  //
  while(m_pData<m_pDataEnd)
  {
    // get chunk ID
    //
    unsigned int iID=0;
    if(!ReadID4(iID)) return false;

    // get chunk size
    //
    unsigned int iChunkSize=0;
    if(!ReadU4(iChunkSize)) return false;


    // attempt to load chunk

    // LAYR
    ///////////////////
    if(iID==iLayerID)
    {
      if(!LoadLAYR(iChunkSize))
      {
        AddError("Loading chunk "+ID4ToString(iID)+" failed!");
        return false;
      }
    }

    // PNTS
    ///////////////////
    else if(iID==iPointsID)
    {
      if(!LoadPNTS(iChunkSize))
      {
        AddError("Loading chunk "+ID4ToString(iID)+" failed!");
        return false;
      }
    }

    // POLS
    ///////////////////
    else if(iID==iPolygonsID)
    {
      if(!LoadPOLS(iChunkSize))
      {
        AddError("Loading chunk "+ID4ToString(iID)+" failed!");
        return false;
      }
    }

    // VMAP
    ///////////////////
    else if(iID==iVertexMapID)
    {
      if(!LoadVMAP(iChunkSize))
      {
        AddError("Loading chunk "+ID4ToString(iID)+" failed!");
        return false;
      }
    }

    // VMAD
    ///////////////////
    else if(iID==iVertexMapDID)
    {
      if(!LoadVMAD(iChunkSize))
      {
        AddError("Loading chunk "+ID4ToString(iID)+" failed!");
        return false;
      }
    }

    // TAGS
    ///////////////////
    else if(iID==iTagsID)
    {
      if(!LoadTAGS(iChunkSize))
      {
        AddError("Loading chunk "+ID4ToString(iID)+" failed!");
        return false;
      }
    }

    // PTAG
    ///////////////////
    else if(iID==iPTagsID)
    {
      if(!LoadPTAG(iChunkSize))
      {
        AddError("Loading chunk "+ID4ToString(iID)+" failed!");
        return false;
      }
    }

    // SURF
    ///////////////////
    else if(iID==iSurfID)
    {
      if(!LoadSURF(iChunkSize))
      {
        AddError("Loading chunk "+ID4ToString(iID)+" failed!");
        return false;
      }
    }

    // unknown
    ///////////////////
    else
    {
      AddError("Warning: Unknown chunk ID "+ID4ToString(iID));
      m_pData+=iChunkSize;
    }


    // quote: If the chunk size is odd, the chunk is followed by a 0 pad byte,
    //        so that the next chunk begins on an even byte boundary.
    if(iChunkSize%2==1) m_pData+=1;
  }

  m_pData=NULL;
  m_pDataEnd=NULL;
  return true;
}
Esempio n. 10
0
void LWOReader::Read( const String& pFilename, LWObject& pObject )
{
    UInt32 dataSize     = 0;
    UInt32 dataRead     = 0;
    UInt32 chunkSize    = 0;
    UInt32 chunkTag     = 0;

    mObject = &pObject;

    mLwoFile.open( pFilename.c_str() );
    if( mLwoFile.fail() )
    {
        mLwoFile.close();
        throw FileNotFoundException( pFilename, Here );
    }

    try
    {
        if( ReadChunk( dataSize ) != ID_FORM )
            throw InvalidLWOFileException( ID_FORM, Here );

        if( ReadID4() != ID_LWO2 )
            throw InvalidLWOFileException( ID_LWO2, Here );
        
        dataRead += sizeof(ID_LWO2);
        while( dataRead < dataSize )
        {            
            chunkTag = ReadChunk(chunkSize);
            dataRead += sizeof(UInt32);     // Chunk tag.
            dataRead += sizeof(UInt32);     // Chunk size.

            switch( chunkTag )
            {
            case ID_TAGS:	    ReadTAGS( chunkSize );  break;
            case ID_CLIP:	    ReadCLIP( chunkSize );  break;
            case ID_ENVL:	    ReadENVL( chunkSize );  break;
            case ID_LAYR:	    ReadLAYR( chunkSize );  break;
            case ID_PNTS:	    ReadPNTS( chunkSize );  break;
            case ID_BBOX:	    ReadBBOX( chunkSize );  break;
            case ID_POLS:	    ReadPOLS( chunkSize );  break;
            case ID_PTAG:	    ReadPTAG( chunkSize );  break;
            case ID_VMAP:	    
            case ID_VMAD:	    ReadVMAP( chunkSize, chunkTag == ID_VMAD );  break;
            case ID_SURF:	    ReadSURF( chunkSize );  break;
            default:            Skip( chunkSize );      break;
            }
            
            dataRead += chunkSize;          // Chunk bytes.
        }        
    }
    catch( Exception& /*e*/ )
    {
        mLwoFile.close();
        throw;
    }
    
    // Fill data structure
    mLwoFile.close();

    LWLayer*                    layer;
    Vector<LWLayer*>::iterator  itLayer;
    for( itLayer = mObject->mLayers.begin(); itLayer != mObject->mLayers.end(); ++itLayer )
    {
        layer = (*itLayer);

        mObject->GetBoundingBox     ( layer->mPointList, layer->mBoundingBox );
        mObject->GetPolyNormals     ( layer->mPointList, layer->mPolygonList );
        mObject->GetPointPolygons   ( layer->mPointList, layer->mPolygonList );
        mObject->ResolvePolySurfaces( layer->mPolygonList );
        mObject->GetVertNormals     ( layer->mPointList, layer->mPolygonList );
        mObject->GetPointVMaps      ( layer->mPointList, layer->mVertexMaps );
        mObject->GetPolyVMaps       ( layer->mPolygonList, layer->mVertexMaps );
    }

    mObject = NULL;
}
Esempio n. 11
0
void LWOReader::ReadVMAP( UInt32 pChunkSize, Bool pPerPoly )
{
    UInt32              dataRead = 0;
    UInt16              dimension;
    LWIndex             vertexIndex;
    LWIndex             polygonIndex;
    
    LWVertexMap*        newVertexMap = GD_NEW(LWVertexMap, this, "VertexMap");

    newVertexMap->mPerPoly = pPerPoly;

    dataRead += ReadID4( newVertexMap->mType );
    dataRead += ReadU2( dimension );
    dataRead += ReadS0( newVertexMap->mName );

    while( dataRead < pChunkSize )
    {
        dataRead += ReadVX( vertexIndex );
        newVertexMap->mVertexIndex.push_back( vertexIndex );

        if( pPerPoly )
        {
            dataRead += ReadVX( polygonIndex );
            newVertexMap->mPolygonIndex.push_back( polygonIndex );
        }

        LWMapValue mapping;

        switch( newVertexMap->mType )
        {
        case ID_PICK:
            mapping.mPick = vertexIndex;
            break;

        case ID_WGHT:
            dataRead += ReadF4( mapping.mWeight );
            break;

        case ID_TXUV:   
            dataRead += ReadF4( mapping.mUV.U );
            dataRead += ReadF4( mapping.mUV.V );
            break;

        case ID_RGB:
            dataRead += ReadF4( mapping.mRGB.R );
            dataRead += ReadF4( mapping.mRGB.G );
            dataRead += ReadF4( mapping.mRGB.B );
            break;

        case ID_RGBA:
            dataRead += ReadF4( mapping.mRGBA.R );
            dataRead += ReadF4( mapping.mRGBA.G );
            dataRead += ReadF4( mapping.mRGBA.B );
            dataRead += ReadF4( mapping.mRGBA.A ); 
            break;

        case ID_MORF:
        case ID_SPOT:
        case ID_MNVW:   
        default:       
            dataRead += Skip( dimension * sizeof(Float) );      
            break;
        }   

        newVertexMap->mValues.push_back( mapping );
    }

    GetCurrentLayer()->mVertexMaps.push_back( newVertexMap );
}