MD5 parser will now reject files with version!=10.

3DS Loader -> improved light and camera handling.
DXF -> minor fixes, refactoring.
Updating DLL revision number.


git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@379 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
pull/1/head
aramis_acg 2009-04-09 21:37:49 +00:00
parent 825118b970
commit bcfbc37301
5 changed files with 93 additions and 105 deletions

View File

@ -594,23 +594,23 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,
nda->mPositionKeys = new aiVectorKey[nda->mNumPositionKeys]; nda->mPositionKeys = new aiVectorKey[nda->mNumPositionKeys];
::memcpy(nda->mPositionKeys,&distanceTrack[0], ::memcpy(nda->mPositionKeys,&distanceTrack[0],
sizeof(aiVectorKey)*nda->mNumPositionKeys); sizeof(aiVectorKey)*nda->mNumPositionKeys);
// The target animation is now encoded in the local transformation
// matrix of the camera, so we must clear the corresponding
// fields in aiCamera or aiLight.
for (unsigned int n = 0; n < pcSOut->mNumCameras;++n) {
if (pcSOut->mCameras[n]->mName == pcOut->mName) {
pcSOut->mCameras[n]->mLookAt = aiVector3D(0.f,0.f,1.f);
}
}
for (unsigned int n = 0; n < pcSOut->mNumLights;++n) {
if (pcSOut->mLights[n]->mName == pcOut->mName) {
pcSOut->mLights[n]->mDirection = aiVector3D(0.f,0.f,1.f);
}
}
} }
#endif #endif
// Cameras or lights define their transformation in their parent node and in the
// corresponding light or camera chunks. However, we read and process the latter
// to to be able to return valid cameras/lights even if no scenegraph is given.
for (unsigned int n = 0; n < pcSOut->mNumCameras;++n) {
if (pcSOut->mCameras[n]->mName == pcOut->mName) {
pcSOut->mCameras[n]->mLookAt = aiVector3D(0.f,0.f,1.f);
}
}
for (unsigned int n = 0; n < pcSOut->mNumLights;++n) {
if (pcSOut->mLights[n]->mName == pcOut->mName) {
pcSOut->mLights[n]->mDirection = aiVector3D(0.f,0.f,1.f);
}
}
// Allocate a new node anim and setup its name // Allocate a new node anim and setup its name
aiNodeAnim* nda = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim(); aiNodeAnim* nda = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim();
nda->mNodeName.Set(pcIn->mName); nda->mNodeName.Set(pcIn->mName);

View File

