Merge pull request #45 from OTHGMars/Assimp_Anim

Assimp animations
This commit is contained in:
Areloch 2019-04-20 03:08:48 -05:00 committed by GitHub
commit 57526bd060
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 1330 additions and 68 deletions

View file

@ -405,6 +405,8 @@ inline void Buffer::Read(Value& obj, Asset& r)
inline bool Buffer::LoadFromStream(IOStream& stream, size_t length, size_t baseOffset)
{
byteLength = length ? length : stream.FileSize();
if ((byteLength + baseOffset) > stream.FileSize())
byteLength = stream.FileSize() - baseOffset;
if (baseOffset) {
stream.Seek(baseOffset, aiOrigin_SET);

View file

@ -345,6 +345,8 @@ inline void Buffer::Read(Value& obj, Asset& r)
inline bool Buffer::LoadFromStream(IOStream& stream, size_t length, size_t baseOffset)
{
byteLength = length ? length : stream.FileSize();
if ((byteLength + baseOffset) > stream.FileSize())
byteLength = stream.FileSize() - baseOffset;
if (baseOffset) {
stream.Seek(baseOffset, aiOrigin_SET);

View file

@ -31,6 +31,9 @@
#include <assimp/postprocess.h>
#include <assimp/types.h>
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; i<mMeshData->mNumVertices; 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
@ -201,7 +195,10 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objOffset)
{
String name = mMeshData->mBones[b]->mName.C_Str();
aiNode* nodePtr = AssimpAppNode::findChildNodeByName(mMeshData->mBones[b]->mName.C_Str(), appNode->mScene->mRootNode);
bones[b] = new AssimpAppNode(appNode->mScene, nodePtr);
if (!nodePtr)
bones[b] = new AssimpAppNode(appNode->mScene, appNode->mNode);
else
bones[b] = new AssimpAppNode(appNode->mScene, nodePtr);
MatrixF boneTransform;
AssimpAppNode::assimpToTorqueMat(mMeshData->mBones[b]->mOffsetMatrix, boneTransform);

View file

@ -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

View file

@ -31,6 +31,8 @@
#include <assimp/postprocess.h>
#include <assimp/types.h>
aiAnimation* AssimpAppNode::sActiveSequence = NULL;
AssimpAppNode::AssimpAppNode(const struct aiScene* scene, const struct aiNode* node, AssimpAppNode* parent)
: mInvertMeshes(false),
mLastTransformTime(TSShapeLoader::DefaultTime - 1),
@ -94,12 +96,131 @@ MatrixF AssimpAppNode::getTransform(F32 time)
//mLastTransform.scale(ColladaUtils::getOptions().unit);
}
mLastTransform.mul(mNodeTransform);
// If this node is animated in the active sequence, fetch the animated transform
if (sActiveSequence)
{
MatrixF mat(true);
getAnimatedTransform(mat, time, sActiveSequence);
mLastTransform.mul(mat);
}
else
mLastTransform.mul(mNodeTransform);
mLastTransformTime = time;
return mLastTransform;
}
void AssimpAppNode::getAnimatedTransform(MatrixF& mat, F32 t, aiAnimation* animSeq)
{
// Find the channel for this node
for (U32 i = 0; i < animSeq->mNumChannels; ++i)
{
if (strcmp(mName, animSeq->mChannels[i]->mNodeName.C_Str()) == 0)
{
aiNodeAnim *nodeAnim = animSeq->mChannels[i];
Point3F trans(Point3F::Zero);
Point3F scale(Point3F::One);
QuatF rot;
rot.identity();
// Transform
if (nodeAnim->mNumPositionKeys == 1)
trans.set(nodeAnim->mPositionKeys[0].mValue.x, nodeAnim->mPositionKeys[0].mValue.y, nodeAnim->mPositionKeys[0].mValue.z);
else
{
Point3F curPos, lastPos;
F32 lastT = 0.0;
for (U32 key = 0; key < nodeAnim->mNumPositionKeys; ++key)
{
F32 curT = (F32)nodeAnim->mPositionKeys[key].mTime;
curPos.set(nodeAnim->mPositionKeys[key].mValue.x, nodeAnim->mPositionKeys[key].mValue.y, nodeAnim->mPositionKeys[key].mValue.z);
if (curT > t)
{
F32 factor = (t - lastT) / (curT - lastT);
trans.interpolate(lastPos, curPos, factor);
break;
}
else if ((curT == t) || (key == nodeAnim->mNumPositionKeys - 1))
{
trans = curPos;
break;
}
lastT = curT;
lastPos = curPos;
}
}
// Rotation
if (nodeAnim->mNumRotationKeys == 1)
rot.set(nodeAnim->mRotationKeys[0].mValue.x, nodeAnim->mRotationKeys[0].mValue.y,
nodeAnim->mRotationKeys[0].mValue.z, nodeAnim->mRotationKeys[0].mValue.w);
else
{
QuatF curRot, lastRot;
F32 lastT = 0.0;
for (U32 key = 0; key < nodeAnim->mNumRotationKeys; ++key)
{
F32 curT = (F32)nodeAnim->mRotationKeys[key].mTime;
curRot.set(nodeAnim->mRotationKeys[key].mValue.x, nodeAnim->mRotationKeys[key].mValue.y,
nodeAnim->mRotationKeys[key].mValue.z, nodeAnim->mRotationKeys[key].mValue.w);
if (curT > t)
{
F32 factor = (t - lastT) / (curT - lastT);
rot.interpolate(lastRot, curRot, factor);
break;
}
else if ((curT == t) || (key == nodeAnim->mNumRotationKeys - 1))
{
rot = curRot;
break;
}
lastT = curT;
lastRot = curRot;
}
}
// Scale
if (nodeAnim->mNumScalingKeys == 1)
scale.set(nodeAnim->mScalingKeys[0].mValue.x, nodeAnim->mScalingKeys[0].mValue.y, nodeAnim->mScalingKeys[0].mValue.z);
else
{
Point3F curScale, lastScale;
F32 lastT = 0.0;
for (U32 key = 0; key < nodeAnim->mNumScalingKeys; ++key)
{
F32 curT = (F32)nodeAnim->mScalingKeys[key].mTime;
curScale.set(nodeAnim->mScalingKeys[key].mValue.x, nodeAnim->mScalingKeys[key].mValue.y, nodeAnim->mScalingKeys[key].mValue.z);
if (curT > t)
{
F32 factor = (t - lastT) / (curT - lastT);
scale.interpolate(lastScale, curScale, factor);
break;
}
else if ((curT == t) || (key == nodeAnim->mNumScalingKeys - 1))
{
scale = curScale;
break;
}
lastT = curT;
lastScale = curScale;
}
}
rot.setMatrix(&mat);
mat.inverse();
mat.setPosition(trans);
mat.scale(scale);
return;
}
}
// Node not found in the animation channels
mat = mNodeTransform;
}
bool AssimpAppNode::animatesTransform(const AppSequence* appSeq)
{
return false;

View file

@ -36,6 +36,7 @@
#ifndef AI_TYPES_H_INC
#include <assimp/types.h>
#endif
#include <assimp/scene.h>
class AssimpAppNode : public AppNode
{
@ -43,6 +44,7 @@ class AssimpAppNode : public AppNode
friend class AssimpAppMesh;
MatrixF getTransform(F32 time);
void getAnimatedTransform(MatrixF& mat, F32 t, aiAnimation* animSeq);
void buildMeshList();
void buildChildList();
@ -67,6 +69,8 @@ public:
//
}
static aiAnimation* sActiveSequence;
//-----------------------------------------------------------------------
const char *getName() { return mName; }
const char *getParentName() { return mParentName; }

View file

@ -10,29 +10,72 @@
#include "console/persistenceManager.h"
#include "ts/assimp/assimpAppMaterial.h"
#include "ts/assimp/assimpAppSequence.h"
#include "ts/assimp/assimpAppNode.h"
AssimpAppSequence::AssimpAppSequence(aiAnimation *a) :
seqStart(0.0f),
mAnim(a)
{
fps = mAnim->mTicksPerSecond;
// From: http://sir-kimmi.de/assimp/lib_html/data.html#anims
// An aiAnimation has a duration. The duration as well as all time stamps are given in ticks.
// To get the correct timing, all time stamp thus have to be divided by aiAnimation::mTicksPerSecond.
// Beware, though, that certain combinations of file format and exporter don't always store this
// information in the exported file. In this case, mTicksPerSecond is set to 0 to indicate the lack of knowledge.
fps = (mAnim->mTicksPerSecond > 0) ? mAnim->mTicksPerSecond : 30.0f;
F32 maxEndTime = 0;
F32 minFrameTime = 1000.0f;
// Detect the frame rate (minimum time between keyframes) and max sequence time
for (U32 i = 0; i < mAnim->mNumChannels; ++i)
{
aiNodeAnim *nodeAnim = mAnim->mChannels[i];
if (nodeAnim->mNumPositionKeys)
maxEndTime = getMax(maxEndTime, (F32) nodeAnim->mPositionKeys[nodeAnim->mNumPositionKeys-1].mTime);
if (nodeAnim->mNumRotationKeys)
maxEndTime = getMax(maxEndTime, (F32) nodeAnim->mRotationKeys[nodeAnim->mNumRotationKeys-1].mTime);
if (nodeAnim->mNumScalingKeys)
maxEndTime = getMax(maxEndTime, (F32) nodeAnim->mScalingKeys[nodeAnim->mNumScalingKeys-1].mTime);
for (U32 key = 1; key < nodeAnim->mNumPositionKeys; ++key)
{
F32 deltaT = nodeAnim->mPositionKeys[key].mTime - nodeAnim->mPositionKeys[key-1].mTime;
minFrameTime = getMin(minFrameTime, deltaT);
}
for (U32 key = 1; key < nodeAnim->mNumRotationKeys; ++key)
{
F32 deltaT = nodeAnim->mRotationKeys[key].mTime - nodeAnim->mRotationKeys[key-1].mTime;
minFrameTime = getMin(minFrameTime, deltaT);
}
for (U32 key = 1; key < nodeAnim->mNumScalingKeys; ++key)
{
F32 deltaT = nodeAnim->mScalingKeys[key].mTime - nodeAnim->mScalingKeys[key-1].mTime;
minFrameTime = getMin(minFrameTime, deltaT);
}
}
fps = (minFrameTime > 0.0f) ? 1.0f / minFrameTime : fps;
fps = mClamp(fps, TSShapeLoader::MinFrameRate, TSShapeLoader::MaxFrameRate);
seqEnd = maxEndTime;
}
AssimpAppSequence::~AssimpAppSequence()
{
}
F32 AssimpAppSequence::getStart() const
{
return 0.0f;
}
F32 AssimpAppSequence::getEnd() const
{
return (F32)mAnim->mDuration / fps;
void AssimpAppSequence::setActive(bool active)
{
if (active)
AssimpAppNode::sActiveSequence = mAnim;
else
{
if (AssimpAppNode::sActiveSequence == mAnim)
AssimpAppNode::sActiveSequence = NULL;
}
}
U32 AssimpAppSequence::getFlags() const
{
return TSShape::Blend;
return TSShape::Blend;
}
F32 AssimpAppSequence::getPriority() const
{
@ -41,5 +84,4 @@ F32 AssimpAppSequence::getPriority() const
F32 AssimpAppSequence::getBlendRefTime() const
{
return -1.0f;
}
}

View file

@ -22,6 +22,9 @@
class AssimpAppSequence : public AppSequence
{
F32 seqStart;
F32 seqEnd;
public:
AssimpAppSequence(aiAnimation *a);
@ -29,18 +32,18 @@ public:
aiAnimation *mAnim;
virtual void setActive(bool active) { }
virtual void setActive(bool active);
virtual S32 getNumTriggers() const { return 0; }
virtual void getTrigger(S32 index, TSShape::Trigger& trigger) const { trigger.state = 0; }
virtual const char* getName() const { return mAnim->mName.C_Str(); }
virtual F32 getStart() const;
virtual F32 getEnd() const;
F32 getStart() const { return seqStart; }
F32 getEnd() const { return seqEnd; }
void setEnd(F32 end) { seqEnd = end; }
virtual U32 getFlags() const;
virtual F32 getPriority() const;
virtual F32 getBlendRefTime() const;
};

View file

@ -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"
@ -147,6 +148,12 @@ void AssimpShapeLoader::enumerateScene()
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;
@ -160,17 +167,25 @@ 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 shapeLog;
shapeLog = aiGetPredefinedLogStream(aiDefaultLogStream_FILE, "assimp.log");
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)
@ -189,6 +204,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);
@ -203,6 +221,8 @@ void AssimpShapeLoader::enumerateScene()
TSShapeLoader::updateProgress(TSShapeLoader::Load_Complete, "Import failed");
Con::printf("[ASSIMP] Import Error: %s", aiGetErrorString());
}
aiDetachLogStream(&shapeLog);
}
void AssimpShapeLoader::processAnimations()
@ -216,6 +236,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);
@ -286,6 +355,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)
@ -374,7 +481,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++)

