public static OpenTK.Matrix4 TKMatrix2(Assimp.Matrix4x4 matOut) { var matIn = new OpenTK.Matrix4(); matOut.A1 = matIn.M11; matOut.B1 = matIn.M12; matOut.C1 = matIn.M13; matOut.D1 = matIn.M14; //Y matOut.A2 = matIn.M21; matOut.B2 = matIn.M22; matOut.C2 = matIn.M23; matOut.D2 = matIn.M24; //Z matOut.A3 = matIn.M31; matOut.B3 = matIn.M32; matOut.C3 = matIn.M33; matOut.D3 = matIn.M34; //Translation matOut.A4 = matIn.M41; matOut.B4 = matIn.M42; matOut.C4 = matIn.M43; matOut.D4 = matIn.M44; return(matIn); }
public static void FromNumerics(this SN.Matrix4x4 matIn, out Assimp.Matrix4x4 matOut) { //Numerics matrix are row vector, so X,Y,Z axes are rows 1-3 and 4th row is translation. //Rows => Columns to make it compatible with assimp //X matOut.A1 = matIn.M11; matOut.B1 = matIn.M12; matOut.C1 = matIn.M13; matOut.D1 = matIn.M14; //Y matOut.A2 = matIn.M21; matOut.B2 = matIn.M22; matOut.C2 = matIn.M23; matOut.D2 = matIn.M24; //Z matOut.A3 = matIn.M31; matOut.B3 = matIn.M32; matOut.C3 = matIn.M33; matOut.D3 = matIn.M34; //Translation matOut.A4 = matIn.M41; matOut.B4 = matIn.M42; matOut.C4 = matIn.M43; matOut.D4 = matIn.M44; }
public static Matrix4x4 ToNumericsTransposed(this Ai.Matrix4x4 value) { return(new Matrix4x4(value.A1, value.B1, value.C1, value.D1, value.A2, value.B2, value.C2, value.D2, value.A3, value.B3, value.C3, value.D3, value.A4, value.B4, value.C4, value.D4)); }
private void UpdateChannel(double time, Node node, aiMatrix4x4 parentTransform) { aiMatrix4x4 nodeTransformation = node.Transform; if (GetChannel(node, out NodeAnimationChannel channel)) { aiMatrix4x4 scale = InterpolateScale(time, channel); aiMatrix4x4 rotation = InterpolateRotation(time, channel); aiMatrix4x4 translation = InterpolateTranslation(time, channel); nodeTransformation = scale * rotation * translation; } if (_boneIDsByName.TryGetValue(node.Name, out uint boneID)) { aiMatrix4x4 m = _firstMesh.Bones[(int)boneID].OffsetMatrix * nodeTransformation * parentTransform * _rootNodeInverseTransform; _boneTransformations[boneID] = m; } foreach (Node childNode in node.Children) { UpdateChannel(time, childNode, nodeTransformation * parentTransform); } }
private void TransformNode(double time, Node aiNode, mat4 parentTransform) { var name = aiNode.Name; var nodeTransform = aiNode.Transform.ToMat4(); var animationChannel = animation.NodeAnimationChannels.SingleOrDefault(m => m.NodeName == name); if (animationChannel != null) { var scaling = InterpolatedHelper.CalcInterpolatedScaling((float)time, animationChannel); var scalingM = mat4.Scale(scaling.X, scaling.Y, scaling.Z); var rotation = InterpolatedHelper.CalcInterpolatedRotation((float)time, animationChannel).GetMatrix(); var rotationM = new Assimp.Matrix4x4(rotation).ToMat4(); var translation = InterpolatedHelper.CalcInterpolatedPosition((float)time, animationChannel); var translationM = mat4.Translate(translation.X, translation.Y, translation.Z); nodeTransform = translationM * rotationM * scalingM; } var globalTransform = parentTransform * nodeTransform; if (allBones.ContainsKey(name)) { allBones[name].finalTransformation = globalTransform * allBones[name].Bone.OffsetMatrix.ToMat4(); } for (int i = 0; i < aiNode.ChildCount; i++) { TransformNode(time, aiNode.Children[i], globalTransform); } }
private static bool NearlyEquals(Ai.Matrix4x4 left, Ai.Matrix4x4 right) { return(NearlyEquals(left.A1, right.A1) && NearlyEquals(left.A2, right.A2) && NearlyEquals(left.A3, right.A3) && NearlyEquals(left.A4, right.A4) && NearlyEquals(left.B1, right.B1) && NearlyEquals(left.B2, right.B2) && NearlyEquals(left.B3, right.B3) && NearlyEquals(left.B4, right.B4) && NearlyEquals(left.C1, right.C1) && NearlyEquals(left.C2, right.C2) && NearlyEquals(left.C3, right.C3) && NearlyEquals(left.C4, right.C4) && NearlyEquals(left.D1, right.D1) && NearlyEquals(left.D2, right.D2) && NearlyEquals(left.D3, right.D3) && NearlyEquals(left.D4, right.D4)); }
public static OpenTK.Matrix4 TKMatrix(Assimp.Matrix4x4 input) { return(new OpenTK.Matrix4(input.A1, input.B1, input.C1, input.D1, input.A2, input.B2, input.C2, input.D2, input.A3, input.B3, input.C3, input.D3, input.A4, input.B4, input.C4, input.D4)); /* return new OpenTK.Matrix4() * { * M11 = input.A1, * M12 = input.A2, * M13 = input.A3, * M14 = input.A4, * M21 = input.B1, * M22 = input.B2, * M23 = input.B3, * M24 = input.B4, * M31 = input.C1, * M32 = input.C2, * M33 = input.C3, * M34 = input.C4, * M41 = input.D1, * M42 = input.D2, * M43 = input.D3, * M44 = input.D4 * };*/ }
// QSRT INFO TO STRING private static string QsrtInfoToString(this Assimp.Matrix4x4 m, string tabspaces, bool showQuaternions) { var checkdeterminatevalid = Math.Abs(m.Determinant()) < 1e-5; string str = ""; // this can fail if the determinante is invalid. if (checkdeterminatevalid == false) { Vector3D scale; Assimp.Quaternion rot; Vector3D rotAngles; Vector3D trans; m.Decompose(out scale, out rot, out trans); QuatToEulerXyz(ref rot, out rotAngles); var rotDeg = rotAngles * (float)(180d / Math.PI); int padamt = 20; if (showQuaternions) { str += "\n" + tabspaces + " " + "As Quaternion ".PadRight(padamt) + rot.ToStringTrimed(); } str += "\n" + tabspaces + " " + "Translation ".PadRight(padamt) + trans.ToStringTrimed(); if (scale.X != scale.Y || scale.Y != scale.Z || scale.Z != scale.X) { str += "\n" + tabspaces + " " + "Scale ".PadRight(padamt) + scale.ToStringTrimed(); } else { str += "\n" + tabspaces + " " + "Scale ".PadRight(padamt) + scale.X.ToString(); //scale.X.ToStringTrimed(); } str += "\n" + tabspaces + " " + "Rotation degrees ".PadRight(padamt) + rotDeg.ToStringTrimed(); // + " radians: " + rotAngles.ToStringTrimed(); str += "\n"; } return(str); }
public static System.Numerics.Matrix4x4 ToNumerics(this Matrix4x4 matrix) { return(new System.Numerics.Matrix4x4(matrix.A1, matrix.B1, matrix.C1, matrix.D1, matrix.A2, matrix.B2, matrix.C2, matrix.D2, matrix.A3, matrix.B3, matrix.C3, matrix.D3, matrix.A4, matrix.B4, matrix.C4, matrix.D4)); }
public static OpenTK.Matrix4d TKMatrixd(Assimp.Matrix4x4 input) { return(new OpenTK.Matrix4d(input.A1, input.B1, input.C1, input.D1, input.A2, input.B2, input.C2, input.D2, input.A3, input.B3, input.C3, input.D3, input.A4, input.B4, input.C4, input.D4)); }
public static void ToNumerics(this Assimp.Matrix4x4 matIn, out SN.Matrix4x4 matOut) { //Assimp matrices are column vector, so X,Y,Z axes are columns 1-3 and 4th column is translation. //Columns => Rows to make it compatible with numerics matOut = new System.Numerics.Matrix4x4(matIn.A1, matIn.B1, matIn.C1, matIn.D1, //X matIn.A2, matIn.B2, matIn.C2, matIn.D2, //Y matIn.A3, matIn.B3, matIn.C3, matIn.D3, //Z matIn.A4, matIn.B4, matIn.C4, matIn.D4); //Translation }
public static Matrix ToMatrix(this Assimp.Matrix4x4 v) { return(Matrix.Transpose(new Matrix( v.A1, v.A2, v.A3, v.A4, v.B1, v.B2, v.B3, v.B4, v.C1, v.C2, v.C3, v.C4, v.D1, v.D2, v.D3, v.D4 ))); }
private Matrix4 ConvertToMatrix4(Assimp.Matrix4x4 m) { var row1 = new Vector4(m.A1, m.A2, m.A3, m.A4); var row2 = new Vector4(m.B1, m.B2, m.B3, m.B4); var row3 = new Vector4(m.C1, m.C2, m.C3, m.C4); var row4 = new Vector4(m.D1, m.D2, m.D3, m.D4); var m4 = new Matrix4(row1, row2, row3, row4); return(m4); }
// T O M G (convert for use with MonoGame) - MATRIX public static Matrix ToMg(this Assimp.Matrix4x4 ma) { Matrix m = Matrix.Identity; m.M11 = TestVal(ma.A1); m.M12 = TestVal(ma.A2); m.M13 = TestVal(ma.A3); m.M14 = TestVal(ma.A4); m.M21 = TestVal(ma.B1); m.M22 = TestVal(ma.B2); m.M23 = TestVal(ma.B3); m.M24 = TestVal(ma.B4); m.M31 = TestVal(ma.C1); m.M32 = TestVal(ma.C2); m.M33 = TestVal(ma.C3); m.M34 = TestVal(ma.C4); m.M41 = TestVal(ma.D1); m.M42 = TestVal(ma.D2); m.M43 = TestVal(ma.D3); m.M44 = TestVal(ma.D4); return(m); }
static NumMatrix4x4 ConvertMatrix(AssMatrix4x4 Mat) { return(NumMatrix4x4.Transpose(*(NumMatrix4x4 *)&Mat)); /*Mat.Decompose(out Vector3D Scaling, out AssQuaternion Rotation, out Vector3D Translation); * * NumMatrix4x4 Rot = NumMatrix4x4.CreateFromQuaternion(ConvertQuat(Rotation)); * NumMatrix4x4 Pos = NumMatrix4x4.CreateTranslation(ConvertVec(Translation)); * NumMatrix4x4 Scl = NumMatrix4x4.CreateScale(ConvertVec(Scaling)); * return Scl * Rot * Pos; * //*/ }
private static Matrix4x4 GetMatrix4x4FromAiMatrix4x4(Ai.Matrix4x4 matrix, bool transpose = true) { if (transpose) { return(new Matrix4x4(matrix.A1, matrix.B1, matrix.C1, matrix.D1, matrix.A2, matrix.B2, matrix.C2, matrix.D2, matrix.A3, matrix.B3, matrix.C3, matrix.D3, matrix.A4, matrix.B4, matrix.C4, matrix.D4)); } else { return(new Matrix4x4(matrix.A1, matrix.A2, matrix.A3, matrix.A4, matrix.B1, matrix.B2, matrix.B3, matrix.B4, matrix.C1, matrix.C2, matrix.C3, matrix.C4, matrix.D1, matrix.D2, matrix.D3, matrix.D4)); } }
/// <summary> /// Transform a direction vector by the given Matrix. Note: this is for assimp /// matrix which is row major. /// </summary> /// <param name="vec">The vector to transform</param> /// <param name="mat">The desired transformation</param> /// <param name="result">The transformed vector</param> public static ai.Vector3D eTransformVector(this ai.Matrix4x4 mat, ai.Vector3D vec) { return(new ai.Vector3D { X = vec.X * mat.A1 + vec.Y * mat.B1 + vec.Z * mat.C1 + mat.A4, Y = vec.X * mat.A2 + vec.Y * mat.B2 + vec.Z * mat.C2 + mat.B4, Z = vec.X * mat.A3 + vec.Y * mat.B3 + vec.Z * mat.C3 + mat.C4 }); }
/// <summary> /// Converts an Assimp <see cref="AssimpMatrix4x4"/> to a numerics <see cref="NumericsMatrix4x4"/>. /// </summary> /// <param name="input">The input <see cref="AssimpMatrix4x4"/>.</param> /// <returns>The output <see cref="NumericsMatrix4x4"/>.</returns> private NumericsMatrix4x4 GetNumericsMatrix4x4(AssimpMatrix4x4 input) { return(new NumericsMatrix4x4(input[1, 1], input[1, 2], input[1, 3], input[1, 4], input[2, 1], input[2, 2], input[2, 3], input[2, 4], input[3, 1], input[3, 2], input[3, 3], input[3, 4], input[4, 1], input[4, 2], input[4, 3], input[4, 4])); }
static public Matrix MatrixAssimpToXna(Assimp.Matrix4x4 matrix) { return(new Matrix( matrix.A1, matrix.A2, matrix.A3, matrix.A4, matrix.B1, matrix.B2, matrix.B3, matrix.B4, matrix.C1, matrix.C2, matrix.C3, matrix.C4, matrix.D1, matrix.D2, matrix.D3, matrix.D4 )); }
public static Assimp.Matrix4x4 convertMatrix(Matrix4 localMat) { Assimp.Matrix4x4 mat = new Assimp.Matrix4x4(); mat.A1 = localMat.Column0.X; mat.A2 = localMat.Column0.Y; mat.A3 = localMat.Column0.Z; mat.A4 = localMat.Column0.W; mat.B1 = localMat.Column1.X; mat.B2 = localMat.Column1.Y; mat.B3 = localMat.Column1.Z; mat.B4 = localMat.Column1.W; mat.C1 = localMat.Column2.X; mat.C2 = localMat.Column2.Y; mat.C3 = localMat.Column2.Z; mat.C4 = localMat.Column2.W; mat.D1 = localMat.Column3.X; mat.D2 = localMat.Column3.Y; mat.D3 = localMat.Column3.Z; mat.D4 = localMat.Column3.W; return(mat); }
/// <summary> /// internal. /// </summary> internal static Matrix ConvertTransform(Assimp.Matrix4x4 mat) { Matrix Result = new Matrix(); Result.a00 = mat.A1; Result.a01 = mat.A2; Result.a02 = mat.A3; Result.a03 = mat.A4; Result.a10 = mat.B1; Result.a11 = mat.B2; Result.a12 = mat.B3; Result.a13 = mat.B4; Result.a20 = mat.C1; Result.a21 = mat.C2; Result.a22 = mat.C3; Result.a23 = mat.C4; Result.a30 = mat.D1; Result.a31 = mat.D2; Result.a32 = mat.D3; Result.a33 = mat.D4; return(Result); }
/// <summary> /// Convert 4x4 Assimp matrix to OpenTK matrix. /// Will be a very useful function becasue Assimp /// matrices are very limited. /// </summary> /// <param name="m"></param> /// <returns></returns> public static tk.Matrix4 eToOpenTK(this ai.Matrix4x4 m) { return(new tk.Matrix4 { M11 = m.A1, M12 = m.B1, M13 = m.C1, M14 = m.D1, M21 = m.A2, M22 = m.B2, M23 = m.C2, M24 = m.D2, M31 = m.A3, M32 = m.B3, M33 = m.C3, M34 = m.D3, M41 = m.A4, M42 = m.B4, M43 = m.C4, M44 = m.D4 }); }
public static Syroot.Maths.Matrix3x4 FromAssimpMatrix(Assimp.Matrix4x4 mat) { var mat4 = new Syroot.Maths.Matrix3x4(); mat4.M11 = mat.A1; mat4.M12 = mat.A2; mat4.M13 = mat.A3; mat4.M14 = mat.A4; mat4.M21 = mat.B1; mat4.M22 = mat.B2; mat4.M23 = mat.B3; mat4.M24 = mat.B4; mat4.M31 = mat.C1; mat4.M32 = mat.C2; mat4.M33 = mat.C3; mat4.M34 = mat.C4; /* mat4.M41 = mat.D1; * mat4.M42 = mat.D2; * mat4.M43 = mat.D3; * mat4.M44 = mat.D4;*/ return(mat4); }
private void CreateByNode(Node node, STSkeleton skeleton, short SmoothIndex, short RigidIndex, bool IsRoot, ref Assimp.Matrix4x4 rootTransform) { Matrix4x4 trafo = node.Transform; Matrix4x4 world = trafo * rootTransform; var transformMat = AssimpHelper.TKMatrix(world); int matchedBoneIndex = skeleton.bones.FindIndex(item => item.Name == node.Name); if (matchedBoneIndex < 0) { tempBoneNodes.Add(node); STBone bone = new STBone(); bone.skeletonParent = skeleton; skeleton.bones.Add(bone); bone.Text = node.Name; bone.SmoothMatrixIndex = (short)skeleton.bones.IndexOf(bone); bone.RigidMatrixIndex = -1; //Todo calculate these STConsole.WriteLine($"-".Repeat(30)); STConsole.WriteLine($"Processing Bone {bone.Text}"); STConsole.WriteLine($"SmoothMatrixIndex {bone.SmoothMatrixIndex}"); STConsole.WriteLine($"RigidMatrixIndex {bone.RigidMatrixIndex}"); STConsole.WriteLine($"Transform Matrix {transformMat}"); STConsole.WriteLine($"-".Repeat(30)); if (IsRoot) { bone.parentIndex = -1; transformMat = AssimpHelper.TKMatrix(world * Matrix4x4.FromRotationX(MathHelper.DegreesToRadians(BoneRotation))); } else { if (tempBoneNodes.Contains(node.Parent)) { bone.parentIndex = tempBoneNodes.IndexOf(node.Parent); } } var scale = transformMat.ExtractScale(); var rotation = transformMat.ExtractRotation(); var position = transformMat.ExtractTranslation(); var rotEular = AssimpHelper.ToEular(rotation); bone.position = new float[] { position.X, position.Y, position.Z }; bone.scale = new float[] { scale.X, scale.Y, scale.Z }; bone.rotation = new float[] { rotEular.X, rotEular.Y, rotEular.Z, 0 }; } else { STConsole.WriteLine($"Duplicate node name found for bone {node.Name}!", Color.Red); } foreach (Node child in node.Children) { CreateByNode(child, skeleton, SmoothIndex, RigidIndex, false, ref rootTransform); } }
private void CreateByNode(Node node, STSkeleton skeleton, string ParentArmatureName, short SmoothIndex, short RigidIndex, bool IsRoot, ref Assimp.Matrix4x4 rootTransform) { Matrix4x4 trafo = node.Transform; Matrix4x4 world = trafo * rootTransform; var transformMat = AssimpHelper.TKMatrix(world); int matchedBoneIndex = skeleton.bones.FindIndex(item => item.Name == node.Name); if (matchedBoneIndex < 0) { tempBoneNodes.Add(node); STBone bone = new STBone(); bone.skeletonParent = skeleton; bone.RotationType = STBone.BoneRotationType.Euler; skeleton.bones.Add(bone); if (DaeHelper.IDMapToName.ContainsKey(node.Name)) { bone.Text = DaeHelper.IDMapToName[node.Name]; } else { bone.Text = node.Name; } bone.SmoothMatrixIndex = (short)skeleton.bones.IndexOf(bone); bone.RigidMatrixIndex = -1; //Todo calculate these if (IsRoot) { bone.parentIndex = -1; if (RotateSkeleton) { transformMat = AssimpHelper.TKMatrix(world * Matrix4x4.FromRotationX(MathHelper.DegreesToRadians(RotateSkeletonAmount))); } else { transformMat = AssimpHelper.TKMatrix(world); } } else { if (tempBoneNodes.Contains(node.Parent)) { bone.parentIndex = tempBoneNodes.IndexOf(node.Parent); } } var scale = transformMat.ExtractScale(); var rotation = transformMat.ExtractRotation(); var position = transformMat.ExtractTranslation(); STConsole.WriteLine($"-".Repeat(30)); STConsole.WriteLine($"Processing Bone {bone.Text}"); STConsole.WriteLine($"scale {scale}"); STConsole.WriteLine($"rotation {rotation}"); STConsole.WriteLine($"position {position}"); STConsole.WriteLine($"-".Repeat(30)); bone.FromTransform(transformMat); } else { STConsole.WriteLine($"Duplicate node name found for bone {node.Name}!", Color.Red); } var identity = Matrix4x4.Identity; foreach (Node child in node.Children) { CreateByNode(child, skeleton, ParentArmatureName, SmoothIndex, RigidIndex, false, ref identity); } }
public static Matrix4x4 ToNumerics(this Ai.Matrix4x4 value) => new Matrix4x4(value.A1, value.A2, value.A3, value.A4, value.B1, value.B2, value.B3, value.B4, value.C1, value.C2, value.C3, value.C4, value.D1, value.D2, value.D3, value.D4);
public unsafe override ProcessedModel ProcessT(Stream stream, string extension) { AssimpContext ac = new AssimpContext(); Scene scene = ac.ImportFileFromStream( stream, PostProcessSteps.FlipWindingOrder | PostProcessSteps.GenerateNormals | PostProcessSteps.FlipUVs, extension); aiMatrix4x4 rootNodeInverseTransform = scene.RootNode.Transform; rootNodeInverseTransform.Inverse(); List <ProcessedMeshPart> parts = new List <ProcessedMeshPart>(); List <ProcessedAnimation> animations = new List <ProcessedAnimation>(); HashSet <string> encounteredNames = new HashSet <string>(); for (int meshIndex = 0; meshIndex < scene.MeshCount; meshIndex++) { Mesh mesh = scene.Meshes[meshIndex]; string meshName = mesh.Name; if (string.IsNullOrEmpty(meshName)) { meshName = $"mesh_{meshIndex}"; } int counter = 1; while (!encounteredNames.Add(meshName)) { meshName = mesh.Name + "_" + counter.ToString(); counter += 1; } int vertexCount = mesh.VertexCount; int positionOffset = 0; int normalOffset = 12; int texCoordsOffset = -1; int boneWeightOffset = -1; int boneIndicesOffset = -1; List <VertexElementDescription> elementDescs = new List <VertexElementDescription>(); elementDescs.Add(new VertexElementDescription("Position", VertexElementSemantic.Position, VertexElementFormat.Float3)); elementDescs.Add(new VertexElementDescription("Normal", VertexElementSemantic.Normal, VertexElementFormat.Float3)); normalOffset = 12; int vertexSize = 24; bool hasTexCoords = mesh.HasTextureCoords(0); elementDescs.Add(new VertexElementDescription("TexCoords", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float2)); texCoordsOffset = vertexSize; vertexSize += 8; bool hasBones = mesh.HasBones; if (hasBones) { elementDescs.Add(new VertexElementDescription("BoneWeights", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float4)); elementDescs.Add(new VertexElementDescription("BoneIndices", VertexElementSemantic.TextureCoordinate, VertexElementFormat.UInt4)); boneWeightOffset = vertexSize; vertexSize += 16; boneIndicesOffset = vertexSize; vertexSize += 16; } byte[] vertexData = new byte[vertexCount * vertexSize]; VertexDataBuilder builder = new VertexDataBuilder(vertexData, vertexSize); Vector3 min = vertexCount > 0 ? mesh.Vertices[0].ToSystemVector3() : Vector3.Zero; Vector3 max = vertexCount > 0 ? mesh.Vertices[0].ToSystemVector3() : Vector3.Zero; for (int i = 0; i < vertexCount; i++) { Vector3 position = mesh.Vertices[i].ToSystemVector3(); min = Vector3.Min(min, position); max = Vector3.Max(max, position); builder.WriteVertexElement( i, positionOffset, position); Vector3 normal = mesh.Normals[i].ToSystemVector3(); builder.WriteVertexElement(i, normalOffset, normal); if (mesh.HasTextureCoords(0)) { builder.WriteVertexElement( i, texCoordsOffset, new Vector2(mesh.TextureCoordinateChannels[0][i].X, mesh.TextureCoordinateChannels[0][i].Y)); } else { builder.WriteVertexElement( i, texCoordsOffset, new Vector2()); } } List <int> indices = new List <int>(); foreach (Face face in mesh.Faces) { if (face.IndexCount == 3) { indices.Add(face.Indices[0]); indices.Add(face.Indices[1]); indices.Add(face.Indices[2]); } } Dictionary <string, uint> boneIDsByName = new Dictionary <string, uint>(); System.Numerics.Matrix4x4[] boneOffsets = new System.Numerics.Matrix4x4[mesh.BoneCount]; if (hasBones) { Dictionary <int, int> assignedBoneWeights = new Dictionary <int, int>(); for (uint boneID = 0; boneID < mesh.BoneCount; boneID++) { Bone bone = mesh.Bones[(int)boneID]; string boneName = bone.Name; int suffix = 1; while (boneIDsByName.ContainsKey(boneName)) { boneName = bone.Name + "_" + suffix.ToString(); suffix += 1; } boneIDsByName.Add(boneName, boneID); foreach (VertexWeight weight in bone.VertexWeights) { int relativeBoneIndex = GetAndIncrementRelativeBoneIndex(assignedBoneWeights, weight.VertexID); builder.WriteVertexElement(weight.VertexID, boneIndicesOffset + (relativeBoneIndex * sizeof(uint)), boneID); builder.WriteVertexElement(weight.VertexID, boneWeightOffset + (relativeBoneIndex * sizeof(float)), weight.Weight); } System.Numerics.Matrix4x4 offsetMat = bone.OffsetMatrix.ToSystemMatrixTransposed(); System.Numerics.Matrix4x4.Decompose(offsetMat, out var scale, out var rot, out var trans); offsetMat = System.Numerics.Matrix4x4.CreateScale(scale) * System.Numerics.Matrix4x4.CreateFromQuaternion(rot) * System.Numerics.Matrix4x4.CreateTranslation(trans); boneOffsets[boneID] = offsetMat; } } builder.FreeGCHandle(); uint indexCount = (uint)indices.Count; int[] int32Indices = indices.ToArray(); byte[] indexData = new byte[indices.Count * sizeof(uint)]; fixed(byte *indexDataPtr = indexData) { fixed(int *int32Ptr = int32Indices) { Buffer.MemoryCopy(int32Ptr, indexDataPtr, indexData.Length, indexData.Length); } } ProcessedMeshPart part = new ProcessedMeshPart( vertexData, elementDescs.ToArray(), indexData, IndexFormat.UInt32, (uint)indices.Count, boneIDsByName, boneOffsets); parts.Add(part); } // Nodes Node rootNode = scene.RootNode; List <ProcessedNode> processedNodes = new List <ProcessedNode>(); ConvertNode(rootNode, -1, processedNodes); ProcessedNodeSet nodes = new ProcessedNodeSet(processedNodes.ToArray(), 0, rootNodeInverseTransform.ToSystemMatrixTransposed()); for (int animIndex = 0; animIndex < scene.AnimationCount; animIndex++) { Animation animation = scene.Animations[animIndex]; Dictionary <string, ProcessedAnimationChannel> channels = new Dictionary <string, ProcessedAnimationChannel>(); for (int channelIndex = 0; channelIndex < animation.NodeAnimationChannelCount; channelIndex++) { NodeAnimationChannel nac = animation.NodeAnimationChannels[channelIndex]; channels[nac.NodeName] = ConvertChannel(nac); } string baseAnimName = animation.Name; if (string.IsNullOrEmpty(baseAnimName)) { baseAnimName = "anim_" + animIndex; } string animationName = baseAnimName; int counter = 1; while (!encounteredNames.Add(animationName)) { animationName = baseAnimName + "_" + counter.ToString(); counter += 1; } } return(new ProcessedModel() { MeshParts = parts.ToArray(), Animations = animations.ToArray(), Nodes = nodes }); }
public static unsafe System.Numerics.Matrix4x4 ToSystemMatrixTransposed(this aiMatrix4x4 mat) { return(System.Numerics.Matrix4x4.Transpose(Unsafe.Read <System.Numerics.Matrix4x4>(&mat))); }
private Mesh ProcessMesh(Assimp.Mesh mesh, Assimp.Scene scene, Assimp.Matrix4x4 transform) { List <Vertex> vertices = new List <Vertex>(); List <uint> indices = new List <uint>(); List <Texture> textures = new List <Texture>(); for (int i = 0; i < mesh.VertexCount; ++i) { var vertex = new Vertex() { Position = new Vector3(mesh.Vertices[i].X, mesh.Vertices[i].Y, mesh.Vertices[i].Z), Normal = new Vector3(mesh.Normals[i].X, mesh.Normals[i].Y, mesh.Normals[i].Z) }; if (mesh.HasTextureCoords(0)) { var texCoords = new Vector2(mesh.TextureCoordinateChannels[0][i].X, mesh.TextureCoordinateChannels[0][i].Y); vertex.TexCoords = texCoords; } else { vertex.TexCoords = new Vector2(0, 0); } if (mesh.HasTangentBasis) { vertex.Tangent = new Vector3(mesh.Tangents[i].X, mesh.Tangents[i].Y, mesh.Tangents[i].Z); vertex.BiTangent = new Vector3(mesh.BiTangents[i].X, mesh.BiTangents[i].Y, mesh.BiTangents[i].Z); } vertices.Add(vertex); } for (int i = 0; i < mesh.FaceCount; ++i) { var face = mesh.Faces[i]; for (int f = 0; f < face.IndexCount; ++f) { indices.Add((uint)face.Indices[f]); } } if (mesh.MaterialIndex >= 0) { var material = scene.Materials[mesh.MaterialIndex]; var diffuseMaps = LoadMaterialTextures(material, TextureType.Diffuse, "texture_diffuse"); textures.AddRange(diffuseMaps); if (diffuseMaps.Count == 0) { textures.Add(Texture.LoadFromData(new[] { (byte)(material.ColorDiffuse.R * 255), (byte)(material.ColorDiffuse.G * 255), (byte)(material.ColorDiffuse.B * 255), (byte)(material.ColorDiffuse.A * 255) }, 1, 1, 4, "texture_diffuse")); } var specularMaps = LoadMaterialTextures(material, TextureType.Specular, "texture_specular"); textures.AddRange(specularMaps); if (specularMaps.Count == 0) { textures.Add(Texture.LoadFromData(new[] { (byte)(material.ColorSpecular.R * 255), (byte)(material.ColorSpecular.G * 255), (byte)(material.ColorSpecular.B * 255), (byte)(material.ColorSpecular.A * 255) }, 1, 1, 4, "texture_specular")); } var normalMaps = LoadMaterialTextures(material, TextureType.Normals, "texture_normal"); textures.AddRange(normalMaps); var emissiveMaps = LoadMaterialTextures(material, TextureType.Emissive, "texture_emissive"); textures.AddRange(emissiveMaps); if (specularMaps.Count == 0) { textures.Add(Texture.LoadFromData(new[] { (byte)(material.ColorEmissive.R * 255), (byte)(material.ColorEmissive.G * 255), (byte)(material.ColorEmissive.B * 255), (byte)(material.ColorEmissive.A * 255) }, 1, 1, 4, "texture_emissive")); } var unknownMaps = LoadMaterialTextures(material, TextureType.Unknown, "texture_unknown"); // includes roughness textures.AddRange(unknownMaps); } var oglTransform = new System.Numerics.Matrix4x4( transform.A1, transform.A2, transform.A3, transform.A4, transform.B1, transform.B2, transform.B3, transform.B4, transform.C1, transform.C2, transform.C3, transform.C4, transform.D1, transform.D2, transform.D3, transform.D4 ); return(new Mesh(vertices, indices, textures, oglTransform)); }
public static Math3d.Matrix4x4 ToMath3D(this Assimp.Matrix4x4 m) => new Math3d.Matrix4x4( m.A1, m.A2, m.A3, m.A4, m.B1, m.B2, m.B3, m.B4, m.C1, m.C2, m.C3, m.C4, m.D1, m.D2, m.D3, m.D4);