I have a hierarchical collection of Bone of type BoneNodeViewModel which I can traverse to create a Skeleton structure of Nodes to export into fbx
the problem is the exported skeleton bones don’t have correct transformation but rather a pose
in Blender if i go into Edit mode for the Skeleton all bones would have identinty matrix as transformations so i would needs to go in pose mode>pose select Apply pose as rest pose
in order to set the bone transformations correctly
How to fix this ? so that the exported Skeleton has no pose ?
or what the correct way to create a Skeleton object ?
thank you .
var scene = new Scene();
var root = scene.RootNode;
root.Name =
$"{sceneName}_Root";
var armatureNode = new Node();
armatureNode.Name =
$"{sceneName}_Master";
bool addallNodes = false;
IList<Bone> bones = new List<Bone>();
foreach (var nodeViewModel in mySceneRoot.Children)
{
if (nodeViewModel is BoneNodeViewModel boneNodeViewModel)
{
if (boneNodeViewModel.Name == armatureNode.Name)
{
if (boneNodeViewModel.Children != null && boneNodeViewModel.Children.Any())
{
foreach (var child in boneNodeViewModel.Children)
{
if (child is BoneNodeViewModel childBoneNodeViewModel)
{
var chBoneNode = CreateBoneNode(childBoneNodeViewModel, bones);
armatureNode.AddChildNode(chBoneNode);
}
}
}
continue;
}
if (!addallNodes && ( boneNodeViewModel.Bone.ParentIndex == -1 && boneNodeViewModel.Children.Count == 0/* && /*!mySceneViewModel.Meshes.Any(m => m.Name == boneNodeViewModel.Name)*/))
{
continue;
}
var rootBoneNode = CreateBoneNode(boneNodeViewModel, bones);
armatureNode.AddChildNode(rootBoneNode);
}
}
armatureNode.Transform.TransformMatrix = Matrix4.Identity;
// armatureNode.Entity=skeleton;
root.AddChildNode(armatureNode);
for (int mi = 0; mi < mySceneViewModel.Meshes.Count; mi++)
{
var meshmodel = mySceneViewModel.Meshes[mi];
var meshNode = new Node();
meshNode.Name = meshmodel.Name;
meshNode.Transform.TransformMatrix = Matrix4.Identity;
var mesh = CreateMesh( meshmodel, bones);
meshNode.Material = CreateMaterial( meshmodel.Name);
meshNode.Entity = mesh;
root.AddChildNode(meshNode);
}
}
private static Node CreateBoneNode(BoneNodeViewModel boneViewModel, IList<Bone> bones)
{
var boneNode = new Node();
boneNode.Name = boneViewModel.Name;
var transform = boneViewModel.Bone.GetLocalTransformMatrix4();
boneNode.Transform.TransformMatrix = transform;
var boneSk = new Skeleton();
boneSk.Name = boneViewModel.Name;
boneSk.Type = SkeletonType.Bone;
var bone = new Bone();
bone.Name = boneViewModel.Name;
bone.BoneTransform = transform;
bone.Node = boneNode;
bones.Add(bone);
boneNode.Entity = boneSk;
foreach (var childNode in boneViewModel.Children)
{
if (childNode is BoneNodeViewModel bvm)
{
var childBoneNode = CreateBoneNode(bvm, bones);
boneNode.AddChildNode(childBoneNode);
}
}
return boneNode;
}
private static Mesh CreateMesh(MeshNodeViewModel meshmodel, IList<Bone> bones)
{
var mesh = new Mesh(meshmodel.Name);
List<int> indices = new(meshmodel.Mesh.Vertices.Count);
indices.AddRange(meshmodel.Mesh.FaceSets[0].Indices);
indices.FlipFaceIndcies();
SkinDeformer rDeformer = new SkinDeformer();
mesh.Deformers.Add(rDeformer);
for (var i = 0; i < indices.Count; i += 3)
{
var triangle = new int[3]
{
indices[i],
indices[i + 1],
indices[i + 2]
};
mesh.CreatePolygon(triangle);
}
AsVector4[] normals = new AsVector4[meshmodel.Mesh.Vertices.Count];
AsVector4[] tangents = new AsVector4[meshmodel.Mesh.Vertices.Count];
AsVector4[] bitangents = new AsVector4[meshmodel.Mesh.Vertices.Count];
List<AsVector4[]> uvs = new List<AsVector4[]>(meshmodel.Mesh.Vertices[0].UVs.Count);
for (int i = 0; i < meshmodel.Mesh.Vertices[0].UVs.Count; i++)
{
uvs.Add(new AsVector4[meshmodel.Mesh.Vertices.Count]);
}
List<AsVector4[]> colors = new List<AsVector4[]>(meshmodel.Mesh.Vertices[0].Colors.Count);
for (int i = 0; i < meshmodel.Mesh.Vertices[0].Colors.Count; i++)
{
colors.Add(new AsVector4[meshmodel.Mesh.Vertices.Count]);
}
for (int vi = 0; vi < meshmodel.Mesh.Vertices.Count; vi++)
{
var vertex = meshmodel.Mesh.Vertices[vi];
mesh.ControlPoints.Add(vertex.Position.ToAspose4());
normals[vi]=(new AsVector4(vertex.Normal.ToAspose3(),vertex.NormalW));
tangents[vi] = (vertex.Tangents[0].ToAspose4());
bitangents[vi] = vertex.Bitangent.ToAspose4();
for (var i = 0; i < vertex.UVs.Count; i++)
{
AsVector4[] selectedUVArray = uvs[i];
selectedUVArray[vi] = new AsVector4(vertex.UVs[i].X, 1-vertex.UVs[i].Y, 0, 1);
}
for (var i = 0; i < vertex.Colors.Count; i++)
{
AsVector4[] selectedColorArray = colors[i];
selectedColorArray[vi] = new AsVector4(vertex.Colors[i].R, vertex.Colors[i].G, vertex.Colors[i].B, vertex.Colors[i].A);
}
for (int i = 0; i < vertex.BoneWeights.Length; i++)
{
// Extract bone information from the vertex
string boneName = vertex.VertexBones[i];
float boneWeight = vertex.BoneWeights[i];
Bone existingBone = rDeformer.Bones.FirstOrDefault(b => b.Name == boneName);
if (existingBone == null)
{
existingBone = new Bone { Name = boneName };
rDeformer.Bones.Add(existingBone);
}
var sbone = bones.FirstOrDefault(b => b.Name == boneName);
existingBone.Node= sbone.Node;
existingBone.BoneTransform=sbone.Transform;
existingBone.Transform = sbone.Transform;
existingBone.SetWeight(vi, boneWeight);
}
}
VertexElementNormal elementNormal = mesh.CreateElement(VertexElementType.Normal, MappingMode.ControlPoint, ReferenceMode.Direct) as VertexElementNormal;
// Copy the data to the vertex element
elementNormal.Data.AddRange(normals);
VertexElementTangent elementTangent = mesh.CreateElement(VertexElementType.Tangent, MappingMode.ControlPoint, ReferenceMode.Direct) as VertexElementTangent;
// Copy the data to the vertex element
elementTangent.Data.AddRange(tangents);
VertexElementBinormal elementBiTangent = mesh.CreateElement(VertexElementType.Binormal, MappingMode.ControlPoint, ReferenceMode.Direct) as VertexElementBinormal;
// Copy the data to the vertex element
elementBiTangent.Data.AddRange(bitangents);
int UVindex = 0;
foreach (var uv in uvs)
{
VertexElementUV elementUV = mesh.CreateElementUV(TextureMapping.Diffuse, MappingMode.PolygonVertex, ReferenceMode.IndexToDirect);
elementUV.Name =$"UVMap_{UVindex}";
elementUV.Data.AddRange(uv);
elementUV.Indices.AddRange(indices);
UVindex++;
}
int Cindex = 0;
foreach (var uv in colors)
{
VertexElementVertexColor elementVertexColor = mesh.CreateElement(VertexElementType.VertexColor, MappingMode.ControlPoint, ReferenceMode.Direct) as VertexElementVertexColor;
elementVertexColor.Name = $"ColorMap_{Cindex}";
elementVertexColor.Data.AddRange(uv);
Cindex++;
}
return mesh;
}