View file

@ -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);
};

View file

@ -0,0 +1,688 @@
//--- OBJECT WRITE BEGIN ---
%guiContent = new GuiControl(AssimpImportDlg,EditorGuiGroup) {
isContainer = "1";
Profile = "ToolsGuiDefaultProfile";
HorizSizing = "width";
VertSizing = "height";
position = "0 0";
Extent = "1024 768";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
tooltipprofile = "ToolsGuiToolTipProfile";
hovertime = "1000";
canSaveDynamicFields = "0";
new GuiWindowCtrl() {
resizeWidth = "0";
resizeHeight = "0";
canMove = "1";
canClose = "1";
canMinimize = "0";
canMaximize = "0";
minSize = "50 50";
closeCommand = "Canvas.popDialog(AssimpImportDlg);";
EdgeSnap = "1";
text = "Open Asset Import Library";
Margin = "0 0 0 0";
Padding = "0 0 0 0";
AnchorTop = "1";
AnchorBottom = "0";
AnchorLeft = "1";
AnchorRight = "0";
isContainer = "1";
Profile = "ToolsGuiWindowProfile";
HorizSizing = "center";
VertSizing = "center";
position = "254 136";
Extent = "416 390";
MinExtent = "8 8";
canSave = "1";
Visible = "1";
Accelerator = "escape";
tooltipprofile = "ToolsGuiToolTipProfile";
hovertime = "1000";
internalName = "window";
canSaveDynamicFields = "0";
new GuiTextCtrl() {
text = "Up Axis";
maxLength = "1024";
Margin = "0 0 0 0";
Padding = "0 0 0 0";
AnchorTop = "1";
AnchorBottom = "0";
AnchorLeft = "1";
AnchorRight = "0";
isContainer = "0";
Profile = "ToolsGuiTextRightProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "10 31";
Extent = "40 16";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
tooltipprofile = "ToolsGuiToolTipProfile";
hovertime = "1000";
canSaveDynamicFields = "0";
};
new GuiPopUpMenuCtrl() {
maxPopupHeight = "200";
sbUsesNAColor = "0";
reverseTextList = "0";
bitmapBounds = "16 16";
maxLength = "1024";
Margin = "0 0 0 0";
Padding = "0 0 0 0";
AnchorTop = "1";
AnchorBottom = "0";
AnchorLeft = "1";
AnchorRight = "0";
isContainer = "0";
Profile = "ToolsGuiPopUpMenuProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "56 30";
Extent = "66 18";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
tooltipprofile = "ToolsGuiToolTipProfile";
hovertime = "1000";
internalName = "upAxis";
canSaveDynamicFields = "0";
};
new GuiCheckBoxCtrl() {
useInactiveState = "0";
text = " Convert To Left Handed";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
isContainer = "0";
Profile = "ToolsGuiCheckBoxProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "10 50";
Extent = "200 13";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
variable = "$Assimp::ConvertToLeftHanded";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "Converts the model to left-handed";
hovertime = "1000";
internalName = "overrideScale";
canSaveDynamicFields = "0";
};
new GuiCheckBoxCtrl() {
useInactiveState = "0";
text = " Triangulate";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
isContainer = "0";
Profile = "ToolsGuiCheckBoxProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "10 70";
Extent = "200 13";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
Active = "0";
variable = "$Assimp::Triangulate";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "Triangulate polygons with more than 3 edges.";
hovertime = "1000";
internalName = "overrideScale";
canSaveDynamicFields = "0";
};
new GuiCheckBoxCtrl() {
useInactiveState = "0";
text = " Calculate Tangent Space";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
isContainer = "0";
Profile = "ToolsGuiCheckBoxProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "10 90";
Extent = "200 13";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
variable = "$Assimp::CalcTangentSpace";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "Calculate tangents and bitangents, if possible.";
hovertime = "1000";
internalName = "overrideScale";
canSaveDynamicFields = "0";
};
new GuiCheckBoxCtrl() {
useInactiveState = "0";
text = " Validate Data Structure";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
isContainer = "0";
Profile = "ToolsGuiCheckBoxProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "10 110";
Extent = "200 13";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
variable = "$Assimp::ValidateDataStructure";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "Perform a full validation of the loader's output.";
hovertime = "1000";
internalName = "overrideScale";
canSaveDynamicFields = "0";
};
new GuiCheckBoxCtrl() {
useInactiveState = "0";
text = " Improve Cache Locality";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
isContainer = "0";
Profile = "ToolsGuiCheckBoxProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "10 130";
Extent = "200 13";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
variable = "$Assimp::ImproveCacheLocality";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "Improve the cache locality of the output vertices.";
hovertime = "1000";
internalName = "overrideScale";
canSaveDynamicFields = "0";
};
new GuiCheckBoxCtrl() {
useInactiveState = "0";
text = " Remove Redundant Materials";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
isContainer = "0";
Profile = "ToolsGuiCheckBoxProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "10 150";
Extent = "200 13";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
variable = "$Assimp::RemoveRedundantMaterials";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "Removes redundant materials.";
hovertime = "1000";
internalName = "overrideScale";
canSaveDynamicFields = "0";
};
new GuiCheckBoxCtrl() {
useInactiveState = "0";
text = " Find Degenerates";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
isContainer = "0";
Profile = "ToolsGuiCheckBoxProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "10 170";
Extent = "200 13";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
variable = "$Assimp::FindDegenerates";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "Remove degenerated polygons from the import.";
hovertime = "1000";
internalName = "overrideScale";
canSaveDynamicFields = "0";
};
new GuiCheckBoxCtrl() {
useInactiveState = "0";
text = " Find Invalid Data";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
isContainer = "0";
Profile = "ToolsGuiCheckBoxProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "10 190";
Extent = "200 13";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
variable = "$Assimp::FindInvalidData";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "Detect invalid model data, such as invalid normal vectors.";
hovertime = "1000";
internalName = "overrideScale";
canSaveDynamicFields = "0";
};
new GuiCheckBoxCtrl() {
useInactiveState = "0";
text = " Generate UV Coordinates";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
isContainer = "0";
Profile = "ToolsGuiCheckBoxProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "10 210";
Extent = "200 13";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
variable = "$Assimp::GenUVCoords";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "Convert spherical, cylindrical, box and planar mapping to proper UVs.";
hovertime = "1000";
internalName = "overrideScale";
canSaveDynamicFields = "0";
};
new GuiCheckBoxCtrl() {
useInactiveState = "0";
text = " Transform UV Coordinates";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
isContainer = "0";
Profile = "ToolsGuiCheckBoxProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "10 230";
Extent = "200 13";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
variable = "$Assimp::TransformUVCoords";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "Preprocess UV transformations (scaling, translation ...)";
hovertime = "1000";
internalName = "overrideScale";
canSaveDynamicFields = "0";
};
new GuiCheckBoxCtrl() {
useInactiveState = "0";
text = " Flip UV Coordinates";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
isContainer = "0";
Profile = "ToolsGuiCheckBoxProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "10 250";
Extent = "200 13";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
variable = "$Assimp::FlipUVs";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "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). This will be needed for most textured models.";
hovertime = "1000";
canSaveDynamicFields = "0";
};
new GuiCheckBoxCtrl() {
useInactiveState = "0";
text = " Find Instances";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
isContainer = "0";
Profile = "ToolsGuiCheckBoxProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "10 270";
Extent = "200 13";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
variable = "$Assimp::FindInstances";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "search for instanced meshes and remove them by references to one master.";
hovertime = "1000";
internalName = "overrideScale";
canSaveDynamicFields = "0";
};
new GuiCheckBoxCtrl() {
useInactiveState = "0";
text = " Limit Bone Weights";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
isContainer = "0";
Profile = "ToolsGuiCheckBoxProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "10 290";
Extent = "200 13";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
variable = "$Assimp::LimitBoneWeights";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "Limit bone weights to 4 per vertex.";
hovertime = "1000";
internalName = "overrideScale";
canSaveDynamicFields = "0";
};
new GuiTextCtrl() {
text = "LOD";
maxLength = "1024";
Margin = "0 0 0 0";
Padding = "0 0 0 0";
AnchorTop = "1";
AnchorBottom = "0";
AnchorLeft = "1";
AnchorRight = "0";
isContainer = "0";
Profile = "ToolsGuiTextRightProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "210 31";
Extent = "22 16";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
tooltipprofile = "ToolsGuiToolTipProfile";
hovertime = "1000";
canSaveDynamicFields = "0";
};
new GuiPopUpMenuCtrl() {
maxPopupHeight = "200";
sbUsesNAColor = "0";
reverseTextList = "0";
bitmapBounds = "16 16";
maxLength = "1024";
Margin = "0 0 0 0";
Padding = "0 0 0 0";
AnchorTop = "1";
AnchorBottom = "0";
AnchorLeft = "1";
AnchorRight = "0";
isContainer = "0";
Profile = "ToolsGuiPopUpMenuProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "238 30";
Extent = "92 18";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "Method used to determine LOD for meshes in the model";
hovertime = "1000";
internalName = "lodType";
canSaveDynamicFields = "0";
};
new GuiTextEditCtrl() {
historySize = "0";
password = "0";
tabComplete = "0";
sinkAllKeyEvents = "0";
passwordMask = "*";
text = "2";
maxLength = "1024";
Margin = "0 0 0 0";
Padding = "0 0 0 0";
AnchorTop = "1";
AnchorBottom = "0";
AnchorLeft = "1";
AnchorRight = "0";
isContainer = "0";
Profile = "ToolsGuiTextEditProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "338 30";
Extent = "49 18";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "Detail size for all meshes in this model (when LOD type is SingleSize)";
hovertime = "1000";
internalName = "singleDetailSize";
canSaveDynamicFields = "0";
};
new GuiCheckBoxCtrl() {
useInactiveState = "0";
text = " Center Model";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
isContainer = "0";
Profile = "ToolsGuiCheckBoxProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "210 50";
Extent = "200 13";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
variable = "$Assimp::adjustCenter";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "Translates model so the origin is at the center";
hovertime = "1000";
canSaveDynamicFields = "0";
};
new GuiCheckBoxCtrl() {
useInactiveState = "0";
text = " Floor Model";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
isContainer = "0";
Profile = "ToolsGuiCheckBoxProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "210 70";
Extent = "200 13";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
variable = "$Assimp::adjustFloor";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "Translates model so the origin is at the bottom";
hovertime = "1000";
canSaveDynamicFields = "0";
};
new GuiCheckBoxCtrl() {
useInactiveState = "0";
text = " Join Identical Vertices";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
isContainer = "0";
Profile = "ToolsGuiCheckBoxProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "210 90";
Extent = "200 13";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
variable = "$Assimp::JoinIdenticalVertices";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "Identifies and joins identical vertex data sets within all imported meshes.";
hovertime = "1000";
canSaveDynamicFields = "0";
};
new GuiCheckBoxCtrl() {
useInactiveState = "0";
text = " Flip Winding Order";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
isContainer = "0";
Profile = "ToolsGuiCheckBoxProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "210 110";
Extent = "200 13";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
variable = "$Assimp::FlipWindingOrder";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "This step adjusts the output face winding order to be clockwise. The default face winding order is counter clockwise.";
hovertime = "1000";
canSaveDynamicFields = "0";
};
new GuiCheckBoxCtrl() {
useInactiveState = "0";
text = " Invert Normals";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
isContainer = "0";
Profile = "ToolsGuiCheckBoxProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "210 130";
Extent = "200 13";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
variable = "$Assimp::FlipNormals";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "Reverse the normal vector direction for all normals.";
hovertime = "1000";
canSaveDynamicFields = "0";
};
new GuiButtonCtrl() {
text = "OK";
groupNum = "-1";
buttonType = "PushButton";
useMouseEvents = "0";
isContainer = "0";
Profile = "ToolsGuiButtonProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "120 348";
Extent = "86 22";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
Command = "AssimpImportDlg.onOK();";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "Load the COLLADA model";
hovertime = "1000";
canSaveDynamicFields = "0";
};
new GuiButtonCtrl() {
text = "Cancel";
groupNum = "-1";
buttonType = "PushButton";
useMouseEvents = "0";
isContainer = "0";
Profile = "ToolsGuiButtonProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "220 348";
Extent = "86 22";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
Command = "AssimpImportDlg.onCancel();";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "Exit without loading the COLLADA model";
hovertime = "1000";
canSaveDynamicFields = "0";
};
};
};
//--- OBJECT WRITE END ---
function AssimpImportDlg::showDialog(%this, %shapePath, %cmd)
{
%this.path = %shapePath;
%this.cmd = %cmd;
if ($Assimp::OverrideUpAxis $= "")
{ // First load, so set best-case defaults
$Assimp::OverrideUpAxis = 1; // y-axis is up in most test shapes
$Assimp::lodType = 0; // DetectDTS
$Assimp::singleDetailSize = "2";
// $Assimp::FlipUVs will be needed for virtually all textured models
$Assimp::FlipUVs = true;
$Assimp::FlipWindingOrder = true; // Makes winding order clock wise
$Assimp::FindDegenerates = true;
$Assimp::FindInvalidData = true;
$Assimp::JoinIdenticalVertices = true;
}
%this-->upAxis.clear();
%this-->upAxis.add("X_AXIS", 0);
%this-->upAxis.add("Y_AXIS", 1);
%this-->upAxis.add("Z_AXIS", 2);
%this-->upAxis.setSelected($Assimp::OverrideUpAxis);
%this-->lodType.clear();
%this-->lodType.add("DetectDTS", 0);
%this-->lodType.add("SingleSize", 1);
%this-->lodType.add("TrailingNumber", 2);
%this-->lodType.setSelected($Assimp::lodType);
%this-->singleDetailSize.text = $Assimp::singleDetailSize;
//Triangulate is a default(currently mandatory) behavior
$Assimp::Triangulate = true;
Canvas.pushDialog(%this);
}
function AssimpImportDlg::onCancel(%this)
{
Canvas.popDialog(%this);
ColladaImportTreeView.clear();
}
function AssimpImportDlg::onOK(%this)
{
Canvas.popDialog(%this);
ColladaImportTreeView.clear();
$Assimp::OverrideUpAxis = %this-->upAxis.getSelected();
$Assimp::lodType = %this-->lodType.getSelected();
$Assimp::singleDetailSize = %this-->singleDetailSize.getText();
// Load the shape (always from the DAE)
$assimp::forceLoad = true;
eval(%this.cmd);
$assimp::forceLoad = true;
}

