Integrating latest 47acbe8
This commit is contained in:
@@ -9,9 +9,7 @@
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME})
|
||||
set(sdkwrapper_dir ${CMAKE_CURRENT_LIST_DIR}/../SDKWrapper)
|
||||
set(sdkwrapper_pal_dir ${sdkwrapper_dir}/Platform/${PAL_PLATFORM_NAME})
|
||||
|
||||
if (NOT PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
return()
|
||||
@@ -23,9 +21,6 @@ ly_add_target(
|
||||
FILES_CMAKE
|
||||
fbxsdkwrapper_files.cmake
|
||||
${sdkwrapper_dir}/sdkwrapper_files.cmake
|
||||
${sdkwrapper_pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
|
||||
PLATFORM_INCLUDE_FILES
|
||||
${pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PUBLIC
|
||||
.
|
||||
@@ -37,4 +32,5 @@ ly_add_target(
|
||||
AZ::AzToolsFramework
|
||||
PUBLIC
|
||||
3rdParty::FbxSdk
|
||||
3rdParty::assimplib
|
||||
)
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace AZ
|
||||
return 10.f;
|
||||
}
|
||||
|
||||
uint64_t FbxMaterialWrapper::GetUniqueId() const
|
||||
AZ::u64 FbxMaterialWrapper::GetUniqueId() const
|
||||
{
|
||||
return m_fbxMaterial->GetUniqueID();
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace AZ
|
||||
AZ::Vector3 GetEmissiveColor() const override;
|
||||
float GetOpacity() const override;
|
||||
float GetShininess() const override;
|
||||
uint64_t GetUniqueId() const override;
|
||||
AZ::u64 GetUniqueId() const override;
|
||||
};
|
||||
} // namespace FbxSDKWrapper
|
||||
} // namespace AZ
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
set(LY_BUILD_DEPENDENCIES
|
||||
PUBLIC
|
||||
3rdParty::AssImp
|
||||
)
|
||||
|
||||
set(LY_COMPILE_DEFINITIONS PUBLIC ASSET_IMPORTER_SDK_SUPPORTED_TRAIT)
|
||||
@@ -19,13 +19,18 @@
|
||||
#include <SceneAPI/FbxSceneBuilder/FbxImportRequestHandler.h>
|
||||
|
||||
#include <SceneAPI/FbxSceneBuilder/FbxImporter.h>
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpBitangentStreamImporter.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpColorStreamImporter.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpMaterialImporter.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpMeshImporter.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpTangentStreamImporter.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpTransformImporter.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpUvMapImporter.h>
|
||||
#endif
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpSkinImporter.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpSkinWeightsImporter.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpBoneImporter.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpAnimationImporter.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpBlendShapeImporter.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/FbxAnimationImporter.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/FbxBlendShapeImporter.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/FbxBoneImporter.h>
|
||||
@@ -39,7 +44,6 @@
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/FbxTransformImporter.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/FbxUvMapImporter.h>
|
||||
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace SceneAPI
|
||||
@@ -86,13 +90,19 @@ namespace AZ
|
||||
g_componentDescriptors.push_back(FbxUvMapImporter::CreateDescriptor());
|
||||
g_componentDescriptors.push_back(FbxTangentStreamImporter::CreateDescriptor());
|
||||
g_componentDescriptors.push_back(FbxBitangentStreamImporter::CreateDescriptor());
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
g_componentDescriptors.push_back(AssImpBitangentStreamImporter::CreateDescriptor());
|
||||
g_componentDescriptors.push_back(AssImpColorStreamImporter::CreateDescriptor());
|
||||
g_componentDescriptors.push_back(AssImpMaterialImporter::CreateDescriptor());
|
||||
g_componentDescriptors.push_back(AssImpMeshImporter::CreateDescriptor());
|
||||
g_componentDescriptors.push_back(AssImpTangentStreamImporter::CreateDescriptor());
|
||||
g_componentDescriptors.push_back(AssImpTransformImporter::CreateDescriptor());
|
||||
g_componentDescriptors.push_back(AssImpUvMapImporter::CreateDescriptor());
|
||||
#endif
|
||||
g_componentDescriptors.push_back(AssImpSkinImporter::CreateDescriptor());
|
||||
g_componentDescriptors.push_back(AssImpSkinWeightsImporter::CreateDescriptor());
|
||||
g_componentDescriptors.push_back(AssImpBoneImporter::CreateDescriptor());
|
||||
g_componentDescriptors.push_back(AssImpAnimationImporter::CreateDescriptor());
|
||||
g_componentDescriptors.push_back(AssImpBlendShapeImporter::CreateDescriptor());
|
||||
|
||||
for (AZ::ComponentDescriptor* descriptor : g_componentDescriptors)
|
||||
{
|
||||
AZ::ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationBus::Handler::RegisterComponentDescriptor, descriptor);
|
||||
|
||||
@@ -21,10 +21,8 @@
|
||||
#include <AzToolsFramework/Debug/TraceContext.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/FbxImporter.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/ImportContexts/FbxImportContexts.h>
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
#include <SceneAPI/FbxSceneBuilder/ImportContexts/AssImpImportContexts.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpMaterialImporter.h>
|
||||
#endif
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/FbxImporterUtilities.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/Utilities/RenamedNodesMap.h>
|
||||
#include <SceneAPI/FbxSDKWrapper/FbxSceneWrapper.h>
|
||||
@@ -32,10 +30,8 @@
|
||||
#include <SceneAPI/SceneCore/Containers/Scene.h>
|
||||
#include <SceneAPI/SceneCore/Utilities/Reporting.h>
|
||||
#include <SceneAPI/SceneData/GraphData/TransformData.h>
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
#include <SceneAPI/SDKWrapper/AssImpSceneWrapper.h>
|
||||
#include <SceneAPI/SDKWrapper/AssImpNodeWrapper.h>
|
||||
#endif
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -59,7 +55,7 @@ namespace AZ
|
||||
FbxImporter::FbxImporter()
|
||||
: m_sceneSystem(new FbxSceneSystem())
|
||||
{
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
|
||||
if (m_useAssetImporterSDK)
|
||||
{
|
||||
m_sceneWrapper = AZStd::make_unique<AssImpSDKWrapper::AssImpSceneWrapper>();
|
||||
@@ -68,9 +64,7 @@ namespace AZ
|
||||
{
|
||||
m_sceneWrapper = AZStd::make_unique<FbxSDKWrapper::FbxSceneWrapper>();
|
||||
}
|
||||
#else
|
||||
m_sceneWrapper = AZStd::make_unique<FbxSDKWrapper::FbxSceneWrapper>();
|
||||
#endif
|
||||
|
||||
BindToCall(&FbxImporter::ImportProcessing);
|
||||
}
|
||||
|
||||
@@ -99,12 +93,10 @@ namespace AZ
|
||||
{
|
||||
convertFunc = AZStd::bind(&FbxImporter::ConvertFbxSceneContext, this, AZStd::placeholders::_1);
|
||||
}
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
else
|
||||
{
|
||||
convertFunc = AZStd::bind(&FbxImporter::ConvertFbxScene, this, AZStd::placeholders::_1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (convertFunc(context.GetScene()))
|
||||
{
|
||||
@@ -284,7 +276,7 @@ namespace AZ
|
||||
|
||||
return true;
|
||||
}
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
|
||||
bool FbxImporter::ConvertFbxScene(Containers::Scene& scene) const
|
||||
{
|
||||
std::shared_ptr<SDKNode::NodeWrapper> fbxRoot = m_sceneWrapper->GetRootNode();
|
||||
@@ -333,6 +325,8 @@ namespace AZ
|
||||
continue;
|
||||
}
|
||||
AZStd::string nodeName = nodeNameMap.GetNodeName(node.m_node);
|
||||
SanitizeNodeName(nodeName);
|
||||
|
||||
AZ_TraceContext("SceneAPI Node Name", nodeName);
|
||||
Containers::SceneGraph::NodeIndex newNode = scene.GetGraph().AddChild(node.m_parent, nodeName.c_str());
|
||||
|
||||
@@ -431,7 +425,13 @@ namespace AZ
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void FbxImporter::SanitizeNodeName(AZStd::string& nodeName) const
|
||||
{
|
||||
// Replace % with something else so it is safe for use in printfs.
|
||||
AZStd::replace(nodeName.begin(), nodeName.end(), '%', '_');
|
||||
}
|
||||
|
||||
} // namespace FbxSceneBuilder
|
||||
} // namespace SceneAPI
|
||||
} // namespace AZ
|
||||
|
||||
@@ -46,15 +46,12 @@ namespace AZ
|
||||
|
||||
protected:
|
||||
bool ConvertFbxSceneContext(Containers::Scene& scene) const;
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
bool ConvertFbxScene(Containers::Scene& scene) const;
|
||||
#endif
|
||||
void SanitizeNodeName(AZStd::string& nodeName) const;
|
||||
|
||||
AZStd::unique_ptr<SDKScene::SceneWrapperBase> m_sceneWrapper;
|
||||
AZStd::shared_ptr<FbxSceneSystem> m_sceneSystem;
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
bool m_useAssetImporterSDK = false;
|
||||
#endif
|
||||
};
|
||||
} // namespace FbxSceneBuilder
|
||||
} // namespace SceneAPI
|
||||
|
||||
@@ -13,12 +13,9 @@
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <SceneAPI/FbxSDKWrapper/FbxSceneWrapper.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/FbxSceneSystem.h>
|
||||
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
#include <SceneAPI/SDKWrapper/AssImpSceneWrapper.h>
|
||||
#include <SceneAPI/SDKWrapper/AssImpTypeConverter.h>
|
||||
#include <assimp/scene.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace AZ
|
||||
@@ -52,7 +49,6 @@ namespace AZ
|
||||
m_adjustTransformInverse.reset(new DataTypes::MatrixType(m_adjustTransform->GetInverseFull()));
|
||||
}
|
||||
}
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
else if (azrtti_istypeof<AssImpSDKWrapper::AssImpSceneWrapper>(fbxScene))
|
||||
{
|
||||
const AssImpSDKWrapper::AssImpSceneWrapper* assImpScene = azrtti_cast<const AssImpSDKWrapper::AssImpSceneWrapper*>(fbxScene);
|
||||
@@ -135,7 +131,6 @@ namespace AZ
|
||||
m_adjustTransformInverse.reset(new DataTypes::MatrixType(m_adjustTransform->GetInverseFull()));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void FbxSceneSystem::SwapVec3ForUpAxis(Vector3& swapVector) const
|
||||
|
||||
@@ -0,0 +1,610 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#include <AssImpTypeConverter.h>
|
||||
#include <assimp/mesh.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
#include <AzToolsFramework/Debug/TraceContext.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/FbxSceneSystem.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/ImportContexts/AssImpImportContexts.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpAnimationImporter.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpImporterUtilities.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/Utilities/RenamedNodesMap.h>
|
||||
#include <SceneAPI/FbxSDKWrapper/FbxAnimCurveWrapper.h>
|
||||
#include <SceneAPI/FbxSDKWrapper/FbxAnimLayerWrapper.h>
|
||||
#include <SceneAPI/FbxSDKWrapper/FbxNodeWrapper.h>
|
||||
#include <SceneAPI/FbxSDKWrapper/FbxSceneWrapper.h>
|
||||
#include <SceneAPI/FbxSDKWrapper/FbxTimeSpanWrapper.h>
|
||||
#include <SceneAPI/SceneCore/Containers/Scene.h>
|
||||
#include <SceneAPI/SceneData/GraphData/AnimationData.h>
|
||||
#include <SceneAPI/SDKWrapper/AssImpNodeWrapper.h>
|
||||
#include <SceneAPI/SDKWrapper/AssImpSceneWrapper.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace SceneAPI
|
||||
{
|
||||
namespace FbxSceneBuilder
|
||||
{
|
||||
const char* AssImpAnimationImporter::s_animationNodeName = "animation";
|
||||
const FbxSDKWrapper::FbxTimeWrapper::TimeMode AssImpAnimationImporter::s_defaultTimeMode =
|
||||
FbxSDKWrapper::FbxTimeWrapper::frames30;
|
||||
|
||||
AssImpAnimationImporter::AssImpAnimationImporter()
|
||||
{
|
||||
BindToCall(&AssImpAnimationImporter::ImportAnimation);
|
||||
}
|
||||
|
||||
void AssImpAnimationImporter::Reflect(ReflectContext* context)
|
||||
{
|
||||
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<AssImpAnimationImporter, SceneCore::LoadingComponent>()->Version(1);
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::string GetName(const aiMeshAnim* anim)
|
||||
{
|
||||
return anim->mName.C_Str();
|
||||
}
|
||||
|
||||
AZStd::string GetName(const aiNodeAnim* anim)
|
||||
{
|
||||
return anim->mNodeName.C_Str();
|
||||
}
|
||||
|
||||
AZStd::string GetName(const aiMeshMorphAnim* anim)
|
||||
{
|
||||
return anim->mName.C_Str();
|
||||
}
|
||||
|
||||
struct ConsolidatedNodeAnim
|
||||
{
|
||||
ConsolidatedNodeAnim() = default;
|
||||
ConsolidatedNodeAnim(const ConsolidatedNodeAnim& other) = delete;
|
||||
|
||||
ConsolidatedNodeAnim(ConsolidatedNodeAnim&& other) noexcept
|
||||
: mNumPositionKeys{ other.mNumPositionKeys },
|
||||
mPositionKeys{ other.mPositionKeys },
|
||||
mNumRotationKeys{ other.mNumRotationKeys },
|
||||
mRotationKeys{ other.mRotationKeys },
|
||||
mNumScalingKeys{ other.mNumScalingKeys },
|
||||
mScalingKeys{ other.mScalingKeys },
|
||||
m_ownedPositionKeys{ std::move(other.m_ownedPositionKeys) },
|
||||
m_ownedScalingKeys{ std::move(other.m_ownedScalingKeys) },
|
||||
m_ownedRotationKeys{ std::move(other.m_ownedRotationKeys) },
|
||||
mPreState{ other.mPreState },
|
||||
mPostState{ other.mPostState }
|
||||
{
|
||||
}
|
||||
|
||||
ConsolidatedNodeAnim& operator=(const ConsolidatedNodeAnim& other) = delete;
|
||||
|
||||
ConsolidatedNodeAnim& operator=(ConsolidatedNodeAnim&& other) noexcept
|
||||
{
|
||||
if (this == &other)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
mNumPositionKeys = other.mNumPositionKeys;
|
||||
mPositionKeys = other.mPositionKeys;
|
||||
mNumRotationKeys = other.mNumRotationKeys;
|
||||
mRotationKeys = other.mRotationKeys;
|
||||
mNumScalingKeys = other.mNumScalingKeys;
|
||||
mScalingKeys = other.mScalingKeys;
|
||||
m_ownedPositionKeys = std::move(other.m_ownedPositionKeys);
|
||||
m_ownedScalingKeys = std::move(other.m_ownedScalingKeys);
|
||||
m_ownedRotationKeys = std::move(other.m_ownedRotationKeys);
|
||||
mPreState = other.mPreState;
|
||||
mPostState = other.mPostState;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// These variables are named using AssImp naming convention for consistency
|
||||
unsigned int mNumPositionKeys{};
|
||||
aiVectorKey* mPositionKeys{};
|
||||
|
||||
unsigned int mNumRotationKeys{};
|
||||
aiQuatKey* mRotationKeys{};
|
||||
|
||||
unsigned int mNumScalingKeys{};
|
||||
aiVectorKey* mScalingKeys{};
|
||||
|
||||
AZStd::vector<aiVectorKey> m_ownedPositionKeys{};
|
||||
AZStd::vector<aiVectorKey> m_ownedScalingKeys{};
|
||||
AZStd::vector<aiQuatKey> m_ownedRotationKeys{};
|
||||
|
||||
aiAnimBehaviour mPreState{};
|
||||
aiAnimBehaviour mPostState{};
|
||||
};
|
||||
|
||||
AZStd::pair<const aiAnimation*, ConsolidatedNodeAnim> MakeMyPair(const aiAnimation* animation, const aiNodeAnim* anim)
|
||||
{
|
||||
ConsolidatedNodeAnim consolidatedNodeAnim{};
|
||||
|
||||
consolidatedNodeAnim.mNumRotationKeys = anim->mNumRotationKeys;
|
||||
consolidatedNodeAnim.mNumPositionKeys = anim->mNumPositionKeys;
|
||||
consolidatedNodeAnim.mNumScalingKeys = anim->mNumScalingKeys;
|
||||
consolidatedNodeAnim.mRotationKeys = anim->mRotationKeys;
|
||||
consolidatedNodeAnim.mPositionKeys = anim->mPositionKeys;
|
||||
consolidatedNodeAnim.mScalingKeys = anim->mScalingKeys;
|
||||
|
||||
return {animation, AZStd::move(consolidatedNodeAnim)};
|
||||
}
|
||||
|
||||
auto MakeMyPair(const aiAnimation* animation, const aiMeshAnim* anim)
|
||||
{
|
||||
return AZStd::make_pair(animation, anim);
|
||||
}
|
||||
|
||||
auto MakeMyPair(const aiAnimation* animation, const aiMeshMorphAnim* anim)
|
||||
{
|
||||
return AZStd::make_pair(animation, anim);
|
||||
}
|
||||
|
||||
|
||||
Events::ProcessingResult AssImpAnimationImporter::ImportAnimation(AssImpSceneNodeAppendedContext& context)
|
||||
{
|
||||
AZ_TraceContext("Importer", "Animation");
|
||||
|
||||
aiNode* currentNode = context.m_sourceNode.GetAssImpNode();
|
||||
const aiScene* scene = context.m_sourceScene.GetAssImpScene();
|
||||
|
||||
// Add check for animation layers at the scene level.
|
||||
|
||||
if (!scene->HasAnimations() || IsPivotNode(currentNode->mName))
|
||||
{
|
||||
return Events::ProcessingResult::Ignored;
|
||||
}
|
||||
|
||||
AZStd::unordered_multimap<AZStd::string, AZStd::pair<const aiAnimation*, ConsolidatedNodeAnim>> boneAnimations;
|
||||
typedef AZStd::pair<const aiAnimation*, const aiMeshMorphAnim*> AnimAndMorphAnim;
|
||||
typedef AZStd::unordered_map<AZStd::string, AnimAndMorphAnim> ChannelToMorphAnim;
|
||||
typedef AZStd::unordered_map<AZStd::string, ChannelToMorphAnim> NodeToChannelToMorphAnim;
|
||||
NodeToChannelToMorphAnim meshMorphAnimations;
|
||||
|
||||
// Goes through all the animation channels of a given type and adds them to a map so we can easily find
|
||||
// all the animations for a given node
|
||||
// In the case of bone animations, the data is copied into a ConsolidatedNodeAnim so we can
|
||||
// do fix-ups later without affecting the original data
|
||||
auto mapAnimationsFunc = [](unsigned numChannels, auto** channels, const aiAnimation* animation, auto& map)
|
||||
{
|
||||
map.reserve(numChannels);
|
||||
|
||||
for (unsigned channelIndex = 0; channelIndex < numChannels; ++channelIndex)
|
||||
{
|
||||
auto* nodeAnim = channels[channelIndex];
|
||||
AZStd::string name = GetName(nodeAnim);
|
||||
|
||||
map.emplace(name, MakeMyPair(animation, nodeAnim));
|
||||
}
|
||||
};
|
||||
|
||||
for (unsigned animIndex = 0; animIndex < scene->mNumAnimations; ++animIndex)
|
||||
{
|
||||
const aiAnimation* animation = scene->mAnimations[animIndex];
|
||||
|
||||
mapAnimationsFunc(animation->mNumChannels, animation->mChannels, animation, boneAnimations);
|
||||
|
||||
for (unsigned channelIndex = 0; channelIndex < animation->mNumMorphMeshChannels; ++channelIndex)
|
||||
{
|
||||
auto* nodeAnim = animation->mMorphMeshChannels[channelIndex];
|
||||
AZStd::string name = GetName(nodeAnim);
|
||||
|
||||
AZStd::vector<AZStd::string> meshNodeNameAndChannel;
|
||||
|
||||
// Morph target animations include the channel in the name,
|
||||
// so if a mesh is named Mesh01, the morph target for the first channel
|
||||
// will be named Mesh01*0
|
||||
AZ::StringFunc::Tokenize(name, meshNodeNameAndChannel, '*');
|
||||
|
||||
if (meshNodeNameAndChannel.size() != 2)
|
||||
{
|
||||
AZ_Error(
|
||||
"AnimationImporter", false,
|
||||
"Morph animation name %s was not in the expected format of: node name, asterisk, node channel. "
|
||||
"Example: 'NodeName*0'",
|
||||
name.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
AZStd::string meshNodeName(meshNodeNameAndChannel[0]);
|
||||
AZStd::string channel(meshNodeNameAndChannel[1]);
|
||||
meshMorphAnimations[meshNodeName][channel] = AnimAndMorphAnim(animation, nodeAnim);
|
||||
}
|
||||
}
|
||||
|
||||
// Go through all the bone animations and find any that reference a pivot node
|
||||
// We'll make a new node anim and store all the combined animation channels there
|
||||
// with the name set to the base bone name
|
||||
decltype(boneAnimations) combinedAnimations;
|
||||
|
||||
for (auto&& animation : boneAnimations)
|
||||
{
|
||||
size_t pos = AZ::StringFunc::Find(animation.first, PivotNodeMarker, 0);
|
||||
|
||||
if (pos != animation.first.npos)
|
||||
{
|
||||
AZStd::string_view name, part;
|
||||
SplitPivotNodeName(aiString(animation.first.c_str()), pos, name, part);
|
||||
|
||||
auto&& iterator = combinedAnimations.find(name);
|
||||
|
||||
if (iterator == combinedAnimations.end())
|
||||
{
|
||||
combinedAnimations.emplace(AZStd::string(name), AZStd::move(animation.second));
|
||||
iterator = combinedAnimations.find(name);
|
||||
}
|
||||
|
||||
if (iterator != combinedAnimations.end())
|
||||
{
|
||||
auto& existingNode = iterator->second.second;
|
||||
auto&& src = animation.second.second;
|
||||
|
||||
if (part == "Translation")
|
||||
{
|
||||
existingNode.mNumPositionKeys = src.mNumPositionKeys;
|
||||
existingNode.mPositionKeys = src.mPositionKeys;
|
||||
}
|
||||
else if (part == "Rotation")
|
||||
{
|
||||
existingNode.mNumRotationKeys = src.mNumRotationKeys;
|
||||
existingNode.mRotationKeys = src.mRotationKeys;
|
||||
}
|
||||
else if (part == "Scaling")
|
||||
{
|
||||
existingNode.mNumScalingKeys = src.mNumScalingKeys;
|
||||
existingNode.mScalingKeys = src.mScalingKeys;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!combinedAnimations.empty())
|
||||
{
|
||||
boneAnimations.swap(combinedAnimations);
|
||||
}
|
||||
|
||||
Events::ProcessingResultCombiner combinedAnimationResult;
|
||||
for (unsigned meshIndex = 0; meshIndex < currentNode->mNumMeshes; ++meshIndex)
|
||||
{
|
||||
aiMesh* mesh = scene->mMeshes[currentNode->mMeshes[meshIndex]];
|
||||
|
||||
if (NodeToChannelToMorphAnim::iterator channelsForMeshName = meshMorphAnimations.find(mesh->mName.C_Str());
|
||||
channelsForMeshName != meshMorphAnimations.end())
|
||||
{
|
||||
const auto [nodeIterName, channels] = *channelsForMeshName;
|
||||
for (const auto& [channel, animAndMorphAnim] : channels)
|
||||
{
|
||||
const auto& [animation, morphAnimation] = animAndMorphAnim;
|
||||
combinedAnimationResult += ImportBlendShapeAnimation(
|
||||
context, animation, morphAnimation, mesh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::string nodeName = s_animationNodeName;
|
||||
RenamedNodesMap::SanitizeNodeName(nodeName, context.m_scene.GetGraph(), context.m_currentGraphPosition);
|
||||
AZ_TraceContext("Animation node name", nodeName);
|
||||
|
||||
// If there are no bone animations, but there are mesh animations,
|
||||
// then a stub animation needs to be created so the exporter can create the exported morph target animation.
|
||||
if (boneAnimations.empty() && !meshMorphAnimations.empty())
|
||||
{
|
||||
const aiAnimation* animation = scene->mAnimations[0];
|
||||
|
||||
// Morph animations need a regular animation on the node, as well.
|
||||
// If there is no bone animation on the current node, then generate one here.
|
||||
AZStd::shared_ptr<SceneData::GraphData::AnimationData> createdAnimationData =
|
||||
AZStd::make_shared<SceneData::GraphData::AnimationData>();
|
||||
createdAnimationData->ReserveKeyFrames(
|
||||
animation->mDuration +
|
||||
1); // +1 because we start at 0 and the last keyframe is at mDuration instead of mDuration-1
|
||||
createdAnimationData->SetTimeStepBetweenFrames(1.0 / animation->mTicksPerSecond);
|
||||
|
||||
// Set every frame of the animation to the start location of the node.
|
||||
aiMatrix4x4 combinedTransform = GetConcatenatedLocalTransform(currentNode);
|
||||
DataTypes::MatrixType localTransform = AssImpSDKWrapper::AssImpTypeConverter::ToTransform(combinedTransform);
|
||||
context.m_sourceSceneSystem.SwapTransformForUpAxis(localTransform);
|
||||
context.m_sourceSceneSystem.ConvertUnit(localTransform);
|
||||
for (unsigned time = 0; time <= animation->mDuration; ++time)
|
||||
{
|
||||
createdAnimationData->AddKeyFrame(localTransform);
|
||||
}
|
||||
|
||||
Containers::SceneGraph::NodeIndex addNode = context.m_scene.GetGraph().AddChild(
|
||||
context.m_currentGraphPosition, nodeName.c_str(), AZStd::move(createdAnimationData));
|
||||
context.m_scene.GetGraph().MakeEndPoint(addNode);
|
||||
|
||||
return combinedAnimationResult.GetResult();
|
||||
}
|
||||
decltype(boneAnimations) parentFillerAnimations;
|
||||
|
||||
// Go through all the animations and make sure we create animations for bones who's parents don't have an animation
|
||||
for (auto&& anim : boneAnimations)
|
||||
{
|
||||
aiNode* node = scene->mRootNode->FindNode(anim.first.c_str());
|
||||
aiNode* parent = node->mParent;
|
||||
|
||||
while (parent && parent != scene->mRootNode)
|
||||
{
|
||||
if (!IsPivotNode(parent->mName))
|
||||
{
|
||||
if (boneAnimations.find(parent->mName.C_Str()) == boneAnimations.end() &&
|
||||
parentFillerAnimations.find(parent->mName.C_Str()) == parentFillerAnimations.end())
|
||||
{
|
||||
// Create 1 key for each type that just copies the current transform
|
||||
ConsolidatedNodeAnim emptyAnimation;
|
||||
aiMatrix4x4 globalTransform = GetConcatenatedLocalTransform(parent);
|
||||
|
||||
aiVector3D position, scale;
|
||||
aiQuaternion rotation;
|
||||
|
||||
globalTransform.Decompose(scale, rotation, position);
|
||||
|
||||
emptyAnimation.mNumRotationKeys = emptyAnimation.mNumPositionKeys = emptyAnimation.mNumScalingKeys = 1;
|
||||
|
||||
emptyAnimation.m_ownedPositionKeys.emplace_back(0, position);
|
||||
emptyAnimation.mPositionKeys = emptyAnimation.m_ownedPositionKeys.data();
|
||||
|
||||
emptyAnimation.m_ownedRotationKeys.emplace_back(0, rotation);
|
||||
emptyAnimation.mRotationKeys = emptyAnimation.m_ownedRotationKeys.data();
|
||||
|
||||
emptyAnimation.m_ownedScalingKeys.emplace_back(0, scale);
|
||||
emptyAnimation.mScalingKeys = emptyAnimation.m_ownedScalingKeys.data();
|
||||
|
||||
parentFillerAnimations.insert(
|
||||
AZStd::make_pair(parent->mName.C_Str(), AZStd::make_pair(anim.second.first, AZStd::move(emptyAnimation))));
|
||||
}
|
||||
}
|
||||
|
||||
parent = parent->mParent;
|
||||
}
|
||||
}
|
||||
|
||||
boneAnimations.insert(AZStd::make_move_iterator(parentFillerAnimations.begin()), AZStd::make_move_iterator(parentFillerAnimations.end()));
|
||||
|
||||
auto animItr = boneAnimations.equal_range(currentNode->mName.C_Str());
|
||||
|
||||
if (animItr.first == animItr.second)
|
||||
{
|
||||
return combinedAnimationResult.GetResult();
|
||||
}
|
||||
|
||||
bool onlyOne = false;
|
||||
|
||||
for (auto it = animItr.first; it != animItr.second; ++it)
|
||||
{
|
||||
if (onlyOne)
|
||||
{
|
||||
AZ_Error("AnimationImporter", false, "Bone %s has multiple animations. Only 1 animation per bone is supported", currentNode->mName.C_Str());
|
||||
break;
|
||||
}
|
||||
|
||||
const aiAnimation* animation = it->second.first;
|
||||
const ConsolidatedNodeAnim* anim = &it->second.second;
|
||||
|
||||
// We don't currently handle having a different number of keys, with 1 exception:
|
||||
// 1 key is essentially a constant so we do handle that case
|
||||
if ((anim->mNumPositionKeys != anim->mNumRotationKeys && anim->mNumPositionKeys > 1 && anim->mNumRotationKeys > 1) ||
|
||||
(anim->mNumPositionKeys != anim->mNumScalingKeys && anim->mNumPositionKeys > 1 && anim->mNumScalingKeys > 1) ||
|
||||
(anim->mNumRotationKeys != anim->mNumScalingKeys && anim->mNumRotationKeys > 1 && anim->mNumScalingKeys > 1))
|
||||
{
|
||||
AZ_Error("AnimationImporter", false, "Bone Animation with different number of position (%d)/rotation (%d)/scaling (%d) keys not supported",
|
||||
anim->mNumPositionKeys, anim->mNumRotationKeys, anim->mNumScalingKeys);
|
||||
return Events::ProcessingResult::Failure;
|
||||
}
|
||||
|
||||
unsigned numAnimationKeys = anim->mNumPositionKeys;
|
||||
|
||||
if (numAnimationKeys <= 1)
|
||||
{
|
||||
numAnimationKeys = AZStd::GetMax(anim->mNumRotationKeys, anim->mNumScalingKeys);
|
||||
}
|
||||
|
||||
auto sampleKeyFrame = [](const auto& keys, unsigned numKeys, double time)
|
||||
{
|
||||
AZ_Error("AnimationImporter", numKeys > 0, "Animation key set must have at least 1 key");
|
||||
|
||||
if (numKeys == 1)
|
||||
{
|
||||
return keys[0].mValue;
|
||||
}
|
||||
|
||||
auto returnValue = keys[0].mValue;
|
||||
|
||||
for (unsigned keyIndex = 0; keyIndex < numKeys; ++keyIndex)
|
||||
{
|
||||
const auto& key = keys[keyIndex];
|
||||
|
||||
// We want to return the key that exactly matches the time if possible, otherwise we'll keep track of the previous time
|
||||
// If we don't find an exact match and end up going past the desired time (or run out of keyframes) then we return the previous key
|
||||
if (key.mTime < time)
|
||||
{
|
||||
returnValue = key.mValue;
|
||||
}
|
||||
else if (key.mTime == time)
|
||||
{
|
||||
return key.mValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
return returnValue;
|
||||
}
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
};
|
||||
|
||||
AZStd::shared_ptr<SceneData::GraphData::AnimationData> createdAnimationData =
|
||||
AZStd::make_shared<SceneData::GraphData::AnimationData>();
|
||||
createdAnimationData->ReserveKeyFrames(animation->mDuration + 1); // +1 because we start at 0 and the last keyframe is at mDuration instead of mDuration-1
|
||||
createdAnimationData->SetTimeStepBetweenFrames(1.0 / animation->mTicksPerSecond);
|
||||
|
||||
for (unsigned time = 0; time <= animation->mDuration; ++time)
|
||||
{
|
||||
auto scale = sampleKeyFrame(anim->mScalingKeys, anim->mNumScalingKeys, time);
|
||||
auto position = sampleKeyFrame(anim->mPositionKeys, anim->mNumPositionKeys, time);
|
||||
auto rotation = sampleKeyFrame(anim->mRotationKeys, anim->mNumRotationKeys, time);
|
||||
|
||||
aiMatrix4x4 transform(scale, rotation, position);
|
||||
|
||||
DataTypes::MatrixType animTransform = AssImpSDKWrapper::AssImpTypeConverter::ToTransform(transform);
|
||||
|
||||
context.m_sourceSceneSystem.SwapTransformForUpAxis(animTransform);
|
||||
context.m_sourceSceneSystem.ConvertBoneUnit(animTransform);
|
||||
|
||||
createdAnimationData->AddKeyFrame(animTransform);
|
||||
}
|
||||
|
||||
Containers::SceneGraph::NodeIndex addNode = context.m_scene.GetGraph().AddChild(
|
||||
context.m_currentGraphPosition, nodeName.c_str(), AZStd::move(createdAnimationData));
|
||||
context.m_scene.GetGraph().MakeEndPoint(addNode);
|
||||
|
||||
onlyOne = true;
|
||||
}
|
||||
|
||||
combinedAnimationResult += Events::ProcessingResult::Success;
|
||||
return combinedAnimationResult.GetResult();
|
||||
}
|
||||
|
||||
Events::ProcessingResult AssImpAnimationImporter::ImportBlendShapeAnimation(
|
||||
AssImpSceneNodeAppendedContext& context,
|
||||
const aiAnimation* animation,
|
||||
const aiMeshMorphAnim* meshMorphAnim,
|
||||
const aiMesh* mesh)
|
||||
{
|
||||
if (meshMorphAnim->mNumKeys == 0)
|
||||
{
|
||||
return Events::ProcessingResult::Ignored;
|
||||
}
|
||||
Events::ProcessingResultCombiner combinedAnimationResult;
|
||||
aiNode* currentNode = context.m_sourceNode.GetAssImpNode();
|
||||
|
||||
// In:
|
||||
// Key index
|
||||
// Time
|
||||
// Values in AssImp, Channel in FBX SDK
|
||||
// Weights in AssImp, Values in FBX SDK
|
||||
// Num values & weights
|
||||
|
||||
// Out:
|
||||
// One BlendShapeAnimationData per value (Channel in FBX SDK) index
|
||||
// SetTimeStepBetweenFrames set on the animation data
|
||||
// Keyframes. Weights (Values in FBX SDK) per key time.
|
||||
// Keyframes generated for every single frame of the animation.
|
||||
|
||||
// Helper class to store key data, when translating from AssImp layout to the engine's scene format.
|
||||
struct KeyData
|
||||
{
|
||||
KeyData(float weight, float time) :
|
||||
m_weight(weight),
|
||||
m_time(time)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool operator<(const KeyData& other) const
|
||||
{
|
||||
return m_time < other.m_time;
|
||||
}
|
||||
|
||||
// Naming in the previous SDK (FBX SDK) and in the engine's scene format
|
||||
// doesn't match AssImp's naming convention.
|
||||
// weight here is the AssImp's name for the data, it was named value in FBX SDK.
|
||||
float m_weight = 0;
|
||||
float m_time = 0;
|
||||
};
|
||||
typedef AZStd::map<int, AZStd::vector<KeyData>> ValueToKeyDataMap;
|
||||
ValueToKeyDataMap valueToKeyDataMap;
|
||||
|
||||
for (int keyIdx = 0; keyIdx < meshMorphAnim->mNumKeys; keyIdx++)
|
||||
{
|
||||
aiMeshMorphKey& key = meshMorphAnim->mKeys[keyIdx];
|
||||
for (int valIdx = 0; valIdx < key.mNumValuesAndWeights; ++valIdx)
|
||||
{
|
||||
int currentValue = key.mValues[valIdx];
|
||||
KeyData thisKey(key.mWeights[valIdx], key.mTime);
|
||||
valueToKeyDataMap[currentValue].insert(
|
||||
AZStd::upper_bound(valueToKeyDataMap[currentValue].begin(), valueToKeyDataMap[currentValue].end(),thisKey),
|
||||
thisKey);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& [meshIdx, keys] : valueToKeyDataMap)
|
||||
{
|
||||
AZStd::shared_ptr<SceneData::GraphData::BlendShapeAnimationData> morphAnimNode =
|
||||
AZStd::make_shared<SceneData::GraphData::BlendShapeAnimationData>();
|
||||
morphAnimNode->ReserveKeyFrames(animation->mDuration + 1);
|
||||
morphAnimNode->SetTimeStepBetweenFrames(1.0 / animation->mTicksPerSecond);
|
||||
|
||||
aiAnimMesh* aiAnimMesh = mesh->mAnimMeshes[meshIdx];
|
||||
AZStd::string_view nodeName(aiAnimMesh->mName.C_Str());
|
||||
|
||||
const unsigned maxKeys = keys.size();
|
||||
unsigned keyIdx = 0;
|
||||
for (unsigned time = 0; time <= animation->mDuration; ++time)
|
||||
{
|
||||
if (keyIdx < maxKeys - 1 && time >= keys[keyIdx+1].m_time)
|
||||
{
|
||||
++keyIdx;
|
||||
}
|
||||
float weight_value = keys[keyIdx].m_weight;
|
||||
if (keyIdx < maxKeys - 1)
|
||||
{
|
||||
float nextWeight = keys[keyIdx+1].m_weight;
|
||||
float normalizedTimeBetweenFrames = 0;
|
||||
|
||||
if (keys[keyIdx + 1].m_time != keys[keyIdx].m_time)
|
||||
{
|
||||
normalizedTimeBetweenFrames =
|
||||
(time - keys[keyIdx].m_time) / (keys[keyIdx + 1].m_time - keys[keyIdx].m_time);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Warning("AnimationImporter", false,
|
||||
"Morph target mesh %s has keys with duplicate time, at indices %d and %d. The second will be ignored.",
|
||||
nodeName.data(),
|
||||
keyIdx,
|
||||
keyIdx+1);
|
||||
}
|
||||
|
||||
// AssImp and FBX both only support linear interpolation for blend shapes.
|
||||
weight_value = AZ::Lerp(weight_value, nextWeight, normalizedTimeBetweenFrames);
|
||||
}
|
||||
morphAnimNode->AddKeyFrame(weight_value);
|
||||
}
|
||||
|
||||
|
||||
const size_t dotIndex = nodeName.find_last_of('.');
|
||||
nodeName = nodeName.substr(dotIndex + 1);
|
||||
|
||||
morphAnimNode->SetBlendShapeName(nodeName.data());
|
||||
|
||||
AZStd::string animNodeName(AZStd::string::format("%s_%s", s_animationNodeName, nodeName.data()));
|
||||
Containers::SceneGraph::NodeIndex addNode = context.m_scene.GetGraph().AddChild(
|
||||
context.m_currentGraphPosition, animNodeName.c_str(), AZStd::move(morphAnimNode));
|
||||
context.m_scene.GetGraph().MakeEndPoint(addNode);
|
||||
|
||||
}
|
||||
|
||||
return Events::ProcessingResult::Success;
|
||||
}
|
||||
|
||||
} // namespace FbxSceneBuilder
|
||||
} // namespace SceneAPI
|
||||
} // namespace AZ
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <SceneAPI/FbxSceneBuilder/ImportContexts/FbxImportContexts.h>
|
||||
#include <SceneAPI/FbxSDKWrapper/FbxTimeWrapper.h>
|
||||
#include <SceneAPI/SceneCore/Components/LoadingComponent.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/ImportContexts/AssImpImportContexts.h>
|
||||
|
||||
struct aiAnimation;
|
||||
struct aiMesh;
|
||||
struct aiMeshMorphAnim;
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace SceneAPI
|
||||
{
|
||||
namespace FbxSceneBuilder
|
||||
{
|
||||
class AssImpAnimationImporter
|
||||
: public SceneCore::LoadingComponent
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(AssImpAnimationImporter, "{93b3f4e3-6fcd-42b9-a74e-5923f76d25c7}", SceneCore::LoadingComponent);
|
||||
|
||||
AssImpAnimationImporter();
|
||||
~AssImpAnimationImporter() override = default;
|
||||
|
||||
static void Reflect(ReflectContext* context);
|
||||
|
||||
Events::ProcessingResult ImportAnimation(AssImpSceneNodeAppendedContext& context);
|
||||
Events::ProcessingResult ImportBlendShapeAnimation(
|
||||
AssImpSceneNodeAppendedContext& context,
|
||||
const aiAnimation* animation,
|
||||
const aiMeshMorphAnim* meshMorphAnim,
|
||||
const aiMesh* mesh);
|
||||
|
||||
protected:
|
||||
static const char* s_animationNodeName;
|
||||
static const FbxSDKWrapper::FbxTimeWrapper::TimeMode s_defaultTimeMode;
|
||||
};
|
||||
} // namespace FbxSceneBuilder
|
||||
} // namespace SceneAPI
|
||||
} // namespace AZ
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <AzToolsFramework/Debug/TraceContext.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpBitangentStreamImporter.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/FbxImporterUtilities.h>
|
||||
#include <SceneAPI/SceneData/GraphData/MeshVertexBitangentData.h>
|
||||
#include <SceneAPI/SDKWrapper/AssImpNodeWrapper.h>
|
||||
#include <SceneAPI/SDKWrapper/AssImpSceneWrapper.h>
|
||||
#include <SceneAPI/SDKWrapper/AssImpTypeConverter.h>
|
||||
#include <SceneAPI/SceneData/GraphData/MeshData.h>
|
||||
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/mesh.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace SceneAPI
|
||||
{
|
||||
namespace FbxSceneBuilder
|
||||
{
|
||||
const char* AssImpBitangentStreamImporter::m_defaultNodeName = "Bitangent";
|
||||
|
||||
AssImpBitangentStreamImporter::AssImpBitangentStreamImporter()
|
||||
{
|
||||
BindToCall(&AssImpBitangentStreamImporter::ImportBitangentStreams);
|
||||
}
|
||||
|
||||
void AssImpBitangentStreamImporter::Reflect(ReflectContext* context)
|
||||
{
|
||||
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<AssImpBitangentStreamImporter, SceneCore::LoadingComponent>()->Version(1);
|
||||
}
|
||||
}
|
||||
|
||||
Events::ProcessingResult AssImpBitangentStreamImporter::ImportBitangentStreams(AssImpSceneNodeAppendedContext& context)
|
||||
{
|
||||
AZ_TraceContext("Importer", m_defaultNodeName);
|
||||
if (!context.m_sourceNode.ContainsMesh())
|
||||
{
|
||||
return Events::ProcessingResult::Ignored;
|
||||
}
|
||||
aiNode* currentNode = context.m_sourceNode.GetAssImpNode();
|
||||
const aiScene* scene = context.m_sourceScene.GetAssImpScene();
|
||||
|
||||
AZStd::shared_ptr<DataTypes::IGraphObject> parentData =
|
||||
context.m_scene.GetGraph().GetNodeContent(context.m_currentGraphPosition);
|
||||
if (!parentData || !parentData->RTTI_IsTypeOf(SceneData::GraphData::MeshData::TYPEINFO_Uuid()))
|
||||
{
|
||||
AZ_Error(Utilities::ErrorWindow, false,
|
||||
"Tried to construct bitangent stream attribute for invalid or non-mesh parent data");
|
||||
return Events::ProcessingResult::Failure;
|
||||
}
|
||||
const SceneData::GraphData::MeshData* const parentMeshData = azrtti_cast<SceneData::GraphData::MeshData*>(parentData.get());
|
||||
size_t vertexCount = parentMeshData->GetVertexCount();
|
||||
|
||||
int sdkMeshIndex = parentMeshData->GetSdkMeshIndex();
|
||||
if (sdkMeshIndex < 0 || sdkMeshIndex >= currentNode->mNumMeshes)
|
||||
{
|
||||
AZ_Error(Utilities::ErrorWindow, false,
|
||||
"Tried to construct bitangent stream attribute for invalid or non-mesh parent data, mesh index is invalid");
|
||||
return Events::ProcessingResult::Failure;
|
||||
}
|
||||
|
||||
aiMesh* mesh = scene->mMeshes[currentNode->mMeshes[sdkMeshIndex]];
|
||||
|
||||
if (!mesh->HasTangentsAndBitangents())
|
||||
{
|
||||
return Events::ProcessingResult::Ignored;
|
||||
}
|
||||
|
||||
AZStd::shared_ptr<SceneData::GraphData::MeshVertexBitangentData> bitangentStream =
|
||||
AZStd::make_shared<AZ::SceneData::GraphData::MeshVertexBitangentData>();
|
||||
|
||||
// AssImp only has one bitangentStream per mesh.
|
||||
bitangentStream->SetBitangentSetIndex(0);
|
||||
|
||||
bitangentStream->SetTangentSpace(AZ::SceneAPI::DataTypes::TangentSpace::FromFbx);
|
||||
bitangentStream->ReserveContainerSpace(vertexCount);
|
||||
|
||||
for (int v = 0; v < mesh->mNumVertices; ++v)
|
||||
{
|
||||
const Vector3 bitangent(
|
||||
AssImpSDKWrapper::AssImpTypeConverter::ToVector3(mesh->mBitangents[v]));
|
||||
bitangentStream->AppendBitangent(bitangent);
|
||||
}
|
||||
|
||||
AZStd::string nodeName(AZStd::string::format("%s",m_defaultNodeName));
|
||||
Containers::SceneGraph::NodeIndex newIndex =
|
||||
context.m_scene.GetGraph().AddChild(context.m_currentGraphPosition, nodeName.c_str());
|
||||
|
||||
Events::ProcessingResult bitangentResults;
|
||||
AssImpSceneAttributeDataPopulatedContext dataPopulated(context, bitangentStream, newIndex, nodeName.c_str());
|
||||
bitangentResults = Events::Process(dataPopulated);
|
||||
|
||||
if (bitangentResults != Events::ProcessingResult::Failure)
|
||||
{
|
||||
bitangentResults = AddAttributeDataNodeWithContexts(dataPopulated);
|
||||
}
|
||||
|
||||
return bitangentResults;
|
||||
}
|
||||
|
||||
} // namespace FbxSceneBuilder
|
||||
} // namespace SceneAPI
|
||||
} // namespace AZ
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <SceneAPI/FbxSceneBuilder/ImportContexts/AssImpImportContexts.h>
|
||||
#include <SceneAPI/SceneCore/Components/LoadingComponent.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace SceneAPI
|
||||
{
|
||||
namespace FbxSceneBuilder
|
||||
{
|
||||
class AssImpBitangentStreamImporter : public SceneCore::LoadingComponent
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(AssImpBitangentStreamImporter, "{49FC818A-956F-43DA-BBAC-73198E0C5A1F}", SceneCore::LoadingComponent);
|
||||
|
||||
AssImpBitangentStreamImporter();
|
||||
~AssImpBitangentStreamImporter() override = default;
|
||||
|
||||
static void Reflect(ReflectContext* context);
|
||||
|
||||
Events::ProcessingResult ImportBitangentStreams(AssImpSceneNodeAppendedContext& context);
|
||||
|
||||
protected:
|
||||
static const char* m_defaultNodeName;
|
||||
};
|
||||
} // namespace FbxSceneBuilder
|
||||
} // namespace SceneAPI
|
||||
} // namespace AZ
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
#include <AzToolsFramework/Debug/TraceContext.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpBlendShapeImporter.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/Utilities/RenamedNodesMap.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/FbxImporterUtilities.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/FbxSceneSystem.h>
|
||||
#include <SceneAPI/SDKWrapper/AssImpNodeWrapper.h>
|
||||
#include <SceneAPI/SDKWrapper/AssImpSceneWrapper.h>
|
||||
#include <SceneAPI/SDKWrapper/AssImpTypeConverter.h>
|
||||
#include <SceneAPI/SceneCore/Utilities/Reporting.h>
|
||||
#include <SceneAPI/SceneData/GraphData/MeshData.h>
|
||||
#include <SceneAPI/SceneData/GraphData/SkinMeshData.h>
|
||||
#include <SceneAPI/SceneData/GraphData/BlendShapeData.h>
|
||||
#include <assimp/scene.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace SceneAPI
|
||||
{
|
||||
namespace FbxSceneBuilder
|
||||
{
|
||||
AssImpBlendShapeImporter::AssImpBlendShapeImporter()
|
||||
{
|
||||
BindToCall(&AssImpBlendShapeImporter::ImportBlendShapes);
|
||||
}
|
||||
|
||||
void AssImpBlendShapeImporter::Reflect(ReflectContext* context)
|
||||
{
|
||||
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<AssImpBlendShapeImporter, SceneCore::LoadingComponent>()->Version(1);
|
||||
}
|
||||
}
|
||||
|
||||
Events::ProcessingResult AssImpBlendShapeImporter::ImportBlendShapes(AssImpSceneNodeAppendedContext& context)
|
||||
{
|
||||
AZ_TraceContext("Importer", "Blend Shapes");
|
||||
int numMesh = context.m_sourceNode.GetAssImpNode()->mNumMeshes;
|
||||
bool animMeshExists = false;
|
||||
for (int idx = 0; idx < numMesh; idx++)
|
||||
{
|
||||
int meshId = context.m_sourceNode.GetAssImpNode()->mMeshes[idx];
|
||||
aiMesh* aiMesh = context.m_sourceScene.GetAssImpScene()->mMeshes[meshId];
|
||||
if (aiMesh->mNumAnimMeshes)
|
||||
{
|
||||
animMeshExists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!animMeshExists)
|
||||
{
|
||||
return Events::ProcessingResult::Ignored;
|
||||
}
|
||||
|
||||
Events::ProcessingResultCombiner combinedBlendShapeResult;
|
||||
|
||||
for (int meshIdx = 0; meshIdx < numMesh; meshIdx++)
|
||||
{
|
||||
int meshId = context.m_sourceNode.GetAssImpNode()->mMeshes[meshIdx];
|
||||
aiMesh* aiMesh = context.m_sourceScene.GetAssImpScene()->mMeshes[meshId];
|
||||
if (!aiMesh->mNumAnimMeshes)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int animIdx = 0; animIdx < aiMesh->mNumAnimMeshes; animIdx++)
|
||||
{
|
||||
AZStd::shared_ptr<SceneData::GraphData::BlendShapeData> blendShapeData =
|
||||
AZStd::make_shared<SceneData::GraphData::BlendShapeData>();
|
||||
|
||||
aiAnimMesh* aiAnimMesh = aiMesh->mAnimMeshes[animIdx];
|
||||
AZStd::string nodeName(aiAnimMesh->mName.C_Str());
|
||||
size_t dotIndex = nodeName.rfind('.');
|
||||
if (dotIndex != AZStd::string::npos)
|
||||
{
|
||||
nodeName.erase(0, dotIndex + 1);
|
||||
}
|
||||
RenamedNodesMap::SanitizeNodeName(nodeName, context.m_scene.GetGraph(), context.m_currentGraphPosition, "BlendShape");
|
||||
AZ_TraceContext("Blend shape name", nodeName);
|
||||
|
||||
int firstMeshVertexIndex = -1;
|
||||
int previousMeshVertexIndex = -1;
|
||||
|
||||
int verticesInMeshFace = 0;
|
||||
|
||||
for (int vertIdx = 0; vertIdx < aiAnimMesh->mNumVertices; ++vertIdx)
|
||||
{
|
||||
AZ::Vector3 vertex(AssImpSDKWrapper::AssImpTypeConverter::ToVector3(aiAnimMesh->mVertices[vertIdx]));
|
||||
|
||||
context.m_sourceSceneSystem.SwapVec3ForUpAxis(vertex);
|
||||
context.m_sourceSceneSystem.ConvertUnit(vertex);
|
||||
|
||||
|
||||
AZ::Vector3 normal;
|
||||
if (aiAnimMesh->HasNormals())
|
||||
{
|
||||
normal = AssImpSDKWrapper::AssImpTypeConverter::ToVector3(aiAnimMesh->mNormals[vertIdx]);
|
||||
context.m_sourceSceneSystem.SwapVec3ForUpAxis(normal);
|
||||
normal.NormalizeSafe();
|
||||
}
|
||||
blendShapeData->AddVertex(vertex, normal);
|
||||
blendShapeData->SetVertexIndexToControlPointIndexMap(vertIdx, vertIdx);
|
||||
}
|
||||
|
||||
// aiAnimMesh just has a list of positions for vertices. The face indices are on the original mesh.
|
||||
for (int faceIdx = 0; faceIdx < aiMesh->mNumFaces; ++faceIdx)
|
||||
{
|
||||
aiFace face = aiMesh->mFaces[faceIdx];
|
||||
DataTypes::IBlendShapeData::Face blendFace;
|
||||
if (face.mNumIndices != 3)
|
||||
{
|
||||
// AssImp should have triangulated everything, so if this happens then someone has
|
||||
// probably changed AssImp's import settings. The engine only supports triangles.
|
||||
AZ_Error(
|
||||
Utilities::ErrorWindow, false,
|
||||
"Mesh for node %s has a face with %d vertices, only 3 vertices are supported per face.",
|
||||
nodeName.c_str(),
|
||||
face.mNumIndices);
|
||||
continue;
|
||||
}
|
||||
for (int idx = 0; idx < face.mNumIndices; ++idx)
|
||||
{
|
||||
blendFace.vertexIndex[idx] = face.mIndices[idx];
|
||||
}
|
||||
|
||||
blendShapeData->AddFace(blendFace);
|
||||
}
|
||||
|
||||
// Report problem if no vertex or face converted to MeshData
|
||||
if (blendShapeData->GetVertexCount() <= 0 || blendShapeData->GetFaceCount() <= 0)
|
||||
{
|
||||
AZ_Error(Utilities::ErrorWindow, false, "Missing geometry data in blendshape node %s.", nodeName.c_str());
|
||||
return Events::ProcessingResult::Failure;
|
||||
}
|
||||
|
||||
Containers::SceneGraph::NodeIndex newIndex =
|
||||
context.m_scene.GetGraph().AddChild(context.m_currentGraphPosition, nodeName.c_str());
|
||||
|
||||
Events::ProcessingResult blendShapeResult;
|
||||
AssImpSceneAttributeDataPopulatedContext dataPopulated(context, blendShapeData, newIndex, nodeName);
|
||||
blendShapeResult = Events::Process(dataPopulated);
|
||||
|
||||
if (blendShapeResult != Events::ProcessingResult::Failure)
|
||||
{
|
||||
blendShapeResult = AddAttributeDataNodeWithContexts(dataPopulated);
|
||||
}
|
||||
combinedBlendShapeResult += blendShapeResult;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return combinedBlendShapeResult.GetResult();
|
||||
}
|
||||
} // namespace FbxSceneBuilder
|
||||
} // namespace SceneAPI
|
||||
} // namespace AZ
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <SceneAPI/FbxSceneBuilder/ImportContexts/AssImpImportContexts.h>
|
||||
#include <SceneAPI/SceneCore/Components/LoadingComponent.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace SceneAPI
|
||||
{
|
||||
namespace FbxSceneBuilder
|
||||
{
|
||||
class AssImpBlendShapeImporter
|
||||
: public SceneCore::LoadingComponent
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(AssImpBlendShapeImporter, "{B0F7174B-9863-4C03-BFB2-83BF29B1A2DD}", SceneCore::LoadingComponent);
|
||||
|
||||
AssImpBlendShapeImporter();
|
||||
~AssImpBlendShapeImporter() override = default;
|
||||
|
||||
static void Reflect(ReflectContext* context);
|
||||
|
||||
Events::ProcessingResult ImportBlendShapes(AssImpSceneNodeAppendedContext& context);
|
||||
};
|
||||
} // namespace FbxSceneBuilder
|
||||
} // namespace SceneAPI
|
||||
} // namespace AZ
|
||||
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
#include <AzToolsFramework/Debug/TraceContext.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/FbxSceneSystem.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpBoneImporter.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpImporterUtilities.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/FbxImporterUtilities.h>
|
||||
#include <SceneAPI/FbxSDKWrapper/FbxNodeWrapper.h>
|
||||
#include <SceneAPI/SceneCore/Containers/Scene.h>
|
||||
#include <SceneAPI/SceneData/GraphData/BoneData.h>
|
||||
#include <SceneAPI/SceneData/GraphData/RootBoneData.h>
|
||||
#include <SceneAPI/SDKWrapper/AssImpNodeWrapper.h>
|
||||
#include <SceneAPI/SDKWrapper/AssImpSceneWrapper.h>
|
||||
#include <SceneAPI/SDKWrapper/AssImpTypeConverter.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace SceneAPI
|
||||
{
|
||||
namespace FbxSceneBuilder
|
||||
{
|
||||
AssImpBoneImporter::AssImpBoneImporter()
|
||||
{
|
||||
BindToCall(&AssImpBoneImporter::ImportBone);
|
||||
}
|
||||
|
||||
void AssImpBoneImporter::Reflect(ReflectContext* context)
|
||||
{
|
||||
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<AssImpBoneImporter, SceneCore::LoadingComponent>()->Version(1);
|
||||
}
|
||||
}
|
||||
|
||||
void EnumBonesInNode(
|
||||
const aiScene* scene, const aiNode* node, AZStd::unordered_map<AZStd::string, aiNode*>& mainBoneList,
|
||||
AZStd::unordered_map<AZStd::string, aiBone*>& boneLookup)
|
||||
{
|
||||
/* From AssImp Documentation
|
||||
a) Create a map or a similar container to store which nodes are necessary for the skeleton. Pre-initialise it for all nodes with a "no".
|
||||
b) For each bone in the mesh:
|
||||
b1) Find the corresponding node in the scene's hierarchy by comparing their names.
|
||||
b2) Mark this node as "yes" in the necessityMap.
|
||||
b3) Mark all of its parents the same way until you 1) find the mesh's node or 2) the parent of the mesh's node.
|
||||
c) Recursively iterate over the node hierarchy
|
||||
c1) If the node is marked as necessary, copy it into the skeleton and check its children
|
||||
c2) If the node is marked as not necessary, skip it and do not iterate over its children.
|
||||
*/
|
||||
|
||||
for (unsigned meshIndex = 0; meshIndex < node->mNumMeshes; ++meshIndex)
|
||||
{
|
||||
aiMesh* mesh = scene->mMeshes[node->mMeshes[meshIndex]];
|
||||
|
||||
for (unsigned boneIndex = 0; boneIndex < mesh->mNumBones; ++boneIndex)
|
||||
{
|
||||
aiBone* bone = mesh->mBones[boneIndex];
|
||||
|
||||
aiNode* boneNode = scene->mRootNode->FindNode(bone->mName);
|
||||
aiNode* boneParent = boneNode->mParent;
|
||||
|
||||
mainBoneList[bone->mName.C_Str()] = boneNode;
|
||||
boneLookup[bone->mName.C_Str()] = bone;
|
||||
|
||||
while (boneParent && boneParent != node && boneParent != node->mParent && boneParent != scene->mRootNode)
|
||||
{
|
||||
mainBoneList[boneParent->mName.C_Str()] = boneParent;
|
||||
|
||||
boneParent = boneParent->mParent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EnumChildren(
|
||||
const aiScene* scene, const aiNode* node, AZStd::unordered_map<AZStd::string, aiNode*>& mainBoneList,
|
||||
AZStd::unordered_map<AZStd::string, aiBone*>& boneLookup)
|
||||
{
|
||||
EnumBonesInNode(scene, node, mainBoneList, boneLookup);
|
||||
|
||||
for (unsigned childIndex = 0; childIndex < node->mNumChildren; ++childIndex)
|
||||
{
|
||||
const aiNode* child = node->mChildren[childIndex];
|
||||
|
||||
EnumChildren(scene, child, mainBoneList, boneLookup);
|
||||
}
|
||||
}
|
||||
|
||||
Events::ProcessingResult AssImpBoneImporter::ImportBone(AssImpNodeEncounteredContext& context)
|
||||
{
|
||||
AZ_TraceContext("Importer", "Bone");
|
||||
|
||||
aiNode* currentNode = context.m_sourceNode.GetAssImpNode();
|
||||
const aiScene* scene = context.m_sourceScene.GetAssImpScene();
|
||||
|
||||
if (IsPivotNode(currentNode->mName))
|
||||
{
|
||||
return Events::ProcessingResult::Ignored;
|
||||
}
|
||||
|
||||
bool isBone = false;
|
||||
|
||||
if (NodeParentIsOfType(context.m_scene.GetGraph(), context.m_currentGraphPosition, DataTypes::IBoneData::TYPEINFO_Uuid()))
|
||||
{
|
||||
isBone = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
AZStd::unordered_map<AZStd::string, aiNode*> mainBoneList;
|
||||
AZStd::unordered_map<AZStd::string, aiBone*> boneLookup;
|
||||
EnumChildren(scene, scene->mRootNode, mainBoneList, boneLookup);
|
||||
|
||||
if (mainBoneList.find(currentNode->mName.C_Str()) != mainBoneList.end())
|
||||
{
|
||||
isBone = true;
|
||||
}
|
||||
|
||||
// If we have an animation, the bones will be listed in there
|
||||
if (!isBone)
|
||||
{
|
||||
for(unsigned animIndex = 0; animIndex < scene->mNumAnimations; ++animIndex)
|
||||
{
|
||||
aiAnimation* animation = scene->mAnimations[animIndex];
|
||||
|
||||
for (unsigned channelIndex = 0; channelIndex < animation->mNumChannels; ++channelIndex)
|
||||
{
|
||||
aiNodeAnim* nodeAnim = animation->mChannels[channelIndex];
|
||||
|
||||
if (nodeAnim->mNodeName == currentNode->mName)
|
||||
{
|
||||
isBone = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isBone)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!isBone)
|
||||
{
|
||||
return Events::ProcessingResult::Ignored;
|
||||
}
|
||||
|
||||
// If the current scene node (our eventual parent) contains bone data, we are not a root bone
|
||||
AZStd::shared_ptr<SceneData::GraphData::BoneData> createdBoneData;
|
||||
|
||||
if (NodeHasAncestorOfType(
|
||||
context.m_scene.GetGraph(), context.m_currentGraphPosition, DataTypes::IBoneData::TYPEINFO_Uuid()))
|
||||
{
|
||||
createdBoneData = AZStd::make_shared<SceneData::GraphData::BoneData>();
|
||||
}
|
||||
else
|
||||
{
|
||||
createdBoneData = AZStd::make_shared<SceneData::GraphData::RootBoneData>();
|
||||
}
|
||||
|
||||
aiMatrix4x4 transform = currentNode->mTransformation;
|
||||
aiNode* parent = currentNode->mParent;
|
||||
|
||||
while (parent)
|
||||
{
|
||||
transform = parent->mTransformation * transform;
|
||||
parent = parent->mParent;
|
||||
}
|
||||
|
||||
SceneAPI::DataTypes::MatrixType globalTransform = AssImpSDKWrapper::AssImpTypeConverter::ToTransform(transform);
|
||||
|
||||
context.m_sourceSceneSystem.SwapTransformForUpAxis(globalTransform);
|
||||
context.m_sourceSceneSystem.ConvertBoneUnit(globalTransform);
|
||||
|
||||
createdBoneData->SetWorldTransform(globalTransform);
|
||||
|
||||
context.m_createdData.push_back(AZStd::move(createdBoneData));
|
||||
|
||||
return Events::ProcessingResult::Success;
|
||||
}
|
||||
} // namespace FbxSceneBuilder
|
||||
} // namespace SceneAPI
|
||||
} // namespace AZ
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <SceneAPI/FbxSceneBuilder/ImportContexts/AssImpImportContexts.h>
|
||||
#include <SceneAPI/SceneCore/Components/LoadingComponent.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace SceneAPI
|
||||
{
|
||||
namespace FbxSceneBuilder
|
||||
{
|
||||
class AssImpBoneImporter
|
||||
: public SceneCore::LoadingComponent
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(AssImpBoneImporter, "{E7A62DE7-B660-4920-BF91-32738175D5A7}", SceneCore::LoadingComponent);
|
||||
|
||||
AssImpBoneImporter();
|
||||
~AssImpBoneImporter() override = default;
|
||||
|
||||
static void Reflect(ReflectContext* context);
|
||||
|
||||
Events::ProcessingResult ImportBone(AssImpNodeEncounteredContext& context);
|
||||
};
|
||||
} // namespace FbxSceneBuilder
|
||||
} // namespace SceneAPI
|
||||
} // namespace AZ
|
||||
@@ -58,11 +58,10 @@ namespace AZ
|
||||
|
||||
AZStd::shared_ptr<DataTypes::IGraphObject> parentData =
|
||||
context.m_scene.GetGraph().GetNodeContent(context.m_currentGraphPosition);
|
||||
AZ_Assert(
|
||||
parentData && parentData->RTTI_IsTypeOf(SceneData::GraphData::MeshData::TYPEINFO_Uuid()),
|
||||
"Tried to construct color stream attribute for invalid or non-mesh parent data");
|
||||
if (!parentData || !parentData->RTTI_IsTypeOf(SceneData::GraphData::MeshData::TYPEINFO_Uuid()))
|
||||
{
|
||||
AZ_Error(Utilities::ErrorWindow, false,
|
||||
"Tried to construct color stream attribute for invalid or non-mesh parent data");
|
||||
return Events::ProcessingResult::Failure;
|
||||
}
|
||||
const SceneData::GraphData::MeshData* const parentMeshData = azrtti_cast<SceneData::GraphData::MeshData*>(parentData.get());
|
||||
@@ -71,9 +70,7 @@ namespace AZ
|
||||
int sdkMeshIndex = parentMeshData->GetSdkMeshIndex();
|
||||
if (sdkMeshIndex < 0)
|
||||
{
|
||||
AZ_Error(
|
||||
Utilities::ErrorWindow,
|
||||
false,
|
||||
AZ_Error(Utilities::ErrorWindow, false,
|
||||
"Tried to construct color stream attribute for invalid or non-mesh parent data, mesh index is missing");
|
||||
return Events::ProcessingResult::Failure;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpImporterUtilities.h>
|
||||
|
||||
#include <AzCore/Debug/Trace.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
|
||||
#include <assimp/scene.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace SceneAPI
|
||||
{
|
||||
namespace FbxSceneBuilder
|
||||
{
|
||||
bool IsSkinnedMesh(const aiNode& node, const aiScene& scene)
|
||||
{
|
||||
unsigned boneCount = 0;
|
||||
|
||||
for (unsigned mesh = 0; mesh < node.mNumMeshes; ++mesh)
|
||||
{
|
||||
if (scene.mMeshes[node.mMeshes[mesh]]->HasBones())
|
||||
{
|
||||
++boneCount;
|
||||
}
|
||||
}
|
||||
|
||||
if (boneCount > 1 && boneCount != node.mNumMeshes)
|
||||
{
|
||||
AZ_Error("AssImpImporterUtilities", false, "Node has %d meshes but only %d are skinned. "
|
||||
"This is unexpected and may result in errors", node.mNumMeshes, boneCount);
|
||||
}
|
||||
|
||||
return boneCount > 0;
|
||||
}
|
||||
|
||||
bool IsPivotNode(const aiString& nodeName, size_t* pos)
|
||||
{
|
||||
AZStd::string_view name(nodeName.C_Str(), nodeName.length);
|
||||
|
||||
size_t myPos;
|
||||
|
||||
if (!pos)
|
||||
{
|
||||
pos = &myPos;
|
||||
}
|
||||
|
||||
*pos = AZ::StringFunc::Find(name, PivotNodeMarker);
|
||||
|
||||
return *pos != name.npos;
|
||||
}
|
||||
|
||||
void SplitPivotNodeName(const aiString& nodeName, size_t pivotPos, AZStd::string_view& baseNodeName, AZStd::string_view& pivotType)
|
||||
{
|
||||
AZStd::string_view nodeNameView(nodeName.data, nodeName.length);
|
||||
baseNodeName = AZStd::string_view(nodeNameView.substr(0, pivotPos));
|
||||
pivotType = AZStd::string_view(nodeNameView.substr(pivotPos + sizeof PivotNodeMarker - 1));
|
||||
}
|
||||
|
||||
aiMatrix4x4 GetConcatenatedLocalTransform(const aiNode* currentNode)
|
||||
{
|
||||
aiNode* parent = currentNode->mParent;
|
||||
aiMatrix4x4 combinedTransform = currentNode->mTransformation;
|
||||
|
||||
while (parent)
|
||||
{
|
||||
size_t pos;
|
||||
|
||||
if (IsPivotNode(parent->mName, &pos))
|
||||
{
|
||||
combinedTransform = parent->mTransformation * combinedTransform;
|
||||
parent = parent->mParent;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return combinedTransform;
|
||||
}
|
||||
} // namespace FbxSceneBuilder
|
||||
} // namespace SceneAPI
|
||||
} // namespace AZ
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <assimp/matrix4x4.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
struct aiNode;
|
||||
struct aiScene;
|
||||
struct aiString;
|
||||
|
||||
|
||||
namespace AZ::SceneAPI::FbxSceneBuilder
|
||||
{
|
||||
inline constexpr char PivotNodeMarker[] = "_$AssimpFbx$_";
|
||||
|
||||
bool IsSkinnedMesh(const aiNode& node, const aiScene& scene);
|
||||
|
||||
// Checks if a node name is a pivot node and optionally returns the position in the name of the pivot marker (for splitting out the parts later)
|
||||
bool IsPivotNode(const aiString& nodeName, size_t* pos = nullptr);
|
||||
|
||||
// Returns the bone name and type of a pivot node
|
||||
void SplitPivotNodeName(const aiString& nodeName, size_t pivotPos, AZStd::string_view& baseNodeName, AZStd::string_view& pivotType);
|
||||
|
||||
// Gets the entire, combined local transform for a node taking pivot nodes into account. When pivot nodes are not used, this just returns the node's transform
|
||||
aiMatrix4x4 GetConcatenatedLocalTransform(const aiNode* currentNode);
|
||||
} // namespace AZ
|
||||
|
||||
@@ -11,9 +11,11 @@
|
||||
*/
|
||||
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpMaterialImporter.h>
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
#include <AzToolsFramework/Debug/TraceContext.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/FbxImporterUtilities.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/Utilities/RenamedNodesMap.h>
|
||||
@@ -54,6 +56,8 @@ namespace AZ
|
||||
}
|
||||
|
||||
Events::ProcessingResultCombiner combinedMaterialImportResults;
|
||||
|
||||
AZStd::unordered_map<int, AZStd::shared_ptr<SceneData::GraphData::MaterialData>> materialMap;
|
||||
for (int idx = 0; idx < context.m_sourceNode.m_assImpNode->mNumMeshes; ++idx)
|
||||
{
|
||||
int meshIndex = context.m_sourceNode.m_assImpNode->mMeshes[idx];
|
||||
@@ -62,8 +66,6 @@ namespace AZ
|
||||
int materialIndex = assImpMesh->mMaterialIndex;
|
||||
AZ_TraceContext("Material Index", materialIndex);
|
||||
|
||||
AZStd::unordered_map<int, AZStd::shared_ptr<SceneData::GraphData::MaterialData>> materialMap;
|
||||
|
||||
auto matFound = materialMap.find(materialIndex);
|
||||
|
||||
AZStd::shared_ptr<SceneData::GraphData::MaterialData> material;
|
||||
@@ -82,19 +84,58 @@ namespace AZ
|
||||
|
||||
material->SetMaterialName(assImpMaterial->GetName());
|
||||
material->SetTexture(DataTypes::IMaterialData::TextureMapType::Diffuse,
|
||||
assImpMaterial->GetTextureFileName(SDKMaterial::MaterialWrapper::MaterialMapType::Diffuse).c_str());
|
||||
ResolveTexturePath(context.m_sourceScene.GetSceneFileName(),
|
||||
assImpMaterial->GetTextureFileName(SDKMaterial::MaterialWrapper::MaterialMapType::Diffuse)).c_str());
|
||||
material->SetTexture(DataTypes::IMaterialData::TextureMapType::Specular,
|
||||
assImpMaterial->GetTextureFileName(SDKMaterial::MaterialWrapper::MaterialMapType::Specular).c_str());
|
||||
ResolveTexturePath(context.m_sourceScene.GetSceneFileName(),
|
||||
assImpMaterial->GetTextureFileName(SDKMaterial::MaterialWrapper::MaterialMapType::Specular)).c_str());
|
||||
material->SetTexture(DataTypes::IMaterialData::TextureMapType::Bump,
|
||||
assImpMaterial->GetTextureFileName(SDKMaterial::MaterialWrapper::MaterialMapType::Bump).c_str());
|
||||
ResolveTexturePath(context.m_sourceScene.GetSceneFileName(),
|
||||
assImpMaterial->GetTextureFileName(SDKMaterial::MaterialWrapper::MaterialMapType::Bump)).c_str());
|
||||
material->SetTexture(DataTypes::IMaterialData::TextureMapType::Normal,
|
||||
assImpMaterial->GetTextureFileName(SDKMaterial::MaterialWrapper::MaterialMapType::Normal).c_str());
|
||||
ResolveTexturePath(context.m_sourceScene.GetSceneFileName(),
|
||||
assImpMaterial->GetTextureFileName(SDKMaterial::MaterialWrapper::MaterialMapType::Normal)).c_str());
|
||||
material->SetUniqueId(assImpMaterial->GetUniqueId());
|
||||
material->SetDiffuseColor(assImpMaterial->GetDiffuseColor());
|
||||
material->SetSpecularColor(assImpMaterial->GetSpecularColor());
|
||||
material->SetEmissiveColor(assImpMaterial->GetEmissiveColor());
|
||||
material->SetShininess(assImpMaterial->GetShininess());
|
||||
|
||||
material->SetUseColorMap(assImpMaterial->GetUseColorMap());
|
||||
material->SetBaseColor(assImpMaterial->GetBaseColor());
|
||||
|
||||
material->SetUseMetallicMap(assImpMaterial->GetUseMetallicMap());
|
||||
material->SetMetallicFactor(assImpMaterial->GetMetallicFactor());
|
||||
material->SetTexture(
|
||||
DataTypes::IMaterialData::TextureMapType::Metallic,
|
||||
ResolveTexturePath(context.m_sourceScene.GetSceneFileName(),
|
||||
assImpMaterial->GetTextureFileName(SDKMaterial::MaterialWrapper::MaterialMapType::Metallic).c_str()));
|
||||
|
||||
material->SetUseRoughnessMap(assImpMaterial->GetUseRoughnessMap());
|
||||
material->SetRoughnessFactor(assImpMaterial->GetRoughnessFactor());
|
||||
material->SetTexture(
|
||||
DataTypes::IMaterialData::TextureMapType::Roughness,
|
||||
ResolveTexturePath(context.m_sourceScene.GetSceneFileName(),
|
||||
assImpMaterial->GetTextureFileName(SDKMaterial::MaterialWrapper::MaterialMapType::Roughness).c_str()));
|
||||
|
||||
material->SetUseEmissiveMap(assImpMaterial->GetUseEmissiveMap());
|
||||
material->SetEmissiveIntensity(assImpMaterial->GetEmissiveIntensity());
|
||||
|
||||
material->SetUseAOMap(assImpMaterial->GetUseAOMap());
|
||||
material->SetTexture(
|
||||
DataTypes::IMaterialData::TextureMapType::AmbientOcclusion,
|
||||
ResolveTexturePath(context.m_sourceScene.GetSceneFileName(),
|
||||
assImpMaterial->GetTextureFileName(SDKMaterial::MaterialWrapper::MaterialMapType::AmbientOcclusion).c_str()));
|
||||
|
||||
material->SetTexture(
|
||||
DataTypes::IMaterialData::TextureMapType::Emissive,
|
||||
ResolveTexturePath(context.m_sourceScene.GetSceneFileName(),
|
||||
assImpMaterial->GetTextureFileName(SDKMaterial::MaterialWrapper::MaterialMapType::Emissive).c_str()));
|
||||
|
||||
material->SetTexture(
|
||||
DataTypes::IMaterialData::TextureMapType::BaseColor,
|
||||
ResolveTexturePath(context.m_sourceScene.GetSceneFileName(),
|
||||
assImpMaterial->GetTextureFileName(SDKMaterial::MaterialWrapper::MaterialMapType::BaseColor).c_str()));
|
||||
|
||||
AZ_Assert(material, "Failed to allocate scene material data.");
|
||||
if (!material)
|
||||
@@ -135,6 +176,39 @@ namespace AZ
|
||||
|
||||
return combinedMaterialImportResults.GetResult();
|
||||
}
|
||||
|
||||
AZStd::string AssImpMaterialImporter::ResolveTexturePath(const AZStd::string& sceneFilePath, const AZStd::string& textureFilePath) const
|
||||
{
|
||||
if (textureFilePath.empty())
|
||||
{
|
||||
return textureFilePath;
|
||||
}
|
||||
|
||||
|
||||
AZStd::string texturePathRelativeToScene;
|
||||
AZStd::string cleanedUpSceneFilePath(sceneFilePath);
|
||||
AZ::StringFunc::Path::StripFullName(cleanedUpSceneFilePath);
|
||||
AZ::StringFunc::Path::Join(cleanedUpSceneFilePath.c_str(), textureFilePath.c_str(), texturePathRelativeToScene);
|
||||
|
||||
// If the texture did start with marker to change directories upward, then it's relative to the FBX file,
|
||||
// and that path needs to be resolved. It can't be resolved later. This was handled internally by FBX SDK,
|
||||
// but is not handled by AssImp.
|
||||
if (textureFilePath.starts_with(".."))
|
||||
{
|
||||
// Not checking for the file existing because it may not be there yet.
|
||||
return texturePathRelativeToScene;
|
||||
}
|
||||
|
||||
// The engine only supports relative paths to scan folders.
|
||||
// FBX files may have paths to textures, relative to the FBX file. Check for those, first.
|
||||
if (AZ::IO::FileIOBase::GetInstance()->Exists(texturePathRelativeToScene.c_str()))
|
||||
{
|
||||
return texturePathRelativeToScene;
|
||||
}
|
||||
|
||||
|
||||
return textureFilePath;
|
||||
}
|
||||
} // namespace FbxSceneBuilder
|
||||
} // namespace SceneAPI
|
||||
} // namespace AZ
|
||||
|
||||
@@ -33,6 +33,9 @@ namespace AZ
|
||||
static void Reflect(ReflectContext* context);
|
||||
|
||||
Events::ProcessingResult ImportMaterials(AssImpSceneNodeAppendedContext& context);
|
||||
|
||||
private:
|
||||
AZStd::string ResolveTexturePath(const AZStd::string& sceneFilePath, const AZStd::string& textureFilePath) const;
|
||||
};
|
||||
} // namespace FbxSceneBuilder
|
||||
} // namespace SceneAPI
|
||||
|
||||
@@ -9,19 +9,17 @@
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpMeshImporter.h>
|
||||
#include <SceneAPI/SDKWrapper/AssImpNodeWrapper.h>
|
||||
#include <SceneAPI/SDKWrapper/AssImpSceneWrapper.h>
|
||||
|
||||
#include <assimp/scene.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <AzToolsFramework/Debug/TraceContext.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/FbxSceneSystem.h>
|
||||
#include <SceneAPI/SceneCore/Containers/Scene.h>
|
||||
#include <SceneAPI/SceneCore/Utilities/Reporting.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpImporterUtilities.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpMeshImporter.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/Utilities/AssImpMeshImporterUtilities.h>
|
||||
#include <SceneAPI/SceneData/GraphData/MeshData.h>
|
||||
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/mesh.h>
|
||||
#include <SceneAPI/SDKWrapper/AssImpNodeWrapper.h>
|
||||
#include <SceneAPI/SDKWrapper/AssImpSceneWrapper.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -46,80 +44,23 @@ namespace AZ
|
||||
Events::ProcessingResult AssImpMeshImporter::ImportMesh(AssImpNodeEncounteredContext& context)
|
||||
{
|
||||
AZ_TraceContext("Importer", "Mesh");
|
||||
if (!context.m_sourceNode.ContainsMesh())
|
||||
{
|
||||
return Events::ProcessingResult::Ignored;
|
||||
}
|
||||
|
||||
AZStd::unordered_map<int, int> assImpMatIndexToLYIndex;
|
||||
int lyMeshIndex = 0;
|
||||
|
||||
aiNode* currentNode = context.m_sourceNode.GetAssImpNode();
|
||||
const aiScene* scene = context.m_sourceScene.GetAssImpScene();
|
||||
|
||||
for (int m = 0; m < currentNode->mNumMeshes; ++m)
|
||||
if (!context.m_sourceNode.ContainsMesh() || IsSkinnedMesh(*currentNode, *scene))
|
||||
{
|
||||
AZStd::shared_ptr<SceneData::GraphData::MeshData> newMesh =
|
||||
AZStd::make_shared<SceneData::GraphData::MeshData>();
|
||||
|
||||
newMesh->SetUnitSizeInMeters(context.m_sourceSceneSystem.GetUnitSizeInMeters());
|
||||
newMesh->SetOriginalUnitSizeInMeters(context.m_sourceSceneSystem.GetOriginalUnitSizeInMeters());
|
||||
|
||||
newMesh->SetSdkMeshIndex(m);
|
||||
|
||||
aiMesh* mesh = scene->mMeshes[currentNode->mMeshes[m]];
|
||||
|
||||
// Lumberyard materials are created in order based on mesh references in the scene
|
||||
if (assImpMatIndexToLYIndex.find(mesh->mMaterialIndex) == assImpMatIndexToLYIndex.end())
|
||||
{
|
||||
assImpMatIndexToLYIndex.insert(AZStd::pair<int, int>(mesh->mMaterialIndex, lyMeshIndex++));
|
||||
}
|
||||
|
||||
for (int vertIdx = 0; vertIdx < mesh->mNumVertices; ++vertIdx)
|
||||
{
|
||||
AZ::Vector3 vertex(
|
||||
mesh->mVertices[vertIdx].x,
|
||||
mesh->mVertices[vertIdx].y,
|
||||
mesh->mVertices[vertIdx].z);
|
||||
|
||||
context.m_sourceSceneSystem.SwapVec3ForUpAxis(vertex);
|
||||
context.m_sourceSceneSystem.ConvertUnit(vertex);
|
||||
newMesh->AddPosition(vertex);
|
||||
|
||||
if (mesh->HasNormals())
|
||||
{
|
||||
AZ::Vector3 normal(
|
||||
mesh->mNormals[vertIdx].x,
|
||||
mesh->mNormals[vertIdx].y,
|
||||
mesh->mNormals[vertIdx].z);
|
||||
context.m_sourceSceneSystem.SwapVec3ForUpAxis(normal);
|
||||
normal.NormalizeSafe();
|
||||
newMesh->AddNormal(normal);
|
||||
}
|
||||
}
|
||||
|
||||
for (int faceIdx = 0; faceIdx < mesh->mNumFaces; ++faceIdx)
|
||||
{
|
||||
aiFace face = mesh->mFaces[faceIdx];
|
||||
AZ::SceneAPI::DataTypes::IMeshData::Face meshFace;
|
||||
if (face.mNumIndices != 3)
|
||||
{
|
||||
// AssImp should have triangulated everything, so if this happens then someone has
|
||||
// probably changed AssImp's import settings. The engine only supports triangles.
|
||||
AZ_Error(Utilities::ErrorWindow, false, "Mesh has a face with %d vertices, only 3 vertices are supported per face.");
|
||||
continue;
|
||||
}
|
||||
for (int idx = 0; idx < face.mNumIndices; ++idx)
|
||||
{
|
||||
meshFace.vertexIndex[idx] = face.mIndices[idx];
|
||||
}
|
||||
|
||||
newMesh->AddFace(meshFace, assImpMatIndexToLYIndex[mesh->mMaterialIndex]);
|
||||
}
|
||||
|
||||
context.m_createdData.push_back(std::move(newMesh));
|
||||
return Events::ProcessingResult::Ignored;
|
||||
}
|
||||
return Events::ProcessingResult::Success;
|
||||
|
||||
if (BuildSceneMeshFromAssImpMesh(currentNode, scene, context.m_sourceSceneSystem, context.m_createdData, [] {
|
||||
return AZStd::make_shared<SceneData::GraphData::MeshData>();
|
||||
}))
|
||||
{
|
||||
return Events::ProcessingResult::Success;
|
||||
}
|
||||
|
||||
return Events::ProcessingResult::Failure;
|
||||
}
|
||||
} // namespace FbxSceneBuilder
|
||||
} // namespace SceneAPI
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <assimp/scene.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <AzToolsFramework/Debug/TraceContext.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpImporterUtilities.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpSkinImporter.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/Utilities/AssImpMeshImporterUtilities.h>
|
||||
#include <SceneAPI/SceneData/GraphData/SkinMeshData.h>
|
||||
#include <SceneAPI/SDKWrapper/AssImpNodeWrapper.h>
|
||||
#include <SceneAPI/SDKWrapper/AssImpSceneWrapper.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace SceneAPI
|
||||
{
|
||||
namespace FbxSceneBuilder
|
||||
{
|
||||
AssImpSkinImporter::AssImpSkinImporter()
|
||||
{
|
||||
BindToCall(&AssImpSkinImporter::ImportSkin);
|
||||
}
|
||||
|
||||
void AssImpSkinImporter::Reflect(ReflectContext* context)
|
||||
{
|
||||
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<AssImpSkinImporter, SceneCore::LoadingComponent>()->Version(1);
|
||||
}
|
||||
}
|
||||
|
||||
Events::ProcessingResult AssImpSkinImporter::ImportSkin(AssImpNodeEncounteredContext& context)
|
||||
{
|
||||
AZ_TraceContext("Importer", "Skin");
|
||||
|
||||
aiNode* currentNode = context.m_sourceNode.GetAssImpNode();
|
||||
const aiScene* scene = context.m_sourceScene.GetAssImpScene();
|
||||
|
||||
if (!context.m_sourceNode.ContainsMesh() || !IsSkinnedMesh(*currentNode, *scene))
|
||||
{
|
||||
return Events::ProcessingResult::Ignored;
|
||||
}
|
||||
|
||||
if (BuildSceneMeshFromAssImpMesh(currentNode, scene, context.m_sourceSceneSystem, context.m_createdData, [] {
|
||||
return AZStd::make_shared<SceneData::GraphData::SkinMeshData>();
|
||||
}))
|
||||
{
|
||||
return Events::ProcessingResult::Success;
|
||||
}
|
||||
|
||||
return Events::ProcessingResult::Failure;
|
||||
}
|
||||
} // namespace FbxSceneBuilder
|
||||
} // namespace SceneAPI
|
||||
} // namespace AZ
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <SceneAPI/FbxSceneBuilder/ImportContexts/AssImpImportContexts.h>
|
||||
#include <SceneAPI/SceneCore/Components/LoadingComponent.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace SceneAPI
|
||||
{
|
||||
namespace FbxSceneBuilder
|
||||
{
|
||||
class AssImpSkinImporter
|
||||
: public SceneCore::LoadingComponent
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(AssImpSkinImporter, "{8FBCA725-C04E-42B7-9669-82DB3BB0901F}", SceneCore::LoadingComponent);
|
||||
|
||||
AssImpSkinImporter();
|
||||
~AssImpSkinImporter() override = default;
|
||||
|
||||
static void Reflect(ReflectContext* context);
|
||||
|
||||
Events::ProcessingResult ImportSkin(AssImpNodeEncounteredContext& context);
|
||||
};
|
||||
} // namespace FbxSceneBuilder
|
||||
} // namespace SceneAPI
|
||||
} // namespace AZ
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
#include <AzToolsFramework/Debug/TraceContext.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpSkinWeightsImporter.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/FbxImporterUtilities.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/Utilities/RenamedNodesMap.h>
|
||||
#include <SceneAPI/SceneCore/Events/ImportEventContext.h>
|
||||
#include <SceneAPI/SceneData/GraphData/SkinWeightData.h>
|
||||
#include <SceneAPI/SDKWrapper/AssImpNodeWrapper.h>
|
||||
#include <SceneAPI/SDKWrapper/AssImpSceneWrapper.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace SceneAPI
|
||||
{
|
||||
namespace FbxSceneBuilder
|
||||
{
|
||||
const AZStd::string AssImpSkinWeightsImporter::s_skinWeightName = "SkinWeight_";
|
||||
|
||||
AssImpSkinWeightsImporter::AssImpSkinWeightsImporter()
|
||||
{
|
||||
BindToCall(&AssImpSkinWeightsImporter::ImportSkinWeights);
|
||||
BindToCall(&AssImpSkinWeightsImporter::SetupNamedBoneLinks);
|
||||
}
|
||||
|
||||
void AssImpSkinWeightsImporter::Reflect(ReflectContext* context)
|
||||
{
|
||||
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<AssImpSkinWeightsImporter, SceneCore::LoadingComponent>()->Version(1);
|
||||
}
|
||||
}
|
||||
|
||||
Events::ProcessingResult AssImpSkinWeightsImporter::ImportSkinWeights(AssImpSceneNodeAppendedContext& context)
|
||||
{
|
||||
AZ_TraceContext("Importer", "Skin Weights");
|
||||
|
||||
aiNode* currentNode = context.m_sourceNode.GetAssImpNode();
|
||||
const aiScene* scene = context.m_sourceScene.GetAssImpScene();
|
||||
|
||||
if(currentNode->mNumMeshes <= 0)
|
||||
{
|
||||
return Events::ProcessingResult::Ignored;
|
||||
}
|
||||
|
||||
Events::ProcessingResultCombiner combinedSkinWeightsResult;
|
||||
|
||||
for(unsigned m = 0; m < currentNode->mNumMeshes; ++m)
|
||||
{
|
||||
auto mesh = scene->mMeshes[currentNode->mMeshes[m]];
|
||||
|
||||
for(unsigned b = 0; b < mesh->mNumBones; ++b)
|
||||
{
|
||||
auto bone = mesh->mBones[b];
|
||||
|
||||
if(bone->mNumWeights <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
AZStd::string skinWeightName = s_skinWeightName;
|
||||
skinWeightName += AZStd::to_string(b);
|
||||
RenamedNodesMap::SanitizeNodeName(skinWeightName, context.m_scene.GetGraph(), context.m_currentGraphPosition);
|
||||
|
||||
AZStd::shared_ptr<SceneData::GraphData::SkinWeightData> skinDeformer = BuildSkinWeightData(bone, mesh->mNumVertices);
|
||||
|
||||
Containers::SceneGraph::NodeIndex newIndex =
|
||||
context.m_scene.GetGraph().AddChild(context.m_currentGraphPosition, skinWeightName.c_str());
|
||||
|
||||
AZ_Error("SkinWeightsImporter", newIndex.IsValid(), "Failed to create SceneGraph node for attribute.");
|
||||
if (!newIndex.IsValid())
|
||||
{
|
||||
combinedSkinWeightsResult += Events::ProcessingResult::Failure;
|
||||
continue;
|
||||
}
|
||||
|
||||
Events::ProcessingResult skinWeightsResult;
|
||||
AssImpSceneAttributeDataPopulatedContext dataPopulated(context, skinDeformer, newIndex, skinWeightName);
|
||||
skinWeightsResult = Events::Process(dataPopulated);
|
||||
|
||||
if (skinWeightsResult != Events::ProcessingResult::Failure)
|
||||
{
|
||||
skinWeightsResult = AddAttributeDataNodeWithContexts(dataPopulated);
|
||||
}
|
||||
|
||||
combinedSkinWeightsResult += skinWeightsResult;
|
||||
}
|
||||
}
|
||||
|
||||
return combinedSkinWeightsResult.GetResult();
|
||||
}
|
||||
|
||||
AZStd::shared_ptr<SceneData::GraphData::SkinWeightData> AssImpSkinWeightsImporter::BuildSkinWeightData(aiBone* bone, unsigned numVertices)
|
||||
{
|
||||
AZStd::shared_ptr<SceneData::GraphData::SkinWeightData> skinWeightData =
|
||||
AZStd::make_shared<SceneData::GraphData::SkinWeightData>();
|
||||
|
||||
// Cache the new object and the link info for now so it can be resolved at a later point when all
|
||||
// names have been updated.
|
||||
Pending pending;
|
||||
pending.m_bone = bone;
|
||||
pending.m_numVertices = numVertices;
|
||||
pending.m_skinWeightData = skinWeightData;
|
||||
m_pendingSkinWeights.push_back(pending);
|
||||
|
||||
return skinWeightData;
|
||||
}
|
||||
|
||||
Events::ProcessingResult AssImpSkinWeightsImporter::SetupNamedBoneLinks(AssImpFinalizeSceneContext& /*context*/)
|
||||
{
|
||||
AZ_TraceContext("Importer", "Skin Weights");
|
||||
|
||||
for (auto& it : m_pendingSkinWeights)
|
||||
{
|
||||
it.m_skinWeightData->ResizeContainerSpace(it.m_numVertices);
|
||||
|
||||
AZStd::string boneName = it.m_bone->mName.C_Str();
|
||||
int boneId = it.m_skinWeightData->GetBoneId(boneName);
|
||||
|
||||
for(unsigned weight = 0; weight < it.m_bone->mNumWeights; ++weight)
|
||||
{
|
||||
DataTypes::ISkinWeightData::Link link;
|
||||
link.boneId = boneId;
|
||||
link.weight = it.m_bone->mWeights[weight].mWeight;
|
||||
|
||||
it.m_skinWeightData->AppendLink(it.m_bone->mWeights[weight].mVertexId, link);
|
||||
}
|
||||
}
|
||||
const auto result = m_pendingSkinWeights.empty() ? Events::ProcessingResult::Ignored : Events::ProcessingResult::Success;
|
||||
m_pendingSkinWeights.clear();
|
||||
return result;
|
||||
}
|
||||
} // namespace FbxSceneBuilder
|
||||
} // namespace SceneAPI
|
||||
} // namespace AZ
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <assimp/scene.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/ImportContexts/AssImpImportContexts.h>
|
||||
#include <SceneAPI/SceneCore/Components/LoadingComponent.h>
|
||||
#include <SceneAPI/SceneCore/DataTypes/GraphData/ISkinWeightData.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace FbxSDKWrapper
|
||||
{
|
||||
class FbxMeshWrapper;
|
||||
}
|
||||
|
||||
namespace SceneData
|
||||
{
|
||||
namespace GraphData
|
||||
{
|
||||
class SkinWeightData;
|
||||
}
|
||||
}
|
||||
|
||||
namespace SceneAPI
|
||||
{
|
||||
namespace Events
|
||||
{
|
||||
class PostImportEventContext;
|
||||
}
|
||||
|
||||
namespace FbxSceneBuilder
|
||||
{
|
||||
class AssImpSkinWeightsImporter
|
||||
: public SceneCore::LoadingComponent
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(AssImpSkinWeightsImporter, "{79B5E863-C155-473A-BC0D-B85F8D8303EB}", SceneCore::LoadingComponent);
|
||||
|
||||
AssImpSkinWeightsImporter();
|
||||
~AssImpSkinWeightsImporter() override = default;
|
||||
|
||||
static void Reflect(ReflectContext* context);
|
||||
|
||||
Events::ProcessingResult ImportSkinWeights(AssImpSceneNodeAppendedContext& context);
|
||||
Events::ProcessingResult SetupNamedBoneLinks(AssImpFinalizeSceneContext& context);
|
||||
|
||||
protected:
|
||||
struct Pending
|
||||
{
|
||||
aiBone* m_bone = nullptr;
|
||||
unsigned m_numVertices = 0;
|
||||
AZStd::shared_ptr<SceneData::GraphData::SkinWeightData> m_skinWeightData;
|
||||
};
|
||||
AZStd::shared_ptr<SceneData::GraphData::SkinWeightData> BuildSkinWeightData(aiBone* bone, unsigned numVertices);
|
||||
|
||||
//! List of skin weights that still need to be filled in. Setting the data for skin weights is
|
||||
//! delayed until after the tree has been fully constructed as bones are linked by name, but until
|
||||
//! the graph has been fully filled in, those names can change which would break the names recorded
|
||||
//! for the skin.
|
||||
AZStd::vector<Pending> m_pendingSkinWeights;
|
||||
|
||||
static const AZStd::string s_skinWeightName;
|
||||
};
|
||||
} // namespace FbxSceneBuilder
|
||||
} // namespace SceneAPI
|
||||
} // namespace AZ
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <AzToolsFramework/Debug/TraceContext.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpTangentStreamImporter.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/FbxImporterUtilities.h>
|
||||
#include <SceneAPI/SceneData/GraphData/MeshVertexTangentData.h>
|
||||
#include <SceneAPI/SDKWrapper/AssImpNodeWrapper.h>
|
||||
#include <SceneAPI/SDKWrapper/AssImpSceneWrapper.h>
|
||||
#include <SceneAPI/SDKWrapper/AssImpTypeConverter.h>
|
||||
#include <SceneAPI/SceneData/GraphData/MeshData.h>
|
||||
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/mesh.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace SceneAPI
|
||||
{
|
||||
namespace FbxSceneBuilder
|
||||
{
|
||||
const char* AssImpTangentStreamImporter::m_defaultNodeName = "Tangent";
|
||||
|
||||
AssImpTangentStreamImporter::AssImpTangentStreamImporter()
|
||||
{
|
||||
BindToCall(&AssImpTangentStreamImporter::ImportTangentStreams);
|
||||
}
|
||||
|
||||
void AssImpTangentStreamImporter::Reflect(ReflectContext* context)
|
||||
{
|
||||
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<AssImpTangentStreamImporter, SceneCore::LoadingComponent>()->Version(1);
|
||||
}
|
||||
}
|
||||
|
||||
Events::ProcessingResult AssImpTangentStreamImporter::ImportTangentStreams(AssImpSceneNodeAppendedContext& context)
|
||||
{
|
||||
AZ_TraceContext("Importer", m_defaultNodeName);
|
||||
if (!context.m_sourceNode.ContainsMesh())
|
||||
{
|
||||
return Events::ProcessingResult::Ignored;
|
||||
}
|
||||
aiNode* currentNode = context.m_sourceNode.GetAssImpNode();
|
||||
const aiScene* scene = context.m_sourceScene.GetAssImpScene();
|
||||
|
||||
AZStd::shared_ptr<DataTypes::IGraphObject> parentData =
|
||||
context.m_scene.GetGraph().GetNodeContent(context.m_currentGraphPosition);
|
||||
if (!parentData || !parentData->RTTI_IsTypeOf(SceneData::GraphData::MeshData::TYPEINFO_Uuid()))
|
||||
{
|
||||
AZ_Error(Utilities::ErrorWindow, false,
|
||||
"Tried to construct tangent stream attribute for invalid or non-mesh parent data");
|
||||
return Events::ProcessingResult::Failure;
|
||||
}
|
||||
const SceneData::GraphData::MeshData* const parentMeshData = azrtti_cast<SceneData::GraphData::MeshData*>(parentData.get());
|
||||
size_t vertexCount = parentMeshData->GetVertexCount();
|
||||
|
||||
int sdkMeshIndex = parentMeshData->GetSdkMeshIndex();
|
||||
if (sdkMeshIndex < 0 || sdkMeshIndex >= currentNode->mNumMeshes)
|
||||
{
|
||||
AZ_Error(Utilities::ErrorWindow, false,
|
||||
"Tried to construct tangent stream attribute for invalid or non-mesh parent data, mesh index is invalid");
|
||||
return Events::ProcessingResult::Failure;
|
||||
}
|
||||
|
||||
aiMesh* mesh = scene->mMeshes[currentNode->mMeshes[sdkMeshIndex]];
|
||||
|
||||
if (!mesh->HasTangentsAndBitangents())
|
||||
{
|
||||
return Events::ProcessingResult::Ignored;
|
||||
}
|
||||
|
||||
AZStd::shared_ptr<SceneData::GraphData::MeshVertexTangentData> tangentStream =
|
||||
AZStd::make_shared<AZ::SceneData::GraphData::MeshVertexTangentData>();
|
||||
|
||||
// AssImp only has one tangentStream per mesh.
|
||||
tangentStream->SetTangentSetIndex(0);
|
||||
|
||||
tangentStream->SetTangentSpace(AZ::SceneAPI::DataTypes::TangentSpace::FromFbx);
|
||||
tangentStream->ReserveContainerSpace(vertexCount);
|
||||
|
||||
for (int v = 0; v < mesh->mNumVertices; ++v)
|
||||
{
|
||||
// Vector4's constructor that takes in a vector3 sets w to 1.0f automatically.
|
||||
const Vector4 tangent(AssImpSDKWrapper::AssImpTypeConverter::ToVector3(mesh->mTangents[v]));
|
||||
tangentStream->AppendTangent(tangent);
|
||||
}
|
||||
|
||||
AZStd::string nodeName(AZStd::string::format("%s", m_defaultNodeName));
|
||||
Containers::SceneGraph::NodeIndex newIndex =
|
||||
context.m_scene.GetGraph().AddChild(context.m_currentGraphPosition, nodeName.c_str());
|
||||
|
||||
Events::ProcessingResult tangentResults;
|
||||
AssImpSceneAttributeDataPopulatedContext dataPopulated(context, tangentStream, newIndex, nodeName.c_str());
|
||||
tangentResults = Events::Process(dataPopulated);
|
||||
|
||||
if (tangentResults != Events::ProcessingResult::Failure)
|
||||
{
|
||||
tangentResults = AddAttributeDataNodeWithContexts(dataPopulated);
|
||||
}
|
||||
|
||||
return tangentResults;
|
||||
}
|
||||
|
||||
} // namespace FbxSceneBuilder
|
||||
} // namespace SceneAPI
|
||||
} // namespace AZ
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <SceneAPI/FbxSceneBuilder/ImportContexts/AssImpImportContexts.h>
|
||||
#include <SceneAPI/SceneCore/Components/LoadingComponent.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace SceneAPI
|
||||
{
|
||||
namespace FbxSceneBuilder
|
||||
{
|
||||
class AssImpTangentStreamImporter : public SceneCore::LoadingComponent
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(AssImpTangentStreamImporter, "{AB2D1D1E-5A19-40AF-B4F4-C652DD578F43}", SceneCore::LoadingComponent);
|
||||
|
||||
AssImpTangentStreamImporter();
|
||||
~AssImpTangentStreamImporter() override = default;
|
||||
|
||||
static void Reflect(ReflectContext* context);
|
||||
|
||||
Events::ProcessingResult ImportTangentStreams(AssImpSceneNodeAppendedContext& context);
|
||||
|
||||
protected:
|
||||
static const char* m_defaultNodeName;
|
||||
};
|
||||
} // namespace FbxSceneBuilder
|
||||
} // namespace SceneAPI
|
||||
} // namespace AZ
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <SceneAPI/SDKWrapper/AssImpNodeWrapper.h>
|
||||
#include <SceneAPI/SDKWrapper/AssImpSceneWrapper.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/AssImpImporterUtilities.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -45,16 +46,25 @@ namespace AZ
|
||||
serializeContext->Class<AssImpTransformImporter, SceneCore::LoadingComponent>()->Version(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Events::ProcessingResult AssImpTransformImporter::ImportTransform(AssImpSceneNodeAppendedContext& context)
|
||||
{
|
||||
AZ_TraceContext("Importer", "transform");
|
||||
aiNode* currentNode = context.m_sourceNode.GetAssImpNode();
|
||||
const aiScene* scene = context.m_sourceScene.GetAssImpScene();
|
||||
|
||||
if (currentNode == scene->mRootNode || IsPivotNode(currentNode->mName))
|
||||
{
|
||||
return Events::ProcessingResult::Ignored;
|
||||
}
|
||||
|
||||
DataTypes::MatrixType localTransform = AssImpSDKWrapper::AssImpTypeConverter::ToTransform(context.m_sourceNode.GetAssImpNode()->mTransformation);
|
||||
aiMatrix4x4 combinedTransform = GetConcatenatedLocalTransform(currentNode);
|
||||
|
||||
DataTypes::MatrixType localTransform = AssImpSDKWrapper::AssImpTypeConverter::ToTransform(combinedTransform);
|
||||
|
||||
context.m_sourceSceneSystem.SwapTransformForUpAxis(localTransform);
|
||||
context.m_sourceSceneSystem.ConvertUnit(localTransform);
|
||||
|
||||
AZStd::shared_ptr<SceneData::GraphData::TransformData> transformData =
|
||||
AZStd::make_shared<SceneData::GraphData::TransformData>(localTransform);
|
||||
AZ_Error(SceneAPI::Utilities::ErrorWindow, transformData, "Failed to allocate transform data.");
|
||||
@@ -63,7 +73,6 @@ namespace AZ
|
||||
return Events::ProcessingResult::Failure;
|
||||
}
|
||||
|
||||
|
||||
// If it is non-endpoint data populated node, add a transform attribute
|
||||
if (context.m_scene.GetGraph().HasNodeContent(context.m_currentGraphPosition))
|
||||
{
|
||||
|
||||
@@ -59,10 +59,10 @@ namespace AZ
|
||||
|
||||
AZStd::shared_ptr<DataTypes::IGraphObject> parentData =
|
||||
context.m_scene.GetGraph().GetNodeContent(context.m_currentGraphPosition);
|
||||
AZ_Assert(parentData && parentData->RTTI_IsTypeOf(SceneData::GraphData::MeshData::TYPEINFO_Uuid()),
|
||||
"Tried to construct uv stream attribute for invalid or non-mesh parent data");
|
||||
if (!parentData || !parentData->RTTI_IsTypeOf(SceneData::GraphData::MeshData::TYPEINFO_Uuid()))
|
||||
{
|
||||
AZ_Error(Utilities::ErrorWindow, false,
|
||||
"Tried to construct uv stream attribute for invalid or non-mesh parent data");
|
||||
return Events::ProcessingResult::Failure;
|
||||
}
|
||||
const SceneData::GraphData::MeshData* const parentMeshData =
|
||||
@@ -75,40 +75,44 @@ namespace AZ
|
||||
|
||||
aiMesh* mesh = scene->mMeshes[currentNode->mMeshes[sdkMeshIndex]];
|
||||
|
||||
if (!mesh->mTextureCoords[0])
|
||||
{
|
||||
return Events::ProcessingResult::Ignored;
|
||||
}
|
||||
|
||||
Events::ProcessingResultCombiner combinedUvMapResults;
|
||||
|
||||
AZStd::shared_ptr<SceneData::GraphData::MeshVertexUVData> uvMap =
|
||||
AZStd::make_shared<AZ::SceneData::GraphData::MeshVertexUVData>();
|
||||
uvMap->ReserveContainerSpace(vertexCount);
|
||||
uvMap->SetCustomName(m_defaultNodeName);
|
||||
|
||||
for (int v = 0; v < mesh->mNumVertices; ++v)
|
||||
for (int texCoordIndex = 0; texCoordIndex < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++texCoordIndex)
|
||||
{
|
||||
AZ::Vector2 vertexUV(
|
||||
mesh->mTextureCoords[0][v].x,
|
||||
mesh->mTextureCoords[0][v].y);
|
||||
uvMap->AppendUV(vertexUV);
|
||||
if (!mesh->mTextureCoords[texCoordIndex])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
AZStd::shared_ptr<SceneData::GraphData::MeshVertexUVData> uvMap =
|
||||
AZStd::make_shared<AZ::SceneData::GraphData::MeshVertexUVData>();
|
||||
uvMap->ReserveContainerSpace(vertexCount);
|
||||
AZStd::string name(AZStd::string::format("%s%d", m_defaultNodeName, texCoordIndex));
|
||||
uvMap->SetCustomName(name.c_str());
|
||||
|
||||
for (int v = 0; v < mesh->mNumVertices; ++v)
|
||||
{
|
||||
AZ::Vector2 vertexUV(
|
||||
mesh->mTextureCoords[texCoordIndex][v].x,
|
||||
// The engine's V coordinate is reverse of how it's stored in the FBX file.
|
||||
1.0f - mesh->mTextureCoords[texCoordIndex][v].y);
|
||||
uvMap->AppendUV(vertexUV);
|
||||
}
|
||||
|
||||
Containers::SceneGraph::NodeIndex newIndex =
|
||||
context.m_scene.GetGraph().AddChild(context.m_currentGraphPosition, name.c_str());
|
||||
|
||||
Events::ProcessingResult uvMapResults;
|
||||
AssImpSceneAttributeDataPopulatedContext dataPopulated(context, uvMap, newIndex, name);
|
||||
uvMapResults = Events::Process(dataPopulated);
|
||||
|
||||
if (uvMapResults != Events::ProcessingResult::Failure)
|
||||
{
|
||||
uvMapResults = AddAttributeDataNodeWithContexts(dataPopulated);
|
||||
}
|
||||
|
||||
combinedUvMapResults += uvMapResults;
|
||||
}
|
||||
|
||||
Containers::SceneGraph::NodeIndex newIndex =
|
||||
context.m_scene.GetGraph().AddChild(context.m_currentGraphPosition, m_defaultNodeName);
|
||||
|
||||
Events::ProcessingResult uvMapResults;
|
||||
AssImpSceneAttributeDataPopulatedContext dataPopulated(context, uvMap, newIndex, m_defaultNodeName);
|
||||
uvMapResults = Events::Process(dataPopulated);
|
||||
|
||||
if (uvMapResults != Events::ProcessingResult::Failure)
|
||||
{
|
||||
uvMapResults = AddAttributeDataNodeWithContexts(dataPopulated);
|
||||
}
|
||||
|
||||
combinedUvMapResults += uvMapResults;
|
||||
|
||||
return combinedUvMapResults.GetResult();
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,6 @@ namespace AZ
|
||||
SceneNodeFinalizeContext finalizeNode(addedAttributes);
|
||||
nodeResults += Events::Process(finalizeNode);
|
||||
}
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
else
|
||||
{
|
||||
AssImpSceneDataPopulatedContext* dataPopulatedContext = azrtti_cast<AssImpSceneDataPopulatedContext*>(&dataPopulated);
|
||||
@@ -75,7 +74,6 @@ namespace AZ
|
||||
AssImpSceneNodeFinalizeContext finalizeNode(addedAttributes);
|
||||
nodeResults += Events::Process(finalizeNode);
|
||||
}
|
||||
#endif
|
||||
|
||||
return nodeResults.GetResult();
|
||||
}
|
||||
@@ -99,14 +97,12 @@ namespace AZ
|
||||
SceneAttributeNodeAppendedContext nodeAppended(*dataPopulatedContext, dataPopulated.m_currentGraphPosition);
|
||||
nodeResults += Events::Process(nodeAppended);
|
||||
}
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
else
|
||||
{
|
||||
AssImpSceneAttributeDataPopulatedContext* dataPopulatedContext = azrtti_cast<AssImpSceneAttributeDataPopulatedContext*>(&dataPopulated);
|
||||
AssImpSceneAttributeNodeAppendedContext nodeAppended(*dataPopulatedContext, dataPopulated.m_currentGraphPosition);
|
||||
nodeResults += Events::Process(nodeAppended);
|
||||
}
|
||||
#endif
|
||||
|
||||
return nodeResults.GetResult();
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#include <SceneAPI/SceneCore/DataTypes/MatrixType.h>
|
||||
#include <SceneAPI/SceneCore/Events/CallProcessorBus.h>
|
||||
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
struct Uuid;
|
||||
|
||||
@@ -79,4 +79,4 @@ namespace AZ
|
||||
}
|
||||
} // namespace FbxSceneBuilder
|
||||
} // namespace SceneAPI
|
||||
} // namespace AZ
|
||||
} // namespace AZ
|
||||
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <assimp/mesh.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/FbxSceneSystem.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/Importers/Utilities/AssImpMeshImporterUtilities.h>
|
||||
#include <SceneAPI/SceneCore/Utilities/Reporting.h>
|
||||
#include <SceneAPI/SceneData/GraphData/BlendShapeData.h>
|
||||
#include <SceneAPI/SceneData/GraphData/MeshData.h>
|
||||
|
||||
namespace AZ::SceneAPI::FbxSceneBuilder
|
||||
{
|
||||
bool BuildSceneMeshFromAssImpMesh(aiNode* currentNode, const aiScene* scene, const FbxSceneSystem& sceneSystem, AZStd::vector<AZStd::shared_ptr<DataTypes::IGraphObject>>& meshes,
|
||||
const AZStd::function<AZStd::shared_ptr<SceneData::GraphData::MeshData>()>& makeMeshFunc)
|
||||
{
|
||||
AZStd::unordered_map<int, int> assImpMatIndexToLYIndex;
|
||||
int lyMeshIndex = 0;
|
||||
|
||||
if(!currentNode || !scene)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int m = 0; m < currentNode->mNumMeshes; ++m)
|
||||
{
|
||||
auto newMesh = makeMeshFunc();
|
||||
|
||||
newMesh->SetUnitSizeInMeters(sceneSystem.GetUnitSizeInMeters());
|
||||
newMesh->SetOriginalUnitSizeInMeters(sceneSystem.GetOriginalUnitSizeInMeters());
|
||||
|
||||
newMesh->SetSdkMeshIndex(m);
|
||||
|
||||
aiMesh* mesh = scene->mMeshes[currentNode->mMeshes[m]];
|
||||
|
||||
// Lumberyard materials are created in order based on mesh references in the scene
|
||||
if (assImpMatIndexToLYIndex.find(mesh->mMaterialIndex) == assImpMatIndexToLYIndex.end())
|
||||
{
|
||||
assImpMatIndexToLYIndex.insert(AZStd::pair<int, int>(mesh->mMaterialIndex, lyMeshIndex++));
|
||||
}
|
||||
|
||||
for (int vertIdx = 0; vertIdx < mesh->mNumVertices; ++vertIdx)
|
||||
{
|
||||
AZ::Vector3 vertex(mesh->mVertices[vertIdx].x, mesh->mVertices[vertIdx].y, mesh->mVertices[vertIdx].z);
|
||||
|
||||
sceneSystem.SwapVec3ForUpAxis(vertex);
|
||||
sceneSystem.ConvertUnit(vertex);
|
||||
newMesh->AddPosition(vertex);
|
||||
newMesh->SetVertexIndexToControlPointIndexMap(vertIdx, vertIdx);
|
||||
|
||||
if (mesh->HasNormals())
|
||||
{
|
||||
AZ::Vector3 normal(mesh->mNormals[vertIdx].x, mesh->mNormals[vertIdx].y, mesh->mNormals[vertIdx].z);
|
||||
sceneSystem.SwapVec3ForUpAxis(normal);
|
||||
normal.NormalizeSafe();
|
||||
newMesh->AddNormal(normal);
|
||||
}
|
||||
}
|
||||
|
||||
for (int faceIdx = 0; faceIdx < mesh->mNumFaces; ++faceIdx)
|
||||
{
|
||||
aiFace face = mesh->mFaces[faceIdx];
|
||||
AZ::SceneAPI::DataTypes::IMeshData::Face meshFace;
|
||||
if (face.mNumIndices != 3)
|
||||
{
|
||||
// AssImp should have triangulated everything, so if this happens then someone has
|
||||
// probably changed AssImp's import settings. The engine only supports triangles.
|
||||
AZ_Error(Utilities::ErrorWindow, false,
|
||||
"Mesh on node %s has a face with %d vertices, only 3 vertices are supported per face.",
|
||||
currentNode->mName.C_Str(),
|
||||
face.mNumIndices);
|
||||
continue;
|
||||
}
|
||||
for (int idx = 0; idx < face.mNumIndices; ++idx)
|
||||
{
|
||||
meshFace.vertexIndex[idx] = face.mIndices[idx];
|
||||
}
|
||||
|
||||
newMesh->AddFace(meshFace, assImpMatIndexToLYIndex[mesh->mMaterialIndex]);
|
||||
}
|
||||
|
||||
meshes.push_back(newMesh);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
struct aiNode;
|
||||
struct aiScene;
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace FbxSDKWrapper
|
||||
{
|
||||
class FbxMeshWrapper;
|
||||
}
|
||||
|
||||
namespace SceneData
|
||||
{
|
||||
namespace GraphData
|
||||
{
|
||||
class MeshData;
|
||||
class BlendShapeData;
|
||||
}
|
||||
}
|
||||
|
||||
namespace SceneAPI
|
||||
{
|
||||
namespace DataTypes
|
||||
{
|
||||
class IGraphObject;
|
||||
}
|
||||
|
||||
class FbxSceneSystem;
|
||||
namespace FbxSceneBuilder
|
||||
{
|
||||
bool BuildSceneMeshFromAssImpMesh(aiNode* currentNode, const aiScene* scene, const FbxSceneSystem& sceneSystem, AZStd::vector<AZStd::shared_ptr<DataTypes::IGraphObject>>& meshes,
|
||||
const AZStd::function<AZStd::shared_ptr<SceneData::GraphData::MeshData>()>& makeMeshFunc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,16 +10,4 @@
|
||||
#
|
||||
|
||||
set(FILES
|
||||
../../ImportContexts/AssImpImportContexts.h
|
||||
../../ImportContexts/AssImpImportContexts.cpp
|
||||
../../Importers/AssImpColorStreamImporter.h
|
||||
../../Importers/AssImpColorStreamImporter.cpp
|
||||
../../Importers/AssImpMaterialImporter.h
|
||||
../../Importers/AssImpMaterialImporter.cpp
|
||||
../../Importers/AssImpMeshImporter.h
|
||||
../../Importers/AssImpMeshImporter.cpp
|
||||
../../Importers/AssImpUvMapImporter.h
|
||||
../../Importers/AssImpUvMapImporter.cpp
|
||||
../../Importers/AssImpTransformImporter.h
|
||||
../../Importers/AssImpTransformImporter.cpp
|
||||
)
|
||||
|
||||
@@ -21,6 +21,8 @@ set(FILES
|
||||
ImportContexts/ImportContexts.cpp
|
||||
ImportContexts/FbxImportContexts.h
|
||||
ImportContexts/FbxImportContexts.cpp
|
||||
ImportContexts/AssImpImportContexts.h
|
||||
ImportContexts/AssImpImportContexts.cpp
|
||||
Importers/FbxAnimationImporter.h
|
||||
Importers/FbxAnimationImporter.cpp
|
||||
Importers/FbxBoneImporter.h
|
||||
@@ -50,6 +52,36 @@ set(FILES
|
||||
Importers/FbxUvMapImporter.cpp
|
||||
Importers/Utilities/FbxMeshImporterUtilities.h
|
||||
Importers/Utilities/FbxMeshImporterUtilities.cpp
|
||||
Importers/Utilities/AssImpMeshImporterUtilities.h
|
||||
Importers/Utilities/AssImpMeshImporterUtilities.cpp
|
||||
Importers/Utilities/RenamedNodesMap.h
|
||||
Importers/Utilities/RenamedNodesMap.cpp
|
||||
Importers/AssImpAnimationImporter.h
|
||||
Importers/AssImpAnimationImporter.cpp
|
||||
Importers/AssImpBitangentStreamImporter.h
|
||||
Importers/AssImpBitangentStreamImporter.cpp
|
||||
Importers/AssImpBlendShapeImporter.h
|
||||
Importers/AssImpBlendShapeImporter.cpp
|
||||
Importers/AssImpBoneImporter.h
|
||||
Importers/AssImpBoneImporter.cpp
|
||||
Importers/AssImpColorStreamImporter.h
|
||||
Importers/AssImpColorStreamImporter.cpp
|
||||
Importers/AssImpImporterUtilities.h
|
||||
Importers/AssImpImporterUtilities.cpp
|
||||
Importers/AssImpMaterialImporter.h
|
||||
Importers/AssImpMaterialImporter.cpp
|
||||
Importers/AssImpMeshImporter.h
|
||||
Importers/AssImpMeshImporter.cpp
|
||||
Importers/AssImpSkinImporter.h
|
||||
Importers/AssImpSkinImporter.cpp
|
||||
Importers/AssImpSkinWeightsImporter.h
|
||||
Importers/AssImpSkinWeightsImporter.cpp
|
||||
Importers/AssImpTangentStreamImporter.h
|
||||
Importers/AssImpTangentStreamImporter.cpp
|
||||
Importers/AssImpTransformImporter.h
|
||||
Importers/AssImpTransformImporter.cpp
|
||||
Importers/AssImpUvMapImporter.h
|
||||
Importers/AssImpUvMapImporter.cpp
|
||||
Importers/AssImpAnimationImporter.h
|
||||
Importers/AssImpAnimationImporter.cpp
|
||||
)
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/material.h>
|
||||
#include <AzCore/Debug/Trace.h>
|
||||
#include <AzCore/Math/Sha1.h>
|
||||
#include <AzCore/Debug/Trace.h>
|
||||
@@ -99,6 +100,105 @@ namespace AZ
|
||||
return shininess;
|
||||
}
|
||||
|
||||
bool AssImpMaterialWrapper::GetUseColorMap() const
|
||||
{
|
||||
// AssImp stores values as floats, so load as float and convert to bool.
|
||||
float useMap = 0.0f;
|
||||
if (m_assImpMaterial->Get(AI_MATKEY_USE_COLOR_MAP, useMap) == aiReturn::aiReturn_FAILURE)
|
||||
{
|
||||
AZ_Warning(AZ::SceneAPI::Utilities::WarningWindow, false, "Unable to get useColorMap from the material. Using default.");
|
||||
}
|
||||
return useMap != 0.0f;
|
||||
}
|
||||
|
||||
AZ::Vector3 AssImpMaterialWrapper::GetBaseColor() const
|
||||
{
|
||||
aiColor3D color(1.f, 1.f, 1.f);
|
||||
if (m_assImpMaterial->Get(AI_MATKEY_BASE_COLOR, color) == aiReturn::aiReturn_FAILURE)
|
||||
{
|
||||
// If a base color is not set, fall back to the diffuse color.
|
||||
// Before PBR support was added, the base color was set to the diffuse color, so
|
||||
// this will match that behavior.
|
||||
return GetDiffuseColor();
|
||||
}
|
||||
return AZ::Vector3(color.r, color.g, color.b);
|
||||
}
|
||||
|
||||
bool AssImpMaterialWrapper::GetUseMetallicMap() const
|
||||
{
|
||||
// AssImp stores values as floats, so load as float and convert to bool.
|
||||
float useMap = 0.0f;
|
||||
if (m_assImpMaterial->Get(AI_MATKEY_USE_METALLIC_MAP, useMap) == aiReturn::aiReturn_FAILURE)
|
||||
{
|
||||
AZ_Warning(AZ::SceneAPI::Utilities::WarningWindow, false, "Unable to get useMetallicMap from the material. Using default.");
|
||||
}
|
||||
return useMap != 0.0f;
|
||||
}
|
||||
|
||||
float AssImpMaterialWrapper::GetMetallicFactor() const
|
||||
{
|
||||
float metallic = 0.0f;
|
||||
if (m_assImpMaterial->Get(AI_MATKEY_METALLIC_FACTOR, metallic) == aiReturn::aiReturn_FAILURE)
|
||||
{
|
||||
AZ_Warning(AZ::SceneAPI::Utilities::WarningWindow, false, "Unable to get metallic from the material. Using default.");
|
||||
}
|
||||
return metallic;
|
||||
}
|
||||
|
||||
bool AssImpMaterialWrapper::GetUseRoughnessMap() const
|
||||
{
|
||||
// AssImp stores values as floats, so load as float and convert to bool.
|
||||
float useMap = 0.0f;
|
||||
if (m_assImpMaterial->Get(AI_MATKEY_USE_ROUGHNESS_MAP, useMap) == aiReturn::aiReturn_FAILURE)
|
||||
{
|
||||
AZ_Warning(AZ::SceneAPI::Utilities::WarningWindow, false, "Unable to get useRoughnessMap from the material. Using default.");
|
||||
}
|
||||
return useMap != 0.0f;
|
||||
}
|
||||
|
||||
float AssImpMaterialWrapper::GetRoughnessFactor() const
|
||||
{
|
||||
float roughness = 0.0f;
|
||||
if (m_assImpMaterial->Get(AI_MATKEY_ROUGHNESS_FACTOR, roughness) == aiReturn::aiReturn_FAILURE)
|
||||
{
|
||||
AZ_Warning(AZ::SceneAPI::Utilities::WarningWindow, false, "Unable to get roughness from the material. Using default.");
|
||||
}
|
||||
return roughness;
|
||||
}
|
||||
|
||||
bool AssImpMaterialWrapper::GetUseEmissiveMap() const
|
||||
{
|
||||
// AssImp stores values as floats, so load as float and convert to bool.
|
||||
float useMap = 0.0f;
|
||||
if (m_assImpMaterial->Get(AI_MATKEY_USE_EMISSIVE_MAP, useMap) == aiReturn::aiReturn_FAILURE)
|
||||
{
|
||||
AZ_Warning(
|
||||
AZ::SceneAPI::Utilities::WarningWindow, false, "Unable to get useEmissiveMap from the material. Using default.");
|
||||
}
|
||||
return useMap != 0.0f;
|
||||
}
|
||||
|
||||
float AssImpMaterialWrapper::GetEmissiveIntensity() const
|
||||
{
|
||||
float emissiveIntensity = 0.0f;
|
||||
if (m_assImpMaterial->Get(AI_MATKEY_EMISSIVE_INTENSITY, emissiveIntensity) == aiReturn::aiReturn_FAILURE)
|
||||
{
|
||||
AZ_Warning(AZ::SceneAPI::Utilities::WarningWindow, false, "Unable to get emissive intensity from the material. Using default.");
|
||||
}
|
||||
return emissiveIntensity;
|
||||
}
|
||||
|
||||
bool AssImpMaterialWrapper::GetUseAOMap() const
|
||||
{
|
||||
// AssImp stores values as floats, so load as float and convert to bool.
|
||||
float useMap = 0.0f;
|
||||
if (m_assImpMaterial->Get(AI_MATKEY_USE_AO_MAP, useMap) == aiReturn::aiReturn_FAILURE)
|
||||
{
|
||||
AZ_Warning(AZ::SceneAPI::Utilities::WarningWindow, false, "Unable to get useAOMap from the material. Using default.");
|
||||
}
|
||||
return useMap != 0.0f;
|
||||
}
|
||||
|
||||
AZStd::string AssImpMaterialWrapper::GetTextureFileName(MaterialMapType textureType) const
|
||||
{
|
||||
/// Engine currently doesn't support multiple textures. Right now we only use first texture.
|
||||
@@ -130,6 +230,43 @@ namespace AZ
|
||||
m_assImpMaterial->GetTexture(aiTextureType_NORMALS, textureIndex, &absTexturePath);
|
||||
}
|
||||
break;
|
||||
case MaterialMapType::Metallic:
|
||||
if (m_assImpMaterial->GetTextureCount(aiTextureType_METALNESS) > textureIndex)
|
||||
{
|
||||
m_assImpMaterial->GetTexture(aiTextureType_METALNESS, textureIndex, &absTexturePath);
|
||||
}
|
||||
break;
|
||||
case MaterialMapType::Roughness:
|
||||
if (m_assImpMaterial->GetTextureCount(aiTextureType_DIFFUSE_ROUGHNESS) > textureIndex)
|
||||
{
|
||||
m_assImpMaterial->GetTexture(aiTextureType_DIFFUSE_ROUGHNESS, textureIndex, &absTexturePath);
|
||||
}
|
||||
break;
|
||||
case MaterialMapType::AmbientOcclusion:
|
||||
if (m_assImpMaterial->GetTextureCount(aiTextureType_AMBIENT_OCCLUSION) > textureIndex)
|
||||
{
|
||||
m_assImpMaterial->GetTexture(aiTextureType_AMBIENT_OCCLUSION, textureIndex, &absTexturePath);
|
||||
}
|
||||
break;
|
||||
case MaterialMapType::Emissive:
|
||||
if (m_assImpMaterial->GetTextureCount(aiTextureType_EMISSION_COLOR) > textureIndex)
|
||||
{
|
||||
m_assImpMaterial->GetTexture(aiTextureType_EMISSION_COLOR, textureIndex, &absTexturePath);
|
||||
}
|
||||
break;
|
||||
case MaterialMapType::BaseColor:
|
||||
if (m_assImpMaterial->GetTextureCount(aiTextureType_BASE_COLOR) > textureIndex)
|
||||
{
|
||||
m_assImpMaterial->GetTexture(aiTextureType_BASE_COLOR, textureIndex, &absTexturePath);
|
||||
}
|
||||
// If the base color texture isn't available, fall back to using the diffuse texture.
|
||||
// Before PBR support was added, the renderer just defaulted to using the diffuse texture
|
||||
// in the base color texture property of the material.
|
||||
else if (m_assImpMaterial->GetTextureCount(aiTextureType_DIFFUSE) > textureIndex)
|
||||
{
|
||||
m_assImpMaterial->GetTexture(aiTextureType_DIFFUSE, textureIndex, &absTexturePath);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
AZ_TraceContext("Unknown value", aznumeric_cast<int>(textureType));
|
||||
AZ_TracePrintf(SceneAPI::Utilities::WarningWindow, "Unrecognized MaterialMapType retrieved");
|
||||
|
||||
@@ -32,6 +32,16 @@ namespace AZ
|
||||
float GetOpacity() const override;
|
||||
float GetShininess() const override;
|
||||
AZStd::string GetTextureFileName(MaterialMapType textureType) const override;
|
||||
|
||||
bool GetUseColorMap() const;
|
||||
AZ::Vector3 GetBaseColor() const;
|
||||
bool GetUseMetallicMap() const;
|
||||
float GetMetallicFactor() const;
|
||||
bool GetUseRoughnessMap() const;
|
||||
float GetRoughnessFactor() const;
|
||||
bool GetUseEmissiveMap() const;
|
||||
float GetEmissiveIntensity() const;
|
||||
bool GetUseAOMap() const;
|
||||
};
|
||||
} // namespace AssImpSDKWrapper
|
||||
}// namespace AZ
|
||||
|
||||
@@ -65,6 +65,19 @@ namespace AZ
|
||||
return m_assImpNode->mNumMeshes != 0;
|
||||
}
|
||||
|
||||
bool AssImpNodeWrapper::ContainsBones(const aiScene& scene) const
|
||||
{
|
||||
for (unsigned meshIndex = 0; meshIndex < m_assImpNode->mNumMeshes; ++meshIndex)
|
||||
{
|
||||
if (scene.mMeshes[m_assImpNode->mMeshes[meshIndex]]->HasBones())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int AssImpNodeWrapper::GetMaterialCount() const
|
||||
{
|
||||
// one mesh uses only a single material
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
|
||||
#pragma once
|
||||
#include <SceneAPI/SDKWrapper/NodeWrapper.h>
|
||||
|
||||
struct aiScene;
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace AssImpSDKWrapper
|
||||
@@ -27,6 +30,7 @@ namespace AZ
|
||||
int GetChildCount() const override;
|
||||
const std::shared_ptr<NodeWrapper> GetChild(int childIndex) const override;
|
||||
const bool ContainsMesh();
|
||||
bool ContainsBones(const aiScene& scene) const;
|
||||
int GetMaterialCount() const override;
|
||||
};
|
||||
} // namespace AssImpSDKWrapper
|
||||
|
||||
@@ -38,12 +38,11 @@ namespace AZ
|
||||
{
|
||||
AZ_TracePrintf(SceneAPI::Utilities::LogWindow, "AssImpSceneWrapper::LoadSceneFromFile %s", fileName);
|
||||
AZ_TraceContext("Filename", fileName);
|
||||
m_importer.SetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, false);
|
||||
m_sceneFileName = fileName;
|
||||
m_assImpScene = m_importer.ReadFile(fileName,
|
||||
aiProcess_CalcTangentSpace //Calculates the tangents and bitangents for the imported meshes
|
||||
| aiProcess_Triangulate //Triangulates all faces of all meshes
|
||||
aiProcess_Triangulate //Triangulates all faces of all meshes
|
||||
| aiProcess_JoinIdenticalVertices //Identifies and joins identical vertex data sets for the imported meshes
|
||||
| aiProcess_SortByPType //Splits meshes with more than one primitive type into homogeneous sub - meshes
|
||||
| aiProcess_FixInfacingNormals //Fixes inward facing normals, AssImp documentation recommends setting this
|
||||
| aiProcess_GenNormals); //Generate normals for meshes
|
||||
if (!m_assImpScene)
|
||||
{
|
||||
|
||||
@@ -44,9 +44,15 @@ namespace AZ
|
||||
|
||||
AZStd::pair<AxisVector, int32_t> GetUpVectorAndSign() const;
|
||||
AZStd::pair<AxisVector, int32_t> GetFrontVectorAndSign() const;
|
||||
|
||||
AZStd::string GetSceneFileName() const { return m_sceneFileName; }
|
||||
protected:
|
||||
|
||||
Assimp::Importer m_importer;
|
||||
|
||||
// FBX SDK automatically resolved relative paths to textures based on the current file location.
|
||||
// AssImp does not, so it needs to be specifically handled.
|
||||
AZStd::string m_sceneFileName;
|
||||
};
|
||||
|
||||
} // namespace AssImpSDKWrapper
|
||||
|
||||
@@ -56,5 +56,10 @@ namespace AZ
|
||||
{
|
||||
return AZ::SceneAPI::DataTypes::Color(color.r, color.g, color.b, color.a);
|
||||
}
|
||||
|
||||
AZ::Vector3 AssImpTypeConverter::ToVector3(const aiVector3D& vector3)
|
||||
{
|
||||
return AZ::Vector3(vector3.x, vector3.y, vector3.z);
|
||||
}
|
||||
} //AssImpSDKWrapper
|
||||
} // namespace AZ
|
||||
|
||||
@@ -33,6 +33,7 @@ namespace AZ
|
||||
static SceneAPI::DataTypes::MatrixType ToTransform(const aiMatrix4x4& matrix);
|
||||
static SceneAPI::DataTypes::MatrixType ToTransform(const AZ::Matrix4x4& matrix);
|
||||
static SceneAPI::DataTypes::Color ToColor(const aiColor4D& color);
|
||||
static AZ::Vector3 ToVector3(const aiVector3D& vector3);
|
||||
};
|
||||
} // namespace AssImpSDKWrapper
|
||||
} // namespace AZ
|
||||
|
||||
@@ -18,43 +18,38 @@ namespace AZ
|
||||
{
|
||||
MaterialWrapper::MaterialWrapper(fbxsdk::FbxSurfaceMaterial* fbxMaterial)
|
||||
:m_fbxMaterial(fbxMaterial)
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
, m_assImpMaterial(nullptr)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
|
||||
MaterialWrapper::MaterialWrapper(aiMaterial* assImpMaterial)
|
||||
:m_fbxMaterial(nullptr)
|
||||
, m_assImpMaterial(assImpMaterial)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
MaterialWrapper::~MaterialWrapper()
|
||||
{
|
||||
m_fbxMaterial = nullptr;
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
m_assImpMaterial = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
fbxsdk::FbxSurfaceMaterial* MaterialWrapper::GetFbxMaterial()
|
||||
{
|
||||
return m_fbxMaterial;
|
||||
}
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
|
||||
aiMaterial* MaterialWrapper::GetAssImpMaterial()
|
||||
{
|
||||
return m_assImpMaterial;
|
||||
}
|
||||
#endif
|
||||
|
||||
AZStd::string MaterialWrapper::GetName() const
|
||||
{
|
||||
return AZStd::string();
|
||||
}
|
||||
|
||||
uint64_t MaterialWrapper::GetUniqueId() const
|
||||
AZ::u64 MaterialWrapper::GetUniqueId() const
|
||||
{
|
||||
return uint64_t();
|
||||
}
|
||||
|
||||
@@ -20,9 +20,8 @@ namespace fbxsdk
|
||||
class FbxSurfaceMaterial;
|
||||
}
|
||||
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
struct aiMaterial;
|
||||
#endif
|
||||
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -37,22 +36,23 @@ namespace AZ
|
||||
Diffuse,
|
||||
Specular,
|
||||
Bump,
|
||||
Normal
|
||||
Normal,
|
||||
Metallic,
|
||||
Roughness,
|
||||
AmbientOcclusion,
|
||||
Emissive,
|
||||
BaseColor
|
||||
};
|
||||
|
||||
MaterialWrapper(fbxsdk::FbxSurfaceMaterial* fbxMaterial);
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
MaterialWrapper(aiMaterial* assImpmaterial);
|
||||
#endif
|
||||
virtual ~MaterialWrapper();
|
||||
|
||||
fbxsdk::FbxSurfaceMaterial* GetFbxMaterial();
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
aiMaterial* GetAssImpMaterial();
|
||||
#endif
|
||||
|
||||
virtual AZStd::string GetName() const;
|
||||
virtual uint64_t GetUniqueId() const;
|
||||
virtual AZ::u64 GetUniqueId() const;
|
||||
virtual AZStd::string GetTextureFileName(MaterialMapType textureType) const;
|
||||
virtual AZ::Vector3 GetDiffuseColor() const;
|
||||
virtual AZ::Vector3 GetSpecularColor() const;
|
||||
@@ -62,9 +62,7 @@ namespace AZ
|
||||
|
||||
protected:
|
||||
fbxsdk::FbxSurfaceMaterial* m_fbxMaterial = nullptr;
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
aiMaterial* m_assImpMaterial = nullptr;
|
||||
#endif
|
||||
};
|
||||
} // namespace SDKMaterial
|
||||
} // namespace AZ
|
||||
|
||||
@@ -18,37 +18,31 @@ namespace AZ
|
||||
{
|
||||
NodeWrapper::NodeWrapper(fbxsdk::FbxNode* fbxNode)
|
||||
:m_fbxNode(fbxNode)
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
, m_assImpNode(nullptr)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
|
||||
NodeWrapper::NodeWrapper(aiNode* aiNode)
|
||||
:m_fbxNode(nullptr)
|
||||
, m_assImpNode(aiNode)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
NodeWrapper::~NodeWrapper()
|
||||
{
|
||||
m_fbxNode = nullptr;
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
m_assImpNode = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
fbxsdk::FbxNode* NodeWrapper::GetFbxNode()
|
||||
{
|
||||
return m_fbxNode;
|
||||
}
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
|
||||
aiNode* NodeWrapper::GetAssImpNode()
|
||||
{
|
||||
return m_assImpNode;
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* NodeWrapper::GetName() const
|
||||
{
|
||||
|
||||
@@ -15,9 +15,9 @@ namespace fbxsdk
|
||||
{
|
||||
class FbxNode;
|
||||
}
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
|
||||
struct aiNode;
|
||||
#endif
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace SDKNode
|
||||
@@ -29,9 +29,7 @@ namespace AZ
|
||||
|
||||
NodeWrapper() = default;
|
||||
NodeWrapper(fbxsdk::FbxNode* fbxNode);
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
NodeWrapper(aiNode* aiNode);
|
||||
#endif
|
||||
virtual ~NodeWrapper();
|
||||
|
||||
enum CurveNodeComponent
|
||||
@@ -42,9 +40,7 @@ namespace AZ
|
||||
};
|
||||
|
||||
fbxsdk::FbxNode* GetFbxNode();
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
aiNode* GetAssImpNode();
|
||||
#endif
|
||||
|
||||
virtual const char* GetName() const;
|
||||
virtual AZ::u64 GetUniqueId() const;
|
||||
@@ -55,9 +51,7 @@ namespace AZ
|
||||
|
||||
|
||||
fbxsdk::FbxNode* m_fbxNode = nullptr;
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
aiNode* m_assImpNode = nullptr;
|
||||
#endif
|
||||
};
|
||||
} //namespace Node
|
||||
} //namespace AZ
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
../../AssImpSceneWrapper.cpp
|
||||
../../AssImpNodeWrapper.cpp
|
||||
../../AssImpSceneWrapper.h
|
||||
../../AssImpNodeWrapper.h
|
||||
../../AssImpMaterialWrapper.h
|
||||
../../AssImpMaterialWrapper.cpp
|
||||
../../AssImpTypeConverter.cpp
|
||||
../../AssImpTypeConverter.h
|
||||
)
|
||||
@@ -19,18 +19,16 @@ namespace AZ
|
||||
|
||||
SceneWrapperBase::SceneWrapperBase(fbxsdk::FbxScene* fbxScene)
|
||||
:m_fbxScene(fbxScene)
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
, m_assImpScene(nullptr)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
|
||||
SceneWrapperBase::SceneWrapperBase(aiScene* aiScene)
|
||||
:m_fbxScene(nullptr)
|
||||
, m_assImpScene(aiScene)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool SceneWrapperBase::LoadSceneFromFile([[maybe_unused]] const char* fileName)
|
||||
{
|
||||
@@ -59,12 +57,10 @@ namespace AZ
|
||||
return m_fbxScene;
|
||||
}
|
||||
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
const aiScene* SceneWrapperBase::GetAssImpScene() const
|
||||
{
|
||||
return m_assImpScene;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
} //namespace Scene
|
||||
|
||||
@@ -17,9 +17,9 @@ namespace fbxsdk
|
||||
{
|
||||
class FbxScene;
|
||||
}
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
|
||||
struct aiScene;
|
||||
#endif
|
||||
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -32,9 +32,7 @@ namespace AZ
|
||||
SceneWrapperBase() = default;
|
||||
SceneWrapperBase(fbxsdk::FbxScene* fbxScene);
|
||||
virtual ~SceneWrapperBase() = default;
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
SceneWrapperBase(aiScene* aiScene);
|
||||
#endif
|
||||
|
||||
virtual bool LoadSceneFromFile(const char* fileName);
|
||||
virtual bool LoadSceneFromFile(const AZStd::string& fileName);
|
||||
@@ -45,14 +43,10 @@ namespace AZ
|
||||
virtual void Clear();
|
||||
|
||||
virtual fbxsdk::FbxScene* GetFbxScene() const;
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
virtual const aiScene* GetAssImpScene() const;
|
||||
#endif
|
||||
|
||||
fbxsdk::FbxScene* m_fbxScene = nullptr;
|
||||
#ifdef ASSET_IMPORTER_SDK_SUPPORTED_TRAIT
|
||||
const aiScene* m_assImpScene = nullptr;
|
||||
#endif
|
||||
|
||||
static const char* s_defaultSceneName;
|
||||
};
|
||||
|
||||
@@ -16,4 +16,12 @@ set(FILES
|
||||
NodeWrapper.cpp
|
||||
MaterialWrapper.h
|
||||
MaterialWrapper.cpp
|
||||
AssImpSceneWrapper.cpp
|
||||
AssImpNodeWrapper.cpp
|
||||
AssImpSceneWrapper.h
|
||||
AssImpNodeWrapper.h
|
||||
AssImpMaterialWrapper.h
|
||||
AssImpMaterialWrapper.cpp
|
||||
AssImpTypeConverter.cpp
|
||||
AssImpTypeConverter.h
|
||||
)
|
||||
|
||||
@@ -23,7 +23,6 @@ namespace AZ
|
||||
{
|
||||
namespace Containers
|
||||
{
|
||||
|
||||
size_t RuleContainer::GetRuleCount() const
|
||||
{
|
||||
return m_rules.size();
|
||||
@@ -57,6 +56,13 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
void RuleContainer::InsertRule(const AZStd::shared_ptr<DataTypes::IRule>& rule, size_t position)
|
||||
{
|
||||
AZ_Assert(AZStd::find(m_rules.begin(), m_rules.end(), rule) == m_rules.end(), "Unable to insert rule as it has already been added.");
|
||||
m_rules.insert(m_rules.begin() + position, rule);
|
||||
}
|
||||
|
||||
|
||||
void RuleContainer::RemoveRule(size_t index)
|
||||
{
|
||||
if (index < m_rules.size())
|
||||
@@ -76,7 +82,6 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RuleContainer::Reflect(ReflectContext* context)
|
||||
{
|
||||
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
|
||||
@@ -156,4 +161,4 @@ namespace AZ
|
||||
|
||||
} // Containers
|
||||
} // SceneAPI
|
||||
} // AZ
|
||||
} // AZ
|
||||
|
||||
@@ -27,7 +27,6 @@ namespace AZ
|
||||
{
|
||||
namespace Containers
|
||||
{
|
||||
|
||||
class RuleContainer
|
||||
{
|
||||
public:
|
||||
@@ -54,6 +53,8 @@ namespace AZ
|
||||
SCENE_CORE_API void AddRule(const AZStd::shared_ptr<DataTypes::IRule>& rule);
|
||||
SCENE_CORE_API void AddRule(AZStd::shared_ptr<DataTypes::IRule>&& rule);
|
||||
|
||||
SCENE_CORE_API void InsertRule(const AZStd::shared_ptr<DataTypes::IRule>& rule, size_t position);
|
||||
|
||||
SCENE_CORE_API void RemoveRule(size_t index);
|
||||
SCENE_CORE_API void RemoveRule(const AZStd::shared_ptr<DataTypes::IRule>& rule);
|
||||
|
||||
|
||||
@@ -43,6 +43,30 @@ namespace AZ
|
||||
AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context);
|
||||
if (behaviorContext)
|
||||
{
|
||||
behaviorContext->Class<SceneGraph::NodeIndex>()
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "scene.graph")
|
||||
->Constructor<>()
|
||||
->Constructor<const SceneGraph::NodeIndex&>()
|
||||
->Method("AsNumber", &SceneGraph::NodeIndex::AsNumber)
|
||||
->Method("Distance", &SceneGraph::NodeIndex::Distance)
|
||||
->Method("IsValid", &SceneGraph::NodeIndex::IsValid)
|
||||
->Method("Equal", &SceneGraph::NodeIndex::operator==)
|
||||
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Equal)
|
||||
->Method("ToString", [](const SceneGraph::NodeIndex& node) { return AZStd::string::format("%u", node.m_value); })
|
||||
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::ToString)
|
||||
;
|
||||
|
||||
behaviorContext->Class<SceneGraph::Name>()
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "scene.graph")
|
||||
->Constructor()
|
||||
->Method("GetPath", &SceneGraph::Name::GetPath)
|
||||
->Method("GetName", &SceneGraph::Name::GetName)
|
||||
->Method("ToString", [](const SceneGraph::Name& self){ return self.GetName(); })
|
||||
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::ToString)
|
||||
;
|
||||
|
||||
behaviorContext->Class<SceneGraph>()
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "scene.graph")
|
||||
@@ -62,41 +86,23 @@ namespace AZ
|
||||
->Method("GetNodeChild", [](const SceneGraph& self, NodeIndex node) { return self.GetNodeChild(node); })
|
||||
->Method("GetNodeCount", &SceneGraph::GetNodeCount)
|
||||
->Method("FindWithPath", [](const SceneGraph& self, const AZStd::string& path)
|
||||
{
|
||||
return self.Find(path);
|
||||
})
|
||||
{
|
||||
return self.Find(path);
|
||||
})
|
||||
->Method("FindWithRootAndPath", [](const SceneGraph& self, NodeIndex root, const AZStd::string& path)
|
||||
{
|
||||
return self.Find(root, path);
|
||||
})
|
||||
{
|
||||
return self.Find(root, path);
|
||||
})
|
||||
->Method("GetNodeContent", [](const SceneGraph& self, NodeIndex node) -> GraphObjectProxy*
|
||||
{
|
||||
auto graphObject = self.GetNodeContent(node);
|
||||
if (graphObject)
|
||||
{
|
||||
auto graphObject = self.GetNodeContent(node);
|
||||
if (graphObject)
|
||||
{
|
||||
GraphObjectProxy* proxy = aznew GraphObjectProxy(graphObject);
|
||||
return proxy;
|
||||
}
|
||||
return nullptr;
|
||||
})
|
||||
;
|
||||
|
||||
behaviorContext->Class<SceneGraph::NodeIndex>()
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "scene.graph")
|
||||
->Method("AsNumber", &SceneGraph::NodeIndex::AsNumber)
|
||||
->Method("Distance", &SceneGraph::NodeIndex::Distance)
|
||||
->Method("IsValid", &SceneGraph::NodeIndex::IsValid)
|
||||
->Method("Equal", &SceneGraph::NodeIndex::operator==)
|
||||
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Equal)
|
||||
;
|
||||
|
||||
behaviorContext->Class<SceneGraph::Name>()
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "scene.graph")
|
||||
->Method("GetPath", &SceneGraph::Name::GetPath)
|
||||
->Method("GetName", &SceneGraph::Name::GetName)
|
||||
;
|
||||
GraphObjectProxy* proxy = aznew GraphObjectProxy(graphObject);
|
||||
return proxy;
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ namespace AZ
|
||||
// Type needs to be able to store an index in a NodeHeader (currently 21-bits).
|
||||
using IndexType = uint32_t;
|
||||
|
||||
NodeIndex() = default;
|
||||
NodeIndex(const NodeIndex& rhs) = default;
|
||||
NodeIndex& operator=(const NodeIndex& rhs) = default;
|
||||
|
||||
@@ -87,10 +88,9 @@ namespace AZ
|
||||
private:
|
||||
static const IndexType INVALID_INDEX = static_cast<IndexType>(-1);
|
||||
|
||||
inline NodeIndex();
|
||||
inline explicit NodeIndex(IndexType value);
|
||||
|
||||
IndexType m_value;
|
||||
IndexType m_value = NodeIndex::INVALID_INDEX;
|
||||
};
|
||||
|
||||
// NodeHeader contains the relationship a node has with its surrounding nodes and additional information about a node.
|
||||
|
||||
@@ -22,11 +22,6 @@ namespace AZ
|
||||
//
|
||||
// NodeIndex
|
||||
//
|
||||
SceneGraph::NodeIndex::NodeIndex()
|
||||
: m_value(NodeIndex::INVALID_INDEX)
|
||||
{
|
||||
}
|
||||
|
||||
bool SceneGraph::NodeIndex::IsValid() const
|
||||
{
|
||||
return m_value != NodeIndex::INVALID_INDEX;
|
||||
|
||||
@@ -104,7 +104,7 @@ namespace AZ
|
||||
RootIterator& operator++();
|
||||
RootIterator operator++(int);
|
||||
|
||||
const Iterator& GetBaseIterator();
|
||||
const Iterator& GetBaseIterator() const;
|
||||
protected:
|
||||
Iterator m_iterator;
|
||||
Function m_converter;
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace AZ
|
||||
}
|
||||
|
||||
template<typename Iterator, typename ReturnType>
|
||||
const Iterator& ConvertIterator<Iterator, ReturnType, void>::GetBaseIterator()
|
||||
const Iterator& ConvertIterator<Iterator, ReturnType, void>::GetBaseIterator() const
|
||||
{
|
||||
return m_iterator;
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace AZ
|
||||
RootIterator& operator++();
|
||||
RootIterator operator++(int);
|
||||
|
||||
const Iterator& GetBaseIterator();
|
||||
const Iterator& GetBaseIterator() const;
|
||||
|
||||
protected:
|
||||
// Pseudo default constructor.
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace AZ
|
||||
}
|
||||
|
||||
template<typename Iterator>
|
||||
auto FilterIterator<Iterator, void>::GetBaseIterator()->const Iterator&
|
||||
auto FilterIterator<Iterator, void>::GetBaseIterator() const -> const Iterator&
|
||||
{
|
||||
return m_iterator;
|
||||
}
|
||||
|
||||
@@ -44,6 +44,8 @@ namespace AZ
|
||||
Iterator cbegin() const;
|
||||
Iterator cend() const;
|
||||
|
||||
[[nodiscard]] bool empty() const;
|
||||
|
||||
private:
|
||||
Iterator m_begin;
|
||||
Iterator m_end;
|
||||
@@ -59,4 +61,4 @@ namespace AZ
|
||||
} // SceneAPI
|
||||
} // AZ
|
||||
|
||||
#include <SceneAPI/SceneCore/Containers/Views/View.inl>
|
||||
#include <SceneAPI/SceneCore/Containers/Views/View.inl>
|
||||
|
||||
@@ -62,6 +62,12 @@ namespace AZ
|
||||
{
|
||||
return m_end;
|
||||
}
|
||||
|
||||
template<typename Iterator>
|
||||
[[nodiscard]] bool View<Iterator>::empty() const
|
||||
{
|
||||
return m_begin == m_end;
|
||||
}
|
||||
}; // Views
|
||||
} // Containers
|
||||
} // SceneAPI
|
||||
|
||||
@@ -37,7 +37,12 @@ namespace AZ
|
||||
Diffuse,
|
||||
Specular,
|
||||
Bump,
|
||||
Normal
|
||||
Normal,
|
||||
Metallic,
|
||||
Roughness,
|
||||
AmbientOcclusion,
|
||||
Emissive,
|
||||
BaseColor
|
||||
};
|
||||
|
||||
~IMaterialData() override = default;
|
||||
@@ -52,6 +57,24 @@ namespace AZ
|
||||
output.Write("EmissiveColor", GetEmissiveColor());
|
||||
output.Write("Opacity", GetOpacity());
|
||||
output.Write("Shininess", GetShininess());
|
||||
output.Write("UseColorMap", GetUseColorMap());
|
||||
output.Write("BaseColor", GetBaseColor());
|
||||
output.Write("UseMetallicMap", GetUseMetallicMap());
|
||||
output.Write("MetallicFactor", GetMetallicFactor());
|
||||
output.Write("UseRoughnessMap", GetUseRoughnessMap());
|
||||
output.Write("RoughnessFactor", GetRoughnessFactor());
|
||||
output.Write("UseEmissiveMap", GetUseEmissiveMap());
|
||||
output.Write("EmissiveIntensity", GetEmissiveIntensity());
|
||||
output.Write("UseAOMap", GetUseAOMap());
|
||||
output.Write("DiffuseTexture", GetTexture(TextureMapType::Diffuse).c_str());
|
||||
output.Write("SpecularTexture", GetTexture(TextureMapType::Specular).c_str());
|
||||
output.Write("BumpTexture", GetTexture(TextureMapType::Bump).c_str());
|
||||
output.Write("NormalTexture", GetTexture(TextureMapType::Normal).c_str());
|
||||
output.Write("MetallicTexture", GetTexture(TextureMapType::Metallic).c_str());
|
||||
output.Write("RoughnessTexture", GetTexture(TextureMapType::Roughness).c_str());
|
||||
output.Write("AmbientOcclusionTexture", GetTexture(TextureMapType::AmbientOcclusion).c_str());
|
||||
output.Write("EmissiveTexture", GetTexture(TextureMapType::Emissive).c_str());
|
||||
output.Write("BaseColorTexture", GetTexture(TextureMapType::BaseColor).c_str());
|
||||
}
|
||||
|
||||
virtual const AZStd::string& GetMaterialName() const = 0;
|
||||
@@ -63,6 +86,16 @@ namespace AZ
|
||||
virtual const AZ::Vector3& GetEmissiveColor() const = 0;
|
||||
virtual float GetOpacity() const = 0;
|
||||
virtual float GetShininess() const = 0;
|
||||
|
||||
virtual bool GetUseColorMap() const = 0;
|
||||
virtual const AZ::Vector3& GetBaseColor() const = 0;
|
||||
virtual bool GetUseMetallicMap() const = 0;
|
||||
virtual float GetMetallicFactor() const = 0;
|
||||
virtual bool GetUseRoughnessMap() const = 0;
|
||||
virtual float GetRoughnessFactor() const = 0;
|
||||
virtual bool GetUseEmissiveMap() const = 0;
|
||||
virtual float GetEmissiveIntensity() const = 0;
|
||||
virtual bool GetUseAOMap() const = 0;
|
||||
|
||||
virtual uint64_t GetUniqueId() const = 0;
|
||||
};
|
||||
|
||||
@@ -44,6 +44,7 @@ namespace AZ
|
||||
float m_channels[4];
|
||||
};
|
||||
|
||||
Color() = default;
|
||||
Color(float r, float g, float b, float a)
|
||||
: red(r), green(g), blue(b), alpha(a)
|
||||
{
|
||||
@@ -53,6 +54,30 @@ namespace AZ
|
||||
{
|
||||
return m_channels[static_cast<AZ::u8>(channel)];
|
||||
}
|
||||
|
||||
bool IsClose(const Color& c, float tolerance = AZ::Constants::Tolerance) const
|
||||
{
|
||||
return (c - (*this)).Abs().IsLessEqualThan(tolerance);
|
||||
}
|
||||
|
||||
bool IsLessEqualThan(float tolerance) const
|
||||
{
|
||||
return AZStd::all_of(AZStd::begin(m_channels), AZStd::end(m_channels), [tolerance] (float channel) { return channel <= tolerance; } );
|
||||
}
|
||||
|
||||
Color& Abs()
|
||||
{
|
||||
for (float& channel : m_channels)
|
||||
{
|
||||
channel = std::abs(channel);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Color operator-(const Color& rhs) const
|
||||
{
|
||||
return Color(red - rhs.red, green - rhs.green, blue - rhs.blue, alpha - rhs.alpha);
|
||||
}
|
||||
};
|
||||
|
||||
class IMeshVertexColorData
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <SceneAPI/SceneCore/DataTypes/Rules/IRule.h>
|
||||
#include <SceneAPI/SceneCore/Utilities/CoordinateSystemConverter.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class ReflectContext;
|
||||
}
|
||||
|
||||
namespace AZ::SceneAPI::DataTypes
|
||||
{
|
||||
class ICoordinateSystemRule
|
||||
: public IRule
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(ICoordinateSystemRule, "{78136748-AC4B-4FC6-B9D8-C5820D67D29F}", IRule);
|
||||
|
||||
enum CoordinateSystem : int
|
||||
{
|
||||
ZUpPositiveYForward = 0,
|
||||
ZUpNegativeYForward = 1
|
||||
};
|
||||
|
||||
virtual ~ICoordinateSystemRule() override = default;
|
||||
|
||||
virtual void UpdateCoordinateSystemConverter() = 0;
|
||||
|
||||
virtual void SetTargetCoordinateSystem(CoordinateSystem targetCoordinateSystem) = 0;
|
||||
virtual CoordinateSystem GetTargetCoordinateSystem() const = 0;
|
||||
|
||||
virtual const CoordinateSystemConverter& GetCoordinateSystemConverter() const = 0;
|
||||
};
|
||||
} // namespace AZ::SceneAPI::DataTypes
|
||||
+9
-16
@@ -12,33 +12,26 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <SceneAPI/SceneCore/DataTypes/Rules/IRule.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class Quaternion;
|
||||
class Vector3;
|
||||
|
||||
namespace SceneAPI
|
||||
{
|
||||
namespace DataTypes
|
||||
{
|
||||
class IOriginRule
|
||||
class ISkinRule
|
||||
: public IRule
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(IOriginRule, "{9FB042DF-1C7F-4815-BC83-BF8D94F907C5}", IRule);
|
||||
AZ_RTTI(ISkinRule, "{5496ECAF-B096-4455-AE72-D55C5B675443}", IRule);
|
||||
|
||||
~ISkinRule() override = default;
|
||||
|
||||
virtual ~IOriginRule() override = default;
|
||||
|
||||
virtual const AZStd::string& GetOriginNodeName() const = 0;
|
||||
virtual bool UseRootAsOrigin() const = 0;
|
||||
virtual const AZ::Quaternion& GetRotation() const = 0;
|
||||
virtual const AZ::Vector3& GetTranslation() const = 0;
|
||||
virtual float GetScale() const = 0;
|
||||
virtual AZ::u32 GetMaxWeightsPerVertex() const = 0;
|
||||
virtual float GetWeightThreshold() const = 0;
|
||||
};
|
||||
} // DataTypes
|
||||
} // SceneAPI
|
||||
} // AZ
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <SceneAPI/SceneCore/DataTypes/Rules/IRule.h>
|
||||
#include <SceneAPI/SceneCore/DataTypes/ManifestBase/ISceneNodeSelectionList.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace SceneAPI
|
||||
{
|
||||
namespace DataTypes
|
||||
{
|
||||
/*!
|
||||
The author of the touch bendable asset will be able to define stiffness, damping and thickness
|
||||
as attributes per bone. Adding those kind of attributes to a node is supported
|
||||
by DCC tools and the FBX API (FbxProperty), but SceneAPI doesn't support parsing those attributes into the
|
||||
Scene Nodes or IGraphObjects. In the meantime, and while parsing Extra Atrributes is not supported by SceneAPI, the
|
||||
content author should manually set the values in this Modifier. The values will be applied to all bones.
|
||||
|
||||
The ShouldOverride*() methods are put in place so in the future the content author can override
|
||||
all the attributes at once without re-exporting assets from the DCC tools.
|
||||
This is more of a convenience.
|
||||
|
||||
If the original asset doesn't have any of these attributes in the bones, then the values
|
||||
of this rule will be applied to the root bone. Children bones will copy the parents attributes
|
||||
for all unspecified attributes.
|
||||
*/
|
||||
class ITouchBendingRule
|
||||
: public IRule
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(ITouchBendingRule, "{2FE2B499-DB71-4D69-8944-6DE2396D6E78}", IRule);
|
||||
|
||||
~ITouchBendingRule() override = default;
|
||||
|
||||
virtual const AZStd::string& GetRootBoneName() const = 0;
|
||||
|
||||
/*!
|
||||
The returned list contains only one mesh in 99.99% of the cases.
|
||||
The mesh is supposed to be the proximity trigger mesh.
|
||||
Most of the time the content author would want the proximity trigger mesh
|
||||
to be as simple as possible for performance reasons. So, something like a simple
|
||||
cube that covers the main render mesh is the ideal thing to do for collision detection.
|
||||
The selected proximity mesh is stored in a list, because there can be extreme cases
|
||||
where several meshes can define the proximity trigger volume. They will all be combined
|
||||
into a single submesh into the exported CGF file, at the expense of performance when the
|
||||
engine calculates if a vegetation mesh is being touched or not.
|
||||
*/
|
||||
virtual ISceneNodeSelectionList& GetSceneNodeSelectionList() = 0;
|
||||
virtual const ISceneNodeSelectionList& GetSceneNodeSelectionList() const = 0;
|
||||
|
||||
///If true, The stifness parameter for all the bones
|
||||
///in the tree will be set to GetOverrideStiffness(), replacing
|
||||
///the value set by the Author of the asset.
|
||||
virtual bool ShouldOverrideStiffness() const = 0;
|
||||
///A value from 0.0f to 1.0f.
|
||||
///0.0 means no stiffness, the tree will look like a sad willow.
|
||||
///Segments (bones) of the tree would never return to its original pose
|
||||
///after being pushed by a Collider.
|
||||
virtual float GetOverrideStiffness() const = 0;
|
||||
|
||||
///If true, The Damping parameter for all the bones
|
||||
///in the tree will be set to GetOverrideDamping(), replacing
|
||||
///the value set by the Author of the asset.
|
||||
virtual bool ShouldOverrideDamping() const = 0;
|
||||
///A value from 0.0 to 1.0. 0.0 means no damping, lots of back and forth movement around its original pose.
|
||||
///1.0 means maximum damping, the segment will quickly converge back to its original pose.
|
||||
virtual float GetOverrideDamping() const = 0;
|
||||
|
||||
///If true, The thickness parameter for all the bones
|
||||
///in the tree will be set to GetOverrideThickness(), replacing
|
||||
///the value set by the Author of the asset.
|
||||
virtual bool ShouldOverrideThickness() const = 0;
|
||||
///If you imagine the Segment (or Bone) to be a cylinder, this is its radius in meters.
|
||||
virtual float GetOverrideThickness() const = 0;
|
||||
|
||||
}; //class ITouchBendingRule
|
||||
} //namespace DataTypes
|
||||
} // namespace SceneAPI
|
||||
} // namespace AZ
|
||||
@@ -40,7 +40,6 @@
|
||||
#include <SceneAPI/SceneCore/DataTypes/Rules/ICommentRule.h>
|
||||
#include <SceneAPI/SceneCore/DataTypes/Rules/IMaterialRule.h>
|
||||
#include <SceneAPI/SceneCore/DataTypes/Rules/IMeshAdvancedRule.h>
|
||||
#include <SceneAPI/SceneCore/DataTypes/Rules/IOriginRule.h>
|
||||
#include <SceneAPI/SceneCore/DataTypes/Rules/ILodRule.h>
|
||||
#include <SceneAPI/SceneCore/DataTypes/Rules/ISkeletonProxyRule.h>
|
||||
#include <SceneAPI/SceneCore/DataTypes/GraphData/IAnimationData.h>
|
||||
@@ -166,7 +165,6 @@ namespace AZ
|
||||
context->Class<AZ::SceneAPI::DataTypes::ICommentRule, AZ::SceneAPI::DataTypes::IRule>()->Version(1);
|
||||
context->Class<AZ::SceneAPI::DataTypes::IMaterialRule, AZ::SceneAPI::DataTypes::IRule>()->Version(1);
|
||||
context->Class<AZ::SceneAPI::DataTypes::IMeshAdvancedRule, AZ::SceneAPI::DataTypes::IRule>()->Version(1);
|
||||
context->Class<AZ::SceneAPI::DataTypes::IOriginRule, AZ::SceneAPI::DataTypes::IRule>()->Version(1);
|
||||
context->Class<AZ::SceneAPI::DataTypes::ILodRule, AZ::SceneAPI::DataTypes::IRule>()->Version(1);
|
||||
context->Class<AZ::SceneAPI::DataTypes::ISkeletonProxyRule, AZ::SceneAPI::DataTypes::IRule>()->Version(1);
|
||||
// Register graph data interfaces
|
||||
|
||||
@@ -18,58 +18,18 @@ namespace AZ::SceneAPI::Events
|
||||
// PreGenerateEventContext
|
||||
/////////////
|
||||
|
||||
PreGenerateEventContext::PreGenerateEventContext(Containers::Scene& scene, const char* platformIdentifier)
|
||||
GenerateEventBaseContext::GenerateEventBaseContext(Containers::Scene& scene, const char* platformIdentifier)
|
||||
: m_scene(scene)
|
||||
, m_platformIdentifier(platformIdentifier)
|
||||
{
|
||||
}
|
||||
|
||||
Containers::Scene& PreGenerateEventContext::GetScene() const
|
||||
Containers::Scene& GenerateEventBaseContext::GetScene() const
|
||||
{
|
||||
return m_scene;
|
||||
}
|
||||
|
||||
const char* PreGenerateEventContext::GetPlatformIdentifier() const
|
||||
{
|
||||
return m_platformIdentifier;
|
||||
}
|
||||
|
||||
/////////////
|
||||
// GenerateEventContext
|
||||
/////////////
|
||||
|
||||
GenerateEventContext::GenerateEventContext(Containers::Scene& scene, const char* platformIdentifier)
|
||||
: m_scene(scene)
|
||||
, m_platformIdentifier(platformIdentifier)
|
||||
{
|
||||
}
|
||||
|
||||
Containers::Scene& GenerateEventContext::GetScene() const
|
||||
{
|
||||
return m_scene;
|
||||
}
|
||||
|
||||
const char* GenerateEventContext::GetPlatformIdentifier() const
|
||||
{
|
||||
return m_platformIdentifier;
|
||||
}
|
||||
|
||||
/////////////
|
||||
// PostGenerateEventContext
|
||||
/////////////
|
||||
|
||||
PostGenerateEventContext::PostGenerateEventContext(Containers::Scene& scene, const char* platformIdentifier)
|
||||
: m_scene(scene)
|
||||
, m_platformIdentifier(platformIdentifier)
|
||||
{
|
||||
}
|
||||
|
||||
Containers::Scene& PostGenerateEventContext::GetScene() const
|
||||
{
|
||||
return m_scene;
|
||||
}
|
||||
|
||||
const char* PostGenerateEventContext::GetPlatformIdentifier() const
|
||||
const char* GenerateEventBaseContext::GetPlatformIdentifier() const
|
||||
{
|
||||
return m_platformIdentifier;
|
||||
}
|
||||
|
||||
@@ -24,13 +24,13 @@ namespace AZ::SceneAPI::Events
|
||||
{
|
||||
class ExportProductList;
|
||||
|
||||
// Signals the scene generation step is about to happen
|
||||
class PreGenerateEventContext
|
||||
class GenerateEventBaseContext
|
||||
: public ICallContext
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(PreGenerateEventContext, "{0D1AB113-D35E-4C35-9820-E7B22F37D90C}", ICallContext)
|
||||
SCENE_CORE_API PreGenerateEventContext(Containers::Scene& scene, const char* platformIdentifier);
|
||||
AZ_RTTI(GenerateEventBaseContext, "{1717EB67-33A1-4516-8167-746093F7AEB6}", ICallContext)
|
||||
|
||||
SCENE_CORE_API GenerateEventBaseContext(Containers::Scene& scene, const char* platformIdentifier);
|
||||
|
||||
SCENE_CORE_API Containers::Scene& GetScene() const;
|
||||
SCENE_CORE_API const char* GetPlatformIdentifier() const;
|
||||
@@ -46,49 +46,57 @@ namespace AZ::SceneAPI::Events
|
||||
const char* m_platformIdentifier = nullptr;
|
||||
};
|
||||
|
||||
// Signals that all appropriate objects should be generated into the Scene
|
||||
class GenerateEventContext
|
||||
: public ICallContext
|
||||
// Signals the scene generation step is about to happen
|
||||
class PreGenerateEventContext
|
||||
: public GenerateEventBaseContext
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(GenerateEventContext, "{B53CCBBF-965A-4709-AD33-AFD5F3AE8580}", ICallContext)
|
||||
AZ_RTTI(PreGenerateEventContext, "{0D1AB113-D35E-4C35-9820-E7B22F37D90C}", GenerateEventBaseContext)
|
||||
using GenerateEventBaseContext::GenerateEventBaseContext;
|
||||
};
|
||||
|
||||
SCENE_CORE_API GenerateEventContext(Containers::Scene& scene, const char* platformIdentifier);
|
||||
// Signals that new data such as procedurally generated objects should be added to the Scene
|
||||
class GenerateEventContext
|
||||
: public GenerateEventBaseContext
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(GenerateEventContext, "{B53CCBBF-965A-4709-AD33-AFD5F3AE8580}", GenerateEventBaseContext)
|
||||
using GenerateEventBaseContext::GenerateEventBaseContext;
|
||||
};
|
||||
|
||||
SCENE_CORE_API Containers::Scene& GetScene() const;
|
||||
SCENE_CORE_API const char* GetPlatformIdentifier() const;
|
||||
// Signals that new LODs should be added to the Scene
|
||||
class GenerateLODEventContext
|
||||
: public GenerateEventBaseContext
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(GenerateLODEventContext, "{2E3A6B98-1409-4895-8092-B7F8A410EF0D}", GenerateEventBaseContext)
|
||||
using GenerateEventBaseContext::GenerateEventBaseContext;
|
||||
};
|
||||
|
||||
private:
|
||||
Containers::Scene& m_scene;
|
||||
|
||||
/**
|
||||
* The platform identifier is configured in the AssetProcessorPlatformConfig.ini and is data driven
|
||||
* it is generally a value like "pc" or "ios" or such.
|
||||
* this const char* points at memory owned by the caller but it will always survive for the duration of the call.
|
||||
*/
|
||||
const char* m_platformIdentifier = nullptr;
|
||||
// Signals that any new data, such as tangents and bitangents, should be added to the Scene
|
||||
class GenerateAdditionEventContext
|
||||
: public GenerateEventBaseContext
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(GenerateAdditionEventContext, "{105106FE-9ED7-48E6-9EA8-C7268BE8C625}", GenerateEventBaseContext)
|
||||
using GenerateEventBaseContext::GenerateEventBaseContext;
|
||||
};
|
||||
|
||||
// Signals that data simplification / complexity reduction should be run
|
||||
class GenerateSimplificationEventContext
|
||||
: public GenerateEventBaseContext
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(GenerateSimplificationEventContext, "{77F44B7F-C5BC-4411-B53F-E4307691841B}", GenerateEventBaseContext)
|
||||
using GenerateEventBaseContext::GenerateEventBaseContext;
|
||||
};
|
||||
|
||||
// Signals that the generation step is complete
|
||||
class PostGenerateEventContext
|
||||
: public ICallContext
|
||||
: public GenerateEventBaseContext
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(PostGenerateEventContext, "{3EE65CBF-6C0E-425A-9ECC-3CC8FC4372F7}", ICallContext)
|
||||
|
||||
SCENE_CORE_API PostGenerateEventContext(Containers::Scene& scene, const char* platformIdentifier);
|
||||
|
||||
SCENE_CORE_API Containers::Scene& GetScene() const;
|
||||
SCENE_CORE_API const char* GetPlatformIdentifier() const;
|
||||
|
||||
private:
|
||||
Containers::Scene& m_scene;
|
||||
|
||||
/**
|
||||
* The platform identifier is configured in the AssetProcessorPlatformConfig.ini and is data driven
|
||||
* it is generally a value like "pc" or "ios" or such.
|
||||
* this const char* points at memory owned by the caller but it will always survive for the duration of the call.
|
||||
*/
|
||||
const char* m_platformIdentifier = nullptr;
|
||||
AZ_RTTI(PostGenerateEventContext, "{3EE65CBF-6C0E-425A-9ECC-3CC8FC4372F7}", GenerateEventBaseContext)
|
||||
using GenerateEventBaseContext::GenerateEventBaseContext;
|
||||
};
|
||||
} // namespace AZ::SceneAPI::Events
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
#include <SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexColorData.h>
|
||||
#include <SceneAPI/SceneCore/DataTypes/Groups/ISceneNodeGroup.h>
|
||||
#include <SceneAPI/SceneCore/DataTypes/Rules/IMeshAdvancedRule.h>
|
||||
#include <SceneAPI/SceneCore/DataTypes/Rules/ITouchBendingRule.h>
|
||||
#include <SceneAPI/SceneCore/DataTypes/Rules/IMaterialRule.h>
|
||||
#include <SceneAPI/SceneCore/DataTypes/Rules/ILodRule.h>
|
||||
#include <SceneAPI/SceneCore/DataTypes/DataTypeUtilities.h>
|
||||
@@ -284,13 +283,6 @@ namespace AZ
|
||||
|
||||
int physicsMaterialFlags = 0;
|
||||
AZStd::vector<AZStd::string> targetNodes;
|
||||
AZStd::shared_ptr<const DataTypes::ITouchBendingRule> touchBendingRule = rules.FindFirstByType<DataTypes::ITouchBendingRule>();
|
||||
if (touchBendingRule)
|
||||
{
|
||||
targetNodes = Utilities::SceneGraphSelector::GenerateTargetNodes(sceneGraph,
|
||||
touchBendingRule->GetSceneNodeSelectionList(), Utilities::SceneGraphSelector::IsMesh);
|
||||
physicsMaterialFlags = AZ::GFxFramework::EMaterialFlags::MTL_FLAG_NODRAW_TOUCHBENDING;
|
||||
}
|
||||
for (auto& nodeName : targetNodes)
|
||||
{
|
||||
auto index = sceneGraph.Find(nodeName);
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include <SceneAPI/SceneCore/DataTypes/GraphData/IBlendShapeData.h>
|
||||
|
||||
namespace AZ::SceneAPI::DataTypes
|
||||
{
|
||||
class MockIBlendShapeData
|
||||
: public IBlendShapeData
|
||||
{
|
||||
public:
|
||||
MOCK_CONST_METHOD0(GetUsedControlPointCount, size_t());
|
||||
MOCK_CONST_METHOD1(GetControlPointIndex, int(int));
|
||||
MOCK_CONST_METHOD1(GetUsedPointIndexForControlPoint, int(int));
|
||||
MOCK_CONST_METHOD0(GetVertexCount, unsigned int());
|
||||
MOCK_CONST_METHOD0(GetFaceCount, unsigned int());
|
||||
MOCK_CONST_METHOD1(GetPosition, const AZ::Vector3&(unsigned int index));
|
||||
MOCK_CONST_METHOD1(GetNormal, const AZ::Vector3&(unsigned int index));
|
||||
MOCK_CONST_METHOD2(GetFaceVertexIndex, unsigned int(unsigned int face, unsigned int vertexIndex));
|
||||
};
|
||||
} // namespace AZ::SceneAPI::DataTypes
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include <SceneAPI/SceneCore/DataTypes/Rules/IBlendShapeRule.h>
|
||||
|
||||
namespace AZ::SceneAPI::DataTypes { class IMockSceneNodeSelectionList; }
|
||||
|
||||
namespace AZ::SceneAPI::DataTypes
|
||||
{
|
||||
class MockIBlendShapeRule
|
||||
: public IBlendShapeRule
|
||||
{
|
||||
public:
|
||||
ISceneNodeSelectionList& GetSceneNodeSelectionList() override
|
||||
{
|
||||
return const_cast<ISceneNodeSelectionList&>(static_cast<const MockIBlendShapeRule*>(this)->GetSceneNodeSelectionList());
|
||||
}
|
||||
|
||||
MOCK_CONST_METHOD0(GetSceneNodeSelectionList, const ISceneNodeSelectionList&());
|
||||
};
|
||||
} // namespace AZ::SceneAPI::DataTypes
|
||||
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <SceneAPI/SceneCore/Utilities/CoordinateSystemConverter.h>
|
||||
#include <AzCore/Math/Matrix3x3.h>
|
||||
|
||||
namespace AZ::SceneAPI
|
||||
{
|
||||
// Default constructor, initializes so that it basically does no conversion.
|
||||
CoordinateSystemConverter::CoordinateSystemConverter()
|
||||
: m_sourceTransform(AZ::Transform::CreateIdentity())
|
||||
, m_targetTransform(AZ::Transform::CreateIdentity())
|
||||
, m_conversionTransform(AZ::Transform::CreateIdentity())
|
||||
, m_conversionTransformInversed(AZ::Transform::CreateIdentity())
|
||||
, m_needsConversion(false)
|
||||
, m_sourceRightHanded(CheckIfIsRightHanded(m_sourceTransform))
|
||||
, m_targetRightHanded(CheckIfIsRightHanded(m_targetTransform))
|
||||
{
|
||||
m_targetBasisIndices[0] = 0;
|
||||
m_targetBasisIndices[1] = 1;
|
||||
m_targetBasisIndices[2] = 2;
|
||||
}
|
||||
|
||||
|
||||
CoordinateSystemConverter::CoordinateSystemConverter(const AZ::Vector3 sourceBasisVectors[3], const AZ::Vector3 targetBasisVectors[3], const AZ::u32 targetBasisIndices[3])
|
||||
{
|
||||
const AZ::Matrix3x3 sourceMatrix3x3 = AZ::Matrix3x3::CreateFromColumns(sourceBasisVectors[0], sourceBasisVectors[1], sourceBasisVectors[2]);
|
||||
m_sourceTransform = AZ::Transform::CreateFromMatrix3x3(sourceMatrix3x3);
|
||||
AZ_Assert(m_sourceTransform.IsOrthogonal(), "Invalid source transformation, basis vectors have to be orthogonal.");
|
||||
|
||||
const AZ::Matrix3x3 targetMatrix3x3 = AZ::Matrix3x3::CreateFromColumns(targetBasisVectors[0], targetBasisVectors[1], targetBasisVectors[2]);
|
||||
m_targetTransform = AZ::Transform::CreateFromMatrix3x3(targetMatrix3x3);
|
||||
AZ_Assert(m_targetTransform.IsOrthogonal(), "Invalid target transformation, basis vectors have to be orthogonal.");
|
||||
|
||||
m_conversionTransform = m_targetTransform * m_sourceTransform.GetInverse();
|
||||
m_conversionTransformInversed = m_conversionTransform.GetInverse();
|
||||
|
||||
m_targetBasisIndices[0] = targetBasisIndices[0];
|
||||
m_targetBasisIndices[1] = targetBasisIndices[1];
|
||||
m_targetBasisIndices[2] = targetBasisIndices[2];
|
||||
|
||||
m_needsConversion = (m_sourceTransform != m_targetTransform);
|
||||
m_sourceRightHanded = CheckIfIsRightHanded(m_sourceTransform);
|
||||
m_targetRightHanded = CheckIfIsRightHanded(m_targetTransform);
|
||||
}
|
||||
|
||||
|
||||
const CoordinateSystemConverter CoordinateSystemConverter::CreateFromBasisVectors(const AZ::Vector3 sourceBasisVectors[3], const AZ::Vector3 targetBasisVectors[3], const AZ::u32 targetBasisIndices[3])
|
||||
{
|
||||
return CoordinateSystemConverter(sourceBasisVectors, targetBasisVectors, targetBasisIndices);
|
||||
}
|
||||
|
||||
|
||||
const CoordinateSystemConverter CoordinateSystemConverter::CreateFromTransforms(const AZ::Transform& sourceTransform, const AZ::Transform& targetTransform, const AZ::u32 targetBasisIndices[3])
|
||||
{
|
||||
AZ::Vector3 sourceBasisVectors[3];
|
||||
sourceBasisVectors[0] = sourceTransform.GetBasisX();
|
||||
sourceBasisVectors[1] = sourceTransform.GetBasisY();
|
||||
sourceBasisVectors[2] = sourceTransform.GetBasisZ();
|
||||
|
||||
AZ::Vector3 targetBasisVectors[3];
|
||||
targetBasisVectors[0] = targetTransform.GetBasisX();
|
||||
targetBasisVectors[1] = targetTransform.GetBasisY();
|
||||
targetBasisVectors[2] = targetTransform.GetBasisZ();
|
||||
|
||||
return CoordinateSystemConverter(sourceBasisVectors, targetBasisVectors, targetBasisIndices);
|
||||
}
|
||||
|
||||
|
||||
bool CoordinateSystemConverter::CheckIfIsRightHanded(const AZ::Transform& transform) const
|
||||
{
|
||||
const AZ::Vector3 right = transform.GetBasisX();
|
||||
const AZ::Vector3 up = transform.GetBasisY();
|
||||
const AZ::Vector3 forward = transform.GetBasisZ();
|
||||
return ((right.Cross(up)).Dot(forward) <= 0.0f);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Conversions
|
||||
//-------------------------------------------------------------------------
|
||||
AZ::Quaternion CoordinateSystemConverter::ConvertQuaternion(const AZ::Quaternion& input) const
|
||||
{
|
||||
if (!m_needsConversion)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
const AZ::Vector3 vec = ConvertVector3( input.GetImaginary() );
|
||||
float w = input.GetW();
|
||||
if (m_sourceRightHanded != m_targetRightHanded)
|
||||
{
|
||||
w = -w;
|
||||
}
|
||||
|
||||
return AZ::Quaternion(vec.GetX(), vec.GetY(), vec.GetZ(), w);
|
||||
}
|
||||
|
||||
|
||||
AZ::Vector3 CoordinateSystemConverter::ConvertVector3(const AZ::Vector3& input) const
|
||||
{
|
||||
if (!m_needsConversion)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
return m_conversionTransform.TransformPoint(input);
|
||||
}
|
||||
|
||||
AZ::Transform CoordinateSystemConverter::ConvertTransform(const AZ::Transform& input) const
|
||||
{
|
||||
if (!m_needsConversion)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
return input * m_conversionTransform;
|
||||
}
|
||||
|
||||
AZ::Matrix3x4 CoordinateSystemConverter::ConvertMatrix3x4(const AZ::Matrix3x4 & input) const
|
||||
{
|
||||
if (!m_needsConversion)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
return input * AZ::Matrix3x4::CreateFromTransform(m_conversionTransform);
|
||||
}
|
||||
|
||||
|
||||
// Convert a scale value, which never flips some axis or so, just switches them.
|
||||
// Think of two coordinate systems, where for example the Z axis is inverted in one of them, the scale will remain the same, in both systems.
|
||||
// However, if we swap Y and Z, the scale Y and Z still have to be swapped.
|
||||
AZ::Vector3 CoordinateSystemConverter::ConvertScale(const AZ::Vector3& input) const
|
||||
{
|
||||
if (!m_needsConversion)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
return AZ::Vector3( input.GetElement(m_targetBasisIndices[0]),
|
||||
input.GetElement(m_targetBasisIndices[1]),
|
||||
input.GetElement(m_targetBasisIndices[2]) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Inverse Conversions
|
||||
//-------------------------------------------------------------------------
|
||||
AZ::Quaternion CoordinateSystemConverter::InverseConvertQuaternion(const AZ::Quaternion& input) const
|
||||
{
|
||||
if (!m_needsConversion)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
const AZ::Vector3 vec = InverseConvertVector3( input.GetImaginary() );
|
||||
float w = input.GetW();
|
||||
if (m_sourceRightHanded != m_targetRightHanded)
|
||||
{
|
||||
w = -w;
|
||||
}
|
||||
|
||||
return AZ::Quaternion(vec.GetX(), vec.GetY(), vec.GetZ(), w);
|
||||
}
|
||||
|
||||
|
||||
AZ::Vector3 CoordinateSystemConverter::InverseConvertVector3(const AZ::Vector3& input) const
|
||||
{
|
||||
if (!m_needsConversion)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
return m_conversionTransformInversed.TransformPoint(input);
|
||||
}
|
||||
|
||||
|
||||
AZ::Transform CoordinateSystemConverter::InverseConvertTransform(const AZ::Transform& input) const
|
||||
{
|
||||
if (!m_needsConversion)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
return input * m_conversionTransformInversed;
|
||||
}
|
||||
|
||||
|
||||
AZ::Vector3 CoordinateSystemConverter::InverseConvertScale(const AZ::Vector3& input) const
|
||||
{
|
||||
return ConvertScale(input);
|
||||
}
|
||||
} // namespace AZ::SceneAPI
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Math/Transform.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/Math/Quaternion.h>
|
||||
#include <SceneAPI/SceneCore/SceneCoreConfiguration.h>
|
||||
|
||||
namespace AZ::SceneAPI
|
||||
{
|
||||
class SCENE_CORE_API CoordinateSystemConverter
|
||||
{
|
||||
public:
|
||||
CoordinateSystemConverter();
|
||||
|
||||
static const CoordinateSystemConverter CreateFromBasisVectors(const AZ::Vector3 sourceBasisVectors[3], const AZ::Vector3 targetBasisVectors[3], const AZ::u32 targetBasisIndices[3]);
|
||||
static const CoordinateSystemConverter CreateFromTransforms(const AZ::Transform& sourceTransform, const AZ::Transform& targetTransform, const AZ::u32 targetBasisIndices[3]);
|
||||
|
||||
// Inline get data.
|
||||
bool IsConversionNeeded() const { return m_needsConversion; }
|
||||
bool IsSourceRightHanded() const { return m_sourceRightHanded; }
|
||||
bool IsTargetRightHanded() const { return m_targetRightHanded; }
|
||||
const AZ::Transform GetSourceTransform() const { return m_sourceTransform; }
|
||||
const AZ::Transform GetTargetTransform() const { return m_targetTransform; }
|
||||
const AZ::Transform GetConversionTransform() const { return m_conversionTransform; }
|
||||
const AZ::Transform GetInverseConversionTransform() const { return m_conversionTransformInversed; }
|
||||
|
||||
// Conversion methods.
|
||||
AZ::Quaternion ConvertQuaternion(const AZ::Quaternion& input) const;
|
||||
AZ::Vector3 ConvertVector3(const AZ::Vector3& input) const;
|
||||
AZ::Vector3 ConvertScale(const AZ::Vector3& input) const;
|
||||
AZ::Transform ConvertTransform(const AZ::Transform& input) const;
|
||||
AZ::Matrix3x4 ConvertMatrix3x4(const AZ::Matrix3x4 & input) const;
|
||||
|
||||
// Inverse conversion methods.
|
||||
AZ::Quaternion InverseConvertQuaternion(const AZ::Quaternion& input) const;
|
||||
AZ::Vector3 InverseConvertVector3(const AZ::Vector3& input) const;
|
||||
AZ::Vector3 InverseConvertScale(const AZ::Vector3& input) const;
|
||||
AZ::Transform InverseConvertTransform(const AZ::Transform& input) const;
|
||||
|
||||
// Helper methods.
|
||||
bool CheckIfIsRightHanded(const AZ::Transform& transform) const;
|
||||
|
||||
private:
|
||||
AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option")
|
||||
AZ::Transform m_sourceTransform;
|
||||
AZ::Transform m_targetTransform;
|
||||
AZ::Transform m_conversionTransform;
|
||||
AZ::Transform m_conversionTransformInversed;
|
||||
AZ_POP_DISABLE_OVERRIDE_WARNING
|
||||
AZ::u32 m_targetBasisIndices[3];
|
||||
bool m_needsConversion;
|
||||
bool m_sourceRightHanded;
|
||||
bool m_targetRightHanded;
|
||||
|
||||
CoordinateSystemConverter(const AZ::Vector3 sourceBasisVectors[3], const AZ::Vector3 targetBasisVectors[3], const AZ::u32 targetBasisIndices[3]);
|
||||
};
|
||||
} // namespace AZ::SceneAPI
|
||||
@@ -44,7 +44,18 @@ namespace AZ
|
||||
return object && object->RTTI_IsTypeOf(DataTypes::IMeshData::TYPEINFO_Uuid());
|
||||
}
|
||||
|
||||
AZStd::vector<AZStd::string> SceneGraphSelector::GenerateTargetNodes(const Containers::SceneGraph& graph, const DataTypes::ISceneNodeSelectionList& list, NodeFilterFunction nodeFilter)
|
||||
Containers::SceneGraph::NodeIndex SceneGraphSelector::RemapToOptimizedMesh(const Containers::SceneGraph& graph, const Containers::SceneGraph::NodeIndex& index)
|
||||
{
|
||||
const auto& nodeName = graph.GetNodeName(index);
|
||||
const AZStd::string optimizedName = AZStd::string(nodeName.GetPath(), nodeName.GetPathLength()) + "_optimized";
|
||||
if (auto optimizedIndex = graph.Find(optimizedName); optimizedIndex.IsValid())
|
||||
{
|
||||
return optimizedIndex;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
AZStd::vector<AZStd::string> SceneGraphSelector::GenerateTargetNodes(const Containers::SceneGraph& graph, const DataTypes::ISceneNodeSelectionList& list, NodeFilterFunction nodeFilter, NodeRemapFunction nodeRemap)
|
||||
{
|
||||
AZStd::vector<AZStd::string> targetNodes;
|
||||
AZStd::set<AZStd::string> selectedNodesSet;
|
||||
@@ -52,8 +63,8 @@ namespace AZ
|
||||
CopySelectionToSet(selectedNodesSet, unselectedNodesSet, list);
|
||||
CorrectRootNode(graph, selectedNodesSet, unselectedNodesSet);
|
||||
|
||||
auto nodeIterator = graph.ConvertToHierarchyIterator(graph.GetRoot());
|
||||
auto view = Containers::Views::MakeSceneGraphDownwardsView<Containers::Views::BreadthFirst>(graph, nodeIterator, graph.GetContentStorage().cbegin(), true);
|
||||
const auto nodeIterator = graph.ConvertToHierarchyIterator(graph.GetRoot());
|
||||
const auto view = Containers::Views::MakeSceneGraphDownwardsView<Containers::Views::BreadthFirst>(graph, nodeIterator, graph.GetContentStorage().cbegin(), true);
|
||||
if (view.begin() == view.end())
|
||||
{
|
||||
return targetNodes;
|
||||
@@ -62,15 +73,24 @@ namespace AZ
|
||||
{
|
||||
Containers::SceneGraph::NodeIndex index = graph.ConvertToNodeIndex(it.GetHierarchyIterator());
|
||||
AZStd::string currentNodeName = graph.GetNodeName(index).GetPath();
|
||||
if (unselectedNodesSet.find(currentNodeName) != unselectedNodesSet.end())
|
||||
if (unselectedNodesSet.contains(currentNodeName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (selectedNodesSet.find(currentNodeName) != selectedNodesSet.end())
|
||||
if (selectedNodesSet.contains(currentNodeName))
|
||||
{
|
||||
if (nodeFilter(graph, index))
|
||||
{
|
||||
targetNodes.push_back(currentNodeName);
|
||||
Containers::SceneGraph::NodeIndex remappedIndex = nodeRemap(graph, index);
|
||||
if (remappedIndex == index)
|
||||
{
|
||||
targetNodes.emplace_back(AZStd::move(currentNodeName));
|
||||
}
|
||||
else
|
||||
{
|
||||
const Containers::SceneGraph::Name& nodeName = graph.GetNodeName(remappedIndex);
|
||||
targetNodes.emplace_back(nodeName.GetPath(), nodeName.GetPathLength());
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -79,16 +99,25 @@ namespace AZ
|
||||
if (parentIndex.IsValid())
|
||||
{
|
||||
AZStd::string parentNodeName = graph.GetNodeName(parentIndex).GetPath();
|
||||
if (unselectedNodesSet.find(parentNodeName) != unselectedNodesSet.end())
|
||||
if (unselectedNodesSet.contains(parentNodeName))
|
||||
{
|
||||
unselectedNodesSet.insert(currentNodeName);
|
||||
}
|
||||
else if (selectedNodesSet.find(parentNodeName) != selectedNodesSet.end())
|
||||
else if (selectedNodesSet.contains(parentNodeName))
|
||||
{
|
||||
selectedNodesSet.insert(currentNodeName);
|
||||
if (nodeFilter(graph, index))
|
||||
{
|
||||
targetNodes.push_back(currentNodeName);
|
||||
Containers::SceneGraph::NodeIndex remappedIndex = nodeRemap(graph, index);
|
||||
if (remappedIndex == index)
|
||||
{
|
||||
targetNodes.emplace_back(AZStd::move(currentNodeName));
|
||||
}
|
||||
else
|
||||
{
|
||||
const Containers::SceneGraph::Name& nodeName = graph.GetNodeName(remappedIndex);
|
||||
targetNodes.emplace_back(nodeName.GetPath(), nodeName.GetPathLength());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -159,12 +188,12 @@ namespace AZ
|
||||
Containers::SceneGraph::NodeIndex index = graph.ConvertToNodeIndex(it.GetHierarchyIterator());
|
||||
AZStd::string currentNodeName = it->first.GetPath();
|
||||
// Check if item is already registered and if so add it to the appropriate list.
|
||||
if (unselectedNodesSet.find(currentNodeName) != unselectedNodesSet.end())
|
||||
if (unselectedNodesSet.contains(currentNodeName))
|
||||
{
|
||||
list.RemoveSelectedNode(AZStd::move(currentNodeName));
|
||||
continue;
|
||||
}
|
||||
if (selectedNodesSet.find(currentNodeName) != selectedNodesSet.end())
|
||||
if (selectedNodesSet.contains(currentNodeName))
|
||||
{
|
||||
list.AddSelectedNode(AZStd::move(currentNodeName));
|
||||
continue;
|
||||
@@ -176,7 +205,7 @@ namespace AZ
|
||||
if (parentIndex.IsValid())
|
||||
{
|
||||
AZStd::string parentNodeName = graph.GetNodeName(parentIndex).GetPath();
|
||||
if (unselectedNodesSet.find(parentNodeName) != unselectedNodesSet.end())
|
||||
if (unselectedNodesSet.contains(parentNodeName))
|
||||
{
|
||||
unselectedNodesSet.insert(currentNodeName);
|
||||
list.RemoveSelectedNode(AZStd::move(currentNodeName));
|
||||
@@ -208,7 +237,7 @@ namespace AZ
|
||||
AZStd::string currentNodeName = it->first.GetPath();
|
||||
if (nodeFilter(graph, index))
|
||||
{
|
||||
if (targetNodes.find(currentNodeName) != targetNodes.end())
|
||||
if (targetNodes.contains(currentNodeName))
|
||||
{
|
||||
list.AddSelectedNode(currentNodeName);
|
||||
}
|
||||
|
||||
@@ -18,39 +18,38 @@
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
#include <SceneAPI/SceneCore/Containers/SceneGraph.h>
|
||||
|
||||
namespace AZ
|
||||
namespace AZ::SceneAPI::DataTypes { class ISceneNodeSelectionList; }
|
||||
|
||||
namespace AZ::SceneAPI::Utilities
|
||||
{
|
||||
namespace SceneAPI
|
||||
// SceneGraphSelector provides utilities including converting selected and unselected node lists
|
||||
// in the MeshGroup into the final target node list.
|
||||
class SceneGraphSelector
|
||||
{
|
||||
namespace DataTypes
|
||||
public:
|
||||
using NodeFilterFunction = bool(const Containers::SceneGraph& graph, Containers::SceneGraph::NodeIndex& index);
|
||||
using NodeRemapFunction = Containers::SceneGraph::NodeIndex(const Containers::SceneGraph& graph, const Containers::SceneGraph::NodeIndex& index);
|
||||
|
||||
SCENE_CORE_API static AZStd::vector<AZStd::string> GenerateTargetNodes(const Containers::SceneGraph& graph, const DataTypes::ISceneNodeSelectionList& list,
|
||||
NodeFilterFunction nodeFilter, NodeRemapFunction nodeRemap = NoRemap);
|
||||
SCENE_CORE_API static void SelectAll(const Containers::SceneGraph& graph, DataTypes::ISceneNodeSelectionList& list);
|
||||
SCENE_CORE_API static void UnselectAll(const Containers::SceneGraph& graph, DataTypes::ISceneNodeSelectionList& list);
|
||||
SCENE_CORE_API static void UpdateNodeSelection(const Containers::SceneGraph& graph, DataTypes::ISceneNodeSelectionList& list);
|
||||
SCENE_CORE_API static void UpdateTargetNodes(const Containers::SceneGraph& graph, DataTypes::ISceneNodeSelectionList& list,
|
||||
const AZStd::unordered_set<AZStd::string>& targetNodes, NodeFilterFunction nodeFilter);
|
||||
|
||||
SCENE_CORE_API static bool IsTreeViewType(const Containers::SceneGraph& graph, Containers::SceneGraph::NodeIndex& index);
|
||||
SCENE_CORE_API static bool IsMesh(const Containers::SceneGraph& graph, Containers::SceneGraph::NodeIndex& index);
|
||||
SCENE_CORE_API static bool IsMeshObject(const AZStd::shared_ptr<const DataTypes::IGraphObject>& object);
|
||||
|
||||
SCENE_CORE_API static Containers::SceneGraph::NodeIndex NoRemap(const Containers::SceneGraph& /*graph*/, const Containers::SceneGraph::NodeIndex& index)
|
||||
{
|
||||
class ISceneNodeSelectionList;
|
||||
return index;
|
||||
}
|
||||
namespace Utilities
|
||||
{
|
||||
// SceneGraphSelector provides utilities including converting selected and unselected node lists
|
||||
// in the MeshGroup into the final target node list.
|
||||
class SceneGraphSelector
|
||||
{
|
||||
public:
|
||||
using NodeFilterFunction = AZStd::function<bool(const Containers::SceneGraph& graph, Containers::SceneGraph::NodeIndex& index)>;
|
||||
SCENE_CORE_API static Containers::SceneGraph::NodeIndex RemapToOptimizedMesh(const Containers::SceneGraph& graph, const Containers::SceneGraph::NodeIndex& index);
|
||||
|
||||
SCENE_CORE_API static AZStd::vector<AZStd::string> GenerateTargetNodes(const Containers::SceneGraph& graph, const DataTypes::ISceneNodeSelectionList& list,
|
||||
NodeFilterFunction nodeFilter);
|
||||
SCENE_CORE_API static void SelectAll(const Containers::SceneGraph& graph, DataTypes::ISceneNodeSelectionList& list);
|
||||
SCENE_CORE_API static void UnselectAll(const Containers::SceneGraph& graph, DataTypes::ISceneNodeSelectionList& list);
|
||||
SCENE_CORE_API static void UpdateNodeSelection(const Containers::SceneGraph& graph, DataTypes::ISceneNodeSelectionList& list);
|
||||
SCENE_CORE_API static void UpdateTargetNodes(const Containers::SceneGraph& graph, DataTypes::ISceneNodeSelectionList& list,
|
||||
const AZStd::unordered_set<AZStd::string>& targetNodes, NodeFilterFunction nodeFilter);
|
||||
|
||||
SCENE_CORE_API static bool IsTreeViewType(const Containers::SceneGraph& graph, Containers::SceneGraph::NodeIndex& index);
|
||||
SCENE_CORE_API static bool IsMesh(const Containers::SceneGraph& graph, Containers::SceneGraph::NodeIndex& index);
|
||||
SCENE_CORE_API static bool IsMeshObject(const AZStd::shared_ptr<const DataTypes::IGraphObject>& object);
|
||||
|
||||
private:
|
||||
static void CopySelectionToSet(AZStd::set<AZStd::string>& selected, AZStd::set<AZStd::string>& unselected, const DataTypes::ISceneNodeSelectionList& list);
|
||||
static void CorrectRootNode(const Containers::SceneGraph& graph, AZStd::set<AZStd::string>& selected, AZStd::set<AZStd::string>& unselected);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
static void CopySelectionToSet(AZStd::set<AZStd::string>& selected, AZStd::set<AZStd::string>& unselected, const DataTypes::ISceneNodeSelectionList& list);
|
||||
static void CorrectRootNode(const Containers::SceneGraph& graph, AZStd::set<AZStd::string>& selected, AZStd::set<AZStd::string>& unselected);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -43,12 +43,12 @@ set(FILES
|
||||
DataTypes/Rules/ICommentRule.h
|
||||
DataTypes/Rules/ILodRule.h
|
||||
DataTypes/Rules/IMeshAdvancedRule.h
|
||||
DataTypes/Rules/IOriginRule.h
|
||||
DataTypes/Rules/IMaterialRule.h
|
||||
DataTypes/Rules/IScriptProcessorRule.h
|
||||
DataTypes/Rules/ISkeletonProxyRule.h
|
||||
DataTypes/Rules/ITouchBendingRule.h
|
||||
DataTypes/Rules/ICoordinateSystemRule.h
|
||||
DataTypes/Rules/IClothRule.h
|
||||
DataTypes/Rules/ISkinRule.h
|
||||
Components/BehaviorComponent.h
|
||||
Components/BehaviorComponent.cpp
|
||||
Components/ExportingComponent.h
|
||||
@@ -123,6 +123,8 @@ set(FILES
|
||||
Import/ManifestImportRequestHandler.cpp
|
||||
Export/MtlMaterialExporter.h
|
||||
Export/MtlMaterialExporter.cpp
|
||||
Utilities/CoordinateSystemConverter.h
|
||||
Utilities/CoordinateSystemConverter.cpp
|
||||
Utilities/SceneGraphSelector.h
|
||||
Utilities/SceneGraphSelector.cpp
|
||||
Utilities/FileUtilities.h
|
||||
|
||||
@@ -115,7 +115,8 @@ namespace AZ
|
||||
|
||||
Events::ProcessingResult MeshGroup::BuildDefault(Containers::Scene& scene) const
|
||||
{
|
||||
if (SceneHasMeshGroup(scene) || !Utilities::DoesSceneGraphContainDataLike<DataTypes::IMeshData>(scene, true) || Utilities::DoesSceneGraphContainDataLike<DataTypes::IBoneData>(scene, true))
|
||||
if (SceneHasMeshGroup(scene) ||
|
||||
!Utilities::DoesSceneGraphContainDataLike<DataTypes::IMeshData>(scene, true))
|
||||
{
|
||||
return Events::ProcessingResult::Ignored;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <SceneAPI/SceneData/Behaviors/ScriptProcessorRuleBehavior.h>
|
||||
#include <SceneAPI/SceneData/Behaviors/SkeletonGroup.h>
|
||||
#include <SceneAPI/SceneData/Behaviors/SkinGroup.h>
|
||||
#include <SceneAPI/SceneData/Behaviors/SkinRuleBehavior.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -40,7 +41,8 @@ namespace AZ
|
||||
Behaviors::MeshGroup::CreateDescriptor(),
|
||||
Behaviors::ScriptProcessorRuleBehavior::CreateDescriptor(),
|
||||
Behaviors::SkeletonGroup::CreateDescriptor(),
|
||||
Behaviors::SkinGroup::CreateDescriptor()
|
||||
Behaviors::SkinGroup::CreateDescriptor(),
|
||||
SkinRuleBehavior::CreateDescriptor()
|
||||
});
|
||||
}
|
||||
} // SceneData
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <SceneAPI/SceneCore/Containers/Views/FilterIterator.h>
|
||||
#include <SceneAPI/SceneCore/Containers/Views/PairIterator.h>
|
||||
#include <SceneAPI/SceneData/Rules/ScriptProcessorRule.h>
|
||||
#include <SceneAPI/SceneCore/Utilities/Reporting.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -36,6 +37,41 @@ namespace AZ
|
||||
{
|
||||
namespace Behaviors
|
||||
{
|
||||
class EditorPythonConsoleNotificationHandler final
|
||||
: protected AzToolsFramework::EditorPythonConsoleNotificationBus::Handler
|
||||
{
|
||||
public:
|
||||
EditorPythonConsoleNotificationHandler()
|
||||
{
|
||||
BusConnect();
|
||||
}
|
||||
|
||||
~EditorPythonConsoleNotificationHandler()
|
||||
{
|
||||
BusDisconnect();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// AzToolsFramework::EditorPythonConsoleNotifications
|
||||
void OnTraceMessage(AZStd::string_view message) override
|
||||
{
|
||||
using namespace AZ::SceneAPI::Utilities;
|
||||
AZ_TracePrintf(LogWindow, "%.*s \n", AZ_STRING_ARG(message));
|
||||
}
|
||||
|
||||
void OnErrorMessage(AZStd::string_view message) override
|
||||
{
|
||||
using namespace AZ::SceneAPI::Utilities;
|
||||
AZ_TracePrintf(ErrorWindow, "[ERROR] %.*s \n", AZ_STRING_ARG(message));
|
||||
}
|
||||
|
||||
void OnExceptionMessage(AZStd::string_view message) override
|
||||
{
|
||||
using namespace AZ::SceneAPI::Utilities;
|
||||
AZ_TracePrintf(ErrorWindow, "[EXCEPTION] %.*s \n", AZ_STRING_ARG(message));
|
||||
}
|
||||
};
|
||||
|
||||
// a event bus to signal during scene building
|
||||
struct ScriptBuildingNotifications
|
||||
: public AZ::EBusTraits
|
||||
@@ -182,6 +218,7 @@ namespace AZ
|
||||
&ScriptBuildingNotificationBus::Events::OnUpdateManifest,
|
||||
scene);
|
||||
};
|
||||
EditorPythonConsoleNotificationHandler logger;
|
||||
m_editorPythonEventsInterface->ExecuteWithLock(executeCallback);
|
||||
|
||||
// attempt to load the manifest string back to a JSON-scene-manifest
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <SceneAPI/SceneCore/Containers/Scene.h>
|
||||
#include <SceneAPI/SceneCore/Containers/Utilities/SceneGraphUtilities.h>
|
||||
#include <SceneAPI/SceneCore/DataTypes/Groups/IMeshGroup.h>
|
||||
#include <SceneAPI/SceneCore/DataTypes/GraphData/ISkinWeightData.h>
|
||||
#include <SceneAPI/SceneData/Rules/SkinRule.h>
|
||||
#include <SceneAPI/SceneData/Behaviors/SkinRuleBehavior.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace SceneAPI
|
||||
{
|
||||
namespace SceneData
|
||||
{
|
||||
void SkinRuleBehavior::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
SkinRule::Reflect(context);
|
||||
|
||||
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<SkinRuleBehavior, SceneCore::BehaviorComponent>()->Version(1);
|
||||
}
|
||||
}
|
||||
|
||||
void SkinRuleBehavior::Activate()
|
||||
{
|
||||
AZ::SceneAPI::Events::ManifestMetaInfoBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
void SkinRuleBehavior::Deactivate()
|
||||
{
|
||||
AZ::SceneAPI::Events::ManifestMetaInfoBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void SkinRuleBehavior::InitializeObject([[maybe_unused]] const Containers::Scene& scene, DataTypes::IManifestObject& target)
|
||||
{
|
||||
if (azrtti_istypeof<DataTypes::IMeshGroup>(target))
|
||||
{
|
||||
DataTypes::IMeshGroup* meshGroup = azrtti_cast<DataTypes::IMeshGroup*>(&target);
|
||||
|
||||
AZ::SceneAPI::Containers::RuleContainer& rules = meshGroup->GetRuleContainer();
|
||||
// Only add the skin rule if the scene contain any skinning data.
|
||||
if (!rules.ContainsRuleOfType<SkinRule>() && Utilities::DoesSceneGraphContainDataLike<DataTypes::ISkinWeightData>(scene, true))
|
||||
{
|
||||
rules.AddRule(AZStd::make_shared<SkinRule>());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Memory/Memory.h>
|
||||
#include <SceneAPI/SceneCore/Events/ManifestMetaInfoBus.h>
|
||||
#include <SceneAPI/SceneCore/Components/BehaviorComponent.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace SceneAPI
|
||||
{
|
||||
namespace SceneData
|
||||
{
|
||||
class SkinRuleBehavior
|
||||
: public SceneCore::BehaviorComponent
|
||||
, public Events::ManifestMetaInfoBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(SkinRuleBehavior, "{B212A863-32DD-4F92-948C-FC0ADAEEAB4A}", SceneCore::BehaviorComponent);
|
||||
|
||||
~SkinRuleBehavior() override = default;
|
||||
|
||||
// From BehaviorComponent
|
||||
void Activate() override;
|
||||
void Deactivate() override;
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
void InitializeObject(const Containers::Scene& scene, DataTypes::IManifestObject& target) override;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -144,6 +144,96 @@ namespace AZ
|
||||
return m_shininess;
|
||||
}
|
||||
|
||||
void MaterialData::SetUseColorMap(bool useColorMap)
|
||||
{
|
||||
m_useColorMap = useColorMap;
|
||||
}
|
||||
|
||||
bool MaterialData::GetUseColorMap() const
|
||||
{
|
||||
return m_useColorMap;
|
||||
}
|
||||
|
||||
void MaterialData::SetBaseColor(const AZ::Vector3& baseColor)
|
||||
{
|
||||
m_baseColor = baseColor;
|
||||
}
|
||||
|
||||
const AZ::Vector3& MaterialData::GetBaseColor() const
|
||||
{
|
||||
return m_baseColor;
|
||||
}
|
||||
|
||||
void MaterialData::SetUseMetallicMap(bool useMetallicMap)
|
||||
{
|
||||
m_useMetallicMap = useMetallicMap;
|
||||
}
|
||||
|
||||
bool MaterialData::GetUseMetallicMap() const
|
||||
{
|
||||
return m_useMetallicMap;
|
||||
}
|
||||
|
||||
void MaterialData::SetMetallicFactor(float metallicFactor)
|
||||
{
|
||||
m_metallicFactor = metallicFactor;
|
||||
}
|
||||
|
||||
float MaterialData::GetMetallicFactor() const
|
||||
{
|
||||
return m_metallicFactor;
|
||||
}
|
||||
|
||||
void MaterialData::SetUseRoughnessMap(bool useRoughnessMap)
|
||||
{
|
||||
m_useRoughnessMap = useRoughnessMap;
|
||||
}
|
||||
|
||||
bool MaterialData::GetUseRoughnessMap() const
|
||||
{
|
||||
return m_useRoughnessMap;
|
||||
}
|
||||
|
||||
void MaterialData::SetRoughnessFactor(float roughnessFactor)
|
||||
{
|
||||
m_roughnessFactor = roughnessFactor;
|
||||
}
|
||||
|
||||
float MaterialData::GetRoughnessFactor() const
|
||||
{
|
||||
return m_roughnessFactor;
|
||||
}
|
||||
|
||||
void MaterialData::SetUseEmissiveMap(bool useEmissiveMap)
|
||||
{
|
||||
m_useEmissiveMap = useEmissiveMap;
|
||||
}
|
||||
|
||||
bool MaterialData::GetUseEmissiveMap() const
|
||||
{
|
||||
return m_useEmissiveMap;
|
||||
}
|
||||
|
||||
void MaterialData::SetEmissiveIntensity(float emissiveIntensity)
|
||||
{
|
||||
m_emissiveIntensity = emissiveIntensity;
|
||||
}
|
||||
|
||||
float MaterialData::GetEmissiveIntensity() const
|
||||
{
|
||||
return m_emissiveIntensity;
|
||||
}
|
||||
|
||||
void MaterialData::SetUseAOMap(bool useAOMap)
|
||||
{
|
||||
m_useAOMap = useAOMap;
|
||||
}
|
||||
|
||||
bool MaterialData::GetUseAOMap() const
|
||||
{
|
||||
return m_useAOMap;
|
||||
}
|
||||
|
||||
uint64_t MaterialData::GetUniqueId() const
|
||||
{
|
||||
return m_uniqueId;
|
||||
@@ -154,7 +244,7 @@ namespace AZ
|
||||
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<MaterialData>()->Version(2)
|
||||
serializeContext->Class<MaterialData>()->Version(4)
|
||||
->Field("textureMap", &MaterialData::m_textureMap)
|
||||
->Field("diffuseColor", &MaterialData::m_diffuseColor)
|
||||
->Field("specularColor", &MaterialData::m_specularColor)
|
||||
@@ -162,7 +252,16 @@ namespace AZ
|
||||
->Field("opacity", &MaterialData::m_opacity)
|
||||
->Field("shininess", &MaterialData::m_shininess)
|
||||
->Field("noDraw", &MaterialData::m_isNoDraw)
|
||||
->Field("uniqueId", &MaterialData::m_uniqueId);
|
||||
->Field("uniqueId", &MaterialData::m_uniqueId)
|
||||
->Field("useColorMap", &MaterialData::m_useColorMap)
|
||||
->Field("baseColor", &MaterialData::m_baseColor)
|
||||
->Field("useMetallicMap", &MaterialData::m_useMetallicMap)
|
||||
->Field("metallicFactor", &MaterialData::m_metallicFactor)
|
||||
->Field("useRoughnessMap", &MaterialData::m_useRoughnessMap)
|
||||
->Field("roughnessFactor", &MaterialData::m_roughnessFactor)
|
||||
->Field("useEmissiveMap", &MaterialData::m_useEmissiveMap)
|
||||
->Field("emissiveIntensity", &MaterialData::m_emissiveIntensity)
|
||||
->Field("useAOMap", &MaterialData::m_useAOMap);
|
||||
|
||||
EditContext* editContext = serializeContext->GetEditContext();
|
||||
if (editContext)
|
||||
@@ -183,7 +282,16 @@ namespace AZ
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialData::m_opacity, "Opacity", "Opacity strength of the material, with 0 fully transparent and 1 fully opaque.")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialData::m_shininess, "Shininess", "The shininess strength of the material.")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialData::m_isNoDraw, "No draw", "If enabled the mesh with material will not be drawn.")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialData::m_textureMap, "Texture map", "List of assigned texture slots.");
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialData::m_textureMap, "Texture map", "List of assigned texture slots.")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialData::m_useColorMap, "Use Color Map", "True to use a color map, false to ignore it.")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialData::m_baseColor, "Base Color", "The base color of the material.")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialData::m_useMetallicMap, "Use Metallic Map", "True to use a metallic map, false to ignore it.")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialData::m_metallicFactor, "Metallic Factor", "How metallic the material is.")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialData::m_useRoughnessMap, "Use Roughness Map", "True to use a roughness map, false to ignore it.")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialData::m_roughnessFactor, "Roughness Factor", "How rough the material is.")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialData::m_useEmissiveMap, "Use Emissive Map", "True to use an emissive map, false to ignore it.")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialData::m_emissiveIntensity, "Emissive Intensity", "The intensity of the emissiveness of the material.")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialData::m_useAOMap, "Use Ambient Occlusion Map", "True to use an ambient occlusion map, false to ignore it.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,16 @@ namespace AZ
|
||||
SCENE_DATA_API virtual void SetOpacity(float opacity);
|
||||
SCENE_DATA_API virtual void SetShininess(float shininess);
|
||||
SCENE_DATA_API virtual void SetUniqueId(uint64_t uid);
|
||||
SCENE_DATA_API virtual void SetUseColorMap(bool useColorMap);
|
||||
SCENE_DATA_API virtual void SetBaseColor(const AZ::Vector3& baseColor);
|
||||
SCENE_DATA_API virtual void SetUseMetallicMap(bool useMetallicMap);
|
||||
SCENE_DATA_API virtual void SetMetallicFactor(float metallicFactor);
|
||||
SCENE_DATA_API virtual void SetUseRoughnessMap(bool useRoughnessMap);
|
||||
SCENE_DATA_API virtual void SetRoughnessFactor(float roughnessFactor);
|
||||
SCENE_DATA_API virtual void SetUseEmissiveMap(bool useEmissiveMap);
|
||||
SCENE_DATA_API virtual void SetEmissiveIntensity(float emissiveIntensity);
|
||||
SCENE_DATA_API virtual void SetUseAOMap(bool useAOMap);
|
||||
|
||||
|
||||
SCENE_DATA_API const AZStd::string& GetTexture(TextureMapType mapType) const override;
|
||||
SCENE_DATA_API bool IsNoDraw() const override;
|
||||
@@ -57,6 +67,15 @@ namespace AZ
|
||||
SCENE_DATA_API float GetOpacity() const override;
|
||||
SCENE_DATA_API float GetShininess() const override;
|
||||
SCENE_DATA_API uint64_t GetUniqueId() const override;
|
||||
SCENE_DATA_API bool GetUseColorMap() const override;
|
||||
SCENE_DATA_API const AZ::Vector3& GetBaseColor() const override;
|
||||
SCENE_DATA_API bool GetUseMetallicMap() const override;
|
||||
SCENE_DATA_API float GetMetallicFactor() const override;
|
||||
SCENE_DATA_API bool GetUseRoughnessMap() const override;
|
||||
SCENE_DATA_API float GetRoughnessFactor() const override;
|
||||
SCENE_DATA_API bool GetUseEmissiveMap() const override;
|
||||
SCENE_DATA_API float GetEmissiveIntensity() const override;
|
||||
SCENE_DATA_API bool GetUseAOMap() const override;
|
||||
|
||||
static void Reflect(ReflectContext* context);
|
||||
|
||||
@@ -66,8 +85,18 @@ namespace AZ
|
||||
AZ::Vector3 m_diffuseColor;
|
||||
AZ::Vector3 m_specularColor;
|
||||
AZ::Vector3 m_emissiveColor;
|
||||
AZ::Vector3 m_baseColor;
|
||||
float m_opacity;
|
||||
float m_shininess;
|
||||
float m_metallicFactor = 0.0f;
|
||||
float m_roughnessFactor = 0.0f;
|
||||
float m_emissiveIntensity = 0.0f;
|
||||
|
||||
bool m_useColorMap = false;
|
||||
bool m_useMetallicMap = false;
|
||||
bool m_useRoughnessMap = false;
|
||||
bool m_useEmissiveMap = false;
|
||||
bool m_useAOMap = false;
|
||||
|
||||
bool m_isNoDraw;
|
||||
|
||||
|
||||
@@ -12,15 +12,65 @@
|
||||
|
||||
#include <SceneAPI/SceneData/GraphData/MeshData.h>
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
AZ_TYPE_INFO_SPECIALIZE(AZ::SceneAPI::DataTypes::IMeshData::Face, "{F9F49C1A-014F-46F5-A46F-B56D8CB46C2B}");
|
||||
|
||||
namespace SceneData
|
||||
{
|
||||
namespace GraphData
|
||||
{
|
||||
namespace DataTypes = AZ::SceneAPI::DataTypes;
|
||||
|
||||
void MeshData::Reflect(ReflectContext* context)
|
||||
{
|
||||
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<MeshData>()->Version(1);
|
||||
}
|
||||
|
||||
BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context);
|
||||
if (behaviorContext)
|
||||
{
|
||||
behaviorContext->Class<SceneAPI::DataTypes::IMeshData>()
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "scene")
|
||||
->Method("GetUnitSizeInMeters", &MeshData::GetUnitSizeInMeters)
|
||||
->Method("GetOriginalUnitSizeInMeters", &MeshData::GetOriginalUnitSizeInMeters);
|
||||
|
||||
behaviorContext->Class<MeshData>()
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "scene")
|
||||
->Method("GetSdkMeshIndex", &MeshData::GetSdkMeshIndex)
|
||||
->Method("GetControlPointIndex", &MeshData::GetControlPointIndex)
|
||||
->Method("GetUsedControlPointCount", &MeshData::GetUsedControlPointCount)
|
||||
->Method("GetUsedPointIndexForControlPoint", &MeshData::GetUsedPointIndexForControlPoint)
|
||||
->Method("GetVertexCount", &MeshData::GetVertexCount)
|
||||
->Method("HasNormalData", &MeshData::HasNormalData)
|
||||
->Method("GetPosition", &MeshData::GetPosition)
|
||||
->Method("GetNormal", &MeshData::GetNormal)
|
||||
->Method("GetFaceCount", &MeshData::GetFaceCount)
|
||||
->Method("GetFaceInfo", &MeshData::GetFaceInfo)
|
||||
->Method("GetFaceMaterialId", &MeshData::GetFaceMaterialId)
|
||||
->Method("GetVertexIndex", &MeshData::GetVertexIndex);
|
||||
|
||||
behaviorContext->Class<SceneAPI::DataTypes::IMeshData::Face>()
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "scene")
|
||||
->Method("GetVertexIndex", [](const SceneAPI::DataTypes::IMeshData::Face& self, int index)
|
||||
{
|
||||
if (index >= 0 && index < 3)
|
||||
{
|
||||
return self.vertexIndex[index];
|
||||
}
|
||||
return aznumeric_cast<unsigned int>(0);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
MeshData::~MeshData() = default;
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@ namespace AZ
|
||||
public:
|
||||
AZ_RTTI(MeshData, "{a2589bd4-42fb-40ba-a38d-cfcd6e9ea169}", AZ::SceneAPI::DataTypes::IMeshData)
|
||||
|
||||
static void Reflect(ReflectContext* context);
|
||||
|
||||
SCENE_DATA_API ~MeshData() override;
|
||||
//assumes 1 to 1 mapping for these position, normal, color, uv
|
||||
//positions with more than one normal or uv (seam) will duplicate shared values in multiple verts
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
*/
|
||||
|
||||
#include <SceneAPI/SceneData/GraphData/MeshVertexBitangentData.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -18,6 +20,29 @@ namespace AZ
|
||||
{
|
||||
namespace GraphData
|
||||
{
|
||||
void MeshVertexBitangentData::Reflect(ReflectContext* context)
|
||||
{
|
||||
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<MeshVertexBitangentData>()->Version(1);
|
||||
}
|
||||
|
||||
BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context);
|
||||
if (behaviorContext)
|
||||
{
|
||||
behaviorContext->Class<MeshVertexBitangentData>()
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "scene")
|
||||
->Method("GetCount", &MeshVertexBitangentData::GetCount)
|
||||
->Method("GetBitangent", &MeshVertexBitangentData::GetBitangent)
|
||||
->Method("GetBitangentSetIndex", &MeshVertexBitangentData::GetBitangentSetIndex)
|
||||
->Method("GetTangentSpace", &MeshVertexBitangentData::GetTangentSpace)
|
||||
->Enum<(int)SceneAPI::DataTypes::TangentSpace::EMotionFX>("EMotionFX")
|
||||
->Enum<(int)SceneAPI::DataTypes::TangentSpace::FromFbx>("FromFbx")
|
||||
->Enum<(int)SceneAPI::DataTypes::TangentSpace::MikkT>("MikkT");
|
||||
}
|
||||
}
|
||||
|
||||
size_t MeshVertexBitangentData::GetCount() const
|
||||
{
|
||||
|
||||
@@ -32,6 +32,8 @@ namespace AZ
|
||||
public:
|
||||
AZ_RTTI(MeshVertexBitangentData, "{F56FB088-4C92-4453-AFE9-4E820F03FA90}", AZ::SceneAPI::DataTypes::IMeshVertexBitangentData);
|
||||
|
||||
static void Reflect(ReflectContext* context);
|
||||
|
||||
SCENE_DATA_API ~MeshVertexBitangentData() override = default;
|
||||
|
||||
SCENE_DATA_API size_t GetCount() const override;
|
||||
|
||||
@@ -11,13 +11,45 @@
|
||||
*/
|
||||
|
||||
#include <SceneAPI/SceneData/GraphData/MeshVertexColorData.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
AZ_TYPE_INFO_SPECIALIZE(SceneAPI::DataTypes::Color, "{937E3BF8-5204-4D40-A8DA-C8F083C89F9F}");
|
||||
|
||||
namespace SceneData
|
||||
{
|
||||
namespace GraphData
|
||||
{
|
||||
void MeshVertexColorData::Reflect(ReflectContext* context)
|
||||
{
|
||||
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<MeshVertexColorData>()->Version(1);
|
||||
}
|
||||
|
||||
BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context);
|
||||
if (behaviorContext)
|
||||
{
|
||||
behaviorContext->Class<MeshVertexColorData>()
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "scene")
|
||||
->Method("GetCustomName", [](const MeshVertexColorData& self) { return self.GetCustomName().GetCStr(); })
|
||||
->Method("GetCount", &MeshVertexColorData::GetCount )
|
||||
->Method("GetColor", &MeshVertexColorData::GetColor);
|
||||
|
||||
behaviorContext->Class<AZ::SceneAPI::DataTypes::Color>("MeshVertexColor")
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "scene")
|
||||
->Property("red", BehaviorValueGetter(&AZ::SceneAPI::DataTypes::Color::red), nullptr)
|
||||
->Property("green", BehaviorValueGetter(&AZ::SceneAPI::DataTypes::Color::green), nullptr)
|
||||
->Property("blue", BehaviorValueGetter(&AZ::SceneAPI::DataTypes::Color::blue), nullptr)
|
||||
->Property("alpha", BehaviorValueGetter(&AZ::SceneAPI::DataTypes::Color::alpha), nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
const AZ::Name& MeshVertexColorData::GetCustomName() const
|
||||
{
|
||||
return m_customName;
|
||||
|
||||
@@ -28,6 +28,8 @@ namespace AZ
|
||||
public:
|
||||
AZ_RTTI(MeshVertexColorData, "{17477B86-B163-4574-8FB2-4916BC218B3D}", AZ::SceneAPI::DataTypes::IMeshVertexColorData);
|
||||
|
||||
static void Reflect(ReflectContext* context);
|
||||
|
||||
SCENE_DATA_API ~MeshVertexColorData() override = default;
|
||||
|
||||
SCENE_DATA_API const AZ::Name& GetCustomName() const override;
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
*/
|
||||
|
||||
#include <SceneAPI/SceneData/GraphData/MeshVertexTangentData.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -18,6 +20,29 @@ namespace AZ
|
||||
{
|
||||
namespace GraphData
|
||||
{
|
||||
void MeshVertexTangentData::Reflect(ReflectContext* context)
|
||||
{
|
||||
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<MeshVertexTangentData>()->Version(1);
|
||||
}
|
||||
|
||||
BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context);
|
||||
if (behaviorContext)
|
||||
{
|
||||
behaviorContext->Class<MeshVertexTangentData>()
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "scene")
|
||||
->Method("GetCount", &MeshVertexTangentData::GetCount)
|
||||
->Method("GetTangent", &MeshVertexTangentData::GetTangent)
|
||||
->Method("GetTangentSetIndex", &MeshVertexTangentData::GetTangentSetIndex)
|
||||
->Method("GetTangentSpace", &MeshVertexTangentData::GetTangentSpace)
|
||||
->Enum<(int)SceneAPI::DataTypes::TangentSpace::EMotionFX>("EMotionFX")
|
||||
->Enum<(int)SceneAPI::DataTypes::TangentSpace::FromFbx>("FromFbx")
|
||||
->Enum<(int)SceneAPI::DataTypes::TangentSpace::MikkT>("MikkT");
|
||||
}
|
||||
}
|
||||
|
||||
size_t MeshVertexTangentData::GetCount() const
|
||||
{
|
||||
|
||||
@@ -31,6 +31,8 @@ namespace AZ
|
||||
public:
|
||||
AZ_RTTI(MeshVertexTangentData, "{C16F0F38-8F8F-45A2-A33B-F2758922A7C4}", AZ::SceneAPI::DataTypes::IMeshVertexTangentData);
|
||||
|
||||
static void Reflect(ReflectContext* context);
|
||||
|
||||
SCENE_DATA_API ~MeshVertexTangentData() override = default;
|
||||
|
||||
SCENE_DATA_API size_t GetCount() const override;
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
*/
|
||||
|
||||
#include <SceneAPI/SceneData/GraphData/MeshVertexUVData.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -18,6 +20,26 @@ namespace AZ
|
||||
{
|
||||
namespace GraphData
|
||||
{
|
||||
void MeshVertexUVData::Reflect(ReflectContext* context)
|
||||
{
|
||||
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<MeshVertexUVData>()->Version(1);
|
||||
}
|
||||
|
||||
BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context);
|
||||
if (behaviorContext)
|
||||
{
|
||||
behaviorContext->Class<MeshVertexUVData>()
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "scene")
|
||||
->Method("GetCustomName",[](const MeshVertexUVData& self) { return self.GetCustomName().GetCStr(); })
|
||||
->Method("GetCount", &MeshVertexUVData::GetCount)
|
||||
->Method("GetUV", &MeshVertexUVData::GetUV);
|
||||
}
|
||||
}
|
||||
|
||||
const AZ::Name& MeshVertexUVData::GetCustomName() const
|
||||
{
|
||||
return m_customName;
|
||||
@@ -49,7 +71,6 @@ namespace AZ
|
||||
m_uvs.push_back(uv);
|
||||
}
|
||||
|
||||
|
||||
void MeshVertexUVData::GetDebugOutput(AZ::SceneAPI::Utilities::DebugOutput& output) const
|
||||
{
|
||||
output.Write("UVs", m_uvs);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user