- Added format auto-detection to most loaders
  - Simplified BaseImporter::CanRead() with some utility methods
  - improved fast_atof -> no overruns anymore. Fuck you, irrlicht.
  - added assimp_cmd tool to allow command line model processing. Mainly adebugging tool for internal purposes, but others might find it useful, too.
  - vc8/vc9: revision number is now written to DLL version header
  - mkutil: some batch scripts to simplify tagging & building of release versions
  - some API cleanup
  - fixing some doxygen markup (+now explicit use of @file <filename>)
  - Icon for assimp_view and assimp_cmd

3DS
  - Normal vectors are not anymore inverted in some cases
  - Improved pivot handling
  - Improved handling of x-flipped meshes

Collada
  - fixed a minor bug (visual_scene element)

LWS 
  - WIP implementation. No animations yet, some bugs and crashes.
  - Animation system remains disabled, WIP code
  - many test files for LWS, but most of them test the anim support, which is, read above, currently disabled.

STL
  - fixing a log warning which appears for every model
  - added binary&ascii test spider, exported from truespace

MD3 
  - Cleaning up output tags for automatically joined player models.


IRR
  - Fixing coordinate system issues. 
  - Instance handling improved.
  - Some of the reported crashes not yet fixed.

PretransformVertices
  - Numerous performance improvements.
  - Added config option to preserve the hierarchy during the step.

RemoveRedundantMaterials
  - Added config option to specify a list of materials which are kept in every case.

UNREAL
  - Added support for the old unreal data format (*.a,*.d,*.uc)
  - tested only with exports from Milkshape
  - more Unreal stuff to come soon



git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@356 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
This commit is contained in:
aramis_acg
2009-03-05 22:32:13 +00:00
parent caaf02b0e4
commit 4bbc03332b
237 changed files with 33463 additions and 2245 deletions

View File