View file

@ -1696,3 +1696,21 @@ function convertColladaModels(%pattern)
$collada::forceLoadDAE = false;
}
function showImportDialog(%shapePath, %cmd)
{
%this.path = %shapePath;
%this.cmd = %cmd;
if ( fileExt(%shapePath) $= ".dts" || fileExt(%shapePath) $= ".dsq"
|| fileExt(%shapePath) $= ".dae" || fileExt(%shapePath) $= ".kmz" )
{
// Regular Load
ColladaImportDlg.showDialog(%shapePath, %cmd);
} else if ( isSupportedFormat(stripChars(fileExt(%shapePath), ".")) )
{
// Assimp Load
if ( isObject(AssimpImportDlg) )
AssimpImportDlg.showDialog(%shapePath, %cmd);
}
}

View file

@ -35,4 +35,5 @@ exec("./GuiEaseEditDlg.ed.cs");
exec("./guiObjectInspector.ed.cs");
exec("./uvEditor.ed.gui");
exec("./objectSelection.ed.cs");
exec("./postFxManager.gui");
exec("./postFxManager.gui");
exec("./assimpImport.ed.gui");

View file

@ -675,7 +675,7 @@ function EWCreatorWindow::addShapeIcon( %this, %datablock )
%shapePath = ( %datablock.shapeFile !$= "" ) ? %datablock.shapeFile : %datablock.shapeName;
%createCmd = "EWCreatorWindow.createObject( \\\"" @ %cmd @ "\\\" );";
%ctrl.altCommand = "ColladaImportDlg.showDialog( \"" @ %shapePath @ "\", \"" @ %createCmd @ "\" );";
%ctrl.altCommand = "showImportDialog( \"" @ %shapePath @ "\", \"" @ %createCmd @ "\" );";
%ctrl.iconBitmap = EditorIconRegistry::findIconByClassName( %class );
%ctrl.text = %name;
@ -701,7 +701,7 @@ function EWCreatorWindow::addStaticIcon( %this, %fullPath )
"Last Modified: " @ fileModifiedTime( %fullPath );
%createCmd = "EWCreatorWindow.createStatic( \\\"" @ %fullPath @ "\\\" );";
%ctrl.altCommand = "ColladaImportDlg.showDialog( \"" @ %fullPath @ "\", \"" @ %createCmd @ "\" );";
%ctrl.altCommand = "showImportDialog( \"" @ %fullPath @ "\", \"" @ %createCmd @ "\" );";
%ctrl.iconBitmap = ( ( %ext $= ".dts" ) ? EditorIconRegistry::findIconByClassName( "TSStatic" ) : "tools/gui/images/iconCollada" );
%ctrl.text = %file;

