LWO: replace legacy reinterpret_cast based code by memcpy to solve Android SIGBUS problems due to unaligned accesses. Fixes #351

pull/366/head
acgessler 2014-09-04 20:49:48 -07:00
parent 1a594b861a
commit 185f01963f
5 changed files with 182 additions and 144 deletions

View File

@ -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;
}

View File

@ -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)
{

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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: