diff --git a/Engine/source/ts/assimp/assimpAppMesh.cpp b/Engine/source/ts/assimp/assimpAppMesh.cpp index 8246dad42..cd9c79bcb 100644 --- a/Engine/source/ts/assimp/assimpAppMesh.cpp +++ b/Engine/source/ts/assimp/assimpAppMesh.cpp @@ -31,6 +31,9 @@ #include #include +bool AssimpAppMesh::fixedSizeEnabled = false; +S32 AssimpAppMesh::fixedSize = 2; + //------------------------------------------------------------------------------ AssimpAppMesh::AssimpAppMesh(const struct aiMesh* mesh, AssimpAppNode* node) @@ -59,8 +62,7 @@ const char* AssimpAppMesh::getName(bool allowFixed) // If all geometry is being fixed to the same size, append the size // to the name - //return allowFixed && fixedSizeEnabled ? avar("%s %d", nodeName, fixedSize) : nodeName; - return nodeName; + return allowFixed && fixedSizeEnabled ? avar("%s %d", nodeName, fixedSize) : nodeName; } MatrixF AssimpAppMesh::getMeshTransform(F32 time) @@ -77,6 +79,8 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objOffset) uvs.reserve(mMeshData->mNumVertices); normals.reserve(mMeshData->mNumVertices); + bool flipNormals = Con::getBoolVariable("$Assimp::FlipNormals", false); + bool noUVFound = false; for (U32 i = 0; imNumVertices; i++) { @@ -93,6 +97,8 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objOffset) tmpVert = Point3F(pt.x, pt.y, pt.z); tmpNormal = Point3F(nrm.x, nrm.y, nrm.z); + if (flipNormals) + tmpNormal *= -1.0f; objOffset.mulP(tmpVert); @@ -155,23 +161,11 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objOffset) const struct aiFace* face = &mMeshData->mFaces[n]; if ( face->mNumIndices == 3 ) { - if (Con::getBoolVariable("$Assimp::FlipNormals", true)) + U32 indexCount = face->mNumIndices; + for (U32 ind = 0; ind < indexCount; ind++) { - U32 indexCount = face->mNumIndices; - for (S32 ind = indexCount - 1; ind >= 0; ind--) - { - U32 index = face->mIndices[ind]; - indices.push_back(index); - } - } - else - { - U32 indexCount = face->mNumIndices; - for (U32 ind = 0; ind < indexCount; ind++) - { - U32 index = face->mIndices[ind]; - indices.push_back(index); - } + U32 index = face->mIndices[ind]; + indices.push_back(index); } } else diff --git a/Engine/source/ts/assimp/assimpAppMesh.h b/Engine/source/ts/assimp/assimpAppMesh.h index 9f6a4f87c..871ef86fe 100644 --- a/Engine/source/ts/assimp/assimpAppMesh.h +++ b/Engine/source/ts/assimp/assimpAppMesh.h @@ -42,6 +42,9 @@ protected: const struct aiMesh* mMeshData; bool mIsSkinMesh; + static bool fixedSizeEnabled; ///< Set to true to fix the detail size to a particular value for all geometry + static S32 fixedSize; ///< The fixed detail size value for all geometry + public: AssimpAppMesh(const struct aiMesh* mesh, AssimpAppNode* node); @@ -54,8 +57,8 @@ public: static void fixDetailSize(bool fixed, S32 size=2) { - //fixedSizeEnabled = fixed; - //fixedSize = size; + fixedSizeEnabled = fixed; + fixedSize = size; } /// Get the name of this mesh diff --git a/Engine/source/ts/assimp/assimpShapeLoader.cpp b/Engine/source/ts/assimp/assimpShapeLoader.cpp index 6192bd5bb..c1b364aa3 100644 --- a/Engine/source/ts/assimp/assimpShapeLoader.cpp +++ b/Engine/source/ts/assimp/assimpShapeLoader.cpp @@ -33,6 +33,7 @@ #include "ts/assimp/assimpShapeLoader.h" #include "ts/assimp/assimpAppNode.h" +#include "ts/assimp/assimpAppMesh.h" #include "ts/assimp/assimpAppMaterial.h" #include "ts/assimp/assimpAppSequence.h" @@ -150,6 +151,9 @@ void AssimpShapeLoader::enumerateScene() if(Con::getBoolVariable("$Assimp::FlipUVs", true)) ppsteps |= aiProcess_FlipUVs; + if(Con::getBoolVariable("$Assimp::FlipWindingOrder", true)) + ppsteps |= aiProcess_FlipWindingOrder; + if(Con::getBoolVariable("$Assimp::Triangulate", true)) ppsteps |= aiProcess_Triangulate; @@ -163,17 +167,21 @@ void AssimpShapeLoader::enumerateScene() aiPropertyStore* props = aiCreatePropertyStore(); - aiSetImportPropertyInteger(props, AI_CONFIG_IMPORT_TER_MAKE_UVS, 1); - aiSetImportPropertyInteger(props, AI_CONFIG_PP_SBP_REMOVE, (aiProcessPreset_TargetRealtime_Quality - | aiProcess_FlipWindingOrder | aiProcess_FlipUVs - | aiProcess_CalcTangentSpace - | aiProcess_FixInfacingNormals) - & ~aiProcess_RemoveRedundantMaterials); - aiSetImportPropertyInteger(props, AI_CONFIG_GLOB_MEASURE_TIME, 1); - aiSetImportPropertyFloat(props, AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE, 80.f); + //aiSetImportPropertyInteger(props, AI_CONFIG_IMPORT_TER_MAKE_UVS, 1); + //aiSetImportPropertyInteger(props, AI_CONFIG_PP_SBP_REMOVE, (aiProcessPreset_TargetRealtime_Quality + // | aiProcess_FlipWindingOrder | aiProcess_FlipUVs + // | aiProcess_CalcTangentSpace + // | aiProcess_FixInfacingNormals) + // & ~aiProcess_RemoveRedundantMaterials); + //aiSetImportPropertyInteger(props, AI_CONFIG_GLOB_MEASURE_TIME, 1); + //aiSetImportPropertyFloat(props, AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE, 80.f); //aiSetImportPropertyInteger(props,AI_CONFIG_PP_PTV_KEEP_HIERARCHY,1); - //Assimp::Importer importer; + struct aiLogStream c; + c = aiGetPredefinedLogStream(aiDefaultLogStream_FILE, "assimp.log"); + aiAttachLogStream(&c); + c = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT, NULL); + aiAttachLogStream(&c); // Attempt to import with Assimp. //mScene = importer.ReadFile(shapePath.getFullPath().c_str(), (aiProcessPreset_TargetRealtime_Quality | aiProcess_FlipWindingOrder | aiProcess_FlipUVs | aiProcess_CalcTangentSpace) @@ -192,6 +200,9 @@ void AssimpShapeLoader::enumerateScene() for ( U32 i = 0; i < mScene->mNumMaterials; i++ ) AppMesh::appMaterials.push_back(new AssimpAppMaterial(mScene->mMaterials[i])); + // Setup LOD checks + detectDetails(); + // Define the root node, and process down the chain. AssimpAppNode* node = new AssimpAppNode(mScene, mScene->mRootNode, 0); @@ -219,6 +230,55 @@ void AssimpShapeLoader::processAnimations() } } +void AssimpShapeLoader::computeBounds(Box3F& bounds) +{ + TSShapeLoader::computeBounds(bounds); + + // Check if the model origin needs adjusting + bool adjustCenter = Con::getBoolVariable("$Assimp::adjustCenter", false); //ColladaUtils::getOptions().adjustCenter + bool adjustFloor = Con::getBoolVariable("$Assimp::adjustFloor", false); //ColladaUtils::getOptions().adjustFloor + if (bounds.isValidBox() && (adjustCenter || adjustFloor)) + { + // Compute shape offset + Point3F shapeOffset = Point3F::Zero; + if (adjustCenter) + { + bounds.getCenter(&shapeOffset); + shapeOffset = -shapeOffset; + } + if (adjustFloor) + shapeOffset.z = -bounds.minExtents.z; + + // Adjust bounds + bounds.minExtents += shapeOffset; + bounds.maxExtents += shapeOffset; + + // Now adjust all positions for root level nodes (nodes with no parent) + for (S32 iNode = 0; iNode < shape->nodes.size(); iNode++) + { + if (!appNodes[iNode]->isParentRoot()) + continue; + + // Adjust default translation + shape->defaultTranslations[iNode] += shapeOffset; + + // Adjust animated translations + for (S32 iSeq = 0; iSeq < shape->sequences.size(); iSeq++) + { + const TSShape::Sequence& seq = shape->sequences[iSeq]; + if (seq.translationMatters.test(iNode)) + { + for (S32 iFrame = 0; iFrame < seq.numKeyframes; iFrame++) + { + S32 index = seq.baseTranslation + seq.translationMatters.count(iNode)*seq.numKeyframes + iFrame; + shape->nodeTranslations[index] += shapeOffset; + } + } + } + } + } +} + void AssimpShapeLoader::updateMaterialsScript(const Torque::Path &path) { Torque::Path scriptPath(path); @@ -289,6 +349,44 @@ bool AssimpShapeLoader::ignoreNode(const String& name) return false; } +void AssimpShapeLoader::detectDetails() +{ + // Set LOD option + bool singleDetail = true; + switch (Con::getIntVariable("$Assimp::lodType", 0)) + { + case ColladaUtils::ImportOptions::DetectDTS: + // Check for a baseXX->startXX hierarchy at the top-level, if we find + // one, use trailing numbers for LOD, otherwise use a single size + for (S32 iNode = 0; singleDetail && (iNode < mScene->mRootNode->mNumChildren); iNode++) { + aiNode* node = mScene->mRootNode->mChildren[iNode]; + if (node && dStrStartsWith(node->mName.C_Str(), "base")) { + for (S32 iChild = 0; iChild < node->mNumChildren; iChild++) { + aiNode* child = node->mChildren[iChild]; + if (child && dStrStartsWith(child->mName.C_Str(), "start")) { + singleDetail = false; + break; + } + } + } + } + break; + + case ColladaUtils::ImportOptions::SingleSize: + singleDetail = true; + break; + + case ColladaUtils::ImportOptions::TrailingNumber: + singleDetail = false; + break; + + default: + break; + } + + AssimpAppMesh::fixDetailSize(singleDetail, Con::getIntVariable("$Assimp::singleDetailSize", 2)); +} + //----------------------------------------------------------------------------- /// This function is invoked by the resource manager based on file extension. TSShape* assimpLoadShape(const Torque::Path &path) @@ -377,7 +475,7 @@ DefineEngineFunction(GetShapeInfo, GuiTreeViewCtrl*, (String filePath), , //Details! for (U32 i = 0; i < shapeScene->mNumMeshes; i++) { - treeObj->insertItem(meshItem, String::ToString("%s", shapeScene->mMeshes[i]->mName)); + treeObj->insertItem(meshItem, String::ToString("%s", shapeScene->mMeshes[i]->mName.C_Str())); } for (U32 i = 0; i < shapeScene->mNumMaterials; i++) diff --git a/Engine/source/ts/assimp/assimpShapeLoader.h b/Engine/source/ts/assimp/assimpShapeLoader.h index 807cd3fab..713e403cc 100644 --- a/Engine/source/ts/assimp/assimpShapeLoader.h +++ b/Engine/source/ts/assimp/assimpShapeLoader.h @@ -36,6 +36,7 @@ protected: const struct aiScene* mScene; virtual bool ignoreNode(const String& name); + void detectDetails(); public: AssimpShapeLoader(); @@ -46,6 +47,8 @@ public: void updateMaterialsScript(const Torque::Path &path); void processAnimations(); + void computeBounds(Box3F& bounds); + static bool canLoadCachedDTS(const Torque::Path& path); };