mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-02-12 19:31:41 +00:00
Merge branch 'Assimp_Settings' of https://github.com/OTHGMars/Torque3D into Preview4_0
This commit is contained in:
commit
ef226f6a65
25 changed files with 4541 additions and 1508 deletions
|
|
@ -27,6 +27,7 @@
|
|||
#include "ts/assimp/assimpAppMesh.h"
|
||||
#include "materials/materialManager.h"
|
||||
#include "ts/tsMaterialList.h"
|
||||
#include "core/stream/fileStream.h"
|
||||
|
||||
// assimp include files.
|
||||
#include <assimp/cimport.h>
|
||||
|
|
@ -34,6 +35,8 @@
|
|||
#include <assimp/postprocess.h>
|
||||
#include <assimp/types.h>
|
||||
|
||||
U32 AssimpAppMaterial::sDefaultMatNumber = 0;
|
||||
|
||||
String AppMaterial::cleanString(const String& str)
|
||||
{
|
||||
String cleanStr(str);
|
||||
|
|
@ -52,7 +55,8 @@ String AppMaterial::cleanString(const String& str)
|
|||
|
||||
AssimpAppMaterial::AssimpAppMaterial(const char* matName)
|
||||
{
|
||||
name = matName;
|
||||
name = ColladaUtils::getOptions().matNamePrefix;
|
||||
name += matName;
|
||||
|
||||
// Set some defaults
|
||||
flags |= TSMaterialList::S_Wrap;
|
||||
|
|
@ -67,9 +71,12 @@ AssimpAppMaterial::AssimpAppMaterial(aiMaterial* mtl) :
|
|||
name = matName.C_Str();
|
||||
if (name.isEmpty())
|
||||
{
|
||||
name = cleanString(TSShapeLoader::getShapePath().getFileName());;
|
||||
name = cleanString(TSShapeLoader::getShapePath().getFileName());
|
||||
name += "_defMat";
|
||||
name += String::ToString("%d", sDefaultMatNumber);
|
||||
sDefaultMatNumber++;
|
||||
}
|
||||
name = ColladaUtils::getOptions().matNamePrefix + name;
|
||||
Con::printf("[ASSIMP] Loading Material: %s", name.c_str());
|
||||
#ifdef TORQUE_DEBUG
|
||||
enumerateMaterialProperties(mtl);
|
||||
|
|
@ -125,7 +132,7 @@ void AssimpAppMaterial::initMaterial(const Torque::Path& path, Material* mat) co
|
|||
if (dStrcmp("MASK", opacityMode.C_Str()) == 0)
|
||||
{
|
||||
translucent = true;
|
||||
blendOp = Material::LerpAlpha;
|
||||
blendOp = Material::None;
|
||||
|
||||
float cutoff;
|
||||
if (AI_SUCCESS == mAIMat->Get("$mat.gltf.alphaCutoff", 0, 0, cutoff))
|
||||
|
|
@ -134,10 +141,16 @@ void AssimpAppMaterial::initMaterial(const Torque::Path& path, Material* mat) co
|
|||
mat->mAlphaTest = true;
|
||||
}
|
||||
}
|
||||
else if (dStrcmp("OPAQUE", opacityMode.C_Str()) != 0)
|
||||
else if (dStrcmp("BLEND", opacityMode.C_Str()) == 0)
|
||||
{
|
||||
translucent = true;
|
||||
blendOp = Material::LerpAlpha;
|
||||
mat->mAlphaTest = false;
|
||||
}
|
||||
else
|
||||
{ // OPAQUE
|
||||
translucent = false;
|
||||
blendOp = Material::LerpAlpha; // Make default so it doesn't get written to materials.cs
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -157,14 +170,14 @@ void AssimpAppMaterial::initMaterial(const Torque::Path& path, Material* mat) co
|
|||
{
|
||||
torquePath = texName.C_Str();
|
||||
if (!torquePath.isEmpty())
|
||||
mat->mDiffuseMapFilename[0] = cleanTextureName(torquePath, cleanFile);
|
||||
mat->mDiffuseMapFilename[0] = cleanTextureName(torquePath, cleanFile, path, false);
|
||||
}
|
||||
|
||||
if (AI_SUCCESS == mAIMat->Get(AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0), texName))
|
||||
{
|
||||
torquePath = texName.C_Str();
|
||||
if (!torquePath.isEmpty())
|
||||
mat->mNormalMapFilename[0] = cleanTextureName(torquePath, cleanFile);
|
||||
mat->mNormalMapFilename[0] = cleanTextureName(torquePath, cleanFile, path, false);
|
||||
}
|
||||
|
||||
#ifdef TORQUE_PBR_MATERIALS
|
||||
|
|
@ -177,27 +190,25 @@ void AssimpAppMaterial::initMaterial(const Torque::Path& path, Material* mat) co
|
|||
if (AI_SUCCESS == mAIMat->Get(AI_MATKEY_TEXTURE(aiTextureType_UNKNOWN, 0), texName))
|
||||
rmName = texName.C_Str();
|
||||
|
||||
//if (aoName.isNotEmpty() && (aoName == rmName))
|
||||
// mat->mOrmMapFilename[0] = cleanTextureName(aoName, cleanFile); // It's an ORM map
|
||||
//else if (aoName.isNotEmpty() || rmName.isNotEmpty())
|
||||
mat->mIsSRGb[0] = true;
|
||||
if (aoName.isNotEmpty() || rmName.isNotEmpty())
|
||||
{ // If we have either map, fill all three slots
|
||||
if (rmName.isNotEmpty())
|
||||
{
|
||||
mat->mRoughMapFilename[0] = cleanTextureName(rmName, cleanFile); // Roughness
|
||||
mat->mRoughMapFilename[0] = cleanTextureName(rmName, cleanFile, path, false); // Roughness
|
||||
mat->mSmoothnessChan[0] = 1.0f;
|
||||
mat->mInvertSmoothness = (floatVal == 1.0f);
|
||||
mat->mMetalMapFilename[0] = cleanTextureName(rmName, cleanFile); // Metallic
|
||||
mat->mMetalMapFilename[0] = cleanTextureName(rmName, cleanFile, path, false); // Metallic
|
||||
mat->mMetalChan[0] = 2.0f;
|
||||
}
|
||||
if (aoName.isNotEmpty())
|
||||
{
|
||||
mat->mAOMapFilename[0] = cleanTextureName(aoName, cleanFile); // occlusion
|
||||
mat->mAOMapFilename[0] = cleanTextureName(aoName, cleanFile, path, false); // occlusion
|
||||
mat->mAOChan[0] = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
mat->mAOMapFilename[0] = cleanTextureName(rmName, cleanFile); // occlusion
|
||||
mat->mAOMapFilename[0] = cleanTextureName(rmName, cleanFile, path, false); // occlusion
|
||||
mat->mAOChan[0] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
|
@ -207,7 +218,7 @@ void AssimpAppMaterial::initMaterial(const Torque::Path& path, Material* mat) co
|
|||
{
|
||||
torquePath = texName.C_Str();
|
||||
if (!torquePath.isEmpty())
|
||||
mat->mSpecularMapFilename[0] = cleanTextureName(torquePath, cleanFile);
|
||||
mat->mSpecularMapFilename[0] = cleanTextureName(torquePath, cleanFile, path, false);
|
||||
}
|
||||
|
||||
/*LinearColorF specularColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
|
@ -234,22 +245,70 @@ void AssimpAppMaterial::initMaterial(const Torque::Path& path, Material* mat) co
|
|||
mat->mDoubleSided = doubleSided;
|
||||
}
|
||||
|
||||
String AssimpAppMaterial::cleanTextureName(String& texName, String& shapeName)
|
||||
String AssimpAppMaterial::cleanTextureName(String& texName, String& shapeName, const Torque::Path& path, bool nameOnly /*= false*/)
|
||||
{
|
||||
Torque::Path foundPath;
|
||||
String cleanStr;
|
||||
|
||||
if (texName[0] == '*')
|
||||
{
|
||||
{ // It's an embedded texture reference. Make the cached name and return
|
||||
cleanStr = shapeName;
|
||||
cleanStr += "_cachedTex";
|
||||
cleanStr += texName.substr(1);
|
||||
return cleanStr;
|
||||
}
|
||||
|
||||
// See if the file exists
|
||||
bool fileFound = false;
|
||||
String testPath = path.getPath();
|
||||
testPath += '/';
|
||||
testPath += texName;
|
||||
testPath.replace('\\', '/');
|
||||
fileFound = Torque::FS::IsFile(testPath);
|
||||
|
||||
cleanStr = texName;
|
||||
cleanStr.replace('\\', '/');
|
||||
if (fileFound)
|
||||
{
|
||||
if (cleanStr.equal(texName))
|
||||
return cleanStr;
|
||||
foundPath = testPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
cleanStr = texName;
|
||||
cleanStr.replace('\\', '/');
|
||||
// See if the file is in a sub-directory of the shape
|
||||
Vector<String> foundFiles;
|
||||
Torque::Path inPath(cleanStr);
|
||||
String mainDotCsDir = Platform::getMainDotCsDir();
|
||||
mainDotCsDir += "/";
|
||||
S32 results = Torque::FS::FindByPattern(Torque::Path(mainDotCsDir + path.getPath() + "/"), inPath.getFullFileName(), true, foundFiles);
|
||||
if (results == 0 || foundFiles.size() == 0) // Not under shape directory, try the full tree
|
||||
results = Torque::FS::FindByPattern(Torque::Path(mainDotCsDir), inPath.getFullFileName(), true, foundFiles);
|
||||
|
||||
if (results > 0 && foundFiles.size() > 0)
|
||||
{
|
||||
fileFound = true;
|
||||
foundPath = foundFiles[0];
|
||||
}
|
||||
}
|
||||
|
||||
if (fileFound)
|
||||
{
|
||||
if (nameOnly)
|
||||
cleanStr = foundPath.getFullFileName();
|
||||
else
|
||||
{ // Unless the file is in the same directory as the materials.cs (covered above)
|
||||
// we need to set the full path from the root directory. If we use "subdirectory/file.ext",
|
||||
// the material manager won't find the image file, but it will be found the next time the
|
||||
// material is loaded from file. If we use "./subdirectory/file.ext", the image will be found
|
||||
// now, but not the next time it's loaded from file...
|
||||
S32 rootLength = dStrlen(Platform::getMainDotCsDir());
|
||||
cleanStr = foundPath.getFullPathWithoutRoot().substr(rootLength-1);
|
||||
}
|
||||
}
|
||||
else if (nameOnly)
|
||||
cleanStr += " (Not Found)";
|
||||
|
||||
return cleanStr;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@ class AssimpAppMaterial : public AppMaterial
|
|||
#ifdef TORQUE_DEBUG
|
||||
void enumerateMaterialProperties(aiMaterial* mtl);
|
||||
#endif
|
||||
static String cleanTextureName(String& texName, String& shapeName);
|
||||
|
||||
public:
|
||||
|
||||
|
|
@ -51,6 +50,9 @@ public:
|
|||
String getName() const { return name; }
|
||||
Material* createMaterial(const Torque::Path& path) const;
|
||||
void initMaterial(const Torque::Path& path, Material* mat) const;
|
||||
|
||||
static String cleanTextureName(String& texName, String& shapeName, const Torque::Path& path, bool nameOnly = false);
|
||||
static U32 sDefaultMatNumber;
|
||||
};
|
||||
|
||||
#endif // _ASSIMP_APPMATERIAL_H_
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objOffset)
|
|||
uvs.reserve(mMeshData->mNumVertices);
|
||||
normals.reserve(mMeshData->mNumVertices);
|
||||
|
||||
bool flipNormals = Con::getBoolVariable("$Assimp::FlipNormals", false);
|
||||
bool flipNormals = ColladaUtils::getOptions().invertNormals;
|
||||
|
||||
bool noUVFound = false;
|
||||
for (U32 i = 0; i<mMeshData->mNumVertices; i++)
|
||||
|
|
@ -203,14 +203,17 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objOffset)
|
|||
MatrixF boneTransform;
|
||||
AssimpAppNode::assimpToTorqueMat(mMeshData->mBones[b]->mOffsetMatrix, boneTransform);
|
||||
Point3F boneScale = boneTransform.getScale();
|
||||
if (boneScale != Point3F::One)
|
||||
Point3F bonePos = boneTransform.getPosition();
|
||||
if (boneScale != Point3F::One && ColladaUtils::getOptions().ignoreNodeScale)
|
||||
{
|
||||
Point3F scaleMult = Point3F::One / boneScale;
|
||||
Point3F scalePos = boneTransform.getPosition();
|
||||
boneTransform.scale(scaleMult);
|
||||
scalePos /= scaleMult;
|
||||
boneTransform.setPosition(scalePos);
|
||||
bonePos /= scaleMult;
|
||||
}
|
||||
|
||||
bonePos *= ColladaUtils::getOptions().unit;
|
||||
boneTransform.setPosition(bonePos);
|
||||
|
||||
initialTransforms.push_back(boneTransform);
|
||||
|
||||
//Weights
|
||||
|
|
|
|||
|
|
@ -91,22 +91,30 @@ MatrixF AssimpAppNode::getTransform(F32 time)
|
|||
else {
|
||||
// no parent (ie. root level) => scale by global shape <unit>
|
||||
mLastTransform.identity();
|
||||
mLastTransform.scale(ColladaUtils::getOptions().unit);
|
||||
if (!isBounds())
|
||||
convertMat(mLastTransform);
|
||||
|
||||
//mLastTransform.scale(ColladaUtils::getOptions().unit);
|
||||
}
|
||||
|
||||
// If this node is animated in the active sequence, fetch the animated transform
|
||||
MatrixF mat(true);
|
||||
if (sActiveSequence)
|
||||
{
|
||||
MatrixF mat(true);
|
||||
getAnimatedTransform(mat, time, sActiveSequence);
|
||||
mLastTransform.mul(mat);
|
||||
}
|
||||
else
|
||||
mLastTransform.mul(mNodeTransform);
|
||||
|
||||
mat = mNodeTransform;
|
||||
|
||||
// Remove node scaling?
|
||||
Point3F nodeScale = mat.getScale();
|
||||
if (nodeScale != Point3F::One && appParent && ColladaUtils::getOptions().ignoreNodeScale)
|
||||
{
|
||||
nodeScale.x = nodeScale.x ? (1.0f / nodeScale.x) : 0;
|
||||
nodeScale.y = nodeScale.y ? (1.0f / nodeScale.y) : 0;
|
||||
nodeScale.z = nodeScale.z ? (1.0f / nodeScale.z) : 0;
|
||||
mat.scale(nodeScale);
|
||||
}
|
||||
|
||||
mLastTransform.mul(mat);
|
||||
|
||||
mLastTransformTime = time;
|
||||
return mLastTransform;
|
||||
}
|
||||
|
|
@ -280,12 +288,9 @@ void AssimpAppNode::convertMat(MatrixF& outMat)
|
|||
{
|
||||
MatrixF rot(true);
|
||||
|
||||
// This is copied directly from ColladaUtils::convertTransform()
|
||||
// ColladaUtils::getOptions().upAxis has been temporarily replaced with $Assimp::OverrideUpAxis for testing
|
||||
// We need a plan for how the full set of assimp import options and settings is going to be managed.
|
||||
switch (Con::getIntVariable("$Assimp::OverrideUpAxis", 2))
|
||||
switch (ColladaUtils::getOptions().upAxis)
|
||||
{
|
||||
case 0: //UPAXISTYPE_X_UP:
|
||||
case UPAXISTYPE_X_UP:
|
||||
// rotate 90 around Y-axis, then 90 around Z-axis
|
||||
rot(0, 0) = 0.0f; rot(1, 0) = 1.0f;
|
||||
rot(1, 1) = 0.0f; rot(2, 1) = 1.0f;
|
||||
|
|
@ -295,7 +300,7 @@ void AssimpAppNode::convertMat(MatrixF& outMat)
|
|||
outMat.mulL(rot);
|
||||
break;
|
||||
|
||||
case 1: //UPAXISTYPE_Y_UP:
|
||||
case UPAXISTYPE_Y_UP:
|
||||
// rotate 180 around Y-axis, then 90 around X-axis
|
||||
rot(0, 0) = -1.0f;
|
||||
rot(1, 1) = 0.0f; rot(2, 1) = 1.0f;
|
||||
|
|
@ -305,7 +310,7 @@ void AssimpAppNode::convertMat(MatrixF& outMat)
|
|||
outMat.mulL(rot);
|
||||
break;
|
||||
|
||||
case 2: //UPAXISTYPE_Z_UP:
|
||||
case UPAXISTYPE_Z_UP:
|
||||
default:
|
||||
// nothing to do
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -58,8 +58,8 @@ AssimpAppSequence::AssimpAppSequence(aiAnimation *a) :
|
|||
}
|
||||
}
|
||||
|
||||
S32 timeFactor = Con::getIntVariable("$Assimp::AnimTiming", 1);
|
||||
S32 fpsRequest = Con::getIntVariable("$Assimp::AnimFPS", 30);
|
||||
S32 timeFactor = ColladaUtils::getOptions().animTiming;
|
||||
S32 fpsRequest = ColladaUtils::getOptions().animFPS;
|
||||
if (timeFactor == 0)
|
||||
{ // Timing specified in frames
|
||||
fps = mClamp(fpsRequest, 5 /*TSShapeLoader::MinFrameRate*/, TSShapeLoader::MaxFrameRate);
|
||||
|
|
@ -70,10 +70,7 @@ AssimpAppSequence::AssimpAppSequence(aiAnimation *a) :
|
|||
else
|
||||
{ // Timing specified in seconds or ms depending on format
|
||||
if (maxEndTime > 1000.0f || mAnim->mDuration > 1000.0f)
|
||||
{
|
||||
timeFactor = 1000.0f; // If it's more than 1000 seconds, assume it's ms.
|
||||
Con::setIntVariable("$Assimp::AnimTiming", 1000);
|
||||
}
|
||||
|
||||
timeFactor = mClamp(timeFactor, 1, 1000);
|
||||
minFrameTime /= (F32)timeFactor;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
|
||||
#include "core/util/tVector.h"
|
||||
#include "core/strings/findMatch.h"
|
||||
#include "core/strings/stringUnit.h"
|
||||
#include "core/stream/fileStream.h"
|
||||
#include "core/fileObject.h"
|
||||
#include "ts/tsShape.h"
|
||||
|
|
@ -133,29 +134,16 @@ void AssimpShapeLoader::enumerateScene()
|
|||
|
||||
// Post-Processing
|
||||
unsigned int ppsteps =
|
||||
Con::getBoolVariable("$Assimp::ConvertToLeftHanded", false) ? aiProcess_ConvertToLeftHanded : 0 |
|
||||
Con::getBoolVariable("$Assimp::CalcTangentSpace", false) ? aiProcess_CalcTangentSpace : 0 |
|
||||
Con::getBoolVariable("$Assimp::JoinIdenticalVertices", false) ? aiProcess_JoinIdenticalVertices : 0 |
|
||||
Con::getBoolVariable("$Assimp::ValidateDataStructure", false) ? aiProcess_ValidateDataStructure : 0 |
|
||||
Con::getBoolVariable("$Assimp::ImproveCacheLocality", false) ? aiProcess_ImproveCacheLocality : 0 |
|
||||
Con::getBoolVariable("$Assimp::RemoveRedundantMaterials", false) ? aiProcess_RemoveRedundantMaterials : 0 |
|
||||
Con::getBoolVariable("$Assimp::FindDegenerates", false) ? aiProcess_FindDegenerates : 0 |
|
||||
Con::getBoolVariable("$Assimp::FindInvalidData", false) ? aiProcess_FindInvalidData : 0 |
|
||||
Con::getBoolVariable("$Assimp::GenUVCoords", false) ? aiProcess_GenUVCoords : 0 |
|
||||
Con::getBoolVariable("$Assimp::TransformUVCoords", false) ? aiProcess_TransformUVCoords : 0 |
|
||||
Con::getBoolVariable("$Assimp::FindInstances", false) ? aiProcess_FindInstances : 0 |
|
||||
Con::getBoolVariable("$Assimp::LimitBoneWeights", false) ? aiProcess_LimitBoneWeights : 0 |
|
||||
Con::getBoolVariable("$Assimp::OptimizeMeshes", false) ? aiProcess_OptimizeMeshes | aiProcess_OptimizeGraph : 0 |
|
||||
0;
|
||||
|
||||
if(Con::getBoolVariable("$Assimp::FlipUVs", true))
|
||||
ppsteps |= aiProcess_FlipUVs;
|
||||
|
||||
if(Con::getBoolVariable("$Assimp::FlipWindingOrder", false))
|
||||
ppsteps |= aiProcess_FlipWindingOrder;
|
||||
|
||||
if(Con::getBoolVariable("$Assimp::Triangulate", true))
|
||||
ppsteps |= aiProcess_Triangulate;
|
||||
(ColladaUtils::getOptions().convertLeftHanded ? aiProcess_MakeLeftHanded : 0) |
|
||||
(ColladaUtils::getOptions().reverseWindingOrder ? aiProcess_FlipWindingOrder : 0) |
|
||||
(ColladaUtils::getOptions().calcTangentSpace ? aiProcess_CalcTangentSpace : 0) |
|
||||
(ColladaUtils::getOptions().joinIdenticalVerts ? aiProcess_JoinIdenticalVertices : 0) |
|
||||
(ColladaUtils::getOptions().removeRedundantMats ? aiProcess_RemoveRedundantMaterials : 0) |
|
||||
(ColladaUtils::getOptions().genUVCoords ? aiProcess_GenUVCoords : 0) |
|
||||
(ColladaUtils::getOptions().transformUVCoords ? aiProcess_TransformUVCoords : 0) |
|
||||
(ColladaUtils::getOptions().flipUVCoords ? aiProcess_FlipUVs : 0) |
|
||||
(ColladaUtils::getOptions().findInstances ? aiProcess_FindInstances : 0) |
|
||||
(ColladaUtils::getOptions().limitBoneWeights ? aiProcess_LimitBoneWeights : 0);
|
||||
|
||||
if (Con::getBoolVariable("$Assimp::OptimizeMeshes", false))
|
||||
ppsteps |= aiProcess_OptimizeMeshes | aiProcess_OptimizeGraph;
|
||||
|
|
@ -163,34 +151,21 @@ void AssimpShapeLoader::enumerateScene()
|
|||
if (Con::getBoolVariable("$Assimp::SplitLargeMeshes", false))
|
||||
ppsteps |= aiProcess_SplitLargeMeshes;
|
||||
|
||||
// Mandatory options
|
||||
//ppsteps |= aiProcess_ValidateDataStructure | aiProcess_Triangulate | aiProcess_ImproveCacheLocality;
|
||||
ppsteps |= aiProcess_Triangulate;
|
||||
//aiProcess_SortByPType | // make 'clean' meshes which consist of a single typ of primitives
|
||||
|
||||
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_PP_PTV_KEEP_HIERARCHY,1);
|
||||
|
||||
struct aiLogStream shapeLog;
|
||||
shapeLog = aiGetPredefinedLogStream(aiDefaultLogStream_FILE, "assimp.log");
|
||||
struct aiLogStream shapeLog = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT, NULL);
|
||||
shapeLog.callback = assimpLogCallback;
|
||||
shapeLog.user = 0;
|
||||
aiAttachLogStream(&shapeLog);
|
||||
#ifdef TORQUE_DEBUG
|
||||
aiEnableVerboseLogging(true);
|
||||
#endif
|
||||
|
||||
//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)
|
||||
// & ~aiProcess_RemoveRedundantMaterials);
|
||||
|
||||
mScene = (aiScene*)aiImportFileExWithProperties(shapePath.getFullPath().c_str(), ppsteps, NULL, props);
|
||||
|
||||
aiReleasePropertyStore(props);
|
||||
|
|
@ -200,11 +175,38 @@ void AssimpShapeLoader::enumerateScene()
|
|||
Con::printf("[ASSIMP] Mesh Count: %d", mScene->mNumMeshes);
|
||||
Con::printf("[ASSIMP] Material Count: %d", mScene->mNumMaterials);
|
||||
|
||||
// Set import options (if they are not set to override)
|
||||
if (ColladaUtils::getOptions().unit <= 0.0f)
|
||||
{
|
||||
F64 unit;
|
||||
if (!getMetaDouble("UnitScaleFactor", unit))
|
||||
{
|
||||
F32 floatVal;
|
||||
S32 intVal;
|
||||
if (getMetaFloat("UnitScaleFactor", floatVal))
|
||||
unit = (F64)floatVal;
|
||||
else if (getMetaInt("UnitScaleFactor", intVal))
|
||||
unit = (F64)intVal;
|
||||
else
|
||||
unit = 1.0;
|
||||
}
|
||||
ColladaUtils::getOptions().unit = (F32)unit;
|
||||
}
|
||||
|
||||
if (ColladaUtils::getOptions().upAxis == UPAXISTYPE_COUNT)
|
||||
{
|
||||
S32 upAxis;
|
||||
if (!getMetaInt("UpAxis", upAxis))
|
||||
upAxis = UPAXISTYPE_Z_UP;
|
||||
ColladaUtils::getOptions().upAxis = (domUpAxisType) upAxis;
|
||||
}
|
||||
|
||||
// Extract embedded textures
|
||||
for (U32 i = 0; i < mScene->mNumTextures; ++i)
|
||||
extractTexture(i, mScene->mTextures[i]);
|
||||
|
||||
// Load all the materials.
|
||||
AssimpAppMaterial::sDefaultMatNumber = 0;
|
||||
for ( U32 i = 0; i < mScene->mNumMaterials; i++ )
|
||||
AppMesh::appMaterials.push_back(new AssimpAppMaterial(mScene->mMaterials[i]));
|
||||
|
||||
|
|
@ -245,8 +247,8 @@ 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
|
||||
bool adjustCenter = ColladaUtils::getOptions().adjustCenter;
|
||||
bool adjustFloor = ColladaUtils::getOptions().adjustFloor;
|
||||
if (bounds.isValidBox() && (adjustCenter || adjustFloor))
|
||||
{
|
||||
// Compute shape offset
|
||||
|
|
@ -289,6 +291,126 @@ void AssimpShapeLoader::computeBounds(Box3F& bounds)
|
|||
}
|
||||
}
|
||||
|
||||
bool AssimpShapeLoader::fillGuiTreeView(const char* sourceShapePath, GuiTreeViewCtrl* tree)
|
||||
{
|
||||
Assimp::Importer importer;
|
||||
Torque::Path path(sourceShapePath);
|
||||
String cleanFile = AppMaterial::cleanString(path.getFileName());
|
||||
|
||||
// Attempt to import with Assimp.
|
||||
const aiScene* shapeScene = importer.ReadFile(path.getFullPath().c_str(), (aiProcessPreset_TargetRealtime_Quality | aiProcess_CalcTangentSpace)
|
||||
& ~aiProcess_RemoveRedundantMaterials & ~aiProcess_GenSmoothNormals);
|
||||
|
||||
if (!shapeScene)
|
||||
return false;
|
||||
mScene = shapeScene;
|
||||
|
||||
// Initialize tree
|
||||
tree->removeItem(0);
|
||||
S32 meshItem = tree->insertItem(0, "Meshes", String::ToString("%i", shapeScene->mNumMeshes));
|
||||
S32 matItem = tree->insertItem(0, "Materials", String::ToString("%i", shapeScene->mNumMaterials));
|
||||
S32 animItem = tree->insertItem(0, "Animations", String::ToString("%i", shapeScene->mNumAnimations));
|
||||
//S32 lightsItem = tree->insertItem(0, "Lights", String::ToString("%i", shapeScene->mNumLights));
|
||||
//S32 texturesItem = tree->insertItem(0, "Textures", String::ToString("%i", shapeScene->mNumTextures));
|
||||
|
||||
//Details!
|
||||
U32 numPolys = 0;
|
||||
U32 numVerts = 0;
|
||||
for (U32 i = 0; i < shapeScene->mNumMeshes; i++)
|
||||
{
|
||||
tree->insertItem(meshItem, String::ToString("%s", shapeScene->mMeshes[i]->mName.C_Str()));
|
||||
numPolys += shapeScene->mMeshes[i]->mNumFaces;
|
||||
numVerts += shapeScene->mMeshes[i]->mNumVertices;
|
||||
}
|
||||
|
||||
U32 defaultMatNumber = 0;
|
||||
for (U32 i = 0; i < shapeScene->mNumMaterials; i++)
|
||||
{
|
||||
aiMaterial* aiMat = shapeScene->mMaterials[i];
|
||||
|
||||
aiString matName;
|
||||
aiMat->Get(AI_MATKEY_NAME, matName);
|
||||
String name = matName.C_Str();
|
||||
if (name.isEmpty())
|
||||
{
|
||||
name = AppMaterial::cleanString(path.getFileName());
|
||||
name += "_defMat";
|
||||
name += String::ToString("%d", defaultMatNumber);
|
||||
defaultMatNumber++;
|
||||
}
|
||||
|
||||
aiString texPath;
|
||||
aiMat->GetTexture(aiTextureType::aiTextureType_DIFFUSE, 0, &texPath);
|
||||
String texName = texPath.C_Str();
|
||||
if (texName.isEmpty())
|
||||
{
|
||||
aiColor3D read_color(1.f, 1.f, 1.f);
|
||||
if (AI_SUCCESS == aiMat->Get(AI_MATKEY_COLOR_DIFFUSE, read_color))
|
||||
texName = String::ToString("Color: (%0.3f, %0.3f, %0.3f)", (F32)read_color.r, (F32)read_color.g, (F32)read_color.b);
|
||||
else
|
||||
texName = "No Texture";
|
||||
}
|
||||
else
|
||||
texName = AssimpAppMaterial::cleanTextureName(texName, cleanFile, sourceShapePath, true);
|
||||
|
||||
tree->insertItem(matItem, String::ToString("%s", name.c_str()), String::ToString("%s", texName.c_str()));
|
||||
}
|
||||
|
||||
for (U32 i = 0; i < shapeScene->mNumAnimations; i++)
|
||||
{
|
||||
String sequenceName = shapeScene->mAnimations[i]->mName.C_Str();
|
||||
if (sequenceName.isEmpty())
|
||||
sequenceName = "ambient";
|
||||
tree->insertItem(animItem, sequenceName.c_str());
|
||||
}
|
||||
|
||||
U32 numNodes = 0;
|
||||
if (shapeScene->mRootNode)
|
||||
{
|
||||
S32 nodesItem = tree->insertItem(0, "Nodes", "");
|
||||
addNodeToTree(nodesItem, shapeScene->mRootNode, tree, numNodes);
|
||||
tree->setItemValue(nodesItem, String::ToString("%i", numNodes));
|
||||
}
|
||||
|
||||
U32 numMetaTags = shapeScene->mMetaData ? shapeScene->mMetaData->mNumProperties : 0;
|
||||
if (numMetaTags)
|
||||
addMetaDataToTree(shapeScene->mMetaData, tree);
|
||||
|
||||
F64 unit;
|
||||
if (!getMetaDouble("UnitScaleFactor", unit))
|
||||
unit = 1.0f;
|
||||
|
||||
S32 upAxis;
|
||||
if (!getMetaInt("UpAxis", upAxis))
|
||||
upAxis = UPAXISTYPE_Z_UP;
|
||||
|
||||
/*for (U32 i = 0; i < shapeScene->mNumLights; i++)
|
||||
{
|
||||
treeObj->insertItem(lightsItem, String::ToString("%s", shapeScene->mLights[i]->mType));
|
||||
}*/
|
||||
|
||||
// Store shape information in the tree control
|
||||
tree->setDataField(StringTable->insert("_nodeCount"), 0, avar("%d", numNodes));
|
||||
tree->setDataField(StringTable->insert("_meshCount"), 0, avar("%d", shapeScene->mNumMeshes));
|
||||
tree->setDataField(StringTable->insert("_polygonCount"), 0, avar("%d", numPolys));
|
||||
tree->setDataField(StringTable->insert("_materialCount"), 0, avar("%d", shapeScene->mNumMaterials));
|
||||
tree->setDataField(StringTable->insert("_lightCount"), 0, avar("%d", shapeScene->mNumLights));
|
||||
tree->setDataField(StringTable->insert("_animCount"), 0, avar("%d", shapeScene->mNumAnimations));
|
||||
tree->setDataField(StringTable->insert("_textureCount"), 0, avar("%d", shapeScene->mNumTextures));
|
||||
tree->setDataField(StringTable->insert("_vertCount"), 0, avar("%d", numVerts));
|
||||
tree->setDataField(StringTable->insert("_metaTagCount"), 0, avar("%d", numMetaTags));
|
||||
tree->setDataField(StringTable->insert("_unit"), 0, avar("%g", (F32)unit));
|
||||
|
||||
if (upAxis == UPAXISTYPE_X_UP)
|
||||
tree->setDataField(StringTable->insert("_upAxis"), 0, "X_AXIS");
|
||||
else if (upAxis == UPAXISTYPE_Y_UP)
|
||||
tree->setDataField(StringTable->insert("_upAxis"), 0, "Y_AXIS");
|
||||
else
|
||||
tree->setDataField(StringTable->insert("_upAxis"), 0, "Z_AXIS");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AssimpShapeLoader::updateMaterialsScript(const Torque::Path &path)
|
||||
{
|
||||
Torque::Path scriptPath(path);
|
||||
|
|
@ -306,7 +428,7 @@ void AssimpShapeLoader::updateMaterialsScript(const Torque::Path &path)
|
|||
if ( Sim::findObject( MATMGR->getMapEntry( mat->getName() ), mappedMat ) )
|
||||
{
|
||||
// Only update existing materials if forced to
|
||||
if (Con::getBoolVariable("$Assimp::ForceUpdateMats", false))
|
||||
if (ColladaUtils::getOptions().forceUpdateMaterials)
|
||||
{
|
||||
mat->initMaterial(scriptPath, mappedMat);
|
||||
persistMgr.setDirty(mappedMat);
|
||||
|
|
@ -351,20 +473,37 @@ bool AssimpShapeLoader::canLoadCachedDTS(const Torque::Path& path)
|
|||
return false;
|
||||
}
|
||||
|
||||
void AssimpShapeLoader::assimpLogCallback(const char* message, char* user)
|
||||
{
|
||||
Con::printf("[Assimp log message] %s", StringUnit::getUnit(message, 0, "\n"));
|
||||
}
|
||||
|
||||
bool AssimpShapeLoader::ignoreNode(const String& name)
|
||||
{
|
||||
// Do not add AssimpFbx dummy nodes to the TSShape. See: Assimp::FBX::ImportSettings::preservePivots
|
||||
// https://github.com/assimp/assimp/blob/master/code/FBXImportSettings.h#L116-L135
|
||||
if (name.find("_$AssimpFbx$_") != String::NPos)
|
||||
return true;
|
||||
return false;
|
||||
|
||||
if (FindMatch::isMatchMultipleExprs(ColladaUtils::getOptions().alwaysImport, name, false))
|
||||
return false;
|
||||
|
||||
return FindMatch::isMatchMultipleExprs(ColladaUtils::getOptions().neverImport, name, false);
|
||||
}
|
||||
|
||||
bool AssimpShapeLoader::ignoreMesh(const String& name)
|
||||
{
|
||||
if (FindMatch::isMatchMultipleExprs(ColladaUtils::getOptions().alwaysImportMesh, name, false))
|
||||
return false;
|
||||
else
|
||||
return FindMatch::isMatchMultipleExprs(ColladaUtils::getOptions().neverImportMesh, name, false);
|
||||
}
|
||||
|
||||
void AssimpShapeLoader::detectDetails()
|
||||
{
|
||||
// Set LOD option
|
||||
bool singleDetail = true;
|
||||
switch (Con::getIntVariable("$Assimp::lodType", 0))
|
||||
switch (ColladaUtils::getOptions().lodType)
|
||||
{
|
||||
case ColladaUtils::ImportOptions::DetectDTS:
|
||||
// Check for a baseXX->startXX hierarchy at the top-level, if we find
|
||||
|
|
@ -395,7 +534,7 @@ void AssimpShapeLoader::detectDetails()
|
|||
break;
|
||||
}
|
||||
|
||||
AssimpAppMesh::fixDetailSize(singleDetail, Con::getIntVariable("$Assimp::singleDetailSize", 2));
|
||||
AssimpAppMesh::fixDetailSize(singleDetail, ColladaUtils::getOptions().singleDetailSize);
|
||||
}
|
||||
|
||||
void AssimpShapeLoader::extractTexture(U32 index, aiTexture* pTex)
|
||||
|
|
@ -448,6 +587,148 @@ void AssimpShapeLoader::extractTexture(U32 index, aiTexture* pTex)
|
|||
}
|
||||
}
|
||||
|
||||
void AssimpShapeLoader::addNodeToTree(S32 parentItem, aiNode* node, GuiTreeViewCtrl* tree, U32& nodeCount)
|
||||
{
|
||||
// Add this node
|
||||
S32 nodeItem = parentItem;
|
||||
String nodeName = node->mName.C_Str();
|
||||
if (!ignoreNode(nodeName))
|
||||
{
|
||||
if (nodeName.isEmpty())
|
||||
nodeName = "null";
|
||||
nodeItem = tree->insertItem(parentItem, nodeName.c_str(), String::ToString("%i", node->mNumChildren));
|
||||
nodeCount++;
|
||||
}
|
||||
|
||||
// Add any child nodes
|
||||
for (U32 n = 0; n < node->mNumChildren; ++n)
|
||||
addNodeToTree(nodeItem, node->mChildren[n], tree, nodeCount);
|
||||
}
|
||||
|
||||
void AssimpShapeLoader::addMetaDataToTree(const aiMetadata* metaData, GuiTreeViewCtrl* tree)
|
||||
{
|
||||
S32 metaItem = tree->insertItem(0, "MetaData", String::ToString("%i", metaData->mNumProperties));
|
||||
|
||||
aiString valString;
|
||||
aiVector3D valVec;
|
||||
|
||||
for (U32 n = 0; n < metaData->mNumProperties; ++n)
|
||||
{
|
||||
String keyStr = metaData->mKeys[n].C_Str();
|
||||
keyStr += ": ";
|
||||
switch (metaData->mValues[n].mType)
|
||||
{
|
||||
case AI_BOOL:
|
||||
keyStr += ((bool)metaData->mValues[n].mData) ? "true" : "false";
|
||||
break;
|
||||
case AI_INT32:
|
||||
keyStr += String::ToString(*((S32*)(metaData->mValues[n].mData)));
|
||||
break;
|
||||
case AI_UINT64:
|
||||
keyStr += String::ToString("%I64u", *((U64*)metaData->mValues[n].mData));
|
||||
break;
|
||||
case AI_FLOAT:
|
||||
keyStr += String::ToString(*((F32*)metaData->mValues[n].mData));
|
||||
break;
|
||||
case AI_DOUBLE:
|
||||
keyStr += String::ToString(*((F64*)metaData->mValues[n].mData));
|
||||
break;
|
||||
case AI_AISTRING:
|
||||
metaData->Get<aiString>(metaData->mKeys[n], valString);
|
||||
keyStr += valString.C_Str();
|
||||
break;
|
||||
case AI_AIVECTOR3D:
|
||||
metaData->Get<aiVector3D>(metaData->mKeys[n], valVec);
|
||||
keyStr += String::ToString("%f, %f, %f", valVec.x, valVec.y, valVec.z);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
tree->insertItem(metaItem, keyStr.c_str(), String::ToString("%i", n));
|
||||
}
|
||||
}
|
||||
|
||||
bool AssimpShapeLoader::getMetabool(const char* key, bool& boolVal)
|
||||
{
|
||||
if (!mScene || !mScene->mMetaData)
|
||||
return false;
|
||||
|
||||
String keyStr = key;
|
||||
for (U32 n = 0; n < mScene->mMetaData->mNumProperties; ++n)
|
||||
{
|
||||
if (keyStr.equal(mScene->mMetaData->mKeys[n].C_Str(), String::NoCase))
|
||||
{
|
||||
if (mScene->mMetaData->mValues[n].mType == AI_BOOL)
|
||||
{
|
||||
boolVal = (bool)mScene->mMetaData->mValues[n].mData;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AssimpShapeLoader::getMetaInt(const char* key, S32& intVal)
|
||||
{
|
||||
if (!mScene || !mScene->mMetaData)
|
||||
return false;
|
||||
|
||||
String keyStr = key;
|
||||
for (U32 n = 0; n < mScene->mMetaData->mNumProperties; ++n)
|
||||
{
|
||||
if (keyStr.equal(mScene->mMetaData->mKeys[n].C_Str(), String::NoCase))
|
||||
{
|
||||
if (mScene->mMetaData->mValues[n].mType == AI_INT32)
|
||||
{
|
||||
intVal = *((S32*)(mScene->mMetaData->mValues[n].mData));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AssimpShapeLoader::getMetaFloat(const char* key, F32& floatVal)
|
||||
{
|
||||
if (!mScene || !mScene->mMetaData)
|
||||
return false;
|
||||
|
||||
String keyStr = key;
|
||||
for (U32 n = 0; n < mScene->mMetaData->mNumProperties; ++n)
|
||||
{
|
||||
if (keyStr.equal(mScene->mMetaData->mKeys[n].C_Str(), String::NoCase))
|
||||
{
|
||||
if (mScene->mMetaData->mValues[n].mType == AI_FLOAT)
|
||||
{
|
||||
floatVal = *((F32*)mScene->mMetaData->mValues[n].mData);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AssimpShapeLoader::getMetaDouble(const char* key, F64& doubleVal)
|
||||
{
|
||||
if (!mScene || !mScene->mMetaData)
|
||||
return false;
|
||||
|
||||
String keyStr = key;
|
||||
for (U32 n = 0; n < mScene->mMetaData->mNumProperties; ++n)
|
||||
{
|
||||
if (keyStr.equal(mScene->mMetaData->mKeys[n].C_Str(), String::NoCase))
|
||||
{
|
||||
if (mScene->mMetaData->mValues[n].mType == AI_DOUBLE)
|
||||
{
|
||||
doubleVal = *((F64*)mScene->mMetaData->mValues[n].mData);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/// This function is invoked by the resource manager based on file extension.
|
||||
TSShape* assimpLoadShape(const Torque::Path &path)
|
||||
|
|
@ -489,6 +770,14 @@ TSShape* assimpLoadShape(const Torque::Path &path)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// Allow TSShapeConstructor object to override properties
|
||||
ColladaUtils::getOptions().reset();
|
||||
TSShapeConstructor* tscon = TSShapeConstructor::findShapeConstructor(path.getFullPath());
|
||||
if (tscon)
|
||||
{
|
||||
ColladaUtils::getOptions() = tscon->mOptions;
|
||||
}
|
||||
|
||||
AssimpShapeLoader loader;
|
||||
TSShape* tss = loader.generateShape(path);
|
||||
if (tss)
|
||||
|
|
@ -510,57 +799,30 @@ TSShape* assimpLoadShape(const Torque::Path &path)
|
|||
return tss;
|
||||
}
|
||||
|
||||
DefineEngineFunction(GetShapeInfo, GuiTreeViewCtrl*, (String filePath), ,
|
||||
"Returns a list of supported shape formats in filter form.\n"
|
||||
"Example output: DSQ Files|*.dsq|COLLADA Files|*.dae|")
|
||||
DefineEngineFunction(GetShapeInfo, bool, (const char* shapePath, const char* ctrl), ,
|
||||
"(string shapePath, GuiTreeViewCtrl ctrl) Collect scene information from "
|
||||
"a shape file and store it in a GuiTreeView control. This function is "
|
||||
"used by the assimp import gui to show a preview of the scene contents "
|
||||
"prior to import, and is probably not much use for anything else.\n"
|
||||
"@param shapePath shape filename\n"
|
||||
"@param ctrl GuiTreeView control to add elements to\n"
|
||||
"@return true if successful, false otherwise\n"
|
||||
"@ingroup Editors\n"
|
||||
"@internal")
|
||||
{
|
||||
Assimp::Importer importer;
|
||||
|
||||
GuiTreeViewCtrl* treeObj = new GuiTreeViewCtrl();
|
||||
treeObj->registerObject();
|
||||
|
||||
Torque::Path path = Torque::Path(filePath);
|
||||
|
||||
// Attempt to import with Assimp.
|
||||
const aiScene* shapeScene = importer.ReadFile(path.getFullPath().c_str(), (aiProcessPreset_TargetRealtime_Quality | aiProcess_CalcTangentSpace)
|
||||
& ~aiProcess_RemoveRedundantMaterials & ~aiProcess_GenSmoothNormals);
|
||||
|
||||
//Populate info
|
||||
S32 meshItem = treeObj->insertItem(0, "Shape", String::ToString("%i", shapeScene->mNumMeshes));
|
||||
S32 matItem = treeObj->insertItem(0, "Materials", String::ToString("%i", shapeScene->mNumMaterials));
|
||||
S32 animItem = treeObj->insertItem(0, "Animations", String::ToString("%i", shapeScene->mNumAnimations));
|
||||
S32 lightsItem = treeObj->insertItem(0, "Lights", String::ToString("%i", shapeScene->mNumLights));
|
||||
S32 texturesItem = treeObj->insertItem(0, "Textures", String::ToString("%i", shapeScene->mNumTextures));
|
||||
//S32 meshItem = ->insertItem(0, "Cameras", String::ToString("%s", shapeScene->mNumCameras));
|
||||
|
||||
//Details!
|
||||
for (U32 i = 0; i < shapeScene->mNumMeshes; i++)
|
||||
GuiTreeViewCtrl* tree;
|
||||
if (!Sim::findObject(ctrl, tree))
|
||||
{
|
||||
treeObj->insertItem(meshItem, String::ToString("%s", shapeScene->mMeshes[i]->mName.C_Str()));
|
||||
Con::errorf("enumColladaScene::Could not find GuiTreeViewCtrl '%s'", ctrl);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (U32 i = 0; i < shapeScene->mNumMaterials; i++)
|
||||
{
|
||||
aiMaterial* aiMat = shapeScene->mMaterials[i];
|
||||
// Check if a cached DTS is available => no need to import the source file
|
||||
// if we can load the DTS instead
|
||||
Torque::Path path(shapePath);
|
||||
if (AssimpShapeLoader::canLoadCachedDTS(path))
|
||||
return false;
|
||||
|
||||
aiString matName;
|
||||
aiMat->Get(AI_MATKEY_NAME, matName);
|
||||
|
||||
aiString texPath;
|
||||
aiMat->GetTexture(aiTextureType::aiTextureType_DIFFUSE, 0, &texPath);
|
||||
|
||||
treeObj->insertItem(matItem, String::ToString("%s", matName.C_Str()), String::ToString("%s", texPath.C_Str()));
|
||||
}
|
||||
|
||||
for (U32 i = 0; i < shapeScene->mNumAnimations; i++)
|
||||
{
|
||||
treeObj->insertItem(animItem, String::ToString("%s", shapeScene->mAnimations[i]->mName.C_Str()));
|
||||
}
|
||||
|
||||
/*for (U32 i = 0; i < shapeScene->mNumLights; i++)
|
||||
{
|
||||
treeObj->insertItem(lightsItem, String::ToString("%s", shapeScene->mLights[i]->mType));
|
||||
}*/
|
||||
|
||||
return treeObj;
|
||||
}
|
||||
AssimpShapeLoader loader;
|
||||
return loader.fillGuiTreeView(shapePath, tree);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@
|
|||
#endif
|
||||
#include <assimp/texture.h>
|
||||
|
||||
class GuiTreeViewCtrl;
|
||||
struct aiNode;
|
||||
struct aiMetadata;
|
||||
//-----------------------------------------------------------------------------
|
||||
class AssimpShapeLoader : public TSShapeLoader
|
||||
{
|
||||
|
|
@ -37,9 +40,18 @@ protected:
|
|||
const struct aiScene* mScene;
|
||||
|
||||
virtual bool ignoreNode(const String& name);
|
||||
virtual bool ignoreMesh(const String& name);
|
||||
void detectDetails();
|
||||
void extractTexture(U32 index, aiTexture* pTex);
|
||||
|
||||
private:
|
||||
void addNodeToTree(S32 parentItem, aiNode* node, GuiTreeViewCtrl* tree, U32& nodeCount);
|
||||
void addMetaDataToTree(const aiMetadata* metaData, GuiTreeViewCtrl* tree);
|
||||
bool getMetabool(const char* key, bool& boolVal);
|
||||
bool getMetaInt(const char* key, S32& intVal);
|
||||
bool getMetaFloat(const char* key, F32& floatVal);
|
||||
bool getMetaDouble(const char* key, F64& doubleVal);
|
||||
|
||||
public:
|
||||
AssimpShapeLoader();
|
||||
~AssimpShapeLoader();
|
||||
|
|
@ -51,7 +63,10 @@ public:
|
|||
|
||||
void computeBounds(Box3F& bounds);
|
||||
|
||||
bool fillGuiTreeView(const char* shapePath, GuiTreeViewCtrl* tree);
|
||||
|
||||
static bool canLoadCachedDTS(const Torque::Path& path);
|
||||
static void assimpLogCallback(const char* message, char* user);
|
||||
};
|
||||
|
||||
#endif // _ASSIMP_SHAPELOADER_H_
|
||||
|
|
|
|||
|
|
@ -81,6 +81,13 @@ namespace ColladaUtils
|
|||
NumLodTypes
|
||||
};
|
||||
|
||||
enum eAnimTimingType
|
||||
{
|
||||
FrameCount = 0,
|
||||
Seconds = 1,
|
||||
Milliseconds = 1000
|
||||
};
|
||||
|
||||
domUpAxisType upAxis; // Override for the collada <up_axis> element
|
||||
F32 unit; // Override for the collada <unit> element
|
||||
eLodType lodType; // LOD type option
|
||||
|
|
@ -97,6 +104,22 @@ namespace ColladaUtils
|
|||
bool forceUpdateMaterials; // Force update of materials.cs
|
||||
bool useDiffuseNames; // Use diffuse texture as the material name
|
||||
|
||||
// Assimp specific preprocess import options
|
||||
bool convertLeftHanded; // Convert to left handed coordinate system.
|
||||
bool calcTangentSpace; // Calculate tangents and bitangents, if possible.
|
||||
bool genUVCoords; // Convert spherical, cylindrical, box and planar mapping to proper UVs.
|
||||
bool transformUVCoords; // Preprocess UV transformations (scaling, translation ...)
|
||||
bool flipUVCoords; // This step flips all UV coordinates along the y-axis and adjusts material settings
|
||||
// and bitangents accordingly.\nAssimp uses TL(0,0):BR(1,1). T3D uses TL(0,1):BR(1,0).
|
||||
bool findInstances; // Search for instanced meshes and remove them by references to one master.
|
||||
bool limitBoneWeights; // Limit bone weights to 4 per vertex.
|
||||
bool joinIdenticalVerts; // Identifies and joins identical vertex data sets within all imported meshes.
|
||||
bool reverseWindingOrder; // This step adjusts the output face winding order to be clockwise. The default face winding order is counter clockwise.
|
||||
bool invertNormals; // Reverse the normal vector direction for all normals.
|
||||
bool removeRedundantMats; // Removes redundant materials.
|
||||
eAnimTimingType animTiming; // How to import timing data as frames, seconds or milliseconds
|
||||
S32 animFPS; // FPS value to use if timing is set in frames and the animations does not have an fps set
|
||||
|
||||
ImportOptions()
|
||||
{
|
||||
reset();
|
||||
|
|
@ -119,6 +142,20 @@ namespace ColladaUtils
|
|||
adjustFloor = false;
|
||||
forceUpdateMaterials = false;
|
||||
useDiffuseNames = false;
|
||||
|
||||
convertLeftHanded = false;
|
||||
calcTangentSpace = false;
|
||||
genUVCoords = false;
|
||||
transformUVCoords = false;
|
||||
flipUVCoords = true;
|
||||
findInstances = false;
|
||||
limitBoneWeights = false;
|
||||
joinIdenticalVerts = true;
|
||||
reverseWindingOrder = true;
|
||||
invertNormals = false;
|
||||
removeRedundantMats = true;
|
||||
animTiming = Seconds;
|
||||
animFPS = 30;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -71,6 +71,14 @@ ImplementEnumType( TSShapeConstructorLodType,
|
|||
{ ColladaUtils::ImportOptions::TrailingNumber, "TrailingNumber" },
|
||||
EndImplementEnumType;
|
||||
|
||||
ImplementEnumType(TSShapeConstructorAnimType,
|
||||
"\n\n"
|
||||
"@ingroup TSShapeConstructor" )
|
||||
{ ColladaUtils::ImportOptions::FrameCount, "Frames" },
|
||||
{ ColladaUtils::ImportOptions::Seconds, "Seconds" },
|
||||
{ ColladaUtils::ImportOptions::Milliseconds, "Milliseconds" },
|
||||
EndImplementEnumType;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -150,6 +158,21 @@ TSShapeConstructor::TSShapeConstructor()
|
|||
mOptions.adjustFloor = false;
|
||||
mOptions.forceUpdateMaterials = false;
|
||||
mOptions.useDiffuseNames = false;
|
||||
|
||||
mOptions.convertLeftHanded = false;
|
||||
mOptions.calcTangentSpace = false;
|
||||
mOptions.genUVCoords = false;
|
||||
mOptions.transformUVCoords = false;
|
||||
mOptions.flipUVCoords = true;
|
||||
mOptions.findInstances = false;
|
||||
mOptions.limitBoneWeights = false;
|
||||
mOptions.joinIdenticalVerts = true;
|
||||
mOptions.reverseWindingOrder = true;
|
||||
mOptions.invertNormals = false;
|
||||
mOptions.removeRedundantMats = true;
|
||||
mOptions.animTiming = ColladaUtils::ImportOptions::Seconds;
|
||||
mOptions.animFPS = 30;
|
||||
|
||||
mShape = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -292,6 +315,35 @@ void TSShapeConstructor::initPersistFields()
|
|||
"Forces update of the materials.cs file in the same folder as the COLLADA "
|
||||
"(.dae) file, even if Materials already exist. No effect for DTS files.\n"
|
||||
"Normally only Materials that are not already defined are written to materials.cs." );
|
||||
|
||||
// Fields added for assimp options
|
||||
addField( "convertLeftHanded", TypeBool, Offset(mOptions.convertLeftHanded, TSShapeConstructor),
|
||||
"Convert to left handed coordinate system." );
|
||||
addField( "calcTangentSpace", TypeBool, Offset(mOptions.calcTangentSpace, TSShapeConstructor),
|
||||
"Calculate tangents and bitangents, if possible." );
|
||||
addField( "genUVCoords", TypeBool, Offset(mOptions.genUVCoords, TSShapeConstructor),
|
||||
"Convert spherical, cylindrical, box and planar mapping to proper UVs." );
|
||||
addField( "transformUVCoords", TypeBool, Offset(mOptions.transformUVCoords, TSShapeConstructor),
|
||||
"Preprocess UV transformations (scaling, translation ...)." );
|
||||
addField( "flipUVCoords", TypeBool, Offset(mOptions.flipUVCoords, TSShapeConstructor),
|
||||
"This step flips all UV coordinates along the y-axis and adjusts material settings and bitangents accordingly.\n"
|
||||
"Assimp uses TL(0,0):BR(1,1). T3D uses TL(0,1):BR(1,0). This will be needed for most textured models." );
|
||||
addField( "findInstances", TypeBool, Offset(mOptions.findInstances, TSShapeConstructor),
|
||||
"Search for instanced meshes and remove them by references to one master." );
|
||||
addField( "limitBoneWeights", TypeBool, Offset(mOptions.limitBoneWeights, TSShapeConstructor),
|
||||
"Limit bone weights to 4 per vertex." );
|
||||
addField( "joinIdenticalVerts", TypeBool, Offset(mOptions.joinIdenticalVerts, TSShapeConstructor),
|
||||
"Identifies and joins identical vertex data sets within all imported meshes." );
|
||||
addField( "reverseWindingOrder", TypeBool, Offset(mOptions.reverseWindingOrder, TSShapeConstructor),
|
||||
"This step adjusts the output face winding order to be clockwise. The default assimp face winding order is counter clockwise." );
|
||||
addField( "invertNormals", TypeBool, Offset(mOptions.invertNormals, TSShapeConstructor),
|
||||
"Reverse the normal vector direction for all normals." );
|
||||
addField( "removeRedundantMats", TypeBool, Offset(mOptions.removeRedundantMats, TSShapeConstructor),
|
||||
"Removes redundant materials." );
|
||||
addField( "animTiming", TYPEID< ColladaUtils::ImportOptions::eAnimTimingType >(), Offset(mOptions.animTiming, TSShapeConstructor),
|
||||
"How to import timing data as frames, seconds or milliseconds." );
|
||||
addField("animFPS", TypeS32, Offset(mOptions.animFPS, TSShapeConstructor),
|
||||
"FPS value to use if timing is set in frames and the animations does not have an fps set.");
|
||||
endGroup( "Collada" );
|
||||
|
||||
addGroup( "Sequences" );
|
||||
|
|
|
|||
|
|
@ -328,9 +328,11 @@ public:
|
|||
|
||||
typedef domUpAxisType TSShapeConstructorUpAxis;
|
||||
typedef ColladaUtils::ImportOptions::eLodType TSShapeConstructorLodType;
|
||||
typedef ColladaUtils::ImportOptions::eAnimTimingType TSShapeConstructorAnimType;
|
||||
|
||||
DefineEnumType( TSShapeConstructorUpAxis );
|
||||
DefineEnumType(TSShapeConstructorLodType);
|
||||
DefineEnumType(TSShapeConstructorAnimType);
|
||||
|
||||
class TSShapeConstructorMethodActionCallback
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue