internal RwClumpStructNode(RwClumpNode clumpNode) : base(RwNodeId.RwStructNode, clumpNode) { mAtomicCount = clumpNode.Atomics.Count; mLightCount = 0; mCameraCount = 0; }
public static Assimp.Scene ToAssimpScene(RwClumpNode clumpNode) { // Scene var aiScene = new Assimp.Scene(); // RootNode var rootFrame = clumpNode.FrameList[0]; var aiRootNode = new Assimp.Node("RootNode", null); aiRootNode.Transform = new Assimp.Matrix4x4(rootFrame.Transform.M11, rootFrame.Transform.M21, rootFrame.Transform.M31, rootFrame.Transform.M41, rootFrame.Transform.M12, rootFrame.Transform.M22, rootFrame.Transform.M32, rootFrame.Transform.M42, rootFrame.Transform.M13, rootFrame.Transform.M23, rootFrame.Transform.M33, rootFrame.Transform.M43, rootFrame.Transform.M14, rootFrame.Transform.M24, rootFrame.Transform.M34, rootFrame.Transform.M44); aiScene.RootNode = aiRootNode; for (int i = 1; i < clumpNode.FrameList.Count; i++) { var frame = clumpNode.FrameList[i]; var frameName = "_" + frame.HAnimFrameExtensionNode.NameId; Assimp.Node aiParentNode = null; if (frame.Parent != null) { string parentName = "RootNode"; if (frame.Parent.HasHAnimExtension) { parentName = "_" + frame.Parent.HAnimFrameExtensionNode.NameId; } aiParentNode = aiRootNode.FindNode(parentName); } var aiNode = new Assimp.Node(frameName, aiParentNode); aiNode.Transform = new Assimp.Matrix4x4(frame.Transform.M11, frame.Transform.M21, frame.Transform.M31, frame.Transform.M41, frame.Transform.M12, frame.Transform.M22, frame.Transform.M32, frame.Transform.M42, frame.Transform.M13, frame.Transform.M23, frame.Transform.M33, frame.Transform.M43, frame.Transform.M14, frame.Transform.M24, frame.Transform.M34, frame.Transform.M44); aiParentNode.Children.Add(aiNode); } // Meshes, Materials for (int atomicIndex = 0; atomicIndex < clumpNode.Atomics.Count; atomicIndex++) { var atomic = clumpNode.Atomics[atomicIndex]; var geometry = clumpNode.GeometryList[atomic.GeometryIndex]; var frame = clumpNode.FrameList[atomic.FrameIndex]; var aiNodeName = $"Atomic{atomicIndex}"; var aiNode = new Assimp.Node(aiNodeName, aiScene.RootNode); var frameWorldTransform = frame.WorldTransform; aiNode.Transform = new Assimp.Matrix4x4(frameWorldTransform.M11, frameWorldTransform.M21, frameWorldTransform.M31, frameWorldTransform.M41, frameWorldTransform.M12, frameWorldTransform.M22, frameWorldTransform.M32, frameWorldTransform.M42, frameWorldTransform.M13, frameWorldTransform.M23, frameWorldTransform.M33, frameWorldTransform.M43, frameWorldTransform.M14, frameWorldTransform.M24, frameWorldTransform.M34, frameWorldTransform.M44); aiScene.RootNode.Children.Add(aiNode); bool hasVertexWeights = geometry.SkinNode != null; for (int meshIndex = 0; meshIndex < geometry.MeshListNode.MaterialMeshes.Length; meshIndex++) { var mesh = geometry.MeshListNode.MaterialMeshes[meshIndex]; var aiMesh = new Assimp.Mesh($"Atomic{atomicIndex}_Geometry{atomic.GeometryIndex}_Mesh{meshIndex}", Assimp.PrimitiveType.Triangle); // get triangle list indices int[] indices; if (geometry.MeshListNode.PrimitiveType == RwPrimitiveType.TriangleList) { indices = mesh.Indices; } else { indices = MeshUtilities.ToTriangleList(mesh.Indices, false); } // Faces for (int i = 0; i < indices.Length; i += 3) { var faceIndices = new[] { i, i + 1, i + 2 }; var aiFace = new Assimp.Face(faceIndices); aiMesh.Faces.Add(aiFace); } // TextureCoordinateChannels, VertexColorChannels, Vertices, MaterialIndex, Normals for (int triIdx = 0; triIdx < indices.Length; triIdx += 3) { for (int triVertIdx = 0; triVertIdx < 3; triVertIdx++) { int vertexIndex = indices[triIdx + triVertIdx]; // TextureCoordinateChannels if (geometry.HasTextureCoordinates) { for (int channelIdx = 0; channelIdx < geometry.TextureCoordinateChannelCount; channelIdx++) { var textureCoordinate = geometry.TextureCoordinateChannels[channelIdx][vertexIndex]; var aiTextureCoordinate = new Assimp.Vector3D(textureCoordinate.X, textureCoordinate.Y, 0f); aiMesh.TextureCoordinateChannels[channelIdx].Add(aiTextureCoordinate); } } // VertexColorChannels if (geometry.HasColors) { var color = geometry.Colors[vertexIndex]; var aiColor = new Assimp.Color4D(color.R / 255f, color.G / 255f, color.B / 255f, color.A / 255f); aiMesh.VertexColorChannels[0].Add(aiColor); } // Vertices if (geometry.HasVertices) { var vertex = geometry.Vertices[vertexIndex]; var aiVertex = new Assimp.Vector3D(vertex.X, vertex.Y, vertex.Z); aiMesh.Vertices.Add(aiVertex); } // Normals if (geometry.HasNormals) { var normal = geometry.Normals[vertexIndex]; var aiNormal = new Assimp.Vector3D(normal.X, normal.Y, normal.Z); aiMesh.Normals.Add(aiNormal); } } } // Bones if (hasVertexWeights) { var skinNode = geometry.SkinNode; var aiBoneMap = new Dictionary <int, Assimp.Bone>(); for (int i = 0; i < indices.Length; i++) { var vertexIndex = indices[i]; int realVertexIndex = i; for (int j = 0; j < 4; j++) { var boneIndex = skinNode.VertexBoneIndices[vertexIndex][j]; var boneWeight = skinNode.VertexBoneWeights[vertexIndex][j]; if (boneWeight == 0.0f) { continue; } if (!aiBoneMap.Keys.Contains(boneIndex)) { var aiBone = new Assimp.Bone(); var boneFrame = clumpNode.FrameList.GetFrameByHierarchyIndex(boneIndex); aiBone.Name = boneFrame.HasHAnimExtension ? "_" + boneFrame.HAnimFrameExtensionNode.NameId : "RootNode"; aiBone.VertexWeights.Add(new Assimp.VertexWeight(realVertexIndex, boneWeight)); Matrix4x4.Invert(frame.WorldTransform, out Matrix4x4 invertedFrameWorldTransform); Matrix4x4.Invert(boneFrame.WorldTransform * invertedFrameWorldTransform, out Matrix4x4 offsetMatrix); aiBone.OffsetMatrix = new Assimp.Matrix4x4(offsetMatrix.M11, offsetMatrix.M21, offsetMatrix.M31, offsetMatrix.M41, offsetMatrix.M12, offsetMatrix.M22, offsetMatrix.M32, offsetMatrix.M42, offsetMatrix.M13, offsetMatrix.M23, offsetMatrix.M33, offsetMatrix.M43, offsetMatrix.M14, offsetMatrix.M24, offsetMatrix.M34, offsetMatrix.M44); aiBoneMap[boneIndex] = aiBone; } if (!aiBoneMap[boneIndex].VertexWeights.Any(x => x.VertexID == realVertexIndex)) { aiBoneMap[boneIndex].VertexWeights.Add(new Assimp.VertexWeight(realVertexIndex, boneWeight)); } } } aiMesh.Bones.AddRange(aiBoneMap.Values); } else { var aiBone = new Assimp.Bone(); // Name aiBone.Name = frame.HasHAnimExtension ? "_" + frame.HAnimFrameExtensionNode.NameId : "RootNode"; // VertexWeights for (int i = 0; i < aiMesh.Vertices.Count; i++) { var aiVertexWeight = new Assimp.VertexWeight(i, 1f); aiBone.VertexWeights.Add(aiVertexWeight); } // OffsetMatrix /* * Matrix4x4.Invert( frame.WorldTransform, out Matrix4x4 offsetMatrix ); * aiBone.OffsetMatrix = new Assimp.Matrix4x4( offsetMatrix.M11, offsetMatrix.M21, offsetMatrix.M31, offsetMatrix.M41, * offsetMatrix.M12, offsetMatrix.M22, offsetMatrix.M32, offsetMatrix.M42, * offsetMatrix.M13, offsetMatrix.M23, offsetMatrix.M33, offsetMatrix.M43, * offsetMatrix.M14, offsetMatrix.M24, offsetMatrix.M34, offsetMatrix.M44 ); */ aiBone.OffsetMatrix = Assimp.Matrix4x4.Identity; aiMesh.Bones.Add(aiBone); } var material = geometry.Materials[mesh.MaterialIndex]; var aiMaterial = new Assimp.Material(); if (material.IsTextured) { // TextureDiffuse var texture = material.TextureReferenceNode; aiMaterial.TextureDiffuse = new Assimp.TextureSlot( texture.Name + ".png", Assimp.TextureType.Diffuse, 0, Assimp.TextureMapping.FromUV, 0, 0, Assimp.TextureOperation.Add, Assimp.TextureWrapMode.Wrap, Assimp.TextureWrapMode.Wrap, 0); } // Name aiMaterial.Name = material.Name ?? $"Geometry{atomic.GeometryIndex}_Material{mesh.MaterialIndex}"; if (material.IsTextured && material.Name == null) { aiMaterial.Name = material.TextureReferenceNode.Name; } aiMaterial.ShadingMode = Assimp.ShadingMode.Phong; // Add mesh to meshes aiScene.Meshes.Add(aiMesh); // Add material to materials aiScene.Materials.Add(aiMaterial); // MaterialIndex aiMesh.MaterialIndex = aiScene.Materials.Count - 1; // Add mesh index to node aiNode.MeshIndices.Add(aiScene.Meshes.Count - 1); } } return(aiScene); }