public static void CopyBoneAssignments(Mesh dst, Mesh src, Dictionary <uint, uint> vertexIdMap) { foreach (KeyValuePair <uint, uint> vertexMapping in vertexIdMap) { List <VertexBoneAssignment> srcVbaList = src.BoneAssignmentList[(int)vertexMapping.Key]; foreach (VertexBoneAssignment srcVba in srcVbaList) { Debug.Assert(srcVba.vertexIndex == (int)vertexMapping.Key); VertexBoneAssignment dstVba = new VertexBoneAssignment(); dstVba.boneIndex = srcVba.boneIndex; dstVba.vertexIndex = (int)vertexMapping.Value; dstVba.weight = srcVba.weight; dst.AddBoneAssignment(dstVba); } } }
public Mesh CreateBoneMesh(string name) { Mesh mesh = CreateManual(name); mesh.SkeletonName = name + ".skeleton"; SubMesh subMesh = mesh.CreateSubMesh("BoneSubMesh"); subMesh.useSharedVertices = true; subMesh.MaterialName = "BaseWhite"; // short[] faces = { 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 2, 1, 2, 5, 1, 5, 4, 1, 4, 3, 1, 3, 2 }; // short[] faces = { 0, 3, 2, 0, 4, 3, 0, 5, 4, 0, 2, 5, 1, 5, 2, 1, 4, 5, 1, 3, 4, 1, 2, 3 }; short[] faces = { 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 2, 1, 2, 5, 1, 5, 4, 1, 4, 3, 1, 3, 2, 0, 3, 2, 0, 4, 3, 0, 5, 4, 0, 2, 5, 1, 5, 2, 1, 4, 5, 1, 3, 4, 1, 2, 3 }; int faceCount = faces.Length / 3; // faces per bone int vertexCount = 6; // vertices per bone // set up vertex data, use a single shared buffer mesh.SharedVertexData = new VertexData(); VertexData vertexData = mesh.SharedVertexData; // set up vertex declaration VertexDeclaration vertexDeclaration = vertexData.vertexDeclaration; int currentOffset = 0; // always need positions vertexDeclaration.AddElement(0, currentOffset, VertexElementType.Float3, VertexElementSemantic.Position); currentOffset += VertexElement.GetTypeSize(VertexElementType.Float3); vertexDeclaration.AddElement(0, currentOffset, VertexElementType.Float3, VertexElementSemantic.Normal); currentOffset += VertexElement.GetTypeSize(VertexElementType.Float3); int boneCount = mesh.Skeleton.BoneCount; // I want 6 vertices per bone - exclude the root bone vertexData.vertexCount = boneCount * vertexCount; // allocate vertex buffer HardwareVertexBuffer vertexBuffer = HardwareBufferManager.Instance.CreateVertexBuffer(vertexDeclaration.GetVertexSize(0), vertexData.vertexCount, BufferUsage.StaticWriteOnly); // set up the binding, one source only VertexBufferBinding binding = vertexData.vertexBufferBinding; binding.SetBinding(0, vertexBuffer); Vector3[] vertices = new Vector3[vertexData.vertexCount]; GetVertices(ref vertices, mesh.Skeleton.RootBone); // Generate vertex data unsafe { // lock the vertex buffer IntPtr data = vertexBuffer.Lock(BufferLocking.Discard); float *pData = (float *)data.ToPointer(); foreach (Vector3 vec in vertices) { // assign to geometry *pData++ = vec.x; *pData++ = vec.y; *pData++ = vec.z; // fake normals *pData++ = 0; *pData++ = 1; *pData++ = 0; } // unlock the buffer vertexBuffer.Unlock(); } // unsafe // Generate index data HardwareIndexBuffer indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer(IndexType.Size16, faces.Length * boneCount, BufferUsage.StaticWriteOnly); subMesh.indexData.indexBuffer = indexBuffer; subMesh.indexData.indexCount = faces.Length * boneCount; subMesh.indexData.indexStart = 0; for (ushort boneIndex = 0; boneIndex < mesh.Skeleton.BoneCount; ++boneIndex) { Axiom.Animating.Bone bone = mesh.Skeleton.GetBone(boneIndex); short[] tmpFaces = new short[faces.Length]; for (int tmp = 0; tmp < faces.Length; ++tmp) { tmpFaces[tmp] = (short)(faces[tmp] + vertexCount * bone.Handle); } indexBuffer.WriteData(faces.Length * bone.Handle * sizeof(short), tmpFaces.Length * sizeof(short), tmpFaces, true); } for (ushort boneIndex = 0; boneIndex < mesh.Skeleton.BoneCount; ++boneIndex) { Axiom.Animating.Bone bone = mesh.Skeleton.GetBone(boneIndex); Axiom.Animating.Bone parentBone = bone; if (bone.Parent != null) { parentBone = (Axiom.Animating.Bone)bone.Parent; } for (int vertexIndex = 0; vertexIndex < vertexCount; ++vertexIndex) { Axiom.Animating.VertexBoneAssignment vba = new Axiom.Animating.VertexBoneAssignment(); // associate the base of the joint display with the bone's parent, // and the rest of the points with the bone. vba.boneIndex = parentBone.Handle; vba.weight = 1.0f; vba.vertexIndex = vertexCount * bone.Handle + vertexIndex; mesh.AddBoneAssignment(vba); } } mesh.Load(); mesh.Touch(); return(mesh); }