I tried to make an fbx file.
for first practice I imported existing fbx file and get all element(vertex, normal, uv, triangle, texture) and created new scene and assigned data from existing fbx.
but result fbx(exported) has no texture.
can you tell me what did I make mistake?
here is code and sample fbx
private void LoadAnsSave(string filePath, string exportPath)
{
var fullPath = Path.GetFullPath(filePath);
var directory = Path.GetDirectoryName(fullPath);
var scene = new Scene();
scene.Open(filePath);
var saveScene = new Scene();
var rootNode = scene.RootNode;
var childNodes = rootNode.ChildNodes;
if ((childNodes != null) && (childNodes.Count > 0))
{
var nodeCount = childNodes.Count;
for (var i = 0; i < nodeCount; i++)
{
var childNode = childNodes[i];
ParseNode(childNode, directory, saveScene);
}
}
saveScene.Save(exportPath, FileFormat.FBX7400ASCII);
}
private static void ParseNode(Node node, string directory, Scene saveScene)
{
var material = node.Material;
var textures = default(Dictionary<TextureType, byte[]>);
if (material != null)
{
textures = new Dictionary<TextureType, byte[]>();
ParseMaterial(material, directory, textures);
if (textures.Count == 0)
{
textures = null;
}
}
foreach (var entity in node.Entities)
{
switch (entity)
{
case Mesh mesh:
var vertexDeclaration = new VertexDeclaration();
var vertexFieldForVertex = vertexDeclaration.AddField(VertexFieldDataType.FVector3, VertexFieldSemantic.Position);
var vertexFieldForNormal = vertexDeclaration.AddField(VertexFieldDataType.FVector3, VertexFieldSemantic.Normal);
var vertexFieldForUv = vertexDeclaration.AddField(VertexFieldDataType.FVector2, VertexFieldSemantic.UV);
var triMesh = TriMesh.FromMesh(mesh);
var vertices = new List<Vector3>();
var normals = new List<Vector3>();
var uvs = new List<Vector2>();
var triangles = new int[triMesh.IndicesCount];
triMesh.IndicesToArray(out triangles);
foreach (var vertex in triMesh)
{
var vertexRaw = vertex.ReadFVector3(vertexFieldForVertex);
var normalRaw = vertex.ReadFVector3(vertexFieldForNormal);
var uvRaw = vertex.ReadFVector2(vertexFieldForUv);
vertices.Add(new Vector3(vertexRaw.x, vertexRaw.y, vertexRaw.z));
normals.Add(new Vector3(normalRaw.x, normalRaw.y, normalRaw.z));
uvs.Add(new Vector2(uvRaw.x, uvRaw.y));
}
var newNode = new Node($"Mesh");
var newMesh = new Mesh();
newMesh.ControlPoints.AddRange(vertices.Select(v => new Aspose.ThreeD.Utilities.Vector4(v.x, v.y, v.z, 0)));
var pb = new PolygonBuilder(newMesh);
for (var j = 0; j < triangles.Length; j += 3)
{
pb.Begin();
pb.AddVertex(triangles[j]);
pb.AddVertex(triangles[j + 1]);
pb.AddVertex(triangles[j + 2]);
pb.End();
}
var elementNormal = newMesh.CreateElement(VertexElementType.Normal, MappingMode.ControlPoint, ReferenceMode.Direct) as VertexElementNormal;
elementNormal.Data.AddRange(normals.Select(v => new Aspose.ThreeD.Utilities.Vector4(v.x, v.y, v.z, 0)));
var elementUv = newMesh.CreateElement(VertexElementType.UV, MappingMode.ControlPoint, ReferenceMode.Direct) as VertexElementUV;
elementUv.Data.AddRange(uvs.Select(v => new Aspose.ThreeD.Utilities.Vector4(v.x, v.y, 0, 0)));
newNode.Entity = mesh;
saveScene.RootNode.AddChildNode(newNode);
if (textures != null)
{
var newMaterial = new PbrMaterial();
var hasTexture = false;
if (textures.TryGetValue(TextureType.FrontAlbedo, out var albedoMap))
{
var texture = new Texture();
texture.Content = albedoMap;
texture.FileName = $"Diffuse.png";
newMaterial.SetTexture(Material.MapDiffuse, texture);
hasTexture = true;
}
if (textures.TryGetValue(TextureType.FrontEmissive, out var emissiveMap))
{
var texture = new Texture();
texture.Content = albedoMap;
texture.FileName = $"Emissive.png";
newMaterial.SetTexture(Material.MapEmissive, texture);
hasTexture = true;
}
if (textures.TryGetValue(TextureType.FrontMetalness, out var metalnessMap))
{
var texture = new Texture();
texture.Content = albedoMap;
texture.FileName = $"Specular.png";
newMaterial.SetTexture(Material.MapSpecular, texture);
hasTexture = true;
}
if (textures.TryGetValue(TextureType.FrontNormal, out var normalMap))
{
var texture = new Texture();
texture.Content = albedoMap;
texture.FileName = $"Normal.png";
newMaterial.SetTexture(Material.MapNormal, texture);
hasTexture = true;
}
if (textures.TryGetValue(TextureType.FrontOcclusion, out var occlusionMap))
{
var texture = new Texture();
texture.Content = albedoMap;
texture.FileName = $"Ambient.png";
newMaterial.SetTexture(Material.MapAmbient, texture);
hasTexture = true;
}
if (hasTexture)
{
newMaterial.Albedo = new Vector3(1,1,1);
newMaterial.EmissiveColor = new Vector3(1, 1, 1);
newMaterial.MetallicFactor = 0.5;
newMaterial.OcclusionFactor = 0.5;
newMaterial.RoughnessFactor = 0.5;
newMaterial.Transparency = 1;
newNode.Material = newMaterial;
}
}
break;
default:
break;
}
}
var childNodes = node.ChildNodes;
if ((childNodes != null) && (childNodes.Count > 0))
{
var childCount = childNodes.Count;
for (var i = 0; i < childCount; i++)
{
ParseNode(childNodes[i], directory, saveScene);
}
}
}
private static void ParseMaterial(Material material, string directory, Dictionary<TextureType, byte[]> textures)
{
var ambientMap = material.GetTexture(Material.MapAmbient);
var diffuseMap = material.GetTexture(Material.MapDiffuse);
var emissiveMap = material.GetTexture(Material.MapEmissive);
var normalMap = material.GetTexture(Material.MapNormal);
var specularMap = material.GetTexture(Material.MapSpecular);
if ((ambientMap != null) && diffuseMap is Texture ambientTexture)
{
if (GetTextureData(ambientTexture, directory, out var textureData))
{
textures[TextureType.FrontOcclusion] = textureData;
}
}
if ((diffuseMap != null) && diffuseMap is Texture diffuseTexture)
{
if (GetTextureData(diffuseTexture, directory, out var textureData))
{
textures[TextureType.FrontAlbedo] = textureData;
textures[TextureType.FrontDisplacement] = textureData;
}
}
if ((emissiveMap != null) && emissiveMap is Texture emissiveTexture)
{
if (GetTextureData(emissiveTexture, directory, out var textureData))
{
textures[TextureType.FrontEmissive] = textureData;
}
}
if ((normalMap != null) && normalMap is Texture normalTexture)
{
if (GetTextureData(normalTexture, directory, out var textureData))
{
textures[TextureType.FrontNormal] = textureData;
}
}
if ((specularMap != null) && specularMap is Texture specularTexture)
{
if (GetTextureData(specularTexture, directory, out var textureData))
{
textures[TextureType.FrontMetalness] = textureData;
}
}
}
private static bool GetTextureData(Texture texture, string directory, out byte[] textureData)
{
try
{
if (texture.Content != null)
{
using (var ms = new MemoryStream(texture.Content))
using (var image = Image.FromStream(ms))
{
byte[] resultData = null;
if (image.RawFormat != ImageFormat.Png)
{
using (var convertStream = new MemoryStream())
{
image.Save(convertStream, ImageFormat.Png);
resultData = convertStream.ToArray();
}
}
else
{
resultData = ms.ToArray();
}
textureData = resultData;
return true;
}
}
var filePath = texture.FileName;
if (string.IsNullOrWhiteSpace(filePath))
{
textureData = default;
return false;
}
var fileName = Path.GetFileName(texture.FileName);
var files = Directory.GetFiles(directory, "*", SearchOption.AllDirectories);
foreach (var file in files)
{
if (Path.GetFileName(file) == fileName)
{
using (var image = Image.FromFile(file))
using (var ms = new MemoryStream())
{
image.Save(ms, ImageFormat.Png);
var width = image.Width;
var height = image.Height;
textureData = ms.ToArray();
return true;
}
}
}
textureData = default;
return false;
}
catch (Exception)
{
textureData = default;
return false;
}
}
private enum TextureType
{
Preview,
FrontAlbedo,
FrontAlpha,
FrontDisplacement,
FrontNormal,
FrontRoughness,
FrontMetalness,
FrontEmissive,
FrontOcclusion,
BackAlbedo,
BackAlpha,
BackDisplacement,
BackNormal,
BackRoughness,
BackMetalness,
BackEmissive,
BackOcclusion,
}