- cleaned up doc, made section on face winding clearer 

MD3 
 - fixed coordinate system 
 - changed default face order for .shader files 

MD2 
 - fixed coordinate system 
 - fixed face order 



git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@367 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
pull/1/head
aramis_acg 2009-03-18 22:01:11 +00:00
parent c2d8881549
commit 93ab7383da
6 changed files with 59 additions and 56 deletions

View File

@ -310,8 +310,7 @@ void MD2Importer::InternReadFile( const std::string& pFile,
DefaultLogger::get()->warn("Texture file name has zero length. It will be skipped."); DefaultLogger::get()->warn("Texture file name has zero length. It will be skipped.");
} }
} }
else else {
{
// apply a default material // apply a default material
aiColor3D clr; aiColor3D clr;
clr.b = clr.g = clr.r = 0.6f; clr.b = clr.g = clr.r = 0.6f;
@ -338,8 +337,7 @@ void MD2Importer::InternReadFile( const std::string& pFile,
unsigned int iCurrent = 0; unsigned int iCurrent = 0;
float fDivisorU = 1.0f,fDivisorV = 1.0f; float fDivisorU = 1.0f,fDivisorV = 1.0f;
if (m_pcHeader->numTexCoords) if (m_pcHeader->numTexCoords) {
{
// allocate storage for texture coordinates, too // allocate storage for texture coordinates, too
pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices]; pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
pcMesh->mNumUVComponents[0] = 2; pcMesh->mNumUVComponents[0] = 2;
@ -356,8 +354,7 @@ void MD2Importer::InternReadFile( const std::string& pFile,
else fDivisorV = (float)m_pcHeader->skinHeight; else fDivisorV = (float)m_pcHeader->skinHeight;
} }
for (unsigned int i = 0; i < (unsigned int)m_pcHeader->numTriangles;++i) for (unsigned int i = 0; i < (unsigned int)m_pcHeader->numTriangles;++i) {
{
// Allocate the face // Allocate the face
pScene->mMeshes[0]->mFaces[i].mIndices = new unsigned int[3]; pScene->mMeshes[0]->mFaces[i].mIndices = new unsigned int[3];
pScene->mMeshes[0]->mFaces[i].mNumIndices = 3; pScene->mMeshes[0]->mFaces[i].mNumIndices = 3;
@ -365,12 +362,11 @@ void MD2Importer::InternReadFile( const std::string& pFile,
// copy texture coordinates // copy texture coordinates
// check whether they are different from the previous value at this index. // check whether they are different from the previous value at this index.
// In this case, create a full separate set of vertices/normals/texcoords // In this case, create a full separate set of vertices/normals/texcoords
for (unsigned int c = 0; c < 3;++c,++iCurrent) for (unsigned int c = 0; c < 3;++c,++iCurrent) {
{
// validate vertex indices // validate vertex indices
register unsigned int iIndex = (unsigned int)pcTriangles[i].vertexIndices[c]; register unsigned int iIndex = (unsigned int)pcTriangles[i].vertexIndices[c];
if (iIndex >= m_pcHeader->numVertices) if (iIndex >= m_pcHeader->numVertices) {
{
DefaultLogger::get()->error("MD2: Vertex index is outside the allowed range"); DefaultLogger::get()->error("MD2: Vertex index is outside the allowed range");
iIndex = m_pcHeader->numVertices-1; iIndex = m_pcHeader->numVertices-1;
} }
@ -391,9 +387,9 @@ void MD2Importer::InternReadFile( const std::string& pFile,
aiVector3D& vNormal = pcMesh->mNormals[iCurrent]; aiVector3D& vNormal = pcMesh->mNormals[iCurrent];
LookupNormalIndex(pcVerts[iIndex].lightNormalIndex,vNormal); LookupNormalIndex(pcVerts[iIndex].lightNormalIndex,vNormal);
// invert z for proper output coordinate system // flip z and y to become right-handed
vNormal.z *= -1.0f; std::swap((float&)vNormal.z,(float&)vNormal.y);
vec.z *= -1.0f; std::swap((float&)vec.z,(float&)vec.y);
if (m_pcHeader->numTexCoords) { if (m_pcHeader->numTexCoords) {
// validate texture coordinates // validate texture coordinates

View File

@ -531,7 +531,7 @@ bool MD3Importer::ReadMultipartFile()
aiNode* tag_torso, *tag_head; aiNode* tag_torso, *tag_head;
std::vector<AttachmentInfo> attach; std::vector<AttachmentInfo> attach;
DefaultLogger::get()->info("Multi-part MD3 player model: lower, upper and head parts are joined"); DefaultLogger::get()->info("Multi part MD3 player model: lower, upper and head parts are joined");
// ensure we won't try to load ourselves recursively // ensure we won't try to load ourselves recursively
BatchLoader::PropertyMap props; BatchLoader::PropertyMap props;
@ -552,21 +552,21 @@ bool MD3Importer::ReadMultipartFile()
// ... and get them. We need all of them. // ... and get them. We need all of them.
scene_lower = batch.GetImport(_lower); scene_lower = batch.GetImport(_lower);
if (!scene_lower) { if (!scene_lower) {
DefaultLogger::get()->error("M3D: Failed to read multipart model, lower.md3 fails to load"); DefaultLogger::get()->error("M3D: Failed to read multi part model, lower.md3 fails to load");
failure = "lower"; failure = "lower";
goto error_cleanup; goto error_cleanup;
} }
scene_upper = batch.GetImport(_upper); scene_upper = batch.GetImport(_upper);
if (!scene_upper) { if (!scene_upper) {
DefaultLogger::get()->error("M3D: Failed to read multipart model, upper.md3 fails to load"); DefaultLogger::get()->error("M3D: Failed to read multi part model, upper.md3 fails to load");
failure = "upper"; failure = "upper";
goto error_cleanup; goto error_cleanup;
} }
scene_head = batch.GetImport(_head); scene_head = batch.GetImport(_head);
if (!scene_head) { if (!scene_head) {
DefaultLogger::get()->error("M3D: Failed to read multipart model, head.md3 fails to load"); DefaultLogger::get()->error("M3D: Failed to read multi part model, head.md3 fails to load");
failure = "head"; failure = "head";
goto error_cleanup; goto error_cleanup;
} }
@ -580,7 +580,7 @@ bool MD3Importer::ReadMultipartFile()
// tag_torso // tag_torso
tag_torso = scene_lower->mRootNode->FindNode("tag_torso"); tag_torso = scene_lower->mRootNode->FindNode("tag_torso");
if (!tag_torso) { if (!tag_torso) {
DefaultLogger::get()->error("M3D: Failed to find attachment tag for multipart model: tag_torso expected"); DefaultLogger::get()->error("M3D: Failed to find attachment tag for multi part model: tag_torso expected");
goto error_cleanup; goto error_cleanup;
} }
scene_upper->mRootNode->mName.Set("upper"); scene_upper->mRootNode->mName.Set("upper");
@ -589,7 +589,7 @@ bool MD3Importer::ReadMultipartFile()
// tag_head // tag_head
tag_head = scene_upper->mRootNode->FindNode("tag_head"); tag_head = scene_upper->mRootNode->FindNode("tag_head");
if (!tag_head) { if (!tag_head) {
DefaultLogger::get()->error("M3D: Failed to find attachment tag for multipart model: tag_head expected"); DefaultLogger::get()->error("M3D: Failed to find attachment tag for multi part model: tag_head expected");
goto error_cleanup; goto error_cleanup;
} }
scene_head->mRootNode->mName.Set("head"); scene_head->mRootNode->mName.Set("head");
@ -601,6 +601,12 @@ bool MD3Importer::ReadMultipartFile()
RemoveSingleNodeFromList (scene_upper->mRootNode->FindNode("tag_torso")); RemoveSingleNodeFromList (scene_upper->mRootNode->FindNode("tag_torso"));
RemoveSingleNodeFromList (scene_head-> mRootNode->FindNode("tag_head" )); RemoveSingleNodeFromList (scene_head-> mRootNode->FindNode("tag_head" ));
// Undo the rotations which we applied to the coordinate systems. We're
// working in global Quake space here
scene_head->mRootNode->mTransformation = aiMatrix4x4();
scene_lower->mRootNode->mTransformation = aiMatrix4x4();
scene_upper->mRootNode->mTransformation = aiMatrix4x4();
// and merge the scenes // and merge the scenes
SceneCombiner::MergeScenes(&mScene,master, attach, SceneCombiner::MergeScenes(&mScene,master, attach,
AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES | AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES |
@ -608,6 +614,10 @@ bool MD3Importer::ReadMultipartFile()
AI_INT_MERGE_SCENE_RESOLVE_CROSS_ATTACHMENTS | AI_INT_MERGE_SCENE_RESOLVE_CROSS_ATTACHMENTS |
(!configSpeedFlag ? AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY : 0)); (!configSpeedFlag ? AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY : 0));
// Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
mScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f,
0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f);
return true; return true;
error_cleanup: error_cleanup:
@ -673,10 +683,7 @@ void MD3Importer::InternReadFile( const std::string& pFile,
// get base path and file name // get base path and file name
// todo ... move to PathConverter // todo ... move to PathConverter
std::string::size_type s = mFile.find_last_of('/'); std::string::size_type s = mFile.find_last_of("/\\");
if (s == std::string::npos) {
s = mFile.find_last_of('\\');
}
if (s == std::string::npos) { if (s == std::string::npos) {
s = 0; s = 0;
} }
@ -907,8 +914,7 @@ void MD3Importer::InternReadFile( const std::string& pFile,
// Ensure correct endianess // Ensure correct endianess
#ifdef AI_BUILD_BIG_ENDIAN #ifdef AI_BUILD_BIG_ENDIAN
for (uint32_t i = 0; i < pcSurfaces->NUM_VERTICES;++i) for (uint32_t i = 0; i < pcSurfaces->NUM_VERTICES;++i) {
{
AI_SWAP2( pcVertices[i].NORMAL ); AI_SWAP2( pcVertices[i].NORMAL );
AI_SWAP2( pcVertices[i].X ); AI_SWAP2( pcVertices[i].X );
AI_SWAP2( pcVertices[i].Y ); AI_SWAP2( pcVertices[i].Y );
@ -917,8 +923,7 @@ void MD3Importer::InternReadFile( const std::string& pFile,
AI_SWAP4( pcUVs[i].U ); AI_SWAP4( pcUVs[i].U );
AI_SWAP4( pcUVs[i].U ); AI_SWAP4( pcUVs[i].U );
} }
for (uint32_t i = 0; i < pcSurfaces->NUM_TRIANGLES;++i) for (uint32_t i = 0; i < pcSurfaces->NUM_TRIANGLES;++i) {
{
AI_SWAP4(pcTriangles[i].INDEXES[0]); AI_SWAP4(pcTriangles[i].INDEXES[0]);
AI_SWAP4(pcTriangles[i].INDEXES[1]); AI_SWAP4(pcTriangles[i].INDEXES[1]);
AI_SWAP4(pcTriangles[i].INDEXES[2]); AI_SWAP4(pcTriangles[i].INDEXES[2]);
@ -939,34 +944,31 @@ void MD3Importer::InternReadFile( const std::string& pFile,
// Fill in all triangles // Fill in all triangles
unsigned int iCurrent = 0; unsigned int iCurrent = 0;
for (unsigned int i = 0; i < (unsigned int)pcSurfaces->NUM_TRIANGLES;++i) for (unsigned int i = 0; i < (unsigned int)pcSurfaces->NUM_TRIANGLES;++i) {
{
pcMesh->mFaces[i].mIndices = new unsigned int[3]; pcMesh->mFaces[i].mIndices = new unsigned int[3];
pcMesh->mFaces[i].mNumIndices = 3; pcMesh->mFaces[i].mNumIndices = 3;
unsigned int iTemp = iCurrent; unsigned int iTemp = iCurrent;
for (unsigned int c = 0; c < 3;++c,++iCurrent) for (unsigned int c = 0; c < 3;++c,++iCurrent) {
{
pcMesh->mFaces[i].mIndices[c] = iCurrent; pcMesh->mFaces[i].mIndices[c] = iCurrent;
// Read vertices // Read vertices
pcMesh->mVertices[iCurrent].x = pcVertices[ pcTriangles->INDEXES[c]].X*AI_MD3_XYZ_SCALE; aiVector3D& vec = pcMesh->mVertices[iCurrent];
pcMesh->mVertices[iCurrent].y = pcVertices[ pcTriangles->INDEXES[c]].Y*AI_MD3_XYZ_SCALE; vec.x = pcVertices[ pcTriangles->INDEXES[c]].X*AI_MD3_XYZ_SCALE;
pcMesh->mVertices[iCurrent].z = pcVertices[ pcTriangles->INDEXES[c]].Z*AI_MD3_XYZ_SCALE; vec.y = pcVertices[ pcTriangles->INDEXES[c]].Y*AI_MD3_XYZ_SCALE;
vec.z = pcVertices[ pcTriangles->INDEXES[c]].Z*AI_MD3_XYZ_SCALE;
// Convert the normal vector to uncompressed float3 format // Convert the normal vector to uncompressed float3 format
LatLngNormalToVec3(pcVertices[pcTriangles->INDEXES[c]].NORMAL, aiVector3D& nor = pcMesh->mNormals[iCurrent];
(float*)&pcMesh->mNormals[iCurrent]); LatLngNormalToVec3(pcVertices[pcTriangles->INDEXES[c]].NORMAL,(float*)&nor);
// Read texture coordinates // Read texture coordinates
pcMesh->mTextureCoords[0][iCurrent].x = pcUVs[ pcTriangles->INDEXES[c]].U; pcMesh->mTextureCoords[0][iCurrent].x = pcUVs[ pcTriangles->INDEXES[c]].U;
pcMesh->mTextureCoords[0][iCurrent].y = 1.0f-pcUVs[ pcTriangles->INDEXES[c]].V; pcMesh->mTextureCoords[0][iCurrent].y = 1.0f-pcUVs[ pcTriangles->INDEXES[c]].V;
} }
// Flip face order if necessary // Flip face order if necessary
if (!shader || shader->cull == Q3Shader::CULL_CCW) { if (!shader || shader->cull == Q3Shader::CULL_CW) {
pcMesh->mFaces[i].mIndices[0] = iTemp+2; std::swap(pcMesh->mFaces[i].mIndices[2],pcMesh->mFaces[i].mIndices[1]);
pcMesh->mFaces[i].mIndices[1] = iTemp+1;
pcMesh->mFaces[i].mIndices[2] = iTemp+0;
} }
pcTriangles++; pcTriangles++;
} }
@ -1008,7 +1010,7 @@ void MD3Importer::InternReadFile( const std::string& pFile,
AI_SWAP4(pcTags->origin.y); AI_SWAP4(pcTags->origin.y);
AI_SWAP4(pcTags->origin.z); AI_SWAP4(pcTags->origin.z);
// Copy local origin // Copy local origin, again flip z,y
nd->mTransformation.a4 = pcTags->origin.x; nd->mTransformation.a4 = pcTags->origin.x;
nd->mTransformation.b4 = pcTags->origin.y; nd->mTransformation.b4 = pcTags->origin.y;
nd->mTransformation.c4 = pcTags->origin.z; nd->mTransformation.c4 = pcTags->origin.z;
@ -1025,6 +1027,10 @@ void MD3Importer::InternReadFile( const std::string& pFile,
for (unsigned int i = 0; i < pScene->mNumMeshes;++i) for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
pScene->mRootNode->mMeshes[i] = i; pScene->mRootNode->mMeshes[i] = i;
// Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
pScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f,
0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f);
} }
#endif // !! ASSIMP_BUILD_NO_MD3_IMPORTER #endif // !! ASSIMP_BUILD_NO_MD3_IMPORTER

View File

@ -145,7 +145,7 @@ struct ShaderMapBlock
struct ShaderDataBlock struct ShaderDataBlock
{ {
ShaderDataBlock() ShaderDataBlock()
: cull (CULL_CCW) : cull (CULL_CW)
{} {}
//! Name of referenced data element //! Name of referenced data element

View File

@ -551,12 +551,12 @@ By contrast, some other environments use left-handed coordinate systems, a promi
DirectX. If you need the imported data to be in a left-handed coordinate system, supply the DirectX. If you need the imported data to be in a left-handed coordinate system, supply the
#aiProcess_MakeLeftHanded flag to the ReadFile() function call. #aiProcess_MakeLeftHanded flag to the ReadFile() function call.
The output face winding is counter-clockwise. Use #aiProcess_FlipWindingOrder to get CW data. The output face winding is clockwise. Use #aiProcess_FlipWindingOrder to get CCW data.
@code @code
x0 x0
x2 x1
x1 x2
@endcode @endcode
The output UV coordinate system has its origin in the lower-left corner: The output UV coordinate system has its origin in the lower-left corner:

View File

@ -63,12 +63,14 @@ extern "C" {
* a special post-processing step which splits meshes with *different* * a special post-processing step which splits meshes with *different*
* primitive types mixed up (e.g. lines and triangles) in several, 'clean' * primitive types mixed up (e.g. lines and triangles) in several, 'clean'
* submeshes. Furthermore there is a configuration option, * submeshes. Furthermore there is a configuration option,
* AI_CONFIG_PP_SBP_REMOVE, to force SortByPType to remove specific primitive * #AI_CONFIG_PP_SBP_REMOVE, to force #aiProcess_SortByPType to remove
* types from the scene - completely. In most cases you'll propably want to * specific primitive types from the imported scene - completely. In most cases
* set this config to * you'll probably want to set this setting to
* @code * @code
* aiPrimitiveType_LINE|aiPrimitiveType_POINT * aiPrimitiveType_LINE|aiPrimitiveType_POINT
* @endcode * @endcode
* @note Take a look at the @link data Data Structures page @endlink for
* more information on the layout and winding order of a face.
*/ */
struct aiFace struct aiFace
{ {

View File

@ -436,14 +436,14 @@ enum aiPostProcessSteps
aiProcess_FlipUVs = 0x80000000, /* don't change */ aiProcess_FlipUVs = 0x80000000, /* don't change */
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
/** <hr>This step adjusts the output face winding order to be clock-wise. /** <hr>This step adjusts the output face winding order to be ccw.
* *
* The default face winding order is counter-clockwise. * The default face winding order is clockwise.
* <br><b>Output face order:</b> * <br><b>Output face order:</b>
* @code * @code
* x0 * x1
* *
* x1 * x0
* x2 * x2
* @endcode * @endcode
*/ */
@ -461,10 +461,9 @@ enum aiPostProcessSteps
/** @def aiProcess_ConvertToLeftHanded /** @def aiProcess_ConvertToLeftHanded
* @brief Shortcut flag for Direct3D-based applications. * @brief Shortcut flag for Direct3D-based applications.
* *
* Supersedes the #aiProcess_MakeLeftHanded, #aiProcess_FlipUVs and * Supersedes the #aiProcess_MakeLeftHanded and #aiProcess_FlipUVs and
* #aiProcess_FlipWindingOrder flags. The output data matches Direct3D's conventions: * The output data matches Direct3D's conventions: left-handed geometry, upper-left
* left-handed geometry, upper-left origin for UV coordinates and finally clockwise * origin for UV coordinates and finally clockwise face order, suitable for CCW culling.
* face order, suitable for CCW culling.
* *
* @deprecated * @deprecated
*/ */