private HxScene.SceneNode ConstructHelixScene(Node node, HelixInternalScene scene) { var group = new HxScene.GroupNode { Name = string.IsNullOrEmpty(node.Name) ? nameof(HxScene.GroupNode) : node.Name, ModelMatrix = node.Transform.ToSharpDXMatrix(configuration.IsSourceMatrixColumnMajor) }; if (node.HasChildren) { foreach (var c in node.Children) { group.AddChildNode(ConstructHelixScene(c, scene)); } } if (node.HasMeshes) { foreach (var idx in node.MeshIndices) { var mesh = scene.Meshes[idx]; var hxNode = OnCreateHxMeshNode(mesh, scene, Matrix.Identity); group.AddChildNode(hxNode); } } if (node.Metadata.Count > 0) { group.Metadata = new Metadata(); foreach (var metadata in node.Metadata.ToHelixMetadata()) { group.Metadata.Add(metadata.Key, metadata.Value); } } return(group); }
private HelixInternalScene ToHelixScene(Scene scene, bool parallel) { var s = new HelixInternalScene { AssimpScene = scene, Meshes = new MeshInfo[scene.MeshCount], Materials = new KeyValuePair <global::Assimp.Material, MaterialCore> [scene.MaterialCount] }; Parallel.Invoke(() => { if (scene.HasMeshes) { if (parallel) { Parallel.ForEach(scene.Meshes, (mesh, state, index) => { s.Meshes[index] = OnCreateHelixGeometry(mesh); }); } else { for (var i = 0; i < scene.MeshCount; ++i) { s.Meshes[i] = OnCreateHelixGeometry(scene.Meshes[i]); } } } }, () => { if (scene.HasMaterials) { embeddedTextures.Clear(); embeddedTextureDict.Clear(); if (scene.HasTextures) { embeddedTextures.AddRange(scene.Textures); for (int i = 0; i < embeddedTextures.Count; ++i) { var key = embeddedTextures[i].Filename; if (string.IsNullOrEmpty(key)) { key = "*" + i.ToString(); } if (!embeddedTextureDict.ContainsKey(key)) { embeddedTextureDict.Add(key, embeddedTextures[i]); } } } for (var i = 0; i < scene.MaterialCount; ++i) { s.Materials[i] = OnCreateHelixMaterial(scene.Materials[i]); } embeddedTextures.Clear(); embeddedTextureDict.Clear(); } }); return(s); }
private ErrorCode LoadAnimations(HelixInternalScene scene) { var dict = new Dictionary <string, HxScene.SceneNode>(SceneNodes.Count); foreach (var node in SceneNodes) { if (node is HxScene.GroupNode && !dict.ContainsKey(node.Name)) { dict.Add(node.Name, node); } } foreach (var node in SceneNodes.Where(x => x is Animations.IBoneMatricesNode) .Select(x => x as Animations.IBoneMatricesNode)) { if (node.Bones != null) { for (var i = 0; i < node.Bones.Length; ++i) { if (dict.TryGetValue(node.Bones[i].Name, out var s)) { ref var b = ref node.Bones[i]; b.ParentNode = s.Parent; b.Node = s; s.IsAnimationNode = true; // Make sure to set this to true } } } }
private ErrorCode LoadAnimations(HelixInternalScene scene) { var dict = new Dictionary <string, HxScene.SceneNode>(SceneNodes.Count); foreach (var node in SceneNodes) { if (node is HxScene.GroupNode && !dict.ContainsKey(node.Name)) { dict.Add(node.Name, node); } } var nodeIdxDict = new Dictionary <string, int>(); foreach (var node in SceneNodes.Where(x => x is Animations.IBoneMatricesNode) .Select(x => x as Animations.IBoneMatricesNode)) { if (node.Bones != null) { nodeIdxDict.Clear(); for (var i = 0; i < node.Bones.Length; ++i) { nodeIdxDict.Add(node.Bones[i].Name, i); } for (var i = 0; i < node.Bones.Length; ++i) { if (dict.TryGetValue(node.Bones[i].Name, out var s)) { ref var b = ref node.Bones[i]; b.ParentNode = s.Parent; b.Node = s; b.BoneLocalTransform = s.ModelMatrix; if (s.Parent != null && nodeIdxDict.TryGetValue(s.Parent.Name, out var idx)) { b.ParentIndex = idx; } s.IsAnimationNode = true; // Make sure to set this to true } } if (Configuration.CreateSkeletonForBoneSkinningMesh && node is HxScene.BoneSkinMeshNode sk && sk.Parent is HxScene.GroupNodeBase group) { var skeleton = sk.CreateSkeletonNode(Configuration.SkeletonMaterial, Configuration.SkeletonEffects, Configuration.SkeletonSizeScale); skeleton.Name = "HxSK_" + sk.Name; group.AddChildNode(skeleton); } //Setup bone matrices initially if it's morphable (unable to render w/o bones) if (node is HxScene.BoneSkinMeshNode sn && sn.MorphTargetWeights.Length > 0 && sn.BoneMatrices?.Length == 0) { sn.UpdateBoneMatrices(); } } }
/// <summary> /// To the hx mesh nodes. /// </summary> /// <param name="mesh">The mesh.</param> /// <param name="scene">The scene.</param> /// <param name="transform"></param> /// <returns></returns> /// <exception cref="System.NotSupportedException">Mesh Type {mesh.Type}</exception> protected virtual HxScene.SceneNode OnCreateHxMeshNode(MeshInfo mesh, HelixInternalScene scene, Matrix transform) { switch (mesh.Type) { case PrimitiveType.Triangle: var material = scene.Materials[mesh.MaterialIndex]; var cullMode = material.Key.HasTwoSided && material.Key.IsTwoSided ? CullMode.Back : CullMode.None; if (Configuration.ForceCullMode) { cullMode = Configuration.CullMode; } var fillMode = material.Key.HasWireFrame && material.Key.IsWireFrameEnabled ? FillMode.Wireframe : FillMode.Solid; //Determine if has bones HxScene.MeshNode mnode; if (mesh.AssimpMesh.HasBones || mesh.AssimpMesh.HasMeshAnimationAttachments) { var mn = new HxScene.BoneSkinMeshNode(); //Bones if (mesh.AssimpMesh.HasBones) { mn.Bones = mesh.AssimpMesh.Bones.Select(x => new HxAnimations.Bone() { Name = x.Name, BindPose = x.OffsetMatrix.ToSharpDXMatrix(configuration.IsSourceMatrixColumnMajor).Inverted(), BoneLocalTransform = Matrix.Identity, InvBindPose = x.OffsetMatrix.ToSharpDXMatrix(configuration.IsSourceMatrixColumnMajor),//Documented at https://github.com/assimp/assimp/pull/1803 }).ToArray(); } else { mn.Geometry = mesh.Mesh; mn.SetupIdentitySkeleton(); } //Morph targets if (mesh.AssimpMesh.HasMeshAnimationAttachments) { int attCount = mesh.AssimpMesh.MeshAnimationAttachmentCount; var mtv = new FastList <MorphTargetVertex>(attCount * mesh.AssimpMesh.VertexCount); foreach (var att in mesh.AssimpMesh.MeshAnimationAttachments) { //NOTE: It seems some files may have invalid normal/tangent data for morph targets. //May need to provide option in future to use 0 normal/tangent deltas or recalculate mtv.AddRange(new MorphTargetVertex[mesh.AssimpMesh.VertexCount].Select((x, i) => new MorphTargetVertex() { deltaPosition = (att.Vertices[i] - mesh.AssimpMesh.Vertices[i]).ToSharpDXVector3(), deltaNormal = att.HasNormals ? (att.Normals[i] - mesh.AssimpMesh.Normals[i]).ToSharpDXVector3() : Vector3.Zero, deltaTangent = att.HasTangentBasis ? (att.Tangents[i] - mesh.AssimpMesh.Tangents[i]).ToSharpDXVector3() : Vector3.Zero })); } mn.MorphTargetWeights = new float[attCount]; mn.InitializeMorphTargets(mtv.ToArray(), mesh.AssimpMesh.VertexCount); } mnode = mn; } else { mnode = new HxScene.MeshNode(); } mnode.Name = string.IsNullOrEmpty(mesh.AssimpMesh.Name) ? $"{nameof(HxScene.MeshNode)}_{Interlocked.Increment(ref MeshIndexForNoName)}" : mesh.AssimpMesh.Name; mnode.Geometry = mesh.Mesh; mnode.Material = material.Value; mnode.ModelMatrix = transform; mnode.CullMode = cullMode; mnode.FillMode = fillMode; return(mnode); case PrimitiveType.Line: var lnode = new HxScene.LineNode { Name = string.IsNullOrEmpty(mesh.AssimpMesh.Name) ? $"{nameof(HxScene.LineNode)}_{Interlocked.Increment(ref MeshIndexForNoName)}" : mesh.AssimpMesh.Name, Geometry = mesh.Mesh, ModelMatrix = transform }; var lmaterial = new LineMaterialCore(); //Must create separate line material lnode.Material = lmaterial; var ml = scene.Materials[mesh.MaterialIndex].Value; if (ml is DiffuseMaterialCore diffuse) { lmaterial.LineColor = diffuse.DiffuseColor; } return(lnode); case PrimitiveType.Point: var pnode = new HxScene.PointNode { Name = string.IsNullOrEmpty(mesh.AssimpMesh.Name) ? $"{nameof(HxScene.PointNode)}_{Interlocked.Increment(ref MeshIndexForNoName)}" : mesh.AssimpMesh.Name, Geometry = mesh.Mesh, ModelMatrix = transform }; var pmaterial = new PointMaterialCore(); //Must create separate point material pnode.Material = pmaterial; var pm = scene.Materials[mesh.MaterialIndex].Value; if (pm is DiffuseMaterialCore diffuse1) { pmaterial.PointColor = diffuse1.DiffuseColor; } return(pnode); default: throw new NotSupportedException($"Mesh Type {mesh.Type} does not supported"); } }
/// <summary> /// To the hx mesh nodes. /// </summary> /// <param name="mesh">The mesh.</param> /// <param name="scene">The scene.</param> /// <param name="transform"></param> /// <returns></returns> /// <exception cref="System.NotSupportedException">Mesh Type {mesh.Type}</exception> protected virtual HxScene.SceneNode OnCreateHxMeshNode(MeshInfo mesh, HelixInternalScene scene, Matrix transform) { switch (mesh.Type) { case PrimitiveType.Triangle: var material = scene.Materials[mesh.MaterialIndex]; var cullMode = material.Key.HasTwoSided && material.Key.IsTwoSided ? CullMode.Back : CullMode.None; if (Configuration.ForceCullMode) { cullMode = Configuration.CullMode; } var fillMode = material.Key.HasWireFrame && material.Key.IsWireFrameEnabled ? FillMode.Wireframe : FillMode.Solid; //Determine if has bones var mnode = mesh.AssimpMesh.HasBones ? new HxScene.BoneSkinMeshNode() { Bones = mesh.AssimpMesh.Bones.Select(x => new HxAnimations.Bone() { Name = x.Name, BindPose = x.OffsetMatrix.ToSharpDXMatrix(configuration.IsSourceMatrixColumnMajor).Inverted(), BoneLocalTransform = Matrix.Identity, InvBindPose = x.OffsetMatrix.ToSharpDXMatrix(configuration.IsSourceMatrixColumnMajor), //Documented at https://github.com/assimp/assimp/pull/1803 }).ToArray() } : new HxScene.MeshNode(); mnode.Name = string.IsNullOrEmpty(mesh.AssimpMesh.Name) ? $"{nameof(HxScene.MeshNode)}_{Interlocked.Increment(ref MeshIndexForNoName)}" : mesh.AssimpMesh.Name; mnode.Geometry = mesh.Mesh; mnode.Material = material.Value; mnode.ModelMatrix = transform; mnode.CullMode = cullMode; mnode.FillMode = fillMode; return(mnode); case PrimitiveType.Line: var lnode = new HxScene.LineNode { Name = string.IsNullOrEmpty(mesh.AssimpMesh.Name) ? $"{nameof(HxScene.LineNode)}_{Interlocked.Increment(ref MeshIndexForNoName)}" : mesh.AssimpMesh.Name, Geometry = mesh.Mesh, ModelMatrix = transform }; var lmaterial = new LineMaterialCore(); //Must create separate line material lnode.Material = lmaterial; var ml = scene.Materials[mesh.MaterialIndex].Value; if (ml is DiffuseMaterialCore diffuse) { lmaterial.LineColor = diffuse.DiffuseColor; } return(lnode); case PrimitiveType.Point: var pnode = new HxScene.PointNode { Name = string.IsNullOrEmpty(mesh.AssimpMesh.Name) ? $"{nameof(HxScene.PointNode)}_{Interlocked.Increment(ref MeshIndexForNoName)}" : mesh.AssimpMesh.Name, Geometry = mesh.Mesh, ModelMatrix = transform }; var pmaterial = new PointMaterialCore(); //Must create separate point material pnode.Material = pmaterial; var pm = scene.Materials[mesh.MaterialIndex].Value; if (pm is DiffuseMaterialCore diffuse1) { pmaterial.PointColor = diffuse1.DiffuseColor; } return(pnode); default: throw new NotSupportedException($"Mesh Type {mesh.Type} does not supported"); } }