/// <summary> /// Stolen from MeshBuilder class, maybe make this static method there public... /// </summary> /// <param name="positions"></param> /// <param name="triangleIndices"></param> /// <param name="normals"></param> private static void ComputeNormals(Vector3Collection positions, IntCollection triangleIndices, out Vector3Collection normals) { normals = new Vector3Collection(positions.Count); normals.AddRange(Enumerable.Repeat(Vector3.Zero, positions.Count)); for (int t = 0; t < triangleIndices.Count; t += 3) { var i1 = triangleIndices[t]; var i2 = triangleIndices[t + 1]; var i3 = triangleIndices[t + 2]; var v1 = positions[i1]; var v2 = positions[i2]; var v3 = positions[i3]; var p1 = v2 - v1; var p2 = v3 - v1; var n = Vector3.Cross(p1, p2); // angle p1.Normalize(); p2.Normalize(); var a = (float)Math.Acos(Vector3.Dot(p1, p2)); n.Normalize(); normals[i1] += (a * n); normals[i2] += (a * n); normals[i3] += (a * n); } for (int i = 0; i < normals.Count; i++) { var n = normals[i]; n.Normalize(); normals[i] = n; } }
public static MeshGeometry3D Merge(params MeshGeometry3D[] meshes) { var positions = new Vector3Collection(); var indices = new IntCollection(); var normals = meshes.All(x => x.Normals != null) ? new Vector3Collection() : null; var colors = meshes.All(x => x.Colors != null) ? new Color4Collection() : null; var textureCoods = meshes.All(x => x.TextureCoordinates != null) ? new Vector2Collection() : null; var tangents = meshes.All(x => x.Tangents != null) ? new Vector3Collection() : null; var bitangents = meshes.All(x => x.BiTangents != null) ? new Vector3Collection() : null; int index = 0; foreach (var part in meshes) { positions.AddRange(part.Positions); indices.AddRange(part.Indices.Select(x => x + index)); index += part.Positions.Count; } if (normals != null) { normals = new Vector3Collection(meshes.SelectMany(x => x.Normals)); } if (colors != null) { colors = new Color4Collection(meshes.SelectMany(x => x.Colors)); } if (textureCoods != null) { textureCoods = new Vector2Collection(meshes.SelectMany(x => x.TextureCoordinates)); } if (tangents != null) { tangents = new Vector3Collection(meshes.SelectMany(x => x.Tangents)); } if (bitangents != null) { bitangents = new Vector3Collection(meshes.SelectMany(x => x.BiTangents)); } var mesh = new MeshGeometry3D() { Positions = positions, Indices = indices, }; mesh.Normals = normals; mesh.Colors = colors; mesh.TextureCoordinates = textureCoods; mesh.Tangents = tangents; mesh.BiTangents = bitangents; return(mesh); }
public static BoneSkinnedMeshGeometry3D CreateSkeletonMesh(IList <Animations.Bone> bones, float scale = 1f) { var builder = new MeshBuilder(true, false); builder.AddPyramid(new Vector3(0, scale / 2, 0), Vector3.UnitZ, Vector3.UnitY, scale, 0, true); var singleBone = builder.ToMesh(); var boneIds = new List <BoneIds>(); var positions = new Vector3Collection(bones.Count * singleBone.Positions.Count); var tris = new IntCollection(bones.Count * singleBone.Indices.Count); int offset = 0; for (int i = 0; i < bones.Count; ++i) { if (bones[i].ParentIndex >= 0) { int currPos = positions.Count; tris.AddRange(singleBone.Indices.Select(x => x + offset)); int j = 0; for (; j < singleBone.Positions.Count - 6; j += 3) { positions.Add(Vector3.TransformCoordinate(singleBone.Positions[j], bones[bones[i].ParentIndex].BindPose)); positions.Add(Vector3.TransformCoordinate(singleBone.Positions[j + 1], bones[bones[i].ParentIndex].BindPose)); positions.Add(bones[i].BindPose.TranslationVector); boneIds.Add(new BoneIds() { Bone1 = bones[i].ParentIndex, Weights = new Vector4(1, 0, 0, 0) }); boneIds.Add(new BoneIds() { Bone1 = bones[i].ParentIndex, Weights = new Vector4(1, 0, 0, 0) }); boneIds.Add(new BoneIds() { Bone1 = i, Weights = new Vector4(1, 0, 0, 0) }); } for (; j < singleBone.Positions.Count; ++j) { positions.Add(Vector3.TransformCoordinate(singleBone.Positions[j], bones[bones[i].ParentIndex].BindPose)); boneIds.Add(new BoneIds() { Bone1 = bones[i].ParentIndex, Weights = new Vector4(1, 0, 0, 0) }); } offset += singleBone.Positions.Count; } } builder = new MeshBuilder(true, false); for (int i = 0; i < bones.Count; ++i) { int currPos = builder.Positions.Count; builder.AddSphere(Vector3.Zero, scale / 2, 12, 12); for (int j = currPos; j < builder.Positions.Count; ++j) { builder.Positions[j] = Vector3.TransformCoordinate(builder.Positions[j], bones[i].BindPose); boneIds.Add(new BoneIds() { Bone1 = i, Weights = new Vector4(1, 0, 0, 0) }); } } positions.AddRange(builder.Positions); tris.AddRange(builder.TriangleIndices.Select(x => x + offset)); var mesh = new BoneSkinnedMeshGeometry3D() { Positions = positions, Indices = tris, VertexBoneIds = boneIds }; mesh.Normals = mesh.CalculateNormals(); return(mesh); }
private static void ComputeNormals(Vector3Collection positions, IntCollection triangleIndices, out Vector3Collection normals) { normals = new Vector3Collection(positions.Count); normals.AddRange(Enumerable.Repeat(Vector3.Zero, positions.Count)); for (int t = 0; t < triangleIndices.Count; t += 3) { var i1 = triangleIndices[t]; var i2 = triangleIndices[t + 1]; var i3 = triangleIndices[t + 2]; var v1 = positions[i1]; var v2 = positions[i2]; var v3 = positions[i3]; var p1 = v2 - v1; var p2 = v3 - v1; var n = Vector3.Cross(p1, p2); // angle p1.Normalize(); p2.Normalize(); var a = (float)Math.Acos(Vector3.Dot(p1, p2)); n.Normalize(); normals[i1] += (a * n); normals[i2] += (a * n); normals[i3] += (a * n); } for (int i = 0; i < normals.Count; i++) { normals[i].Normalize(); } }