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); }
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); }
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 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); }