123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #include <AzCore/Serialization/SerializeContext.h>
- #include <AzCore/std/smart_ptr/make_shared.h>
- #include <AzToolsFramework/Debug/TraceContext.h>
- #include <SceneAPI/SceneBuilder/Importers/AssImpBitangentStreamImporter.h>
- #include <SceneAPI/SceneBuilder/Importers/ImporterUtilities.h>
- #include <SceneAPI/SceneBuilder/Importers/Utilities/AssImpMeshImporterUtilities.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 <SceneAPI/SceneCore/Utilities/Reporting.h>
- #include <assimp/scene.h>
- #include <assimp/mesh.h>
- namespace AZ
- {
- namespace SceneAPI
- {
- namespace SceneBuilder
- {
- 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(3); // LYN-3250
- }
- }
- Events::ProcessingResult AssImpBitangentStreamImporter::ImportBitangentStreams(AssImpSceneNodeAppendedContext& context)
- {
- AZ_TraceContext("Importer", m_defaultNodeName);
- if (!context.m_sourceNode.ContainsMesh())
- {
- return Events::ProcessingResult::Ignored;
- }
- const aiNode* currentNode = context.m_sourceNode.GetAssImpNode();
- const aiScene* scene = context.m_sourceScene.GetAssImpScene();
- const auto meshHasTangentsAndBitangents = [&scene](const unsigned int meshIndex)
- {
- return scene->mMeshes[meshIndex]->HasTangentsAndBitangents();
- };
- // If there are no bitangents on any meshes, there's nothing to import in this function.
- const bool anyMeshHasTangentsAndBitangents = AZStd::any_of(currentNode->mMeshes, currentNode->mMeshes + currentNode->mNumMeshes, meshHasTangentsAndBitangents);
- if (!anyMeshHasTangentsAndBitangents)
- {
- return Events::ProcessingResult::Ignored;
- }
- // AssImp nodes with multiple meshes on them occur when AssImp split a mesh on material.
- // This logic recombines those meshes to minimize the changes needed to replace FBX SDK with AssImp, FBX SDK did not separate meshes,
- // and the engine has code to do this later.
- const bool allMeshesHaveTangentsAndBitangents = AZStd::all_of(currentNode->mMeshes, currentNode->mMeshes + currentNode->mNumMeshes, meshHasTangentsAndBitangents);
- if (!allMeshesHaveTangentsAndBitangents)
- {
- AZ_Error(
- Utilities::ErrorWindow, false,
- "Node with name %s has meshes with and without bitangents. "
- "Placeholder incorrect bitangents will be generated to allow the data to process, "
- "but the source art needs to be fixed to correct this. Either apply bitangents to all meshes on this node, "
- "or remove all bitangents from all meshes on this node.",
- currentNode->mName.C_Str());
- }
- const uint64_t vertexCount = GetVertexCountForAllMeshesOnNode(*currentNode, *scene);
- 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->SetGenerationMethod(AZ::SceneAPI::DataTypes::TangentGenerationMethod::FromSourceScene);
- bitangentStream->ReserveContainerSpace(vertexCount);
- for (unsigned int sdkMeshIndex = 0; sdkMeshIndex < currentNode->mNumMeshes; ++sdkMeshIndex)
- {
- const aiMesh* mesh = scene->mMeshes[currentNode->mMeshes[sdkMeshIndex]];
- for (unsigned int v = 0; v < mesh->mNumVertices; ++v)
- {
- if (!mesh->HasTangentsAndBitangents())
- {
- // This node has mixed meshes with and without bitangents.
- // An error was already thrown above. Output stub bitangents so
- // the mesh can still be output in some form, even if the data isn't correct.
- // The bitangent count needs to match the vertex count on the associated mesh node.
- bitangentStream->AppendBitangent(Vector3::CreateAxisY());
- }
- else
- {
- const Vector3 bitangent(
- AssImpSDKWrapper::AssImpTypeConverter::ToVector3(mesh->mBitangents[v]));
- bitangentStream->AppendBitangent(bitangent);
- }
- }
- }
- Containers::SceneGraph::NodeIndex newIndex =
- context.m_scene.GetGraph().AddChild(context.m_currentGraphPosition, m_defaultNodeName);
- Events::ProcessingResult bitangentResults;
- AssImpSceneAttributeDataPopulatedContext dataPopulated(context, bitangentStream, newIndex, m_defaultNodeName);
- bitangentResults = Events::Process(dataPopulated);
- if (bitangentResults != Events::ProcessingResult::Failure)
- {
- bitangentResults = AddAttributeDataNodeWithContexts(dataPopulated);
- }
- return bitangentResults;
- }
- } // namespace SceneBuilder
- } // namespace SceneAPI
- } // namespace AZ
|