Prechádzať zdrojové kódy

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

acgessler 11 rokov pred
rodič
commit
185f01963f
5 zmenil súbory, kde vykonal 182 pridanie a 144 odobranie
  1. 24 22
      code/IFF.h
  2. 57 39
      code/LWOBLoader.cpp
  3. 56 44
      code/LWOLoader.cpp
  4. 9 3
      code/LWOLoader.h
  5. 36 36
      code/LWOMaterial.cpp

+ 24 - 22
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;
 }

+ 57 - 39
code/LWOBLoader.cpp

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

+ 56 - 44
code/LWOLoader.cpp

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

+ 9 - 3
code/LWOLoader.h

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

+ 36 - 36
code/LWOMaterial.cpp

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