LWO: replace legacy reinterpret_cast based code by memcpy to solve Android SIGBUS problems due to unaligned accesses. Fixes #351
parent
1a594b861a
commit
185f01963f
46
code/IFF.h
46
code/IFF.h
|
@ -12,8 +12,6 @@
|
|||
namespace Assimp {
|
||||
namespace IFF {
|
||||
|
||||
#include "./../include/assimp/Compiler/pushpack1.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//! Describes an IFF chunk header
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -24,7 +22,7 @@ struct ChunkHeader
|
|||
|
||||
//! Length of the chunk data, in bytes
|
||||
uint32_t length;
|
||||
} PACK_STRUCT;
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -37,9 +35,7 @@ struct SubChunkHeader
|
|||
|
||||
//! Length of the chunk data, in bytes
|
||||
uint16_t length;
|
||||
} PACK_STRUCT;
|
||||
|
||||
#include "./../include/assimp/Compiler/poppack1.h"
|
||||
};
|
||||
|
||||
|
||||
#define AI_IFF_FOURCC(a,b,c,d) ((uint32_t) (((uint8_t)a << 24u) | \
|
||||
|
@ -52,28 +48,34 @@ struct SubChunkHeader
|
|||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//! Load a chunk header
|
||||
//! @param outFile Pointer to the file data - points to the chunk data afterwards
|
||||
//! @return Pointer to the chunk header
|
||||
//! @return Copy of the chunk header
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
inline ChunkHeader* LoadChunk(uint8_t*& outFile)
|
||||
inline ChunkHeader LoadChunk(uint8_t*& outFile)
|
||||
{
|
||||
ChunkHeader* head = (ChunkHeader*) outFile;
|
||||
AI_LSWAP4(head->length);
|
||||
AI_LSWAP4(head->type);
|
||||
outFile += sizeof(ChunkHeader);
|
||||
ChunkHeader head;
|
||||
::memcpy(&head.type, outFile, 4);
|
||||
outFile += 4;
|
||||
::memcpy(&head.length, outFile, 4);
|
||||
outFile += 4;
|
||||
AI_LSWAP4(head.length);
|
||||
AI_LSWAP4(head.type);
|
||||
return head;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//! Load a sub chunk header
|
||||
//! @param outFile Pointer to the file data - points to the chunk data afterwards
|
||||
//! @return Pointer to the sub chunk header
|
||||
//! @return Copy of the sub chunk header
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
inline SubChunkHeader* LoadSubChunk(uint8_t*& outFile)
|
||||
inline SubChunkHeader LoadSubChunk(uint8_t*& outFile)
|
||||
{
|
||||
SubChunkHeader* head = (SubChunkHeader*) outFile;
|
||||
AI_LSWAP2(head->length);
|
||||
AI_LSWAP4(head->type);
|
||||
outFile += sizeof(SubChunkHeader);
|
||||
SubChunkHeader head;
|
||||
::memcpy(&head.type, outFile, 4);
|
||||
outFile += 4;
|
||||
::memcpy(&head.length, outFile, 2);
|
||||
outFile += 2;
|
||||
AI_LSWAP2(head.length);
|
||||
AI_LSWAP4(head.type);
|
||||
return head;
|
||||
}
|
||||
|
||||
|
@ -84,14 +86,14 @@ inline SubChunkHeader* LoadSubChunk(uint8_t*& outFile)
|
|||
//! @param fileType Receives the type of the file
|
||||
//! @return 0 if everything was OK, otherwise an error message
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
inline const char* ReadHeader(uint8_t* outFile,uint32_t& fileType)
|
||||
inline const char* ReadHeader(uint8_t* outFile, uint32_t& fileType)
|
||||
{
|
||||
ChunkHeader* head = LoadChunk(outFile);
|
||||
if(AI_IFF_FOURCC_FORM != head->type)
|
||||
ChunkHeader head = LoadChunk(outFile);
|
||||
if(AI_IFF_FOURCC_FORM != head.type)
|
||||
{
|
||||
return "The file is not an IFF file: FORM chunk is missing";
|
||||
}
|
||||
fileType = *((uint32_t*)(head+1));
|
||||
::memcpy(&fileType, outFile, 4);
|
||||
AI_LSWAP4(fileType);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -58,30 +58,31 @@ void LWOImporter::LoadLWOBFile()
|
|||
while (running)
|
||||
{
|
||||
if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)break;
|
||||
LE_NCONST IFF::ChunkHeader* const head = IFF::LoadChunk(mFileBuffer);
|
||||
const IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
|
||||
|
||||
if (mFileBuffer + head->length > end)
|
||||
if (mFileBuffer + head.length > end)
|
||||
{
|
||||
throw DeadlyImportError("LWOB: Invalid chunk length");
|
||||
break;
|
||||
}
|
||||
uint8_t* const next = mFileBuffer+head->length;
|
||||
switch (head->type)
|
||||
uint8_t* const next = mFileBuffer+head.length;
|
||||
switch (head.type)
|
||||
{
|
||||
// vertex list
|
||||
case AI_LWO_PNTS:
|
||||
{
|
||||
if (!mCurLayer->mTempPoints.empty())
|
||||
DefaultLogger::get()->warn("LWO: PNTS chunk encountered twice");
|
||||
else LoadLWOPoints(head->length);
|
||||
else LoadLWOPoints(head.length);
|
||||
break;
|
||||
}
|
||||
// face list
|
||||
case AI_LWO_POLS:
|
||||
{
|
||||
|
||||
if (!mCurLayer->mFaces.empty())
|
||||
DefaultLogger::get()->warn("LWO: POLS chunk encountered twice");
|
||||
else LoadLWOBPolygons(head->length);
|
||||
else LoadLWOBPolygons(head.length);
|
||||
break;
|
||||
}
|
||||
// list of tags
|
||||
|
@ -89,14 +90,14 @@ void LWOImporter::LoadLWOBFile()
|
|||
{
|
||||
if (!mTags->empty())
|
||||
DefaultLogger::get()->warn("LWO: SRFS chunk encountered twice");
|
||||
else LoadLWOTags(head->length);
|
||||
else LoadLWOTags(head.length);
|
||||
break;
|
||||
}
|
||||
|
||||
// surface chunk
|
||||
case AI_LWO_SURF:
|
||||
{
|
||||
LoadLWOBSurface(head->length);
|
||||
LoadLWOBSurface(head.length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -137,14 +138,17 @@ void LWOImporter::CountVertsAndFacesLWOB(unsigned int& verts, unsigned int& face
|
|||
{
|
||||
while (cursor < end && max--)
|
||||
{
|
||||
uint16_t numIndices = *cursor++;
|
||||
verts += numIndices;faces++;
|
||||
uint16_t numIndices;
|
||||
::memcpy(&numIndices, cursor++, 2);
|
||||
verts += numIndices;
|
||||
faces++;
|
||||
cursor += numIndices;
|
||||
int16_t surface = *cursor++;
|
||||
int16_t surface;
|
||||
::memcpy(&surface, cursor++, 2);
|
||||
if (surface < 0)
|
||||
{
|
||||
// there are detail polygons
|
||||
numIndices = *cursor++;
|
||||
::memcpy(&numIndices, cursor++, 2);
|
||||
CountVertsAndFacesLWOB(verts,faces,cursor,end,numIndices);
|
||||
}
|
||||
}
|
||||
|
@ -159,13 +163,22 @@ void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it,
|
|||
while (cursor < end && max--)
|
||||
{
|
||||
LWO::Face& face = *it;++it;
|
||||
if((face.mNumIndices = *cursor++))
|
||||
uint16_t numIndices;
|
||||
::memcpy(&numIndices, cursor++, 2);
|
||||
face.mNumIndices = numIndices;
|
||||
if(face.mNumIndices)
|
||||
{
|
||||
if (cursor + face.mNumIndices >= end)break;
|
||||
if (cursor + face.mNumIndices >= end)
|
||||
{
|
||||
break;
|
||||
}
|
||||
face.mIndices = new unsigned int[face.mNumIndices];
|
||||
for (unsigned int i = 0; i < face.mNumIndices;++i)
|
||||
{
|
||||
unsigned int & mi = face.mIndices[i] = *cursor++;
|
||||
unsigned int & mi = face.mIndices[i];
|
||||
uint16_t index;
|
||||
::memcpy(&index, cursor++, 2);
|
||||
mi = index;
|
||||
if (mi > mCurLayer->mTempPoints.size())
|
||||
{
|
||||
DefaultLogger::get()->warn("LWOB: face index is out of range");
|
||||
|
@ -174,14 +187,19 @@ void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it,
|
|||
}
|
||||
}
|
||||
else DefaultLogger::get()->warn("LWOB: Face has 0 indices");
|
||||
int16_t surface = *cursor++;
|
||||
int16_t surface;
|
||||
::memcpy(&surface, cursor++, 2);
|
||||
if (surface < 0)
|
||||
{
|
||||
surface = -surface;
|
||||
|
||||
// there are detail polygons.
|
||||
const uint16_t numPolygons = *cursor++;
|
||||
if (cursor < end)CopyFaceIndicesLWOB(it,cursor,end,numPolygons);
|
||||
uint16_t numPolygons;
|
||||
::memcpy(&numPolygons, cursor++, 2);
|
||||
if (cursor < end)
|
||||
{
|
||||
CopyFaceIndicesLWOB(it,cursor,end,numPolygons);
|
||||
}
|
||||
}
|
||||
face.surfaceIndex = surface-1;
|
||||
}
|
||||
|
@ -235,7 +253,7 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
|
|||
if (mFileBuffer + 6 >= end)
|
||||
break;
|
||||
|
||||
IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
|
||||
IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
|
||||
|
||||
/* A single test file (sonycam.lwo) seems to have invalid surface chunks.
|
||||
* I'm assuming it's the fault of a single, unknown exporter so there are
|
||||
|
@ -244,18 +262,18 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
|
|||
* We don't break if the chunk limit is exceeded. Instead, we're computing
|
||||
* how much storage is actually left and work with this value from now on.
|
||||
*/
|
||||
if (mFileBuffer + head->length > end) {
|
||||
if (mFileBuffer + head.length > end) {
|
||||
DefaultLogger::get()->error("LWOB: Invalid surface chunk length. Trying to continue.");
|
||||
head->length = (uint16_t) (end - mFileBuffer);
|
||||
head.length = (uint16_t) (end - mFileBuffer);
|
||||
}
|
||||
|
||||
uint8_t* const next = mFileBuffer+head->length;
|
||||
switch (head->type)
|
||||
uint8_t* const next = mFileBuffer+head.length;
|
||||
switch (head.type)
|
||||
{
|
||||
// diffuse color
|
||||
case AI_LWO_COLR:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,COLR,3);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,COLR,3);
|
||||
surf.mColor.r = GetU1() / 255.0f;
|
||||
surf.mColor.g = GetU1() / 255.0f;
|
||||
surf.mColor.b = GetU1() / 255.0f;
|
||||
|
@ -264,35 +282,35 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
|
|||
// diffuse strength ...
|
||||
case AI_LWO_DIFF:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,DIFF,2);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,DIFF,2);
|
||||
surf.mDiffuseValue = GetU2() / 255.0f;
|
||||
break;
|
||||
}
|
||||
// specular strength ...
|
||||
case AI_LWO_SPEC:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SPEC,2);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SPEC,2);
|
||||
surf.mSpecularValue = GetU2() / 255.0f;
|
||||
break;
|
||||
}
|
||||
// luminosity ...
|
||||
case AI_LWO_LUMI:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LUMI,2);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,LUMI,2);
|
||||
surf.mLuminosity = GetU2() / 255.0f;
|
||||
break;
|
||||
}
|
||||
// transparency
|
||||
case AI_LWO_TRAN:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TRAN,2);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TRAN,2);
|
||||
surf.mTransparency = GetU2() / 255.0f;
|
||||
break;
|
||||
}
|
||||
// surface flags
|
||||
case AI_LWO_FLAG:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,FLAG,2);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,FLAG,2);
|
||||
uint16_t flag = GetU2();
|
||||
if (flag & 0x4 ) surf.mMaximumSmoothAngle = 1.56207f;
|
||||
if (flag & 0x8 ) surf.mColorHighlights = 1.f;
|
||||
|
@ -302,14 +320,14 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
|
|||
// maximum smoothing angle
|
||||
case AI_LWO_SMAN:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SMAN,4);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SMAN,4);
|
||||
surf.mMaximumSmoothAngle = fabs( GetF4() );
|
||||
break;
|
||||
}
|
||||
// glossiness
|
||||
case AI_LWO_GLOS:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,GLOS,2);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,GLOS,2);
|
||||
surf.mGlossiness = (float)GetU2();
|
||||
break;
|
||||
}
|
||||
|
@ -317,42 +335,42 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
|
|||
case AI_LWO_CTEX:
|
||||
{
|
||||
pTex = SetupNewTextureLWOB(surf.mColorTextures,
|
||||
head->length);
|
||||
head.length);
|
||||
break;
|
||||
}
|
||||
// diffuse texture
|
||||
case AI_LWO_DTEX:
|
||||
{
|
||||
pTex = SetupNewTextureLWOB(surf.mDiffuseTextures,
|
||||
head->length);
|
||||
head.length);
|
||||
break;
|
||||
}
|
||||
// specular texture
|
||||
case AI_LWO_STEX:
|
||||
{
|
||||
pTex = SetupNewTextureLWOB(surf.mSpecularTextures,
|
||||
head->length);
|
||||
head.length);
|
||||
break;
|
||||
}
|
||||
// bump texture
|
||||
case AI_LWO_BTEX:
|
||||
{
|
||||
pTex = SetupNewTextureLWOB(surf.mBumpTextures,
|
||||
head->length);
|
||||
head.length);
|
||||
break;
|
||||
}
|
||||
// transparency texture
|
||||
case AI_LWO_TTEX:
|
||||
{
|
||||
pTex = SetupNewTextureLWOB(surf.mOpacityTextures,
|
||||
head->length);
|
||||
head.length);
|
||||
break;
|
||||
}
|
||||
// texture path
|
||||
case AI_LWO_TIMG:
|
||||
{
|
||||
if (pTex) {
|
||||
GetS0(pTex->mFileName,head->length);
|
||||
GetS0(pTex->mFileName,head.length);
|
||||
}
|
||||
else DefaultLogger::get()->warn("LWOB: Unexpected TIMG chunk");
|
||||
break;
|
||||
|
@ -360,7 +378,7 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
|
|||
// texture strength
|
||||
case AI_LWO_TVAL:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TVAL,1);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TVAL,1);
|
||||
if (pTex) {
|
||||
pTex->mStrength = (float)GetU1()/ 255.f;
|
||||
}
|
||||
|
@ -370,7 +388,7 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
|
|||
// texture flags
|
||||
case AI_LWO_TFLG:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TFLG,2);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TFLG,2);
|
||||
|
||||
if (pTex)
|
||||
{
|
||||
|
|
|
@ -787,7 +787,8 @@ void LWOImporter::LoadLWO2Polygons(unsigned int length)
|
|||
CountVertsAndFacesLWO2(iNumVertices,iNumFaces,cursor,end);
|
||||
|
||||
// allocate the output array and copy face indices
|
||||
if (iNumFaces) {
|
||||
if (iNumFaces)
|
||||
{
|
||||
cursor = (uint16_t*)mFileBuffer;
|
||||
|
||||
mCurLayer->mFaces.resize(iNumFaces,LWO::Face(type));
|
||||
|
@ -802,13 +803,18 @@ void LWOImporter::CountVertsAndFacesLWO2(unsigned int& verts, unsigned int& face
|
|||
{
|
||||
while (cursor < end && max--)
|
||||
{
|
||||
AI_LSWAP2P(cursor);
|
||||
uint16_t numIndices = *cursor++;
|
||||
uint16_t numIndices;
|
||||
::memcpy(&numIndices, cursor++, 2);
|
||||
AI_LSWAP2(numIndices);
|
||||
numIndices &= 0x03FF;
|
||||
verts += numIndices;++faces;
|
||||
|
||||
verts += numIndices;
|
||||
++faces;
|
||||
|
||||
for(uint16_t i = 0; i < numIndices; i++)
|
||||
{
|
||||
ReadVSizedIntLWO2((uint8_t*&)cursor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -817,10 +823,16 @@ void LWOImporter::CopyFaceIndicesLWO2(FaceList::iterator& it,
|
|||
uint16_t*& cursor,
|
||||
const uint16_t* const end)
|
||||
{
|
||||
while (cursor < end) {
|
||||
|
||||
LWO::Face& face = *it++;;
|
||||
if((face.mNumIndices = (*cursor++) & 0x03FF)) /* byte swapping has already been done */ {
|
||||
while (cursor < end)
|
||||
{
|
||||
LWO::Face& face = *it++;
|
||||
uint16_t numIndices;
|
||||
::memcpy(&numIndices, cursor++, 2);
|
||||
AI_LSWAP2(numIndices);
|
||||
face.mNumIndices = numIndices & 0x03FF;
|
||||
|
||||
if(face.mNumIndices) /* byte swapping has already been done */
|
||||
{
|
||||
face.mIndices = new unsigned int[face.mNumIndices];
|
||||
for(unsigned int i = 0; i < face.mNumIndices; i++)
|
||||
{
|
||||
|
@ -848,8 +860,8 @@ void LWOImporter::LoadLWO2PolygonTags(unsigned int length)
|
|||
if (type != AI_LWO_SURF && type != AI_LWO_SMGP)
|
||||
return;
|
||||
|
||||
while (mFileBuffer < end) {
|
||||
|
||||
while (mFileBuffer < end)
|
||||
{
|
||||
unsigned int i = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mFaceIDXOfs;
|
||||
unsigned int j = GetU2();
|
||||
|
||||
|
@ -1106,19 +1118,19 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
|
|||
// first - get the index of the clip
|
||||
clip.idx = GetU4();
|
||||
|
||||
IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
|
||||
switch (head->type)
|
||||
IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
|
||||
switch (head.type)
|
||||
{
|
||||
case AI_LWO_STIL:
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,STIL,1);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,STIL,1);
|
||||
|
||||
// "Normal" texture
|
||||
GetS0(clip.path,head->length);
|
||||
GetS0(clip.path,head.length);
|
||||
clip.type = Clip::STILL;
|
||||
break;
|
||||
|
||||
case AI_LWO_ISEQ:
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,ISEQ,16);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,ISEQ,16);
|
||||
// Image sequence. We'll later take the first.
|
||||
{
|
||||
uint8_t digits = GetU1(); mFileBuffer++;
|
||||
|
@ -1127,12 +1139,12 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
|
|||
|
||||
std::string s;
|
||||
std::ostringstream ss;
|
||||
GetS0(s,head->length);
|
||||
GetS0(s,head.length);
|
||||
|
||||
head->length -= (unsigned int)s.length()+1;
|
||||
head.length -= (unsigned int)s.length()+1;
|
||||
ss << s;
|
||||
ss << std::setw(digits) << offset + start;
|
||||
GetS0(s,head->length);
|
||||
GetS0(s,head.length);
|
||||
ss << s;
|
||||
clip.path = ss.str();
|
||||
clip.type = Clip::SEQ;
|
||||
|
@ -1148,7 +1160,7 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
|
|||
break;
|
||||
|
||||
case AI_LWO_XREF:
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,XREF,4);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,XREF,4);
|
||||
|
||||
// Just a cross-reference to another CLIp
|
||||
clip.type = Clip::REF;
|
||||
|
@ -1156,7 +1168,7 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
|
|||
break;
|
||||
|
||||
case AI_LWO_NEGA:
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,NEGA,2);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,NEGA,2);
|
||||
clip.negate = (0 != GetU2());
|
||||
break;
|
||||
|
||||
|
@ -1194,17 +1206,17 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length)
|
|||
while (true)
|
||||
{
|
||||
if (mFileBuffer + 6 >= end)break;
|
||||
LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
|
||||
LE_NCONST IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
|
||||
|
||||
if (mFileBuffer + head->length > end)
|
||||
if (mFileBuffer + head.length > end)
|
||||
throw DeadlyImportError("LWO2: Invalid envelope chunk length");
|
||||
|
||||
uint8_t* const next = mFileBuffer+head->length;
|
||||
switch (head->type)
|
||||
uint8_t* const next = mFileBuffer+head.length;
|
||||
switch (head.type)
|
||||
{
|
||||
// Type & representation of the envelope
|
||||
case AI_LWO_TYPE:
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TYPE,2);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TYPE,2);
|
||||
mFileBuffer++; // skip user format
|
||||
|
||||
// Determine type of envelope
|
||||
|
@ -1214,20 +1226,20 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length)
|
|||
|
||||
// precondition
|
||||
case AI_LWO_PRE:
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,PRE,2);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,PRE,2);
|
||||
envelope.pre = (LWO::PrePostBehaviour)GetU2();
|
||||
break;
|
||||
|
||||
// postcondition
|
||||
case AI_LWO_POST:
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,POST,2);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,POST,2);
|
||||
envelope.post = (LWO::PrePostBehaviour)GetU2();
|
||||
break;
|
||||
|
||||
// keyframe
|
||||
case AI_LWO_KEY:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,KEY,8);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,KEY,8);
|
||||
|
||||
envelope.keys.push_back(LWO::Key());
|
||||
LWO::Key& key = envelope.keys.back();
|
||||
|
@ -1240,7 +1252,7 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length)
|
|||
// interval interpolation
|
||||
case AI_LWO_SPAN:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SPAN,4);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SPAN,4);
|
||||
if (envelope.keys.size()<2)
|
||||
DefaultLogger::get()->warn("LWO2: Unexpected SPAN chunk");
|
||||
else {
|
||||
|
@ -1286,22 +1298,22 @@ void LWOImporter::LoadLWO2File()
|
|||
while (true)
|
||||
{
|
||||
if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)break;
|
||||
IFF::ChunkHeader* const head = IFF::LoadChunk(mFileBuffer);
|
||||
const IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
|
||||
|
||||
if (mFileBuffer + head->length > end)
|
||||
if (mFileBuffer + head.length > end)
|
||||
{
|
||||
throw DeadlyImportError("LWO2: Chunk length points behind the file");
|
||||
break;
|
||||
}
|
||||
uint8_t* const next = mFileBuffer+head->length;
|
||||
uint8_t* const next = mFileBuffer+head.length;
|
||||
unsigned int iUnnamed = 0;
|
||||
|
||||
if(!head->length) {
|
||||
if(!head.length) {
|
||||
mFileBuffer = next;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (head->type)
|
||||
switch (head.type)
|
||||
{
|
||||
// new layer
|
||||
case AI_LWO_LAYR:
|
||||
|
@ -1311,7 +1323,7 @@ void LWOImporter::LoadLWO2File()
|
|||
LWO::Layer& layer = mLayers->back();
|
||||
mCurLayer = &layer;
|
||||
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LAYR,16);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,LAYR,16);
|
||||
|
||||
// layer index.
|
||||
layer.mIndex = GetU2();
|
||||
|
@ -1327,7 +1339,7 @@ void LWOImporter::LoadLWO2File()
|
|||
mCurLayer->mPivot.x = GetF4();
|
||||
mCurLayer->mPivot.y = GetF4();
|
||||
mCurLayer->mPivot.z = GetF4();
|
||||
GetS0(layer.mName,head->length-16);
|
||||
GetS0(layer.mName,head.length-16);
|
||||
|
||||
// if the name is empty, generate a default name
|
||||
if (layer.mName.empty()) {
|
||||
|
@ -1360,7 +1372,7 @@ void LWOImporter::LoadLWO2File()
|
|||
break;
|
||||
|
||||
unsigned int old = (unsigned int)mCurLayer->mTempPoints.size();
|
||||
LoadLWOPoints(head->length);
|
||||
LoadLWOPoints(head.length);
|
||||
mCurLayer->mPointIDXOfs = old;
|
||||
break;
|
||||
}
|
||||
|
@ -1379,7 +1391,7 @@ void LWOImporter::LoadLWO2File()
|
|||
|
||||
if (mCurLayer->mTempPoints.empty())
|
||||
DefaultLogger::get()->warn("LWO2: Unexpected VMAP chunk");
|
||||
else LoadLWO2VertexMap(head->length,head->type == AI_LWO_VMAD);
|
||||
else LoadLWO2VertexMap(head.length,head.type == AI_LWO_VMAD);
|
||||
break;
|
||||
}
|
||||
// face list
|
||||
|
@ -1389,7 +1401,7 @@ void LWOImporter::LoadLWO2File()
|
|||
break;
|
||||
|
||||
unsigned int old = (unsigned int)mCurLayer->mFaces.size();
|
||||
LoadLWO2Polygons(head->length);
|
||||
LoadLWO2Polygons(head.length);
|
||||
mCurLayer->mFaceIDXOfs = old;
|
||||
break;
|
||||
}
|
||||
|
@ -1401,7 +1413,7 @@ void LWOImporter::LoadLWO2File()
|
|||
|
||||
if (mCurLayer->mFaces.empty())
|
||||
DefaultLogger::get()->warn("LWO2: Unexpected PTAG");
|
||||
else LoadLWO2PolygonTags(head->length);
|
||||
else LoadLWO2PolygonTags(head.length);
|
||||
break;
|
||||
}
|
||||
// list of tags
|
||||
|
@ -1409,28 +1421,28 @@ void LWOImporter::LoadLWO2File()
|
|||
{
|
||||
if (!mTags->empty())
|
||||
DefaultLogger::get()->warn("LWO2: SRFS chunk encountered twice");
|
||||
else LoadLWOTags(head->length);
|
||||
else LoadLWOTags(head.length);
|
||||
break;
|
||||
}
|
||||
|
||||
// surface chunk
|
||||
case AI_LWO_SURF:
|
||||
{
|
||||
LoadLWO2Surface(head->length);
|
||||
LoadLWO2Surface(head.length);
|
||||
break;
|
||||
}
|
||||
|
||||
// clip chunk
|
||||
case AI_LWO_CLIP:
|
||||
{
|
||||
LoadLWO2Clip(head->length);
|
||||
LoadLWO2Clip(head.length);
|
||||
break;
|
||||
}
|
||||
|
||||
// envelope chunk
|
||||
case AI_LWO_ENVL:
|
||||
{
|
||||
LoadLWO2Envelope(head->length);
|
||||
LoadLWO2Envelope(head.length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -402,7 +402,9 @@ protected:
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
inline float LWOImporter::GetF4()
|
||||
{
|
||||
float f = *((float*)mFileBuffer);mFileBuffer += 4;
|
||||
float f;
|
||||
::memcpy(&f, mFileBuffer, 4);
|
||||
mFileBuffer += 4;
|
||||
AI_LSWAP4(f);
|
||||
return f;
|
||||
}
|
||||
|
@ -410,7 +412,9 @@ inline float LWOImporter::GetF4()
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
inline uint32_t LWOImporter::GetU4()
|
||||
{
|
||||
uint32_t f = *((uint32_t*)mFileBuffer);mFileBuffer += 4;
|
||||
uint32_t f;
|
||||
::memcpy(&f, mFileBuffer, 4);
|
||||
mFileBuffer += 4;
|
||||
AI_LSWAP4(f);
|
||||
return f;
|
||||
}
|
||||
|
@ -418,7 +422,9 @@ inline uint32_t LWOImporter::GetU4()
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
inline uint16_t LWOImporter::GetU2()
|
||||
{
|
||||
uint16_t f = *((uint16_t*)mFileBuffer);mFileBuffer += 2;
|
||||
uint16_t f;
|
||||
::memcpy(&f, mFileBuffer, 2);
|
||||
mFileBuffer += 2;
|
||||
AI_LSWAP2(f);
|
||||
return f;
|
||||
}
|
||||
|
|
|
@ -527,13 +527,13 @@ void LWOImporter::LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex )
|
|||
while (true)
|
||||
{
|
||||
if (mFileBuffer + 6 >= end)break;
|
||||
LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
|
||||
LE_NCONST IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
|
||||
|
||||
if (mFileBuffer + head->length > end)
|
||||
if (mFileBuffer + head.length > end)
|
||||
throw DeadlyImportError("LWO2: Invalid SURF.BLOCK chunk length");
|
||||
|
||||
uint8_t* const next = mFileBuffer+head->length;
|
||||
switch (head->type)
|
||||
uint8_t* const next = mFileBuffer+head.length;
|
||||
switch (head.type)
|
||||
{
|
||||
case AI_LWO_PROJ:
|
||||
tex.mapMode = (Texture::MappingMode)GetU2();
|
||||
|
@ -549,7 +549,7 @@ void LWOImporter::LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex )
|
|||
tex.mClipIdx = GetU2();
|
||||
break;
|
||||
case AI_LWO_VMAP:
|
||||
GetS0(tex.mUVChannelIndex,head->length);
|
||||
GetS0(tex.mUVChannelIndex,head.length);
|
||||
break;
|
||||
case AI_LWO_WRPH:
|
||||
tex.wrapAmountH = GetF4();
|
||||
|
@ -595,13 +595,13 @@ void LWOImporter::LoadLWO2TextureHeader(unsigned int size, LWO::Texture& tex )
|
|||
while (true)
|
||||
{
|
||||
if (mFileBuffer + 6 >= end)break;
|
||||
LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
|
||||
const IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
|
||||
|
||||
if (mFileBuffer + head->length > end)
|
||||
if (mFileBuffer + head.length > end)
|
||||
throw DeadlyImportError("LWO2: Invalid texture header chunk length");
|
||||
|
||||
uint8_t* const next = mFileBuffer+head->length;
|
||||
switch (head->type)
|
||||
uint8_t* const next = mFileBuffer+head.length;
|
||||
switch (head.type)
|
||||
{
|
||||
case AI_LWO_CHAN:
|
||||
tex.type = GetU4();
|
||||
|
@ -698,20 +698,20 @@ void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader* /*head*/, u
|
|||
while (true)
|
||||
{
|
||||
if (mFileBuffer + 6 >= end)break;
|
||||
LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
|
||||
const IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
|
||||
|
||||
if (mFileBuffer + head->length > end)
|
||||
if (mFileBuffer + head.length > end)
|
||||
throw DeadlyImportError("LWO2: Invalid shader header chunk length");
|
||||
|
||||
uint8_t* const next = mFileBuffer+head->length;
|
||||
switch (head->type)
|
||||
uint8_t* const next = mFileBuffer+head.length;
|
||||
switch (head.type)
|
||||
{
|
||||
case AI_LWO_ENAB:
|
||||
shader.enabled = GetU2() ? true : false;
|
||||
break;
|
||||
|
||||
case AI_LWO_FUNC:
|
||||
GetS0( shader.functionName, head->length );
|
||||
GetS0( shader.functionName, head.length );
|
||||
}
|
||||
mFileBuffer = next;
|
||||
}
|
||||
|
@ -756,18 +756,18 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
|
|||
{
|
||||
if (mFileBuffer + 6 >= end)
|
||||
break;
|
||||
LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
|
||||
const IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
|
||||
|
||||
if (mFileBuffer + head->length > end)
|
||||
if (mFileBuffer + head.length > end)
|
||||
throw DeadlyImportError("LWO2: Invalid surface chunk length");
|
||||
|
||||
uint8_t* const next = mFileBuffer+head->length;
|
||||
switch (head->type)
|
||||
uint8_t* const next = mFileBuffer+head.length;
|
||||
switch (head.type)
|
||||
{
|
||||
// diffuse color
|
||||
case AI_LWO_COLR:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,COLR,12);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,COLR,12);
|
||||
surf.mColor.r = GetF4();
|
||||
surf.mColor.g = GetF4();
|
||||
surf.mColor.b = GetF4();
|
||||
|
@ -776,14 +776,14 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
|
|||
// diffuse strength ... hopefully
|
||||
case AI_LWO_DIFF:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,DIFF,4);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,DIFF,4);
|
||||
surf.mDiffuseValue = GetF4();
|
||||
break;
|
||||
}
|
||||
// specular strength ... hopefully
|
||||
case AI_LWO_SPEC:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SPEC,4);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SPEC,4);
|
||||
surf.mSpecularValue = GetF4();
|
||||
break;
|
||||
}
|
||||
|
@ -794,21 +794,21 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
|
|||
if (surf.mTransparency == 10e10f)
|
||||
break;
|
||||
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TRAN,4);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TRAN,4);
|
||||
surf.mTransparency = GetF4();
|
||||
break;
|
||||
}
|
||||
// additive transparency
|
||||
case AI_LWO_ADTR:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,ADTR,4);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,ADTR,4);
|
||||
surf.mAdditiveTransparency = GetF4();
|
||||
break;
|
||||
}
|
||||
// wireframe mode
|
||||
case AI_LWO_LINE:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LINE,2);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,LINE,2);
|
||||
if (GetU2() & 0x1)
|
||||
surf.mWireframe = true;
|
||||
break;
|
||||
|
@ -816,49 +816,49 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
|
|||
// glossiness
|
||||
case AI_LWO_GLOS:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,GLOS,4);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,GLOS,4);
|
||||
surf.mGlossiness = GetF4();
|
||||
break;
|
||||
}
|
||||
// bump intensity
|
||||
case AI_LWO_BUMP:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,BUMP,4);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,BUMP,4);
|
||||
surf.mBumpIntensity = GetF4();
|
||||
break;
|
||||
}
|
||||
// color highlights
|
||||
case AI_LWO_CLRH:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,CLRH,4);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,CLRH,4);
|
||||
surf.mColorHighlights = GetF4();
|
||||
break;
|
||||
}
|
||||
// index of refraction
|
||||
case AI_LWO_RIND:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,RIND,4);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,RIND,4);
|
||||
surf.mIOR = GetF4();
|
||||
break;
|
||||
}
|
||||
// polygon sidedness
|
||||
case AI_LWO_SIDE:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SIDE,2);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SIDE,2);
|
||||
surf.bDoubleSided = (3 == GetU2());
|
||||
break;
|
||||
}
|
||||
// maximum smoothing angle
|
||||
case AI_LWO_SMAN:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SMAN,4);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SMAN,4);
|
||||
surf.mMaximumSmoothAngle = fabs( GetF4() );
|
||||
break;
|
||||
}
|
||||
// vertex color channel to be applied to the surface
|
||||
case AI_LWO_VCOL:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,VCOL,12);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,VCOL,12);
|
||||
surf.mDiffuseValue *= GetF4(); // strength
|
||||
ReadVSizedIntLWO2(mFileBuffer); // skip envelope
|
||||
surf.mVCMapType = GetU4(); // type of the channel
|
||||
|
@ -870,18 +870,18 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
|
|||
// surface bock entry
|
||||
case AI_LWO_BLOK:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,BLOK,4);
|
||||
LE_NCONST IFF::SubChunkHeader* head2 = IFF::LoadSubChunk(mFileBuffer);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,BLOK,4);
|
||||
IFF::SubChunkHeader head2 = IFF::LoadSubChunk(mFileBuffer);
|
||||
|
||||
switch (head2->type)
|
||||
switch (head2.type)
|
||||
{
|
||||
case AI_LWO_PROC:
|
||||
case AI_LWO_GRAD:
|
||||
case AI_LWO_IMAP:
|
||||
LoadLWO2TextureBlock(head2, head->length);
|
||||
LoadLWO2TextureBlock(&head2, head.length);
|
||||
break;
|
||||
case AI_LWO_SHDR:
|
||||
LoadLWO2ShaderBlock(head2, head->length);
|
||||
LoadLWO2ShaderBlock(&head2, head.length);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
Loading…
Reference in New Issue