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; }
void LWOReader::ReadTMAP( LWTextureMapping* pTextureMapping, UInt32 pChunkSize ) { UInt32 dataRead = 0; UInt16 subChunkSize; UInt32 subChunkTag; UInt32 bytesHold; LWIndex env; while( dataRead < pChunkSize ) { subChunkTag = ReadSubChunk(subChunkSize,2); dataRead += sizeof(subChunkTag); // Subchunk tag. dataRead += sizeof(subChunkSize); // Subchunk size. bytesHold = dataRead; switch( subChunkTag ) { case ID_CNTR: dataRead += ReadVEC12( pTextureMapping->mCenter ); dataRead += ReadVX( env ); break; case ID_SIZE: dataRead += ReadVEC12( pTextureMapping->mSize ); dataRead += ReadVX( env ); break; case ID_ROTA: dataRead += ReadVEC12( pTextureMapping->mRotation ); dataRead += ReadVX( env ); break; case ID_OREF: dataRead += ReadS0( pTextureMapping->mReferenceObject ); break; case ID_FALL: dataRead += ReadU2( pTextureMapping->mFalloffType ); dataRead += ReadVEC12( pTextureMapping->mFalloffVector ); dataRead += ReadVX( env ); break; case ID_CSYS: dataRead += ReadU2( pTextureMapping->mCoordinateSys ); 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 ); } }
bool LWOFile::LoadUVMap(unsigned int iChunkSize) { Layer *pLayer=GetLastLayer(); const char *pChunkEndPos=m_pData+iChunkSize-4; unsigned short iDimension=0; if(!ReadU2(iDimension)) { return false; } // not 2 floats per vertex if(iDimension!=2) { // just skip m_pData+=iChunkSize-4-2; AddError("Warning: UVMap has "+ConvertToString(iDimension)+" floats per vertex (2 expected)"); return true; } unsigned int iStrBytes=0; std::string strName; if(!ReadS0(strName,iStrBytes)) { return false; } // VMAP { type[ID4], dimension[U2], name[S0], // ( vert[VX], value[F4] # dimension )* } UVMap *pUVMap=new UVMap(); pUVMap->m_strName=strName; pUVMap->m_Values.resize(2*pLayer->m_iPoints); pLayer->m_UVMaps.push_back(pUVMap); float *pValues=&(pUVMap->m_Values[0]); memset(pValues,0,sizeof(float)*2*pLayer->m_iPoints); while(m_pData<pChunkEndPos) { unsigned int iVertexID=0; if(!ReadVX(iVertexID)) return false; if(iVertexID>=pLayer->m_iPoints) return false; if(!ReadF4(pValues[iVertexID*2+0])) return false; if(!ReadF4(pValues[iVertexID*2+1])) return false; // flip v coordinate pValues[iVertexID*2+1]=1-pValues[iVertexID*2+1]; } return true; }
void LWOReader::ReadTAGS( UInt32 pChunkSize ) { UInt32 dataRead = 0; String newTag; while( dataRead < pChunkSize ) { newTag = ""; dataRead += ReadS0( newTag ); mObject->mTags.push_back( newTag ); } }
void LWOReader::ReadLAYR( UInt32 pChunkSize ) { UInt32 dataRead = 0; LWLayer* newLayer = GD_NEW(LWLayer, this, "Layer"); dataRead += ReadU2( newLayer->mNumber ); dataRead += ReadU2( newLayer->mFlags ); dataRead += ReadVEC12( newLayer->mPivot ); dataRead += ReadS0( newLayer->mName ); if( dataRead < pChunkSize ) dataRead += ReadU2( newLayer->mParent ); mObject->mLayers.push_back( newLayer ); }
bool LWOFile::LoadTAGS(unsigned int iChunkSize) { if(m_StringTable.size() != 0) { AddError("TAGS already defined!"); return false; } const char *pChunkEndPos=m_pData+iChunkSize; while(m_pData<pChunkEndPos) { std::string strTemp; if(!ReadS0(strTemp)) return false; m_StringTable.push_back(strTemp); } return true; }
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 ); } }
bool LWOFile::LoadLAYR(unsigned int iChunkSize) { Layer *pLayer=new Layer(); m_Layers.push_back(pLayer); // LAYR { number[U2], flags[U2], pivot[VEC12], name[S0], parent[U2] ? } const char *pChunkEndPos=m_pData+iChunkSize; if(!ReadU2(pLayer->m_iID)) return false; if(!ReadU2(pLayer->m_iFlags)) return false; if(!ReadF4(pLayer->m_vPivot[0])) return false; if(!ReadF4(pLayer->m_vPivot[1])) return false; if(!ReadF4(pLayer->m_vPivot[2])) return false; if(!ReadS0(pLayer->m_strName)) return false; // parent id is optional, so read it only if theres data left if(m_pData<pChunkEndPos) { if(!ReadU2(pLayer->m_iParentID)) return false; } else { pLayer->m_iParentID=0; } return true; }
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; }
void LWOReader::ReadBLOK( LWSurface* pSurface, UInt32 pChunkSize ) { UInt32 dataRead = 0; UInt16 subChunkSize; UInt32 subChunkTag; UInt32 bytesHold; LWSurfaceBlock* newSurfaceBlock = GD_NEW(LWSurfaceBlock, this, "SurfaceBlock"); //dataRead += ReadS0( newSurfaceBlock->mOrdinalString ); // Read all subchunks while( dataRead < pChunkSize ) { subChunkTag = ReadSubChunk(subChunkSize,1); dataRead += sizeof(subChunkTag); // Subchunk tag. dataRead += sizeof(subChunkSize); // Subchunk size. bytesHold = dataRead; switch( subChunkTag ) { case ID_IMAP: case ID_PROC: case ID_GRAD: case ID_SHDR: newSurfaceBlock->mType = subChunkTag; ReadHEAD( newSurfaceBlock, subChunkSize ); dataRead += subChunkSize; break; case ID_TMAP: ReadTMAP( &newSurfaceBlock->mTextureMapping, subChunkSize ); dataRead += subChunkSize; break; case ID_PROJ: dataRead += ReadU2( newSurfaceBlock->mImageMap.mProjectionMode ); break; case ID_AXIS: dataRead += ReadU2( newSurfaceBlock->mImageMap.mProjectionAxis ); break; case ID_IMAG: newSurfaceBlock->mImageMap.mValid = true; dataRead += ReadVX( newSurfaceBlock->mImageMap.mImageMap ); break; case ID_WRAP: dataRead += ReadU2( newSurfaceBlock->mImageMap.mWrapModeWidth ); dataRead += ReadU2( newSurfaceBlock->mImageMap.mWrapModeHeight ); break; case ID_VMAP: dataRead += ReadS0( newSurfaceBlock->mImageMap.mUVVertexMapName ); 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 ); } pSurface->mBlocks.push_back( newSurfaceBlock ); }
void LWOReader::ReadSURF( UInt32 pChunkSize ) { UInt32 dataRead = 0; UInt16 subChunkSize; UInt32 subChunkTag; UInt32 bytesHold; LWIndex env; LWSurface* newSurface = GD_NEW(LWSurface, this, "Surface"); dataRead += ReadS0( newSurface->mSurfaceName ); dataRead += ReadS0( newSurface->mSurfaceFile ); // Read all subchunks while( dataRead < pChunkSize ) { if( (pChunkSize - dataRead) < 6 ) { dataRead += Skip( pChunkSize - dataRead ); return; } subChunkTag = ReadSubChunk(subChunkSize); dataRead += sizeof(subChunkTag); // Subchunk tag. dataRead += sizeof(subChunkSize); // Subchunk size. bytesHold = dataRead; switch( subChunkTag ) { case ID_COLR: dataRead += ReadCOL12( newSurface->mBaseColor ); dataRead += ReadVX( env ); break; case ID_DIFF: dataRead += ReadFP4( newSurface->mDiffuse ); dataRead += ReadVX( env ); break; case ID_LUMI: dataRead += ReadFP4( newSurface->mLuminosity ); dataRead += ReadVX( env ); break; case ID_SPEC: dataRead += ReadFP4( newSurface->mSpecular ); dataRead += ReadVX( env ); break; case ID_REFL: dataRead += ReadFP4( newSurface->mReflection ); dataRead += ReadVX( env ); break; case ID_TRAN: dataRead += ReadFP4( newSurface->mTransparency ); dataRead += ReadVX( env ); break; case ID_TRNL: dataRead += ReadFP4( newSurface->mTranslucency ); dataRead += ReadVX( env ); break; case ID_GLOS: dataRead += ReadFP4( newSurface->mSpecularGlossiness ); dataRead += ReadVX( env ); break; case ID_SHRP: dataRead += ReadFP4( newSurface->mDiffuseSharpness ); dataRead += ReadVX( env ); break; case ID_BUMP: dataRead += ReadFP4( newSurface->mBumpStrength ); dataRead += ReadVX( env ); break; case ID_SIDE: dataRead += ReadU2( newSurface->mPolySide ); break; case ID_SMAN: dataRead += ReadANG4( newSurface->mMaxSmoothingAngle ); break; case ID_RFOP: dataRead += ReadU2( newSurface->mReflectionOptions ); break; case ID_RIMG: dataRead += ReadVX( newSurface->mReflectionMapImage ); break; case ID_RSAN: dataRead += ReadANG4( newSurface->mReflMapSeamAngle ); dataRead += ReadVX( env ); break; case ID_RBLR: dataRead += ReadFP4( newSurface->mReflBlurPercent ); dataRead += ReadVX( env ); break; case ID_CLRH: dataRead += ReadFP4( newSurface->mColorHighlights ); dataRead += ReadVX( env ); break; case ID_TROP: dataRead += ReadU2( newSurface->mTransparencyOptions ); dataRead += Skip( subChunkSize - sizeof(UInt16) ); break; case ID_CLRF: dataRead += ReadFP4( newSurface->mColorFilter ); dataRead += ReadVX( env ); break; case ID_ADTR: dataRead += ReadFP4( newSurface->mAdditiveTransparency ); dataRead += ReadVX( env ); break; case ID_ALPH: dataRead += ReadU2( newSurface->mAlphaMode ); dataRead += ReadFP4( newSurface->mAlphaValue ); break; case ID_BLOK: ReadBLOK( newSurface, subChunkSize ); dataRead += subChunkSize; break; case ID_VCOL: case ID_LINE: case ID_GLOW: case ID_TBLR: case ID_TIMG: case ID_RIND: 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 ); } mObject->mSurfaces.push_back( newSurface ); }
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 ); }
void LWOReader::ReadCLIP( UInt32 pChunkSize ) { UInt32 dataRead = 0; UInt32 subChunkTag; UInt16 subChunkSize; UInt32 bytesHold; LWClip* newClip = GD_NEW(LWClip, this, "Clip"); dataRead += ReadU4( newClip->mIndex ); // Read all subchunks while( dataRead < pChunkSize ) { if( (pChunkSize - dataRead) < 6 ) { dataRead += Skip( pChunkSize - dataRead ); return; } subChunkTag = ReadSubChunk(subChunkSize); dataRead += sizeof(subChunkTag); // Subchunk tag. dataRead += sizeof(subChunkSize); // Subchunk size. bytesHold = dataRead; switch( subChunkTag ) { case ID_STIL: dataRead += ReadS0( newClip->mStillImage ); break; case ID_XREF: dataRead += ReadVX( newClip->mXRefIndex ); dataRead += ReadS0( newClip->mXRefInstName ); break; case ID_ISEQ: case ID_ANIM: case ID_STCC: case ID_TIME: case ID_CONT: case ID_BRIT: case ID_SATR: case ID_HUE: case ID_GAMM: case ID_NEGA: case ID_IFLT: case ID_PFLT: 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 ); } mObject->mClips.push_back( newClip ); }