@@ -68,21 +68,21 @@ LWOImporter::~LWOImporter()
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool LWOImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
bool LWOImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
// simple check of file extension is enough for the moment
std::string::size_type pos = pFile.find_last_of('.');
// no file extension - can't read
if( pos == std::string::npos)return false;
std::string extension = pFile.substr( pos);
const std::string extension = GetExtension(pFile);
if (extension == "lwo" || extension == "lxo")
return true;
if (extension.length() < 4)return false;
if (extension[0] != '.')return false;
return ! (extension[1] != 'l' && extension[1] != 'L' ||
extension[2] != 'w' && extension[2] != 'W' &&
extension[2] != 'x' && extension[2] != 'X' ||
extension[3] != 'o' && extension[3] != 'O');
// if check for extension is not enough, check for the magic tokens
if (!extension.length() || checkSig) {
uint32_t tokens[3];
tokens[0] = AI_LWO_FOURCC_LWOB;
tokens[1] = AI_LWO_FOURCC_LWO2;
tokens[2] = AI_LWO_FOURCC_LXOB;
return CheckMagicToken(pIOHandler,pFile,tokens,3,8);
}
return false;
}
// ------------------------------------------------------------------------------------------------
@@ -109,21 +109,23 @@ void LWOImporter::InternReadFile( const std::string& pFile,
if((this->fileSize = (unsigned int)file->FileSize()) < 12)
throw new ImportErrorException("LWO: The file is too small to contain the IFF header");
// allocate storage and copy the contents of the file to a memory buffer
// Allocate storage and copy the contents of the file to a memory buffer
std::vector< uint8_t > mBuffer(fileSize);
file->Read( &mBuffer[0], 1, fileSize);
this->pScene = pScene;
// determine the type of the file
// Determine the type of the file
uint32_t fileType;
const char* sz = IFF::ReadHeader(&mBuffer[0],fileType);
if (sz)throw new ImportErrorException(sz);
mFileBuffer = &mBuffer[0] + 12;
fileSize -= 12;
hasNamedLayer = false;
// create temporary storage on the stack but store pointers to it in the class
// Initialize some members with their default values
hasNamedLayer = false;
// Create temporary storage on the stack but store pointers to it in the class
// instance. Therefore everything will be destructed properly if an exception
// is thrown and we needn't take care of that.
LayerList _mLayers;
@@ -218,6 +220,11 @@ void LWOImporter::InternReadFile( const std::string& pFile,
for (FaceList::iterator it = layer.mFaces.begin(), end = layer.mFaces.end();
it != end;++it,++i)
{
// Check whether we support this face's type
if ((*it).type != AI_LWO_FACE && (*it).type != AI_LWO_PTCH) {
continue;
}
unsigned int idx = (*it).surfaceIndex;
if (idx >= mTags->size())
{
@@ -282,7 +289,7 @@ void LWOImporter::InternReadFile( const std::string& pFile,
if (0xffffffff == vUVChannelIndices[mui])break;
pvUV[mui] = mesh->mTextureCoords[mui] = new aiVector3D[mesh->mNumVertices];
// LightWave doesn't support more than 2 UV components
// LightWave doesn't support more than 2 UV components (?)
// so we can directly setup this value
mesh->mNumUVComponents[0] = 2;
}
@@ -318,6 +325,7 @@ void LWOImporter::InternReadFile( const std::string& pFile,
register unsigned int idx = face.mIndices[q];
*pv = layer.mTempPoints[idx] + layer.mPivot;
pv->z *= -1.0f; // DX to OGL
//std::swap(pv->z,pv->y);
pv++;
// process UV coordinates
@@ -585,7 +593,8 @@ void LWOImporter::GenerateNodeGraph(std::vector<aiNode*>& apcNodes)
pScene->mRootNode->mChildren = apcNewNodes;
pScene->mRootNode->mNumChildren = newSize;
}
if (!pScene->mRootNode->mNumChildren)throw new ImportErrorException("LWO: Unable to build a valid node graph");
if (!pScene->mRootNode->mNumChildren)
throw new ImportErrorException("LWO: Unable to build a valid node graph");
// remove a single root node
// TODO: implement directly in the above loop, no need to deallocate here
@@ -717,31 +726,44 @@ void LWOImporter::LoadLWOPoints(unsigned int length)
void LWOImporter::LoadLWO2Polygons(unsigned int length)
{
LE_NCONST uint16_t* const end = (LE_NCONST uint16_t*)(mFileBuffer+length);
uint32_t type = GetU4();
const uint32_t type = GetU4();
// Determine the type of the polygons
switch (type)
{
// read unsupported stuff too (although we wont process it)
case AI_LWO_BONE:
DefaultLogger::get()->warn("LWO2: Encountered unsupported primitive chunk (BONE)");
break;
case AI_LWO_MBAL:
DefaultLogger::get()->warn("LWO2: Encountered unsupported primitive chunk (METABALL)");
break;
case AI_LWO_CURV:
DefaultLogger::get()->warn("LWO2: Encountered unsupported primitive chunk (SPLINE)");;
break;
// These are ok with no restrictions
case AI_LWO_PTCH:
case AI_LWO_FACE:
break;
default:
DefaultLogger::get()->warn("LWO2: Unsupported polygon type (PTCH and FACE are supported)");
// hm!? wtf is this? ok ...
DefaultLogger::get()->error("LWO2: Encountered unknown polygon type");
break;
}
// first find out how many faces and vertices we'll finally need
uint16_t* cursor = (uint16_t*)mFileBuffer;
uint16_t* cursor= (uint16_t*)mFileBuffer;
unsigned int iNumFaces = 0,iNumVertices = 0;
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);
mCurLayer->mFaces.resize(iNumFaces,LWO::Face(type));
FaceList::iterator it = mCurLayer->mFaces.begin();
CopyFaceIndicesLWO2(it,cursor,end);
}
@@ -898,6 +920,7 @@ inline void AddToSingleLinkedList(ReferrerList& refList, unsigned int srcIdx, un
}
// ------------------------------------------------------------------------------------------------
// Load LWO2 vertex map
void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
{
LE_NCONST uint8_t* const end = mFileBuffer+length;
@@ -915,24 +938,24 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
switch (type)
{
case AI_LWO_TXUV:
if (dims != 2)
{
if (dims != 2) {
DefaultLogger::get()->warn("LWO2: Found UV channel with != 2 components");
return;
}
base = FindEntry(mCurLayer->mUVChannels,name,perPoly);
break;
case AI_LWO_WGHT:
if (dims != 1)
{
if (dims != 1) {
DefaultLogger::get()->warn("LWO2: found vertex weight map with != 1 components");
return;
}
base = FindEntry(mCurLayer->mWeightChannels,name,perPoly);
break;
case AI_LWO_RGB:
case AI_LWO_RGBA:
if (dims != 3 && dims != 4)
{
if (dims != 3 && dims != 4) {
DefaultLogger::get()->warn("LWO2: found vertex color map with != 3&4 components");
return;
}
base = FindEntry(mCurLayer->mVColorChannels,name,perPoly);
break;
@@ -1028,6 +1051,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
}
// ------------------------------------------------------------------------------------------------
// Load LWO2 clip
void LWOImporter::LoadLWO2Clip(unsigned int length)
{
AI_LWO_VALIDATE_CHUNK_LENGTH(length,CLIP,10);
@@ -1042,6 +1066,7 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
switch (head->type)
{
case AI_LWO_STIL:
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,STIL,1);
// "Normal" texture
GetS0(clip.path,head->length);
@@ -1049,7 +1074,7 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
break;
case AI_LWO_ISEQ:
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,ISEQ,16);
// Image sequence. We'll later take the first.
{
uint8_t digits = GetU1(); mFileBuffer++;
@@ -1078,18 +1103,124 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
break;
case AI_LWO_XREF:
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,XREF,4);
// Just a cross-reference to another CLIp
clip.type = Clip::REF;
clip.clipRef = GetU4();
break;
case AI_LWO_NEGA:
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,NEGA,2);
clip.negate = (0 != GetU2());
break;
default:
DefaultLogger::get()->warn("LWO2: Encountered unknown CLIP subchunk");
}
}
// ------------------------------------------------------------------------------------------------
// Load envelope description
void LWOImporter::LoadLWO2Envelope(unsigned int length)
{
LE_NCONST uint8_t* const end = mFileBuffer + length;
AI_LWO_VALIDATE_CHUNK_LENGTH(length,ENVL,4);
mEnvelopes.push_back(LWO::Envelope());
LWO::Envelope& envelope = mEnvelopes.back();
// Get the index of the envelope
envelope.index = ReadVSizedIntLWO2(mFileBuffer);
// ... and read all subchunks
while (true)
{
if (mFileBuffer + 6 >= end)break;
LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
if (mFileBuffer + head->length > end)
throw new ImportErrorException("LWO2: Invalid envelope chunk length");
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);
mFileBuffer++; // skip user format
// Determine type of envelope
envelope.type = (LWO::EnvelopeType)*mFileBuffer;
++mFileBuffer;
break;
// precondition
case AI_LWO_PRE:
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);
envelope.post = (LWO::PrePostBehaviour)GetU2();
break;
// keyframe
case AI_LWO_KEY:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,KEY,8);
envelope.keys.push_back(LWO::Key());
LWO::Key& key = envelope.keys.back();
key.time = GetF4();
key.value = GetF4();
break;
}
// interval interpolation
case AI_LWO_SPAN:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SPAN,4);
if (envelope.keys.size()<2)
DefaultLogger::get()->warn("LWO2: Unexpected SPAN chunk");
else {
LWO::Key& key = envelope.keys.back();
switch (GetU4())
{
case AI_LWO_STEP:
key.inter = LWO::IT_STEP;break;
case AI_LWO_LINE:
key.inter = LWO::IT_LINE;break;
case AI_LWO_TCB:
key.inter = LWO::IT_TCB;break;
case AI_LWO_HERM:
key.inter = LWO::IT_HERM;break;
case AI_LWO_BEZI:
key.inter = LWO::IT_BEZI;break;
case AI_LWO_BEZ2:
key.inter = LWO::IT_BEZ2;break;
default:
DefaultLogger::get()->warn("LWO2: Unknown interval interpolation mode");
};
// todo ... read params
}
break;
}
default:
DefaultLogger::get()->warn("LWO2: Encountered unknown ENVL subchunk");
}
// regardless how much we did actually read, go to the next chunk
mFileBuffer = next;
}
}
// ------------------------------------------------------------------------------------------------
// Load file - master function
void LWOImporter::LoadLWO2File()
{
bool skip = false;
@@ -1121,8 +1252,7 @@ void LWOImporter::LoadLWO2File()
// load this layer or ignore it? Check the layer index property
// NOTE: The first layer is the default layer, so the layer
// index is one-based now
if (0xffffffff != configLayerIndex && configLayerIndex != mLayers->size())
{
if (0xffffffff != configLayerIndex && configLayerIndex != mLayers->size()-1) {
skip = true;
}
else skip = false;
@@ -1138,16 +1268,14 @@ void LWOImporter::LoadLWO2File()
GetS0(layer.mName,head->length-16);
// if the name is empty, generate a default name
if (layer.mName.empty())
{
if (layer.mName.empty()) {
char buffer[128]; // should be sufficiently large
::sprintf(buffer,"Layer_%i", iUnnamed++);
layer.mName = buffer;
}
// load this layer or ignore it? Check the layer name property
if (configLayerName.length() && configLayerName != layer.mName)
{
if (configLayerName.length() && configLayerName != layer.mName) {
skip = true;
}
else hasNamedLayer = true;
@@ -1161,7 +1289,8 @@ void LWOImporter::LoadLWO2File()
// vertex list
case AI_LWO_PNTS:
{
if (skip)break;
if (skip)
break;
unsigned int old = (unsigned int)mCurLayer->mTempPoints.size();
LoadLWOPoints(head->length);
@@ -1178,7 +1307,8 @@ void LWOImporter::LoadLWO2File()
// --- intentionally no break here
case AI_LWO_VMAP:
{
if (skip)break;
if (skip)
break;
if (mCurLayer->mTempPoints.empty())
DefaultLogger::get()->warn("LWO2: Unexpected VMAP chunk");
@@ -1188,7 +1318,8 @@ void LWOImporter::LoadLWO2File()
// face list
case AI_LWO_POLS:
{
if (skip)break;
if (skip)
break;
unsigned int old = (unsigned int)mCurLayer->mFaces.size();
LoadLWO2Polygons(head->length);
@@ -1198,7 +1329,8 @@ void LWOImporter::LoadLWO2File()
// polygon tags
case AI_LWO_PTAG:
{
if (skip)break;
if (skip)
break;
if (mCurLayer->mFaces.empty())
DefaultLogger::get()->warn("LWO2: Unexpected PTAG");
@@ -1227,9 +1359,16 @@ void LWOImporter::LoadLWO2File()
LoadLWO2Clip(head->length);
break;
}
// envelope chunk
case AI_LWO_ENVL:
{
LoadLWO2Envelope(head->length);
break;
}
}
mFileBuffer = next;
}
}
#endif // !! ASSIMP_BUILD_NO_LWO_IMPORTER
#endif // !! ASSIMP_BUILD_NO_LWO_IMPORTER