Builder.AddTokenizedErrorMessage(FTokenizedMessage::Create(EMessageSeverity::Error,LOCTEXT("FailedToImport_InvalidRoot","Could not find root node.")),FFbxErrors::SkeletalMesh_InvalidRoot);
Builder.AddTokenizedErrorMessage(FTokenizedMessage::Create(EMessageSeverity::Error,LOCTEXT("FailedToImport_InvalidRoot","Could not find root node.")),FFbxErrors::SkeletalMesh_InvalidRoot);
}
}
else
else
{
{
Builder.AddTokenizedErrorMessage(FTokenizedMessage::Create(EMessageSeverity::Error,LOCTEXT("FailedToImport_InvalidNode","Could not find any node.")),FFbxErrors::SkeletalMesh_InvalidNode);
Builder.AddTokenizedErrorMessage(FTokenizedMessage::Create(EMessageSeverity::Error,LOCTEXT("FailedToImport_InvalidNode","Could not find any node.")),FFbxErrors::SkeletalMesh_InvalidNode);
UE_LOG(LogTemp,Log,TEXT("%s"),*(FText::Format(FText::FromString("Importing data for attribute \"{0}\""),FText::FromString(ToFString(AttribName)))).ToString());
UE_LOG(LogTemp,Log,TEXT("%s"),*(FText::Format(FText::FromString("Importing data for attribute \"{0}\""),FText::FromString(ToFString(AttribName)))).ToString());
if(AutoSetArraySize)// This should always be false since for now we are just extending the array each time we want to add an element
if(AutoSetArraySize)// This should always be false since for now we are just extending the array each time we want to add an element
{
{
int32Size=0;
int32Size=0;
if(UseWedgeIndices)
if(UseWedgeIndices)
{
{
for(autoPrim:Mesh->primitives)
for(autoPrim:Mesh->primitives)
{
{
Size+=GetNumWedges(&Prim);// Number of wedges
Size+=GetNumWedges(&Prim);// Number of wedges
}
}
}
}
else
else
{
{
for(autoPrim:Mesh->primitives)
for(autoPrim:Mesh->primitives)
{
{
Size+=Scene->accessors[Prim.attributes.begin()->second].count;// Number of vertices
Size+=Scene->accessors[Prim.attributes.begin()->second].count;// Number of vertices
}
}
}
}
OutArray.SetNumUninitialized(Size);
OutArray.SetNumUninitialized(Size);
}
}
// Getting an attribute for individual triangle corners ("wedges")
// Getting an attribute for individual triangle corners ("wedges")
elseif(UseWedgeIndices&&AttribName!="__WedgeIndices")// Make sure we don't try to access indices for the index array itself!
elseif(UseWedgeIndices&&AttribName!="__WedgeIndices")// Make sure we don't try to access indices for the index array itself!
// Require the parent because it will have been invalidated from the garbage collection
// Force GC so we can cleanly create a new asset (and not do an 'in place' replacement)
Parent=Package;
CollectGarbage(GARBAGE_COLLECTION_KEEPFLAGS);
}
else
// Create a package for each mesh
{
Package=CreatePackage(NULL,*NewPackageName);
// failed to delete
AddTokenizedErrorMessage(FTokenizedMessage::Create(EMessageSeverity::Error,FText::Format(FText::FromString(FString("{0} wasn't created.\n\nThe asset is referenced by other content.")),FText::FromString(MeshName))),FFbxErrors::Generic_CannotDeleteReferenced);
// Require the parent because it will have been invalidated from the garbage collection
returnNULL;
Parent=Package;
}
}
else
}
{
// failed to delete
if(InStaticMesh!=NULL&&LODIndex>0)
AddTokenizedErrorMessage(FTokenizedMessage::Create(EMessageSeverity::Error,FText::Format(FText::FromString(FString("{0} wasn't created.\n\nThe asset is referenced by other content.")),FText::FromString(MeshName))),FFbxErrors::Generic_CannotDeleteReferenced);
FText::Format(FText::FromString(FString("StaticMesh has a large number({1}) of materials and may render inefficently. Consider breaking up the mesh into multiple Static Mesh Assets.")),
FText::AsNumber(UniqueMaterials.Num())
if(UniqueMaterials.Num()>8)
)),
{
FFbxErrors::StaticMesh_TooManyMaterials);
AddTokenizedErrorMessage(
}
FTokenizedMessage::Create(
EMessageSeverity::Warning,
// Sort materials based on _SkinXX in the name.
FText::Format(FText::FromString(FString("StaticMesh has a large number({1}) of materials and may render inefficently. Consider breaking up the mesh into multiple Static Mesh Assets.")),
AddTokenizedErrorMessage(FTokenizedMessage::Create(EMessageSeverity::Error,FText::Format(FText::FromString(FString("Error_NoGeometryInMesh","There is no geometry information in mesh '{0}'")),FText::FromString(ToFString(Mesh->name)))),FFbxErrors::Generic_Mesh_NoGeometry);
AddTokenizedErrorMessage(FTokenizedMessage::Create(EMessageSeverity::Error,FText::Format(FText::FromString(FString("Error_NoGeometryInMesh","There is no geometry information in mesh '{0}'")),FText::FromString(ToFString(Mesh->name)))),FFbxErrors::Generic_Mesh_NoGeometry);
AddTokenizedErrorMessage(FTokenizedMessage::Create(EMessageSeverity::Error,FText::Format(FText::FromString(FString("Error_NoTrianglesFoundInMesh","No triangles were found on mesh '{0}'")),FText::FromString(ToFString(Mesh->name)))),FFbxErrors::StaticMesh_NoTriangles);
AddTokenizedErrorMessage(FTokenizedMessage::Create(EMessageSeverity::Error,FText::Format(FText::FromString(FString("Error_NoTrianglesFoundInMesh","No triangles were found on mesh '{0}'")),FText::FromString(ToFString(Mesh->name)))),FFbxErrors::StaticMesh_NoTriangles);
/// Forward-declared TinyGLTF types since its header can only be #included in one source file.
structFRawMesh;
/// This also means that we must use pointers to these types outside of GLTFMeshBuilder.cpp.
namespacetinygltf
/// Forward-declared TinyGLTF types since its header can only be #included in one source file.
{
/// This also means that we must use pointers to these types outside of GLTFMeshBuilder.cpp.
classTinyGLTFLoader;
namespacetinygltf
classScene;
{
classNode;
classTinyGLTFLoader;
structACCESSOR;
classScene;
typedefstructACCESSORAccessor;
classNode;
structPRIMITIVE;
structACCESSOR;
typedefstructPRIMITIVEPrimitive;
typedefstructACCESSORAccessor;
structMESH;
structPRIMITIVE;
typedefstructMESHMesh;
typedefstructPRIMITIVEPrimitive;
structMATERIAL;
structMESH;
typedefstructMATERIALMaterial;
typedefstructMESHMesh;
}
structMATERIAL;
typedefstructMATERIALMaterial;
/// Works in conjunction with TinyGLTF and Unreal's Static Mesh build system to return a UStaticMesh to the factory. This class is adapted from FbxImporter.
}
classGLTFMeshBuilder
{
/// Works in conjunction with TinyGLTF and Unreal's Static Mesh build system to return a UStaticMesh to the factory. This class is adapted from FbxImporter.
public:
UCLASS()
GLTFMeshBuilder(FStringFilePath);
classGLTFLOADER_APIUGLTFMeshBuilder:publicUObject
~GLTFMeshBuilder();
{
GENERATED_BODY()
/// Returns whether we have a valid glTF scene loaded up. For a new MeshBuilder, this should always be queried before calling other functions.
public:
boolLoadedSuccessfully(){returnLoadSuccess;}
UGLTFMeshBuilder();
UGLTFMeshBuilder(FStringFilePath);
/// Returns the number of meshes owned by a given node.
~UGLTFMeshBuilder();
int32GetMeshCount(FStringNodeName);
/// Returns whether we have a valid glTF scene loaded up. For a new MeshBuilder, this should always be queried before calling other functions.
/// Returns the name of the scene's root node.
boolLoadedSuccessfully(){returnLoadSuccess;}
FStringGetRootNode();
/// Returns the number of meshes owned by a given node.
/// Obtains the mesh names of a node (and optionally its children); useful as an argument to <B>ImportStaticMeshAsSingle()</B>.
/// Returns the error message left by TinyGLTFLoader, if any.
/// @name Level 4: ConvertAttrib
FStringGetError();
///@{
/// Fills a TArray with a particular vertex attribute. Set InAttribName to "__WedgeIndex" to use the "indices" accessor for each primitive, or "__MaterialIndices" to obtain the material index.
private:
/// @param OutArray The array to fill with data from the imported file.
// Templated data copy functions, from highest to lowest level:
/// @param Mesh The glTF from which to convert the specified attribute.
/// @param AttribName The name of the attribute to convert.
/// @name Level 4: ConvertAttrib
/// @param UseWedgeIndices Whether to copy data for each triangle corner ("wedge") or each vertex.
///@{
/// @param AutoSetArraySize Whether to resize the array to the number of elements in this attribute (usually false since we may be adding to data from another mesh).
/// Fills a TArray with a particular vertex attribute. Set InAttribName to "__WedgeIndex" to use the "indices" accessor for each primitive, or "__MaterialIndices" to obtain the material index.
/// @param OutArray The array to fill with data from the imported file.
///@}
/// @param Mesh The glTF from which to convert the specified attribute.
/// @param AttribName The name of the attribute to convert.
/// @name Level 3: GetBufferData
/// @param UseWedgeIndices Whether to copy data for each triangle corner ("wedge") or each vertex.
///@{
/// @param AutoSetArraySize Whether to resize the array to the number of elements in this attribute (usually false since we may be adding to data from another mesh).
/// Fills a TArray with typed data; works at the glTF Accessor level and figures out which arguments to send to <B>BufferCopy()</B>.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.