public Node Import(string path, string texturePakPath = null) { // Import scene. var aiScene = AssimpHelper.ImportScene(path, false); var materialBuildInfos = BuildProceduralMaterials(Path.GetDirectoryName(path), aiScene.Materials, texturePakPath); var rootNode = ConvertNode(aiScene.RootNode, aiScene.Meshes, materialBuildInfos); return(rootNode); }
private static IGeometry ConvertCollisionGeometry(Assimp.Node curAiNode, Assimp.Matrix4x4 nodeWorldTransform, List <Assimp.Mesh> aiMeshes, List <MaterialBuildInfo> materialBuildInfos) { var vertices = new List <Assimp.Vector3D>(); var triangles = new List <Basic.Triangle>(); foreach (var aiMeshIndex in curAiNode.MeshIndices) { var aiMesh = aiMeshes[aiMeshIndex]; for (var i = 0; i < aiMesh.Faces.Count; i++) { var aiFace = aiMesh.Faces[i]; var triangle = new Basic.Triangle(); var flip = false; if (!flip) { triangle.A = ( ushort )vertices.AddUnique(aiMesh.Vertices[aiFace.Indices[0]]); triangle.B = aiFace.IndexCount > 1 ? ( ushort )vertices.AddUnique(aiMesh.Vertices[aiFace.Indices[1]]) : triangle.A; triangle.C = aiFace.IndexCount > 2 ? ( ushort )vertices.AddUnique(aiMesh.Vertices[aiFace.Indices[2]]) : triangle.B; } else { triangle.C = ( ushort )vertices.AddUnique(aiMesh.Vertices[aiFace.Indices[0]]); triangle.B = aiFace.IndexCount > 1 ? ( ushort )vertices.AddUnique(aiMesh.Vertices[aiFace.Indices[1]]) : triangle.A; triangle.A = aiFace.IndexCount > 2 ? ( ushort )vertices.AddUnique(aiMesh.Vertices[aiFace.Indices[2]]) : triangle.B; } triangles.Add(triangle); } } var geometry = new Basic.Geometry { Meshes = new[] { new Basic.Mesh { PrimitiveType = PrimitiveType.Triangles, Primitives = triangles.Cast <Basic.IPrimitive>().ToArray(), } }, VertexPositions = vertices.Select(x => { Assimp.Unmanaged.AssimpLibrary.Instance.TransformVecByMatrix4(ref x, ref nodeWorldTransform); return(AssimpHelper.FromAssimp(x)); } ).ToArray() }; geometry.Bounds = BoundingSphere.Calculate(geometry.VertexPositions); return(geometry); }
public Assimp.Scene ConvertToScene(Model model, Config config) { // Start building scene var aiScene = AssimpHelper.CreateDefaultScene(); // Convert materials for (var i = 0; i < model.Materials.Count; i++) { var material = model.Materials[i]; var aiMaterial = new Assimp.Material { Name = FormatMaterialName(material, i) }; if (material.TextureId != null) { aiMaterial.TextureDiffuse = new Assimp.TextureSlot { TextureType = Assimp.TextureType.Diffuse, FilePath = Path.Combine("textures", FormatTextureName(material.TextureId.Value)) }; } aiScene.Materials.Add(aiMaterial); } // Convert nodes var aiNodeLookup = new Dictionary <Node, Assimp.Node>(); for (var i = 0; i < model.Nodes.Count; i++) { var node = model.Nodes[i]; var aiNode = new Assimp.Node(FormatNodeName(node, i), node.Parent != null ? aiNodeLookup[node.Parent] : aiScene.RootNode); aiNodeLookup[node] = aiNode; aiNode.Transform = node.Transform.ToAssimp(); if (node.Geometry != null) { ConvertMeshList(node.Geometry.Meshes, node, i, model.Nodes, aiScene, aiNode); if (node.Geometry.TranslucentMeshes != null) { ConvertMeshList(node.Geometry.TranslucentMeshes, node, i, model.Nodes, aiScene, aiNode); } } aiNode.Parent.Children.Add(aiNode); } return(aiScene); }
public BoneAnimation LoadBoneAnimation(Assimp.Scene aScene, Assimp.Node aNode, BoneAnimation parent) { var boneAnimation = new BoneAnimation() { Parent = parent, Children = new List <BoneAnimation>(), Positions = new List <Vector3>(), Rotations = new List <Quaternion>(), Scales = new List <Vector3>() }; boneAnimation.Name = aNode.Name; var animationChanel = aScene.Animations[0].NodeAnimationChannels.Where(n => n.NodeName == boneAnimation.Name).FirstOrDefault(); if (animationChanel != null) { boneAnimation.IsAnimate = true; foreach (var aScale in animationChanel.ScalingKeys) { var scale = new Vector3(aScale.Value.X, aScale.Value.Y, aScale.Value.Z); boneAnimation.Scales.Add(scale); } foreach (var aRotation in animationChanel.RotationKeys) { var rotation = new Quaternion(aRotation.Value.X, aRotation.Value.Y, aRotation.Value.Z, aRotation.Value.W); boneAnimation.Rotations.Add(rotation); } foreach (var aTranslate in animationChanel.PositionKeys) { var translate = new Vector3(aTranslate.Value.X, aTranslate.Value.Y, aTranslate.Value.Z); boneAnimation.Positions.Add(translate); } } else { boneAnimation.IsAnimate = false; boneAnimation.Transformation = Matrix.Transpose(AssimpHelper.MatrixAssimpToXna(aNode.Transform)); } foreach (var child in aNode.Children) { boneAnimation.Children.Add(LoadBoneAnimation(aScene, child, boneAnimation)); } BoneAnimations.Add(boneAnimation); return(boneAnimation); }
public PropertiesView() { InitializeComponent(); ViewModel = Locator.Current.GetService <PropertiesViewModel>(); DataContext = ViewModel; AssimpHelper.LoadAssimpNativeLibrary(); var assimpWpfImporter = new AssimpWpfImporter(); var supportedImportFormats = assimpWpfImporter.SupportedImportFormats; var assimpWpfExporter = new AssimpWpfExporter(); var supportedExportFormats = assimpWpfExporter.ExportFormatDescriptions.Select(f => f.FileExtension).ToArray(); //var themeResources = Application.LoadComponent(new Uri("Resources/Styles/ExpressionDark.xaml", UriKind.Relative)) as ResourceDictionary; //Resources.MergedDictionaries.Add(themeResources); spectrumAnalyzer.RegisterSoundPlayer(NAudioSimpleEngine.Instance); waveformTimeline.RegisterSoundPlayer(NAudioSimpleEngine.Instance); nAudioSimple = NAudioSimpleEngine.Instance; NAudioSimpleEngine.Instance.PropertyChanged += NAudioEngine_PropertyChanged; //appControl.ExeName = "binkpl64.exe"; //appControl.Args = "test2.bk2 /J /I2 /P"; //this.Unloaded += new RoutedEventHandler((s, e) => { appControl.Dispose(); }); this.WhenActivated(disposables => { ViewModel.WhenAnyValue(x => x.LoadedBitmapFrame).Subscribe(source => { if (source is { } frame) { LoadImage(frame); } }); ViewModel.WhenAnyValue(x => x.LoadedModelPath).Subscribe(source => { if (source is { } modelpath) { LoadModel(modelpath); } }); ViewModel.PreviewAudioCommand.Subscribe(path => { TempConvertToWemWav(path); }); }); }
Bone GetBone(Mesh mesh, Assimp.Bone aBone) { var bone = mesh.Bones.FirstOrDefault(b => b.Name == aBone.Name); if (bone == null) { var offsetMatrix = aBone.OffsetMatrix; offsetMatrix.Transpose(); bone = new Bone(); bone.Name = aBone.Name; bone.Index = mesh.Bones.Count; bone.Offset = AssimpHelper.MatrixAssimpToXna(offsetMatrix); bone.OffsetInverse = Matrix.Invert(AssimpHelper.MatrixAssimpToXna(offsetMatrix)); mesh.Bones.Add(bone); } return(bone); }
public LandTableSA2 Import(string path, string texturePakPath = null) { var landTable = new LandTableSA2(); var aiScene = AssimpHelper.ImportScene(path, false); var meshNodes = FindMeshNodes(aiScene.RootNode); // Convert textures & build materials var convertMaterialsAndTextures = ConvertMaterialsAndTextures(Path.GetDirectoryName(path), aiScene.Materials, texturePakPath); landTable.TexturePakFileName = Path.GetFileNameWithoutExtension(texturePakPath); landTable.Textures = convertMaterialsAndTextures.TextureReferences; var displayModels = new List <LandModelSA2>(); var collisionModels = new List <LandModelSA2>(); foreach (var aiMeshNode in meshNodes) { if (!aiMeshNode.Name.Contains("hkRB")) { displayModels.Add(ConvertDisplayModel(aiScene, convertMaterialsAndTextures.MaterialBuildInfos, aiMeshNode)); } else { collisionModels.Add(ConvertCollisionModel(aiScene, convertMaterialsAndTextures.MaterialBuildInfos, aiMeshNode)); displayModels.Add(ConvertDisplayModel(aiScene, convertMaterialsAndTextures.MaterialBuildInfos, aiMeshNode)); //var collisionModel = new LandModelSA2(); //collisionModel.Flags |= SurfaceFlags.Collidable; //collisionModel.RootNode = ConvertNode( aiMeshNode, aiScene.Meshes, convertMaterialsAndTextures.MaterialBuildInfos, // ConvertCollisionGeometry ); //var collisionGeometry = ( Basic.Geometry )collisionModel.RootNode.Geometry; //collisionModel.Bounds = collisionGeometry.Bounds; //collisionModels.Add( collisionModel ); } } landTable.Models.AddRange(displayModels); landTable.Models.AddRange(collisionModels); return(landTable); }
public void Initialize() { var vertices = new List <MeshVerticeInfo>(); var indices = new List <int>(); AssimpContext importer = new AssimpContext(); Scene aScene = importer.ImportFile(FilePath, PostProcessPreset.TargetRealTimeMaximumQuality); foreach (var aMesh in aScene.Meshes) { for (int faceIndex = 0; faceIndex < aMesh.FaceCount; faceIndex++) { for (int vertexNum = 0; vertexNum < 3; vertexNum++) { int verticeIndice = aMesh.Faces[faceIndex].Indices[vertexNum]; Vector3 verticePosition = AssimpHelper.VectorAssimpToXna(aMesh.Vertices[verticeIndice]); Vector3 verticeNormal = AssimpHelper.VectorAssimpToXna(aMesh.Normals[verticeIndice]); Vector3 uv = AssimpHelper.VectorAssimpToXna(aMesh.TextureCoordinateChannels[0][verticeIndice]); var verticeUv = new Vector2(uv.X, uv.Y); var vertice = new MeshVerticeInfo() { Position = verticePosition, Normal = verticeNormal, TextureCoordinate = verticeUv }; indices.Add(vertices.Count); vertices.Add(vertice); } } FaceCount += aMesh.FaceCount; } VertexBuffer = new VertexBuffer(GraphicsDevice, typeof(SimpleModelVertex), vertices.Count, BufferUsage.WriteOnly); VertexBuffer.SetData <SimpleModelVertex>(vertices.Select(v => v.ToSimpleModelVertex()).ToArray()); IndexBuffer = new IndexBuffer(GraphicsDevice, typeof(int), indices.Count, BufferUsage.WriteOnly); IndexBuffer.SetData(indices.ToArray()); }
public override Motion Import(string filepath, Config config) { var aiScene = AssimpHelper.ImportScene(filepath); var aiAnimation = aiScene.Animations.FirstOrDefault(); if (aiAnimation == null) { return(null); } var motion = new Motion { Duration = ConvertTime(aiAnimation.DurationInTicks, aiAnimation.TicksPerSecond) }; foreach (var aiChannel in aiAnimation.NodeAnimationChannels) { var nodeName = aiChannel.NodeName; var nodeIndex = ( short )(config.NodeIndexResolver?.Invoke(nodeName) ?? FindNodeIndex(aiScene.RootNode, nodeName)); Debug.Assert(nodeIndex != -1); if (aiChannel.HasPositionKeys) { var controller = new NodeController(ControllerType.Position, nodeIndex, aiChannel.NodeName); foreach (var aiKey in aiChannel.PositionKeys) { controller.Keys.Add(new Vector3Key { Time = ConvertTime(aiKey.Time, aiAnimation.TicksPerSecond), Value = aiKey.Value.FromAssimp() }); } motion.Controllers.Add(controller); } if (aiChannel.HasRotationKeys) { var controller = new NodeController(ControllerType.Rotation, nodeIndex, aiChannel.NodeName); foreach (var aiKey in aiChannel.RotationKeys) { controller.Keys.Add(new QuaternionKey { Time = ConvertTime(aiKey.Time, aiAnimation.TicksPerSecond), Value = Quaternion.Inverse(aiKey.Value.FromAssimp()) }); } motion.Controllers.Add(controller); } if (aiChannel.HasScalingKeys) { var controller = new NodeController(ControllerType.Scale, nodeIndex, aiChannel.NodeName); foreach (var aiKey in aiChannel.ScalingKeys) { controller.Keys.Add(new Vector3Key { Time = ConvertTime(aiKey.Time, aiAnimation.TicksPerSecond), Value = aiKey.Value.FromAssimp() }); } motion.Controllers.Add(controller); } } return(motion); }
private static List <MaterialBuildInfo> BuildProceduralMaterials(string baseDirectory, List <Assimp.Material> aiMaterials, string texturePakPath) { var textureArchive = new GvmArchive(); var textureArchiveStream = new MemoryStream(); var textureArchiveWriter = ( GvmArchiveWriter )textureArchive.Create(textureArchiveStream); var textureIdLookup = new Dictionary <string, int>(StringComparer.InvariantCultureIgnoreCase); if (texturePakPath != null && File.Exists(texturePakPath)) { var extension = Path.GetExtension(texturePakPath); var fileStream = ( Stream )File.OpenRead(texturePakPath); if (extension.Equals(".prs", StringComparison.InvariantCultureIgnoreCase)) { try { var decompressedFileStream = new MemoryStream(); Prs.Decompress(fileStream, decompressedFileStream); fileStream.Dispose(); fileStream = decompressedFileStream; } catch (Exception) { // Not compressed } fileStream.Position = 0; } var existingTextureArchive = new GvmArchive(); var existingTextureArchiveReader = ( GvmArchiveReader )existingTextureArchive.Open(fileStream); for (var i = 0; i < existingTextureArchiveReader.Entries.Count; i++) { var entry = existingTextureArchiveReader.Entries[i]; // Make copy of entry stream var entryStreamCopy = new MemoryStream(); entry.Open().CopyTo(entryStreamCopy); entryStreamCopy.Position = 0; var texture = new VrSharp.GvrTexture.GvrTexture(entryStreamCopy); Console.WriteLine(texture.GlobalIndex); entryStreamCopy.Position = 0; // Clean entry name from the added extension var entryName = Path.ChangeExtension(entry.Name, null); textureArchiveWriter.CreateEntry(entryStreamCopy, entryName); textureIdLookup[entryName] = i; } } var materials = new List <MaterialBuildInfo>(); foreach (var aiMaterial in aiMaterials) { var textureName = Path.GetFileNameWithoutExtension(aiMaterial.TextureDiffuse.FilePath).ToLowerInvariant(); if (!textureIdLookup.TryGetValue(textureName, out var textureId)) { textureId = textureIdLookup[textureName] = textureIdLookup.Count; var texturePath = Path.GetFullPath(Path.Combine(baseDirectory, aiMaterial.TextureDiffuse.FilePath)); if (File.Exists(texturePath)) { // Convert texture var texture = new GvrTexture { GlobalIndex = ( uint )(1 + textureId) }; var textureStream = new MemoryStream(); var textureBitmap = new Bitmap(texturePath); texture.Write(textureBitmap, textureStream); textureStream.Position = 0; // Add it textureArchiveWriter.CreateEntry(textureStream, textureName); } } var material = new MaterialBuildInfo { Ambient = AssimpHelper.FromAssimp(aiMaterial.ColorAmbient), Diffuse = AssimpHelper.FromAssimp(aiMaterial.ColorDiffuse), Specular = AssimpHelper.FromAssimp(aiMaterial.ColorSpecular), ClampU = aiMaterial.TextureDiffuse.WrapModeU == Assimp.TextureWrapMode.Clamp, ClampV = aiMaterial.TextureDiffuse.WrapModeV == Assimp.TextureWrapMode.Clamp, FlipU = aiMaterial.TextureDiffuse.WrapModeU == Assimp.TextureWrapMode.Mirror, FlipV = aiMaterial.TextureDiffuse.WrapModeV == Assimp.TextureWrapMode.Mirror, DestinationAlpha = DstAlphaOp.InverseDst, Exponent = 0, FilterMode = FilterMode.Trilinear, MipMapDAdjust = MipMapDAdjust.D050, SourceAlpha = SrcAlphaOp.Src, SuperSample = false, TextureId = (short)textureId, }; materials.Add(material); } // Write texture archive to file textureArchiveWriter.Flush(); textureArchiveStream.Position = 0; if (texturePakPath != null) { // Compress it. var textureArchivePrsStream = new MemoryStream(); Prs.Compress(textureArchiveStream, textureArchivePrsStream); // Save compressed file. textureArchivePrsStream.Position = 0; using (var outFile = File.Create(texturePakPath)) textureArchivePrsStream.CopyTo(outFile); } return(materials); }
public Node Import(string path, string texturePakPath = null) { // Import scene. var aiScene = AssimpHelper.ImportScene(path, true); // Find the node root of the animated hierarchy. This assumes that only 1 hierarchy exists, and any other // nodes that part of the scene root are mesh nodes. var aiRootNode = FindHierarchyRootNode(aiScene.RootNode); // Convert the nodes in the animated hierarchy from Assimps format, and also keep track of additional info. var convertedNodes = ConvertNodes(aiRootNode); // Find the mesh nodes within the scene. A mesh node is a node with 1 or more meshes attached to it. var meshNodes = FindMeshNodes(aiScene.RootNode); // Map each mesh node to a target node in the animated hierarchy. This is because we can't add extra nodes // to the hierarchy, so we must determine the most appropriate node to add the mesh to. var mappedMeshes = MapMeshNodesToTargetNodes(meshNodes, aiScene.Meshes, convertedNodes); // Convert the materials and textures var materialBuildInfos = BuildProceduralMaterials(Path.GetDirectoryName(path), aiScene.Materials, texturePakPath); // Take the mapped meshes and merge them into 1 geometry per target node // Also builds any supplementary geometries have have to be added to store additional weighted vertex info var geometryBuildInfos = BuildProceduralGeometries(mappedMeshes, convertedNodes, materialBuildInfos); var weightedVertexIdLookup = new Dictionary <Vertex, int>(); var nextWeightedVertexId = 4095; foreach (var geometryBuildInfo in geometryBuildInfos) { // Get target node inverse world transform to transform the vertices the target node's local space Matrix4x4.Invert(geometryBuildInfo.TargetNodeInfo.Node.WorldTransform, out var targetNodeInvWorldTransform); // Start building geometry var geometry = new Geometry(); if (!geometryBuildInfo.IsSupplementary && geometryBuildInfo.UnweightedVertices.Count > 0) { // Add unweighted vertices geometry.VertexList.Add(new VertexNChunk(geometryBuildInfo.UnweightedVertices.Select(x => new VertexN { Position = Vector3.Transform(x.Position, targetNodeInvWorldTransform), Normal = Vector3.TransformNormal(x.Normal, targetNodeInvWorldTransform) }).ToArray()) { BaseIndex = geometryBuildInfo.UnweightedVertices[0].Id }); } if (!sDisableWeights) { BuildWeightedVertexChunks(geometry, geometryBuildInfo, ref targetNodeInvWorldTransform, weightedVertexIdLookup, ref nextWeightedVertexId); } if (!geometryBuildInfo.IsSupplementary) { BuildPolygonList(geometry, geometryBuildInfo, weightedVertexIdLookup); } geometryBuildInfo.TargetNodeInfo.Node.Geometry = geometry; } foreach (var nodeInfo in convertedNodes) { nodeInfo.Node.OptimizeFlags(); } var rootNode = convertedNodes[0]; return(rootNode.Node); }
public void Initialize() { var importer = new AssimpContext(); var aScene = importer.ImportFile(FilePath, PostProcessPreset.TargetRealTimeMaximumQuality); Meshes = new List <Mesh>(); foreach (var aMesh in aScene.Meshes) { var verticesResult = new List <MeshSkinnedVerticeInfo>(); var indicesResult = new List <int>(); var mesh = new Mesh(); mesh.Bones = new List <Bone>(); mesh.Name = aMesh.Name; Dictionary <int, List <VerticeWeight> > VerticeWeights = new Dictionary <int, List <VerticeWeight> >(); foreach (var aBone in aMesh.Bones) { Bone bone = GetBone(mesh, aBone); foreach (var vw in aBone.VertexWeights) { if (!VerticeWeights.ContainsKey(vw.VertexID)) { VerticeWeights.Add(vw.VertexID, new List <VerticeWeight>()); } VerticeWeights[vw.VertexID].Add(new VerticeWeight() { Bone = bone, Weight = vw.Weight }); } } var c = aScene.Materials[aMesh.MaterialIndex].ColorDiffuse; for (int faceIndex = 0; faceIndex < aMesh.Faces.Count(); faceIndex++) { for (int vertexNum = 0; vertexNum < 3; vertexNum++) { int verticeIndice = 0; if (vertexNum < aMesh.Faces[faceIndex].Indices.Count()) { verticeIndice = aMesh.Faces[faceIndex].Indices[vertexNum]; } Vector3 verticePosition = AssimpHelper.VectorAssimpToXna(aMesh.Vertices[verticeIndice]); Vector3 verticeNormal = AssimpHelper.VectorAssimpToXna(aMesh.Normals[verticeIndice]); var uv = AssimpHelper.VectorAssimpToXna(aMesh.TextureCoordinateChannels[0][verticeIndice]); var verticeUv = new Vector2(uv.X, uv.Y); BlendInfo blendInfo = GetBlendInfo(VerticeWeights, verticeIndice); var vertice = new MeshSkinnedVerticeInfo() { Position = verticePosition, Normal = verticeNormal, TextureCoordinate = verticeUv, BoneID = blendInfo.BoneId, BoneWeight = blendInfo.Weight }; indicesResult.Add(verticesResult.Count); verticesResult.Add(vertice); } } mesh.TextureFilePath = aScene.Materials[aMesh.MaterialIndex].TextureDiffuse.FilePath; mesh.VertexBuffer = new VertexBuffer(GraphicsDevice, typeof(SkinnedModelVertex), verticesResult.Count, BufferUsage.WriteOnly); mesh.VertexBuffer.SetData <SkinnedModelVertex>(verticesResult.Select(v => v.ToVertexPositionNormalTextureBones()).ToArray()); mesh.IndexBuffer = new IndexBuffer(GraphicsDevice, typeof(int), indicesResult.Count, BufferUsage.WriteOnly); mesh.IndexBuffer.SetData(indicesResult.ToArray()); mesh.FaceCount = aMesh.FaceCount; Meshes.Add(mesh); } }
private static Node ConvertNode(Assimp.Node aiNode, List <Assimp.Mesh> aiMeshes, List <MaterialBuildInfo> materialBuildInfos) { Node ConvertHierarchyNodeRecursively(Assimp.Node curAiNode, ref Node previousSibling, Node parent, ref Assimp.Matrix4x4 parentNodeWorldTransform) { var nodeWorldTransform = curAiNode.Transform * parentNodeWorldTransform; var nodeInverseWorldTransform = nodeWorldTransform; nodeInverseWorldTransform.Inverse(); curAiNode.Transform.Decompose(out var scale, out var rotation, out var translation); // Create node var node = new Node(AssimpHelper.FromAssimp(translation), AngleVector.FromQuaternion(AssimpHelper.FromAssimp(rotation)), AssimpHelper.FromAssimp(scale), parent); if (curAiNode.HasMeshes) { var geometry = new Geometry(); // Convert meshes var vertexPositions = new List <Assimp.Vector3D>(); var vertexNormals = new List <Assimp.Vector3D>(); var vertexUVs = new List <Assimp.Vector3D>(); var vertexColors = new List <Assimp.Color4D>(); var lastRenderState = new MeshRenderState(); foreach (var aiMeshIndex in curAiNode.MeshIndices) { var aiMesh = aiMeshes[aiMeshIndex]; var material = materialBuildInfos[aiMesh.MaterialIndex]; var mesh = new Mesh(); var renderState = new MeshRenderState(); renderState.IndexFlags = IndexAttributeFlags.HasPosition | IndexAttributeFlags.Position16BitIndex; var useColors = false; var hasColors = aiMesh.HasVertexColors(0); var hasUVs = aiMesh.HasTextureCoords(0); var hasNormals = aiMesh.HasNormals; if (hasColors || !hasNormals) { renderState.IndexFlags |= IndexAttributeFlags.HasColor | IndexAttributeFlags.Color16BitIndex; useColors = true; } else { renderState.IndexFlags |= IndexAttributeFlags.HasNormal | IndexAttributeFlags.Normal16BitIndex; } if (hasUVs) { renderState.IndexFlags |= IndexAttributeFlags.HasUV | IndexAttributeFlags.UV16BitIndex; } // Convert faces var triangleIndices = new Index[aiMesh.FaceCount * 3]; for (var i = 0; i < aiMesh.Faces.Count; i++) { var aiFace = aiMesh.Faces[i]; Debug.Assert(aiFace.IndexCount == 3); for (var j = 0; j < aiFace.Indices.Count; j++) { int aiFaceIndex = aiFace.Indices[j]; var position = aiMesh.Vertices[aiFaceIndex]; var positionIndex = vertexPositions.IndexOf(position); if (positionIndex == -1) { positionIndex = vertexPositions.Count; vertexPositions.Add(position); } var normalIndex = 0; var colorIndex = 0; var uvIndex = 0; if (useColors) { var color = hasColors ? aiMesh.VertexColorChannels[0][aiFaceIndex] : new Assimp.Color4D(); colorIndex = vertexColors.IndexOf(color); if (colorIndex == -1) { colorIndex = vertexColors.Count; vertexColors.Add(color); } } else { var normal = aiMesh.Normals[aiFaceIndex]; normalIndex = vertexNormals.IndexOf(normal); if (normalIndex == -1) { normalIndex = vertexNormals.Count; vertexNormals.Add(normal); } } if (hasUVs) { var uv = aiMesh.TextureCoordinateChannels[0][aiFaceIndex]; uvIndex = vertexUVs.IndexOf(uv); if (uvIndex == -1) { uvIndex = vertexUVs.Count; vertexUVs.Add(uv); } } triangleIndices[(i * 3) + j] = new Index { PositionIndex = ( ushort )positionIndex, NormalIndex = ( ushort )normalIndex, ColorIndex = ( ushort )colorIndex, UVIndex = ( ushort )uvIndex }; } } // Build display list var displayList = new GXDisplayList(GXPrimitive.Triangles, triangleIndices); mesh.DisplayLists.Add(displayList); // Set up render params var indexFlagsParam = new IndexAttributeFlagsParam(renderState.IndexFlags); mesh.Parameters.Add(indexFlagsParam); if (useColors) { mesh.Parameters.Add(new LightingParams(LightingParams.Preset.Colors)); } else { mesh.Parameters.Add(new LightingParams(LightingParams.Preset.Normals)); } mesh.Parameters.Add(new TextureParams(( ushort )(material.TextureId))); mesh.Parameters.Add(new MipMapParams()); geometry.OpaqueMeshes.Add(mesh); } // Build vertex buffers if (vertexPositions.Count > 0) { geometry.VertexBuffers.Add(new VertexPositionBuffer(vertexPositions.Select(x => { Assimp.Unmanaged.AssimpLibrary.Instance.TransformVecByMatrix4(ref x, ref nodeInverseWorldTransform); return(AssimpHelper.FromAssimp(x)); }).ToArray())); } if (vertexNormals.Count > 0) { nodeInverseWorldTransform.Transpose(); geometry.VertexBuffers.Add(new VertexNormalBuffer(vertexNormals.Select(x => { Assimp.Unmanaged.AssimpLibrary.Instance.TransformVecByMatrix4(ref x, ref nodeInverseWorldTransform); return(AssimpHelper.FromAssimp(x)); }).ToArray())); } if (vertexColors.Count > 0) { geometry.VertexBuffers.Add(new VertexColorBuffer(vertexColors.Select(AssimpHelper.FromAssimp).ToArray())); } if (vertexUVs.Count > 0) { geometry.VertexBuffers.Add(new VertexUVBuffer(vertexUVs.Select(x => UVCodec.Encode1023(AssimpHelper .FromAssimpAsVector2(x))) .ToArray())); } } // Set sibling (next) reference of previous if (previousSibling != null) { previousSibling.Sibling = node; } previousSibling = node; if (curAiNode.HasChildren) { Node childPreviousSibling = null; foreach (var aiChildNode in curAiNode.Children) { var childNode = ConvertHierarchyNodeRecursively(aiChildNode, ref childPreviousSibling, node, ref nodeWorldTransform); // Make sure to set the 'first child' reference if we haven't already if (node.Child == null) { node.Child = childNode; } } } return(node); } // Dummy! Node dummy = null; var identity = Assimp.Matrix4x4.Identity; return(ConvertHierarchyNodeRecursively(aiNode, ref dummy, null, ref identity)); }
public void ExportCollada(string filepath) { var aiScene = AssimpHelper.CreateDefaultScene(); foreach (var geometry in Geometries) { for (var meshIndex = 0; meshIndex < geometry.Meshes.Count; meshIndex++) { var aiMeshNode = new Assimp.Node(geometry.Meshes.Count > 1 ? $"{geometry.Name}_mesh_{meshIndex}" : geometry.Name, aiScene.RootNode); aiScene.RootNode.Children.Add(aiMeshNode); var mesh = geometry.Meshes[meshIndex]; var aiMesh = new Assimp.Mesh(); var aiMaterial = new Assimp.Material { Name = mesh.Material.Name, //ColorDiffuse = AssimpHelper.ToAssimp( mesh.Material.Diffuse ), //ColorSpecular = AssimpHelper.ToAssimp( mesh.Material.Specular ), //ColorAmbient = AssimpHelper.ToAssimp( mesh.Material.Ambient ), Shininess = 0, ShininessStrength = 0, Reflectivity = 0, TextureDiffuse = new Assimp.TextureSlot { TextureType = Assimp.TextureType.Diffuse, FilePath = mesh.Material.TextureName, WrapModeU = Assimp.TextureWrapMode.Wrap, WrapModeV = Assimp.TextureWrapMode.Wrap, } }; aiMesh.MaterialIndex = aiScene.MaterialCount; aiScene.Materials.Add(aiMaterial); foreach (var vertex in mesh.Vertices) { aiMesh.Vertices.Add(AssimpHelper.ToAssimp(vertex.Position)); aiMesh.Normals.Add(AssimpHelper.ToAssimp(vertex.Normal)); aiMesh.VertexColorChannels[0].Add(AssimpHelper.ToAssimp(vertex.Color)); aiMesh.TextureCoordinateChannels[0].Add(AssimpHelper.ToAssimp(vertex.UV)); } for (int i = 0; i < mesh.Indices.Length; i += 3) { var aiFace = new Assimp.Face(); for (int j = 0; j < 3; j++) { aiFace.Indices.Add(mesh.Indices[i + j]); } aiMesh.Faces.Add(aiFace); } aiMeshNode.MeshIndices.Add(aiScene.MeshCount); aiScene.Meshes.Add(aiMesh); } } AssimpHelper.ExportCollada(aiScene, filepath); }
public static Model Import(string filepath, bool conformanceMode = true) { var model = new Model(); Geometry geometry = null; if (conformanceMode) { geometry = new Geometry { Name = "polySurfaceShape6" }; model.Geometries.Add(geometry); } var aiScene = AssimpHelper.ImportScene(filepath, false); void ConvertNode(Assimp.Node aiNode) { if (aiNode.HasMeshes) { var nodeWorldTransform = AssimpHelper.CalculateWorldTransform(aiNode); if (!conformanceMode) { geometry = new Geometry { Name = aiNode.Name } } ; foreach (var aiMeshIndex in aiNode.MeshIndices) { var aiMesh = aiScene.Meshes[aiMeshIndex]; var aiMaterial = aiScene.Materials[aiMesh.MaterialIndex]; var mesh = new Mesh(); mesh.Material.Name = aiMaterial.Name; //mesh.Material.Ambient = new Vector4( aiMaterial.ColorAmbient.R, aiMaterial.ColorAmbient.G, aiMaterial.ColorAmbient.B, aiMaterial.ColorAmbient.A ); //mesh.Material.Diffuse = new Vector4( aiMaterial.ColorDiffuse.R, aiMaterial.ColorDiffuse.G, aiMaterial.ColorDiffuse.B,aiMaterial.ColorDiffuse.A ); //mesh.Material.Specular = new Vector4( aiMaterial.ColorSpecular.R, aiMaterial.ColorSpecular.G, aiMaterial.ColorSpecular.B, aiMaterial.ColorSpecular.A ); mesh.Material.TextureName = Path.ChangeExtension(Path.GetFileNameWithoutExtension(aiMaterial.TextureDiffuse.FilePath), "dds"); mesh.Vertices = new Vertex[aiMesh.VertexCount]; for (int i = 0; i < mesh.Vertices.Length; i++) { ref var vertex = ref mesh.Vertices[i]; vertex.Position = Vector3.Transform(AssimpHelper.FromAssimp(aiMesh.Vertices[i]), nodeWorldTransform); vertex.Normal = aiMesh.HasNormals ? Vector3.TransformNormal(AssimpHelper.FromAssimp(aiMesh.Normals[i]), nodeWorldTransform) : new Vector3(); vertex.Color = aiMesh.HasVertexColors(0) ? AssimpHelper.FromAssimp(aiMesh.VertexColorChannels[0][i]) : Color.White; vertex.UV = aiMesh.HasTextureCoords(0) ? AssimpHelper.FromAssimpAsVector2(aiMesh.TextureCoordinateChannels[0][i]) : new Vector2(); } mesh.Indices = aiMesh.GetIndices(); geometry.Meshes.Add(mesh); } if (!conformanceMode) { model.Geometries.Add(geometry); } } foreach (var aiChildNode in aiNode.Children) { ConvertNode(aiChildNode); } } ConvertNode(aiScene.RootNode); if (conformanceMode) { var meshes = new List <Mesh>(geometry.Meshes); var meshMap = new List <int>(); var nextUniqueNewMeshIndex = sOriginalMaterialNames.Length; for (int i = 0; i < meshes.Count; i++) { var newMeshIndex = Array.IndexOf(sOriginalMaterialNames, meshes[i].Material.Name); if (newMeshIndex == -1) { newMeshIndex = nextUniqueNewMeshIndex++; } meshMap.Add(newMeshIndex); } geometry.Meshes.Clear(); for (int i = 0; i < nextUniqueNewMeshIndex; i++) { if (!meshMap.Contains(i)) { geometry.Meshes.Add(new Mesh { Indices = new int[0], Vertices = new Vertex[0], Material = new Material { Name = sOriginalMaterialNames[i % sOriginalMaterialNames.Length], TextureName = sOriginalTextureNames[i % sOriginalTextureNames.Length] } }); } else { geometry.Meshes.Add(null); } } for (int i = 0; i < meshMap.Count; i++) { geometry.Meshes[meshMap[i]] = meshes[i]; } } return(model); }
private static IGeometry ConvertDisplayGeometry(Assimp.Node curAiNode, Assimp.Matrix4x4 nodeWorldTransform, List <Assimp.Mesh> aiMeshes, List <MaterialBuildInfo> materialBuildInfos) { var nodeInverseWorldTransform = nodeWorldTransform; nodeInverseWorldTransform.Inverse(); var nodeInverseTransposeWorldTransform = nodeInverseWorldTransform; nodeInverseTransposeWorldTransform.Transpose(); var geometry = new Geometry(); // Convert meshes var vertexPositions = new List <Assimp.Vector3D>(); var vertexNormals = new List <Assimp.Vector3D>(); var vertexUVs = new List <Assimp.Vector3D>(); var vertexColors = new List <Assimp.Color4D>(); var lastRenderState = new MeshRenderState(); foreach (var aiMeshIndex in curAiNode.MeshIndices) { var aiMesh = aiMeshes[aiMeshIndex]; var material = materialBuildInfos[aiMesh.MaterialIndex]; var mesh = new Mesh(); var renderState = new MeshRenderState(); renderState.IndexFlags = IndexAttributeFlags.HasPosition; var useColors = false; var hasColors = aiMesh.HasVertexColors(0); var hasUVs = aiMesh.HasTextureCoords(0); var hasNormals = aiMesh.HasNormals; if (hasColors || !hasNormals) { renderState.IndexFlags |= IndexAttributeFlags.HasColor; useColors = true; } else { renderState.IndexFlags |= IndexAttributeFlags.HasNormal; } if (hasUVs) { renderState.IndexFlags |= IndexAttributeFlags.HasUV; } // Convert faces var triangleIndices = new Index[aiMesh.FaceCount * 3]; for (var i = 0; i < aiMesh.Faces.Count; i++) { var aiFace = aiMesh.Faces[i]; for (var j = 0; j < 3; j++) { var triangleIndicesIndex = (i * 3) + 2 - j; if (j >= aiFace.IndexCount) { triangleIndices[triangleIndicesIndex] = triangleIndices[triangleIndicesIndex + 1]; continue; } int aiFaceIndex = aiFace.Indices[j]; var position = aiMesh.Vertices[aiFaceIndex]; var positionIndex = vertexPositions.AddUnique(position); if (positionIndex > byte.MaxValue) { renderState.IndexFlags |= IndexAttributeFlags.Position16BitIndex; } var normalIndex = 0; var colorIndex = 0; var uvIndex = 0; if (useColors) { var color = hasColors ? aiMesh.VertexColorChannels[0][aiFaceIndex] : new Assimp.Color4D(); colorIndex = vertexColors.AddUnique(color); if (colorIndex > byte.MaxValue) { renderState.IndexFlags |= IndexAttributeFlags.Color16BitIndex; } } else { var normal = aiMesh.Normals[aiFaceIndex]; normalIndex = vertexNormals.AddUnique(normal); if (normalIndex > byte.MaxValue) { renderState.IndexFlags |= IndexAttributeFlags.Normal16BitIndex; } } if (hasUVs) { var uv = aiMesh.TextureCoordinateChannels[0][aiFaceIndex]; uvIndex = vertexUVs.AddUnique(uv); if (uvIndex > byte.MaxValue) { renderState.IndexFlags |= IndexAttributeFlags.UV16BitIndex; } } triangleIndices[triangleIndicesIndex] = new Index { PositionIndex = ( ushort )positionIndex, NormalIndex = ( ushort )normalIndex, ColorIndex = ( ushort )colorIndex, UVIndex = ( ushort )uvIndex }; } } // Build display list var displayList = new GXDisplayList(GXPrimitive.Triangles, triangleIndices); mesh.DisplayLists.Add(displayList); // Set up render params if (renderState.IndexFlags != lastRenderState.IndexFlags) { mesh.Parameters.Add(new IndexAttributeFlagsParam(renderState.IndexFlags)); } // Set up render lighting params { if (useColors) { renderState.LightingValue1 = 0x0b11; } else { renderState.LightingValue2 = 0x0011; } renderState.LightingValue2 = 1; if (renderState.LightingValue1 != lastRenderState.LightingValue1 || renderState.LightingValue2 != lastRenderState.LightingValue2) { mesh.Parameters.Add(new LightingParams() { Value1 = renderState.LightingValue1, Value2 = renderState.LightingValue2 }); } } // Set up render texture params { renderState.TextureId = ( ushort )material.TextureId; renderState.TileMode = TileMode.WrapU | TileMode.WrapV; if (renderState.TextureId != lastRenderState.TextureId || renderState.TileMode != lastRenderState.TileMode) { mesh.Parameters.Add(new TextureParams(renderState.TextureId, renderState.TileMode)); } } // Set up render mipmap params { renderState.MipMapValue1 = 0x104a; renderState.MipMapValue2 = 0; if (renderState.MipMapValue1 != lastRenderState.MipMapValue1 || renderState.MipMapValue2 != lastRenderState.MipMapValue2) { mesh.Parameters.Add(new MipMapParams { Value1 = renderState.MipMapValue1, Value2 = renderState.MipMapValue2 }); } } //if ( material.UseAlpha ) //{ // mesh.Parameters.Add( new BlendAlphaParam() { Flags = BlendAlphaFlags.UseAlpha } ); // geometry.TranslucentMeshes.Add( mesh ); //} //else //{ // geometry.OpaqueMeshes.Add( mesh ); //} geometry.OpaqueMeshes.Add(mesh); lastRenderState = renderState; } // Build vertex buffers if (vertexPositions.Count > 0) { Debug.Assert(vertexPositions.Count <= ushort.MaxValue); var localVertexPositions = vertexPositions.Select(x => { Assimp.Unmanaged.AssimpLibrary.Instance.TransformVecByMatrix4(ref x, ref nodeWorldTransform); return(AssimpHelper.FromAssimp(x)); }).ToArray(); geometry.VertexBuffers.Add(new VertexPositionBuffer(localVertexPositions)); geometry.Bounds = BoundingSphere.Calculate(localVertexPositions); } if (vertexNormals.Count > 0) { Debug.Assert(vertexNormals.Count <= ushort.MaxValue); geometry.VertexBuffers.Add(new VertexNormalBuffer(vertexNormals.Select(x => { Assimp.Unmanaged.AssimpLibrary.Instance.TransformVecByMatrix4(ref x, ref nodeInverseTransposeWorldTransform); return(AssimpHelper.FromAssimp(x)); }).ToArray())); } if (vertexColors.Count > 0) { Debug.Assert(vertexColors.Count <= ushort.MaxValue); geometry.VertexBuffers.Add(new VertexColorBuffer(vertexColors.Select(AssimpHelper.FromAssimp).ToArray())); } if (vertexUVs.Count > 0) { Debug.Assert(vertexUVs.Count <= ushort.MaxValue); geometry.VertexBuffers.Add(new VertexUVBuffer(vertexUVs.Select(x => UVCodec.Encode255(AssimpHelper .FromAssimpAsVector2(x))) .ToArray())); } return(geometry); }