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; }
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; }
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::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 ); }