Merge branch 'Menotdan-model-prefab-fix'
This commit is contained in:
@@ -269,7 +269,7 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context)
|
||||
|
||||
// Import all of the objects recursive but use current model data to skip loading file again
|
||||
options.Cached = &cached;
|
||||
Function<bool(Options& splitOptions, const StringView& objectName, String& outputPath)> splitImport = [&context, &autoImportOutput](Options& splitOptions, const StringView& objectName, String& outputPath)
|
||||
Function<bool(Options& splitOptions, const StringView& objectName, String& outputPath, MeshData* meshData)> splitImport = [&context, &autoImportOutput](Options& splitOptions, const StringView& objectName, String& outputPath, MeshData* meshData)
|
||||
{
|
||||
// Recursive importing of the split object
|
||||
String postFix = objectName;
|
||||
@@ -279,6 +279,33 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context)
|
||||
// TODO: check for name collisions with material/texture assets
|
||||
outputPath = autoImportOutput / String(StringUtils::GetFileNameWithoutExtension(context.TargetAssetPath)) + TEXT(" ") + postFix + TEXT(".flax");
|
||||
splitOptions.SubAssetFolder = TEXT(" "); // Use the same folder as asset as they all are imported to the subdir for the prefab (see SubAssetFolder usage above)
|
||||
|
||||
if (splitOptions.Type == ModelTool::ModelType::Model && meshData)
|
||||
{
|
||||
// These settings interfere with submesh reimporting
|
||||
splitOptions.CenterGeometry = false;
|
||||
splitOptions.UseLocalOrigin = false;
|
||||
|
||||
// This properly sets the transformation of the mesh during reimport
|
||||
auto* nodes = &splitOptions.Cached->Data->Nodes;
|
||||
Vector3 scale = Vector3::One;
|
||||
|
||||
// TODO: Improve this hack.
|
||||
// This is the same hack as in ImportModel::CreatePrefab(), and it is documented further there
|
||||
auto* currentNode = &(*nodes)[meshData->NodeIndex];
|
||||
while (true)
|
||||
{
|
||||
if (currentNode->ParentIndex == -1)
|
||||
{
|
||||
scale *= currentNode->LocalTransform.Scale;
|
||||
break;
|
||||
}
|
||||
currentNode = &(*nodes)[currentNode->ParentIndex];
|
||||
}
|
||||
|
||||
splitOptions.Translation = meshData->OriginTranslation * scale * -1.0f;
|
||||
}
|
||||
|
||||
return AssetsImportingManager::Import(context.InputPath, outputPath, &splitOptions);
|
||||
};
|
||||
auto splitOptions = options;
|
||||
@@ -294,7 +321,7 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context)
|
||||
|
||||
splitOptions.Type = ModelTool::ModelType::Model;
|
||||
splitOptions.ObjectIndex = groupIndex;
|
||||
if (!splitImport(splitOptions, group.GetKey(), prefabObject.AssetPath))
|
||||
if (!splitImport(splitOptions, group.GetKey(), prefabObject.AssetPath, group.First()))
|
||||
{
|
||||
prefabObjects.Add(prefabObject);
|
||||
}
|
||||
@@ -305,7 +332,7 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context)
|
||||
auto& animation = data->Animations[i];
|
||||
splitOptions.Type = ModelTool::ModelType::Animation;
|
||||
splitOptions.ObjectIndex = i;
|
||||
splitImport(splitOptions, animation.Name, prefabObject.AssetPath);
|
||||
splitImport(splitOptions, animation.Name, prefabObject.AssetPath, nullptr);
|
||||
}
|
||||
}
|
||||
else if (options.SplitObjects)
|
||||
@@ -361,7 +388,7 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context)
|
||||
auto& group = meshesByName[options.ObjectIndex];
|
||||
if (&dataThis == data)
|
||||
{
|
||||
// Use meshes only from the the grouping (others will be removed manually)
|
||||
// Use meshes only from the grouping (others will be removed manually)
|
||||
{
|
||||
auto& lod = dataThis.LODs[0];
|
||||
meshesToDelete.Add(lod.Meshes);
|
||||
@@ -665,7 +692,42 @@ CreateAssetResult ImportModel::CreatePrefab(CreateAssetContext& context, ModelDa
|
||||
// Setup node in hierarchy
|
||||
nodeToActor.Add(nodeIndex, nodeActor);
|
||||
nodeActor->SetName(node.Name);
|
||||
nodeActor->SetLocalTransform(node.LocalTransform);
|
||||
|
||||
// When use local origin is checked, it shifts everything over the same amount, including the root. This tries to work around that.
|
||||
if (!(nodeIndex == 0 && options.UseLocalOrigin))
|
||||
{
|
||||
// TODO: Improve this hack.
|
||||
// Assimp importer has the meter -> centimeter conversion scale applied to the local transform of
|
||||
// the root node, and only the root node. The OpenFBX importer has the same scale applied
|
||||
// to each node, *except* the root node. This difference makes it hard to calculate the
|
||||
// global scale properly. Position offsets are not calculated properly from Assimp without summing up
|
||||
// the global scale because translations from Assimp don't get scaled with the global scaler option,
|
||||
// but the OpenFBX importer does scale them. So this hack will end up only applying the global scale
|
||||
// change if its using Assimp due to the difference in where the nodes' local transform scales are set.
|
||||
auto* currentNode = &node;
|
||||
Vector3 scale = Vector3::One;
|
||||
while (true)
|
||||
{
|
||||
if (currentNode->ParentIndex == -1)
|
||||
{
|
||||
scale *= currentNode->LocalTransform.Scale;
|
||||
break;
|
||||
}
|
||||
currentNode = &data.Nodes[currentNode->ParentIndex];
|
||||
}
|
||||
|
||||
// Only set translation, since scale and rotation is applied earlier.
|
||||
Transform positionOffset = Transform::Identity;
|
||||
positionOffset.Translation = node.LocalTransform.Translation * scale;
|
||||
|
||||
if (options.UseLocalOrigin)
|
||||
{
|
||||
positionOffset.Translation += data.Nodes[0].LocalTransform.Translation;
|
||||
}
|
||||
|
||||
nodeActor->SetLocalTransform(positionOffset);
|
||||
}
|
||||
|
||||
if (nodeIndex == 0)
|
||||
{
|
||||
// Special case for root actor to link any unlinked nodes
|
||||
|
||||
@@ -483,7 +483,6 @@ bool ProcessMesh(ModelData& result, AssimpImporterData& data, const aiMesh* aMes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -645,64 +644,31 @@ bool ImportMesh(int32 index, ModelData& result, AssimpImporterData& data, String
|
||||
|
||||
// Link mesh
|
||||
meshData->NodeIndex = nodeIndex;
|
||||
AssimpNode* curNode = &data.Nodes[meshData->NodeIndex];
|
||||
Vector3 translation = Vector3::Zero;
|
||||
Vector3 scale = Vector3::One;
|
||||
Quaternion rotation = Quaternion::Identity;
|
||||
|
||||
while (true)
|
||||
{
|
||||
translation += curNode->LocalTransform.Translation;
|
||||
scale *= curNode->LocalTransform.Scale;
|
||||
rotation *= curNode->LocalTransform.Orientation;
|
||||
|
||||
if (curNode->ParentIndex == -1)
|
||||
break;
|
||||
curNode = &data.Nodes[curNode->ParentIndex];
|
||||
}
|
||||
|
||||
meshData->OriginTranslation = translation;
|
||||
meshData->OriginOrientation = rotation;
|
||||
meshData->Scaling = scale;
|
||||
|
||||
if (result.LODs.Count() <= lodIndex)
|
||||
result.LODs.Resize(lodIndex + 1);
|
||||
result.LODs[lodIndex].Meshes.Add(meshData);
|
||||
}
|
||||
|
||||
auto root = data.Scene->mRootNode;
|
||||
Array<Transform> points;
|
||||
if (root->mNumChildren == 0)
|
||||
{
|
||||
aiQuaternion aiQuat;
|
||||
aiVector3D aiPos;
|
||||
aiVector3D aiScale;
|
||||
root->mTransformation.Decompose(aiScale, aiQuat, aiPos);
|
||||
auto quat = ToQuaternion(aiQuat);
|
||||
auto pos = ToFloat3(aiPos);
|
||||
auto scale = ToFloat3(aiScale);
|
||||
Transform trans = Transform(pos, quat, scale);
|
||||
points.Add(trans);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int j = 0; j < root->mNumChildren; j++)
|
||||
{
|
||||
aiQuaternion aiQuat;
|
||||
aiVector3D aiPos;
|
||||
aiVector3D aiScale;
|
||||
root->mChildren[j]->mTransformation.Decompose(aiScale, aiQuat, aiPos);
|
||||
auto quat = ToQuaternion(aiQuat);
|
||||
auto pos = ToFloat3(aiPos);
|
||||
auto scale = ToFloat3(aiScale);
|
||||
Transform trans = Transform(pos, quat, scale);
|
||||
points.Add(trans);
|
||||
}
|
||||
}
|
||||
|
||||
Float3 translation = Float3::Zero;
|
||||
Float3 scale = Float3::Zero;
|
||||
Quaternion orientation = Quaternion::Identity;
|
||||
for (auto point : points)
|
||||
{
|
||||
translation += point.Translation;
|
||||
scale += point.Scale;
|
||||
orientation *= point.Orientation;
|
||||
}
|
||||
|
||||
if (points.Count() > 0)
|
||||
{
|
||||
meshData->OriginTranslation = translation / (float)points.Count();
|
||||
meshData->OriginOrientation = Quaternion::Invert(orientation);
|
||||
meshData->Scaling = scale / (float)points.Count();
|
||||
}
|
||||
else
|
||||
{
|
||||
meshData->OriginTranslation = translation;
|
||||
meshData->OriginOrientation = Quaternion::Invert(orientation);
|
||||
meshData->Scaling = Float3(1);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -790,6 +756,7 @@ bool ModelTool::ImportDataAssimp(const char* path, ModelData& data, Options& opt
|
||||
aiProcess_GenUVCoords |
|
||||
aiProcess_FindDegenerates |
|
||||
aiProcess_FindInvalidData |
|
||||
aiProcess_GlobalScale |
|
||||
//aiProcess_ValidateDataStructure |
|
||||
aiProcess_ConvertToLeftHanded;
|
||||
if (importMeshes)
|
||||
@@ -807,6 +774,7 @@ bool ModelTool::ImportDataAssimp(const char* path, ModelData& data, Options& opt
|
||||
// Setup import options
|
||||
context.AssimpImporter.SetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE, options.SmoothingNormalsAngle);
|
||||
context.AssimpImporter.SetPropertyFloat(AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE, options.SmoothingTangentsAngle);
|
||||
context.AssimpImporter.SetPropertyFloat(AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY, 100.0f); // Convert to cm
|
||||
//context.AssimpImporter.SetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT, MAX_uint16);
|
||||
context.AssimpImporter.SetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, false);
|
||||
context.AssimpImporter.SetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, false);
|
||||
@@ -827,14 +795,14 @@ bool ModelTool::ImportDataAssimp(const char* path, ModelData& data, Options& opt
|
||||
}
|
||||
|
||||
// Create root node
|
||||
AssimpNode& rootNode = context.Nodes.AddOne();
|
||||
/*AssimpNode& rootNode = context.Nodes.AddOne();
|
||||
rootNode.ParentIndex = -1;
|
||||
rootNode.LodIndex = 0;
|
||||
rootNode.Name = TEXT("Root");
|
||||
rootNode.LocalTransform = Transform::Identity;
|
||||
rootNode.Name = TEXT("Root");*/
|
||||
|
||||
// Process imported scene nodes
|
||||
ProcessNodes(context, context.Scene->mRootNode, 0);
|
||||
ProcessNodes(context, context.Scene->mRootNode, -1);
|
||||
|
||||
// Import materials
|
||||
if (ImportMaterials(data, context, errorMsg))
|
||||
|
||||
@@ -1340,7 +1340,8 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option
|
||||
if (skeletonMapping.SourceToSource[mesh.NodeIndex] != mesh.NodeIndex)
|
||||
{
|
||||
// Transform vertices
|
||||
const auto transformationMatrix = hierarchyUpdater.CombineMatricesFromNodeIndices(skeletonMapping.SourceToSource[mesh.NodeIndex], mesh.NodeIndex);
|
||||
const Matrix transformationMatrix = hierarchyUpdater.CombineMatricesFromNodeIndices(skeletonMapping.SourceToSource[mesh.NodeIndex], mesh.NodeIndex);
|
||||
|
||||
if (!transformationMatrix.IsIdentity())
|
||||
mesh.TransformBuffer(transformationMatrix);
|
||||
}
|
||||
@@ -1350,6 +1351,38 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option
|
||||
}
|
||||
}
|
||||
}
|
||||
if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Geometry) && options.Type == ModelType::Prefab)
|
||||
{
|
||||
// Apply just the scale and rotations.
|
||||
for (int32 lodIndex = 0; lodIndex < data.LODs.Count(); lodIndex++)
|
||||
{
|
||||
for (int32 meshIndex = 0; meshIndex < data.LODs[lodIndex].Meshes.Count(); meshIndex++)
|
||||
{
|
||||
auto& mesh = *data.LODs[lodIndex].Meshes[meshIndex];
|
||||
auto& node = data.Nodes[mesh.NodeIndex];
|
||||
auto currentNode = &data.Nodes[mesh.NodeIndex];
|
||||
|
||||
Vector3 scale = Vector3::One;
|
||||
Quaternion rotation = Quaternion::Identity;
|
||||
while (true)
|
||||
{
|
||||
scale *= currentNode->LocalTransform.Scale;
|
||||
rotation *= currentNode->LocalTransform.Orientation;
|
||||
if (currentNode->ParentIndex == -1)
|
||||
break;
|
||||
currentNode = &data.Nodes[currentNode->ParentIndex];
|
||||
}
|
||||
|
||||
// Transform vertices
|
||||
auto transformationMatrix = Matrix::Identity;
|
||||
transformationMatrix.SetScaleVector(scale);
|
||||
transformationMatrix = transformationMatrix * Matrix::RotationQuaternion(rotation);
|
||||
|
||||
if (!transformationMatrix.IsIdentity())
|
||||
mesh.TransformBuffer(transformationMatrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Animations))
|
||||
{
|
||||
for (auto& animation : data.Animations)
|
||||
|
||||
Reference in New Issue
Block a user