@ -357,6 +357,11 @@ void Discreet3DSImporter::ParseChunk(const char* name, unsigned int num)
{ {
ASSIMP_3DS_BEGIN_CHUNK(); ASSIMP_3DS_BEGIN_CHUNK();
// IMPLEMENTATION NOTE;
// Cameras or lights define their transformation in their parent node and in the
// corresponding light or camera chunks. However, we read and process the latter
// to to be able to return valid cameras/lights even if no scenegraph is given.
// get chunk type // get chunk type
switch (chunk.Flag) switch (chunk.Flag)
{ {
@ -410,13 +415,8 @@ void Discreet3DSImporter::ParseChunk(const char* name, unsigned int num)
// This starts a new camera // This starts a new camera
aiCamera* camera = new aiCamera(); aiCamera* camera = new aiCamera();
mScene->mCameras.push_back(camera); mScene->mCameras.push_back(camera);
camera->mName.Set(std::string(name, num)); camera->mName.Set(std::string(name, num));
// Camera position and look-at vector are difficult to handle. If an animation track is given,
// we must make sure that the track is relative to these values - or , easier we must copy the
// information here to the node matrix of the camera's parent in the graph.
// First read the position of the camera // First read the position of the camera
camera->mPosition.x = stream->GetF4(); camera->mPosition.x = stream->GetF4();
camera->mPosition.y = stream->GetF4(); camera->mPosition.y = stream->GetF4();
@ -429,7 +429,7 @@ void Discreet3DSImporter::ParseChunk(const char* name, unsigned int num)
float len = camera->mLookAt.Length(); float len = camera->mLookAt.Length();
if (len < 1e-5f) { if (len < 1e-5f) {
// There are some files with lookat == position. Don't know why or whether it's ok. // There are some files with lookat == position. Don't know why or whether it's ok or not.
DefaultLogger::get()->error("3DS: Unable to read proper camera look-at vector"); DefaultLogger::get()->error("3DS: Unable to read proper camera look-at vector");
camera->mLookAt = aiVector3D(0.f,1.f,0.f); camera->mLookAt = aiVector3D(0.f,1.f,0.f);
@ -558,14 +558,15 @@ void Discreet3DSImporter::ParseKeyframeChunk()
// Little helper function for ParseHierarchyChunk // Little helper function for ParseHierarchyChunk
void Discreet3DSImporter::InverseNodeSearch(D3DS::Node* pcNode,D3DS::Node* pcCurrent) void Discreet3DSImporter::InverseNodeSearch(D3DS::Node* pcNode,D3DS::Node* pcCurrent)
{ {
if (!pcCurrent) if (!pcCurrent) {
{
mRootNode->push_back(pcNode); mRootNode->push_back(pcNode);
return; return;
} }
if (pcCurrent->mHierarchyPos == pcNode->mHierarchyPos)
{ if (pcCurrent->mHierarchyPos == pcNode->mHierarchyPos) {
if(pcCurrent->mParent)pcCurrent->mParent->push_back(pcNode); if(pcCurrent->mParent)
pcCurrent->mParent->push_back(pcNode);
else pcCurrent->push_back(pcNode); else pcCurrent->push_back(pcNode);
return; return;
} }
@ -576,12 +577,12 @@ void Discreet3DSImporter::InverseNodeSearch(D3DS::Node* pcNode,D3DS::Node* pcCur
// Find a node with a specific name in the import hierarchy // Find a node with a specific name in the import hierarchy
D3DS::Node* FindNode(D3DS::Node* root, const std::string& name) D3DS::Node* FindNode(D3DS::Node* root, const std::string& name)
{ {
if (root->mName == name)return root; if (root->mName == name)
for (std::vector<D3DS::Node*>::iterator it = root->mChildren.begin(); return root;
it != root->mChildren.end(); ++it) for (std::vector<D3DS::Node*>::iterator it = root->mChildren.begin();it != root->mChildren.end(); ++it) {
{
D3DS::Node* nd; D3DS::Node* nd;
if (( nd = FindNode(*it,name)))return nd; if (( nd = FindNode(*it,name)))
return nd;
} }
return NULL; return NULL;
} }
@ -631,9 +632,8 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
{ {
case Discreet3DS::CHUNK_TRACKOBJNAME: case Discreet3DS::CHUNK_TRACKOBJNAME:
// This is the name of the object to which the track applies // This is the name of the object to which the track applies. The chunk also
// The chunk also defines the position of this object in the // defines the position of this object in the hierarchy.
// hierarchy.
{ {
// First of all: get the name of the object // First of all: get the name of the object
@ -643,9 +643,8 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
while (stream->GetI1())++cnt; while (stream->GetI1())++cnt;
std::string name = std::string(sz,cnt); std::string name = std::string(sz,cnt);
// Now find out whether we have this node already // Now find out whether we have this node already (target animation channels
// (target animation channels are stored with a // are stored with a separate object ID)
// separate object ID)
D3DS::Node* pcNode = FindNode(mRootNode,name); D3DS::Node* pcNode = FindNode(mRootNode,name);
if (pcNode) if (pcNode)
{ {
@ -694,9 +693,8 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
{ {
const char* sz = (const char*) stream->GetPtr(); const char* sz = (const char*) stream->GetPtr();
while (stream->GetI1()); while (stream->GetI1());
// mCurrentNode->mDummyName = std::string(sz);
// FIX: if object name is DUMMY, take this one instead // If object name is DUMMY, take this one instead
if (mCurrentNode->mName == "$$$DUMMY") { if (mCurrentNode->mName == "$$$DUMMY") {
//DefaultLogger::get()->warn("3DS: Skipping dummy object name for non-dummy object"); //DefaultLogger::get()->warn("3DS: Skipping dummy object name for non-dummy object");
mCurrentNode->mName = std::string(sz); mCurrentNode->mName = std::string(sz);
@ -933,16 +931,12 @@ void Discreet3DSImporter::ParseFaceChunk()
// Get chunk type // Get chunk type
switch (chunk.Flag) switch (chunk.Flag)
{ {
case Discreet3DS::CHUNK_SMOOLIST: case Discreet3DS::CHUNK_SMOOLIST:
{ {
// This is the list of smoothing groups - a bitfield for // This is the list of smoothing groups - a bitfield for every face.
// every frame. Up to 32 smoothing groups assigned to a // Up to 32 smoothing groups assigned to a single face.
// face.
unsigned int num = chunkSize/4, m = 0; unsigned int num = chunkSize/4, m = 0;
for (std::vector<D3DS::Face>::iterator i = mMesh.mFaces.begin(); for (std::vector<D3DS::Face>::iterator i = mMesh.mFaces.begin(); m != num;++i, ++m) {
m != num;++i, ++m)
{
// nth bit is set for nth smoothing group // nth bit is set for nth smoothing group
(*i).iSmoothGroup = stream->GetI4(); (*i).iSmoothGroup = stream->GetI4();
}} }}
@ -956,26 +950,15 @@ void Discreet3DSImporter::ParseFaceChunk()
// find the index of the material // find the index of the material
unsigned int idx = 0xcdcdcdcd, cnt = 0; unsigned int idx = 0xcdcdcdcd, cnt = 0;
for (std::vector<D3DS::Material>::const_iterator for (std::vector<D3DS::Material>::const_iterator i = mScene->mMaterials.begin();i != mScene->mMaterials.end();++i,++cnt) {
i = mScene->mMaterials.begin(); // use case independent comparisons. hopefully it will work.
i != mScene->mMaterials.end();++i,++cnt) if ((*i).mName.length() && !ASSIMP_stricmp(sz, (*i).mName.c_str())) {
{
// compare case-independent to be sure it works
if ((*i).mName.length() && !ASSIMP_stricmp(sz, (*i).mName.c_str()))
{
idx = cnt; idx = cnt;
break; break;
} }
} }
if (0xcdcdcdcd == idx) if (0xcdcdcdcd == idx) {
{
DefaultLogger::get()->error(std::string("3DS: Unknown material: ") + sz); DefaultLogger::get()->error(std::string("3DS: Unknown material: ") + sz);
// --------------------------------------------------------------
// This material is not known. Ignore this. We will later
// assign the default material to all faces using *this*
// material. We use 0xcdcdcdcd as special value to indicate this.
// --------------------------------------------------------------
} }
// Now continue and read all material indices // Now continue and read all material indices
@ -1013,8 +996,7 @@ void Discreet3DSImporter::ParseMeshChunk()
// This is the list of all vertices in the current mesh // This is the list of all vertices in the current mesh
int num = (int)(uint16_t)stream->GetI2(); int num = (int)(uint16_t)stream->GetI2();
mMesh.mPositions.reserve(num); mMesh.mPositions.reserve(num);
while (num-- > 0) while (num-- > 0) {
{
aiVector3D v; aiVector3D v;
v.x = stream->GetF4(); v.x = stream->GetF4();
v.y = stream->GetF4(); v.y = stream->GetF4();
@ -1024,8 +1006,8 @@ void Discreet3DSImporter::ParseMeshChunk()
break; break;
case Discreet3DS::CHUNK_TRMATRIX: case Discreet3DS::CHUNK_TRMATRIX:
{ {
// This is the RLEATIVE transformation matrix of the // This is the RLEATIVE transformation matrix of the current mesh. Vertices are
// current mesh. However, all vertices are pretransformed // pretransformed by this matrix wonder.
mMesh.mMat.a1 = stream->GetF4(); mMesh.mMat.a1 = stream->GetF4();
mMesh.mMat.b1 = stream->GetF4(); mMesh.mMat.b1 = stream->GetF4();
mMesh.mMat.c1 = stream->GetF4(); mMesh.mMat.c1 = stream->GetF4();
@ -1046,8 +1028,7 @@ void Discreet3DSImporter::ParseMeshChunk()
// This is the list of all UV coords in the current mesh // This is the list of all UV coords in the current mesh
int num = (int)(uint16_t)stream->GetI2(); int num = (int)(uint16_t)stream->GetI2();
mMesh.mTexCoords.reserve(num); mMesh.mTexCoords.reserve(num);
while (num-- > 0) while (num-- > 0) {
{
aiVector3D v; aiVector3D v;
v.x = stream->GetF4(); v.x = stream->GetF4();
v.y = stream->GetF4(); v.y = stream->GetF4();
@ -1060,8 +1041,7 @@ void Discreet3DSImporter::ParseMeshChunk()
// This is the list of all faces in the current mesh // This is the list of all faces in the current mesh
int num = (int)(uint16_t)stream->GetI2(); int num = (int)(uint16_t)stream->GetI2();
mMesh.mFaces.reserve(num); mMesh.mFaces.reserve(num);
while (num-- > 0) while (num-- > 0) {
{
// 3DS faces are ALWAYS triangles // 3DS faces are ALWAYS triangles
mMesh.mFaces.push_back(D3DS::Face()); mMesh.mFaces.push_back(D3DS::Face());
D3DS::Face& sFace = mMesh.mFaces.back(); D3DS::Face& sFace = mMesh.mFaces.back();
@ -1073,9 +1053,8 @@ void Discreet3DSImporter::ParseMeshChunk()
stream->IncPtr(2); // skip edge visibility flag stream->IncPtr(2); // skip edge visibility flag
} }
// Resize the material array (0xcdcdcdcd marks the // Resize the material array (0xcdcdcdcd marks the default material; so if a face is
// default material; so if a face is not referenced // not referenced by a material, $$DEFAULT will be assigned to it)
// by a material $$DEFAULT will be assigned to it)
mMesh.mFaceMaterials.resize(mMesh.mFaces.size(),0xcdcdcdcd); mMesh.mFaceMaterials.resize(mMesh.mFaces.size(),0xcdcdcdcd);
// Larger 3DS files could have multiple FACE chunks here // Larger 3DS files could have multiple FACE chunks here
@ -1095,21 +1074,18 @@ void Discreet3DSImporter::ParseMeshChunk()
void Discreet3DSImporter::ParseMaterialChunk() void Discreet3DSImporter::ParseMaterialChunk()
{ {
ASSIMP_3DS_BEGIN_CHUNK(); ASSIMP_3DS_BEGIN_CHUNK();
// get chunk type
switch (chunk.Flag) switch (chunk.Flag)
{ {
case Discreet3DS::CHUNK_MAT_MATNAME: case Discreet3DS::CHUNK_MAT_MATNAME:
{ {
// The material name string is already zero-terminated, but // The material name string is already zero-terminated, but we need to be sure ...
// we need to be sure ...
const char* sz = (const char*)stream->GetPtr(); const char* sz = (const char*)stream->GetPtr();
unsigned int cnt = 0; unsigned int cnt = 0;
while (stream->GetI1())++cnt; while (stream->GetI1())
++cnt;
if (!cnt) if (!cnt) {
{
// This may not be, we use the default name instead // This may not be, we use the default name instead
DefaultLogger::get()->error("3DS: Empty material name"); DefaultLogger::get()->error("3DS: Empty material name");
} }
@ -1172,7 +1148,8 @@ void Discreet3DSImporter::ParseMaterialChunk()
*pcf = ParsePercentageChunk(); *pcf = ParsePercentageChunk();
// NOTE: transparency, not opacity // NOTE: transparency, not opacity
if (is_qnan(*pcf))*pcf = 1.0f; if (is_qnan(*pcf))
*pcf = 1.0f;
else *pcf = 1.0f - *pcf * (float)0xFFFF / 100.0f; else *pcf = 1.0f - *pcf * (float)0xFFFF / 100.0f;
} }
break; break;
@ -1191,7 +1168,8 @@ void Discreet3DSImporter::ParseMaterialChunk()
{ // This is the shininess of the material { // This is the shininess of the material
float* pcf = &mScene->mMaterials.back().mSpecularExponent; float* pcf = &mScene->mMaterials.back().mSpecularExponent;
*pcf = ParsePercentageChunk(); *pcf = ParsePercentageChunk();
if (is_qnan(*pcf))*pcf = 0.0f; if (is_qnan(*pcf))
*pcf = 0.0f;
else *pcf *= (float)0xFFFF; else *pcf *= (float)0xFFFF;
} }
break; break;
@ -1200,7 +1178,8 @@ void Discreet3DSImporter::ParseMaterialChunk()
{ // This is the shininess strength of the material { // This is the shininess strength of the material
float* pcf = &mScene->mMaterials.back().mShininessStrength; float* pcf = &mScene->mMaterials.back().mShininessStrength;
*pcf = ParsePercentageChunk(); *pcf = ParsePercentageChunk();
if (is_qnan(*pcf))*pcf = 0.0f; if (is_qnan(*pcf))
*pcf = 0.0f;
else *pcf *= (float)0xffff / 100.0f; else *pcf *= (float)0xffff / 100.0f;
} }
break; break;
@ -1208,7 +1187,8 @@ void Discreet3DSImporter::ParseMaterialChunk()
case Discreet3DS::CHUNK_MAT_SELF_ILPCT: case Discreet3DS::CHUNK_MAT_SELF_ILPCT:
{ // This is the self illumination strength of the material { // This is the self illumination strength of the material
float f = ParsePercentageChunk(); float f = ParsePercentageChunk();
if (is_qnan(f))f = 0.0f; if (is_qnan(f))
f = 0.0f;
else f *= (float)0xFFFF / 100.0f; else f *= (float)0xFFFF / 100.0f;
mScene->mMaterials.back().mEmissive = aiColor3D(f,f,f); mScene->mMaterials.back().mEmissive = aiColor3D(f,f,f);
} }
@ -1259,11 +1239,11 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
{ {
case Discreet3DS::CHUNK_MAPFILE: case Discreet3DS::CHUNK_MAPFILE:
{ {
// The material name string is already zero-terminated, but // The material name string is already zero-terminated, but we need to be sure ...
// we need to be sure ...
const char* sz = (const char*)stream->GetPtr(); const char* sz = (const char*)stream->GetPtr();
unsigned int cnt = 0; unsigned int cnt = 0;
while (stream->GetI1())++cnt; while (stream->GetI1())
++cnt;
pcOut->mMapName = std::string(sz,cnt); pcOut->mMapName = std::string(sz,cnt);
} }
break; break;
@ -1284,8 +1264,7 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
pcOut->mScaleU = stream->GetF4(); pcOut->mScaleU = stream->GetF4();
if (0.0f == pcOut->mScaleU) if (0.0f == pcOut->mScaleU)
{ {
DefaultLogger::get()->warn("Texture coordinate scaling in the " DefaultLogger::get()->warn("Texture coordinate scaling in the x direction is zero. Assuming 1.");
"x direction is zero. Assuming 1");
pcOut->mScaleU = 1.0f; pcOut->mScaleU = 1.0f;
} }
break; break;
@ -1294,8 +1273,7 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
pcOut->mScaleV = stream->GetF4(); pcOut->mScaleV = stream->GetF4();
if (0.0f == pcOut->mScaleV) if (0.0f == pcOut->mScaleV)
{ {
DefaultLogger::get()->warn("Texture coordinate scaling in the " DefaultLogger::get()->warn("Texture coordinate scaling in the y direction is zero. Assuming 1.");
"y direction is zero. Assuming 1");
pcOut->mScaleV = 1.0f; pcOut->mScaleV = 1.0f;
} }
break; break;

View File

@ -112,7 +112,8 @@ bool DXFImporter::GetNextLine()
{ {
if(!SkipLine(&buffer)) if(!SkipLine(&buffer))
return false; return false;
if(!SkipSpaces(&buffer))return GetNextLine(); if(!SkipSpaces(&buffer))
return GetNextLine();
else if (*buffer == '{') { else if (*buffer == '{') {
// some strange meta data ... // some strange meta data ...
while (true) while (true)
@ -139,11 +140,12 @@ bool DXFImporter::GetNextToken()
SkipSpaces(&buffer); SkipSpaces(&buffer);
groupCode = strtol10s(buffer,&buffer); groupCode = strtol10s(buffer,&buffer);
if(!GetNextLine())return false; if(!GetNextLine())
return false;
// copy the data line to a separate buffer // copy the data line to a separate buffer
char* m = cursor, *end = &cursor[4096]; char* m = cursor, *end = &cursor[4096];
while (!IsLineEnd ( *buffer ) && m < end) while (!IsSpaceOrNewLine( *buffer ) && m < end)
*m++ = *buffer++; *m++ = *buffer++;
*m = '\0'; *m = '\0';
@ -163,7 +165,7 @@ void DXFImporter::InternReadFile( const std::string& pFile,
throw new ImportErrorException( "Failed to open DXF file " + pFile + ""); throw new ImportErrorException( "Failed to open DXF file " + pFile + "");
// read the contents of the file in a buffer // read the contents of the file in a buffer
unsigned int m = (unsigned int)file->FileSize(); size_t m = file->FileSize();
std::vector<char> buffer2(m+1); std::vector<char> buffer2(m+1);
buffer = &buffer2[0]; buffer = &buffer2[0];
file->Read( &buffer2[0], m,1); file->Read( &buffer2[0], m,1);
@ -182,13 +184,17 @@ void DXFImporter::InternReadFile( const std::string& pFile,
if (2 == groupCode) { if (2 == groupCode) {
// ENTITIES and BLOCKS sections - skip the whole rest, no need to waste our time with them // ENTITIES and BLOCKS sections - skip the whole rest, no need to waste our time with them
if (!::strcmp(cursor,"ENTITIES") || !::strcmp(cursor,"BLOCKS")) if (!::strcmp(cursor,"ENTITIES") || !::strcmp(cursor,"BLOCKS")) {
if (!ParseEntities())break; else bRepeat = true; if (!ParseEntities())
break;
else bRepeat = true;
}
// other sections - skip them to make sure there will be no name conflicts // other sections - skip them to make sure there will be no name conflicts
else { else {
while (GetNextToken()) { while ( GetNextToken()) {
if (!groupCode && !::strcmp(cursor,"ENDSEC"))break; if (!::strcmp(cursor,"ENDSEC"))
break;
} }
} }
} }
@ -202,7 +208,8 @@ void DXFImporter::InternReadFile( const std::string& pFile,
// find out how many valud layers we have // find out how many valud layers we have
for (std::vector<LayerInfo>::const_iterator it = mLayers.begin(),end = mLayers.end(); it != end;++it) { for (std::vector<LayerInfo>::const_iterator it = mLayers.begin(),end = mLayers.end(); it != end;++it) {
if (!(*it).vPositions.empty())++pScene->mNumMeshes; if (!(*it).vPositions.empty())
++pScene->mNumMeshes;
} }
if (!pScene->mNumMeshes) if (!pScene->mNumMeshes)
@ -476,8 +483,7 @@ bool DXFImporter::ParsePolyLineVertex(aiVector3D& out,aiColor4D& clr, unsigned i
case 0: ret = true; case 0: ret = true;
break; break;
// todo - handle the correct layer for the vertex // todo - handle the correct layer for the vertex. At the moment it is assumed that all vertices of
// At the moment it is assumed that all vertices of
// a polyline are placed on the same global layer. // a polyline are placed on the same global layer.
// x position of the first corner // x position of the first corner
@ -519,7 +525,9 @@ bool DXFImporter::Parse3DFace()
while (GetNextToken()) { while (GetNextToken()) {
switch (groupCode) { switch (groupCode) {
case 0: ret = true;break; case 0:
ret = true;
break;
// 8 specifies the layer // 8 specifies the layer
case 8: { case 8: {
@ -572,10 +580,12 @@ bool DXFImporter::Parse3DFace()
// color // color
case 62: clr = g_aclrDxfIndexColors[strtol10(cursor) % AI_DXF_NUM_INDEX_COLORS]; break; case 62: clr = g_aclrDxfIndexColors[strtol10(cursor) % AI_DXF_NUM_INDEX_COLORS]; break;
}; };
if (ret)break; if (ret)
break;
} }
if (!bThird)vip[2] = vip[1]; if (!bThird)
vip[2] = vip[1];
// use a default layer if necessary // use a default layer if necessary
if (!out) { if (!out) {

View File

@ -115,7 +115,7 @@ void MD5Parser::ParseHeader()
SkipSpaces(); SkipSpaces();
unsigned int iVer = ::strtol10(buffer,(const char**)&buffer); unsigned int iVer = ::strtol10(buffer,(const char**)&buffer);
if (10 != iVer) { if (10 != iVer) {
ReportWarning("MD5 version tag is unknown (10 is expected)"); ReportError("MD5 version tag is unknown (10 is expected)");
} }
SkipLine(); SkipLine();

View File

@ -1 +1 @@
#define SVNRevision 369 #define SVNRevision 377