View file

@ -45,26 +45,52 @@
internalName = "window";
canSaveDynamicFields = "0";
new GuiCheckBoxCtrl() {
useInactiveState = "0";
text = " Swap Y and Z coordinates.";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
new GuiTextCtrl() {
text = "Up Axis";
maxLength = "1024";
Margin = "0 0 0 0";
Padding = "0 0 0 0";
AnchorTop = "1";
AnchorBottom = "0";
AnchorLeft = "1";
AnchorRight = "0";
isContainer = "0";
Profile = "ToolsGuiCheckBoxProfile";
Profile = "ToolsGuiTextRightProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "10 30";
Extent = "200 13";
position = "10 31";
Extent = "40 16";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
variable = "$Assimp::SwapYZ";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "Corrects transformations so Z is up.";
hovertime = "1000";
internalName = "overrideScale";
canSaveDynamicFields = "0";
};
new GuiPopUpMenuCtrl() {
maxPopupHeight = "200";
sbUsesNAColor = "0";
reverseTextList = "0";
bitmapBounds = "16 16";
maxLength = "1024";
Margin = "0 0 0 0";
Padding = "0 0 0 0";
AnchorTop = "1";
AnchorBottom = "0";
AnchorLeft = "1";
AnchorRight = "0";
isContainer = "0";
Profile = "ToolsGuiPopUpMenuProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "56 30";
Extent = "66 18";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
tooltipprofile = "ToolsGuiToolTipProfile";
hovertime = "1000";
internalName = "upAxis";
canSaveDynamicFields = "0";
};
@ -106,6 +132,7 @@
MinExtent = "8 2";
canSave = "1";
Visible = "1";
Active = "0";
variable = "$Assimp::Triangulate";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "Triangulate polygons with more than 3 edges.";
@ -300,7 +327,7 @@
new GuiCheckBoxCtrl() {
useInactiveState = "0";
text = " Find Instances";
text = " Flip UV Coordinates";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
@ -313,6 +340,28 @@
MinExtent = "8 2";
canSave = "1";
Visible = "1";
variable = "$Assimp::FlipUVs";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "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). This will be needed for most textured models.";
hovertime = "1000";
canSaveDynamicFields = "0";
};
new GuiCheckBoxCtrl() {
useInactiveState = "0";
text = " Find Instances";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
isContainer = "0";
Profile = "ToolsGuiCheckBoxProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "10 270";
Extent = "200 13";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
variable = "$Assimp::FindInstances";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "search for instanced meshes and remove them by references to one master.";
@ -331,7 +380,7 @@
Profile = "ToolsGuiCheckBoxProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "10 270";
position = "10 290";
Extent = "200 13";
MinExtent = "8 2";
canSave = "1";
@ -343,7 +392,196 @@
internalName = "overrideScale";
canSaveDynamicFields = "0";
};
new GuiTextCtrl() {
text = "LOD";
maxLength = "1024";
Margin = "0 0 0 0";
Padding = "0 0 0 0";
AnchorTop = "1";
AnchorBottom = "0";
AnchorLeft = "1";
AnchorRight = "0";
isContainer = "0";
Profile = "ToolsGuiTextRightProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "210 31";
Extent = "22 16";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
tooltipprofile = "ToolsGuiToolTipProfile";
hovertime = "1000";
canSaveDynamicFields = "0";
};
new GuiPopUpMenuCtrl() {
maxPopupHeight = "200";
sbUsesNAColor = "0";
reverseTextList = "0";
bitmapBounds = "16 16";
maxLength = "1024";
Margin = "0 0 0 0";
Padding = "0 0 0 0";
AnchorTop = "1";
AnchorBottom = "0";
AnchorLeft = "1";
AnchorRight = "0";
isContainer = "0";
Profile = "ToolsGuiPopUpMenuProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "238 30";
Extent = "92 18";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "Method used to determine LOD for meshes in the model";
hovertime = "1000";
internalName = "lodType";
canSaveDynamicFields = "0";
};
new GuiTextEditCtrl() {
historySize = "0";
password = "0";
tabComplete = "0";
sinkAllKeyEvents = "0";
passwordMask = "*";
text = "2";
maxLength = "1024";
Margin = "0 0 0 0";
Padding = "0 0 0 0";
AnchorTop = "1";
AnchorBottom = "0";
AnchorLeft = "1";
AnchorRight = "0";
isContainer = "0";
Profile = "ToolsGuiTextEditProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "338 30";
Extent = "49 18";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "Detail size for all meshes in this model (when LOD type is SingleSize)";
hovertime = "1000";
internalName = "singleDetailSize";
canSaveDynamicFields = "0";
};
new GuiCheckBoxCtrl() {
useInactiveState = "0";
text = " Center Model";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
isContainer = "0";
Profile = "ToolsGuiCheckBoxProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "210 50";
Extent = "200 13";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
variable = "$Assimp::adjustCenter";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "Translates model so the origin is at the center";
hovertime = "1000";
canSaveDynamicFields = "0";
};
new GuiCheckBoxCtrl() {
useInactiveState = "0";
text = " Floor Model";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
isContainer = "0";
Profile = "ToolsGuiCheckBoxProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "210 70";
Extent = "200 13";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
variable = "$Assimp::adjustFloor";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "Translates model so the origin is at the bottom";
hovertime = "1000";
canSaveDynamicFields = "0";
};
new GuiCheckBoxCtrl() {
useInactiveState = "0";
text = " Join Identical Vertices";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
isContainer = "0";
Profile = "ToolsGuiCheckBoxProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "210 90";
Extent = "200 13";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
variable = "$Assimp::JoinIdenticalVertices";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "Identifies and joins identical vertex data sets within all imported meshes.";
hovertime = "1000";
canSaveDynamicFields = "0";
};
new GuiCheckBoxCtrl() {
useInactiveState = "0";
text = " Flip Winding Order";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
isContainer = "0";
Profile = "ToolsGuiCheckBoxProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "210 110";
Extent = "200 13";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
variable = "$Assimp::FlipWindingOrder";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "This step adjusts the output face winding order to be clockwise. The default face winding order is counter clockwise.";
hovertime = "1000";
canSaveDynamicFields = "0";
};
new GuiCheckBoxCtrl() {
useInactiveState = "0";
text = " Invert Normals";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
isContainer = "0";
Profile = "ToolsGuiCheckBoxProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "210 130";
Extent = "200 13";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
variable = "$Assimp::FlipNormals";
tooltipprofile = "ToolsGuiToolTipProfile";
ToolTip = "Reverse the normal vector direction for all normals.";
hovertime = "1000";
canSaveDynamicFields = "0";
};
new GuiButtonCtrl() {
text = "OK";
groupNum = "-1";
@ -392,7 +630,35 @@ function AssimpImportDlg::showDialog(%this, %shapePath, %cmd)
{
%this.path = %shapePath;
%this.cmd = %cmd;
if ($Assimp::OverrideUpAxis $= "")
{ // First load, so set best-case defaults
$Assimp::OverrideUpAxis = 1; // y-axis is up in most test shapes
$Assimp::lodType = 0; // DetectDTS
$Assimp::singleDetailSize = "2";
// $Assimp::FlipUVs will be needed for virtually all textured models
$Assimp::FlipUVs = true;
$Assimp::FlipWindingOrder = true; // Makes winding order clock wise
$Assimp::FindDegenerates = true;
$Assimp::FindInvalidData = true;
$Assimp::JoinIdenticalVertices = true;
}
%this-->upAxis.clear();
%this-->upAxis.add("X_AXIS", 0);
%this-->upAxis.add("Y_AXIS", 1);
%this-->upAxis.add("Z_AXIS", 2);
%this-->upAxis.setSelected($Assimp::OverrideUpAxis);
%this-->lodType.clear();
%this-->lodType.add("DetectDTS", 0);
%this-->lodType.add("SingleSize", 1);
%this-->lodType.add("TrailingNumber", 2);
%this-->lodType.setSelected($Assimp::lodType);
%this-->singleDetailSize.text = $Assimp::singleDetailSize;
//Triangulate is a default(currently mandatory) behavior
$Assimp::Triangulate = true;
@ -410,6 +676,11 @@ function AssimpImportDlg::onOK(%this)
Canvas.popDialog(%this);
ColladaImportTreeView.clear();
$Assimp::OverrideUpAxis = %this-->upAxis.getSelected();
$Assimp::lodType = %this-->lodType.getSelected();
$Assimp::singleDetailSize = %this-->singleDetailSize.getText();
// Load the shape (always from the DAE)
$assimp::forceLoad = true;
eval(%this.cmd);

View file

@ -267,7 +267,7 @@ function ShapeEdSelectWindow::onSelect( %this, %path )
else
{
%cmd = "ShapeEditor.selectShape( \"" @ %path @ "\", false );";
ColladaImportDlg.showDialog( %path, %cmd );
showImportDialog( %path, %cmd );
}
}