Example #1
0
        public static ModelRoot ToGLTF(this Papa papa)
        {
            ModelRoot root     = ModelRoot.CreateModel();
            Scene     scene    = root.UseScene("default");
            Node      rootNode = scene
                                 .CreateNode()
                                 .WithLocalRotation(Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), (float)(-90 * (Math.PI / 180))));

            foreach (PapaModel papaModel in papa.Models)
            {
                Node modelNode = rootNode
                                 .CreateNode();

                // Skinned model
                if (papaModel.Skeleton != null)
                {
                    List <(Node, Matrix4x4)> skeleton = CreateSkeleton(modelNode, papaModel.Skeleton);

                    foreach (PapaMeshBinding meshBinding in papaModel.MeshBindings)
                    {
                        modelNode
                        .CreateNode(papaModel.Name)
                        .WithSkinnedMesh(root.CreateMesh(BuildSkinnedMesh(meshBinding)), skeleton.ToArray());
                    }

                    if (papa.Animations.Count != 0)
                    {
                        CreateAnimations(root, skeleton, papa.Animations);
                    }
                }
                else
                {
                    foreach (PapaMeshBinding meshBinding in papaModel.MeshBindings)
                    {
                        var meshBuilder = BuildMesh(meshBinding);

                        modelNode
                        .CreateNode(meshBinding.Name)
                        .WithMesh(root.CreateMesh(meshBuilder));
                    }
                }
            }

            return(root);
        }
Example #2
0
        public Mesh CreateSchema2Mesh(ModelRoot root, Func <TMaterial, Material> materialEvaluator)
        {
            var dstMesh = root.CreateMesh(_MeshName);

            foreach (var p in _Primitives)
            {
                p.CopyToMesh(dstMesh, materialEvaluator);
            }

            return(dstMesh);
        }
        public Mesh CreateSchema2Mesh(ModelRoot root, Func <TMaterial, Material> materialEvaluator)
        {
            if (_Primitives.Count == 0)
            {
                return(null);
            }

            var dstMesh = root.CreateMesh(_MeshName);

            foreach (var p in _Primitives)
            {
                p.CopyToMesh(dstMesh, materialEvaluator);
            }

            dstMesh.SetMorphWeights(default);
        public Mesh CreateSchema2Mesh(ModelRoot root, Converter <TMaterial, Material> materialEvaluator)
        {
            if (_Primitives.Count == 0)
            {
                return(null);
            }

            var dstMesh = root.CreateMesh();

            this.TryCopyNameAndExtrasTo(dstMesh);

            foreach (var p in _Primitives)
            {
                p.CopyToMesh(dstMesh, materialEvaluator);
            }

            dstMesh.SetMorphWeights(default);
Example #5
0
        public static ModelRoot ToGLTF(this MapGeometry mgeo)
        {
            ModelRoot root     = ModelRoot.CreateModel();
            Scene     scene    = root.UseScene("Map");
            Node      rootNode = scene.CreateNode("Map");

            // Find all layer combinations used in the Map
            // so we can group the meshes
            var layerModelMap = new Dictionary <MapGeometryLayer, List <MapGeometryModel> >();

            foreach (MapGeometryModel model in mgeo.Models)
            {
                if (!layerModelMap.ContainsKey(model.Layer))
                {
                    layerModelMap.Add(model.Layer, new List <MapGeometryModel>());
                }

                layerModelMap[model.Layer].Add(model);
            }

            // Create node for each layer combination
            var layerNodeMap = new Dictionary <MapGeometryLayer, Node>();

            foreach (var layerModelPair in layerModelMap)
            {
                layerNodeMap.Add(layerModelPair.Key, rootNode.CreateNode(DeriveLayerCombinationName(layerModelPair.Key)));
            }

            foreach (MapGeometryModel model in mgeo.Models)
            {
                IMeshBuilder <MaterialBuilder> meshBuilder = BuildMapGeometryMeshStatic(model);

                layerNodeMap[model.Layer]
                .CreateNode()
                .WithMesh(root.CreateMesh(meshBuilder))
                .WithLocalTransform(new AffineTransform(model.Transformation));
            }

            return(root);
        }
Example #6
0
        public static ModelRoot ToGltf(this StaticObject staticObject)
        {
            ModelRoot root  = ModelRoot.CreateModel();
            Scene     scene = root.UseScene("default");

            var mesh = VERTEX.CreateCompatibleMesh();

            foreach (StaticObjectSubmesh submesh in staticObject.Submeshes)
            {
                MaterialBuilder material  = new MaterialBuilder(submesh.Name);
                var             primitive = mesh.UsePrimitive(material);

                List <VERTEX> vertices = new List <VERTEX>();
                foreach (StaticObjectVertex vertex in submesh.Vertices)
                {
                    vertices.Add(new VERTEX()
                                 .WithGeometry(vertex.Position)
                                 .WithMaterial(vertex.UV));
                }

                for (int i = 0; i < submesh.Indices.Count; i += 3)
                {
                    VERTEX v1 = vertices[(int)submesh.Indices[i + 0]];
                    VERTEX v2 = vertices[(int)submesh.Indices[i + 1]];
                    VERTEX v3 = vertices[(int)submesh.Indices[i + 2]];

                    primitive.AddTriangle(v1, v2, v3);
                }
            }

            scene
            .CreateNode()
            .WithMesh(root.CreateMesh(mesh));

            return(root);
        }
Example #7
0
        public Mesh FindOrCreateMesh(ModelRoot model, string meshName)
        {
            var mesh = model.LogicalMeshes.FirstOrDefault(m => m.Name == meshName) ?? model.CreateMesh(meshName);

            return(mesh);
        }
        private Mesh CreateGltfMesh(string meshName, VMesh vmesh, ModelRoot model, bool includeJoints)
        {
            ProgressDialog.SetProgress($"Creating mesh: {meshName}");

            var data = vmesh.GetData();
            var vbib = vmesh.VBIB;

            var mesh = model.CreateMesh(meshName);

            mesh.Name = meshName;

            foreach (var sceneObject in data.GetArray("m_sceneObjects"))
            {
                foreach (var drawCall in sceneObject.GetArray("m_drawCalls"))
                {
                    var vertexBufferInfo  = drawCall.GetArray("m_vertexBuffers")[0]; // In what situation can we have more than 1 vertex buffer per draw call?
                    var vertexBufferIndex = (int)vertexBufferInfo.GetIntegerProperty("m_hBuffer");
                    var vertexBuffer      = vbib.VertexBuffers[vertexBufferIndex];

                    var indexBufferInfo  = drawCall.GetSubCollection("m_indexBuffer");
                    var indexBufferIndex = (int)indexBufferInfo.GetIntegerProperty("m_hBuffer");
                    var indexBuffer      = vbib.IndexBuffers[indexBufferIndex];

                    // Create one primitive per draw call
                    var primitive = mesh.CreatePrimitive();

                    // Avoid duplicate attribute names
                    var attributeCounters = new Dictionary <string, int>();

                    // Set vertex attributes
                    foreach (var attribute in vertexBuffer.Attributes)
                    {
                        attributeCounters.TryGetValue(attribute.Name, out var attributeCounter);
                        attributeCounters[attribute.Name] = attributeCounter + 1;
                        var accessorName = GetAccessorName(attribute.Name, attributeCounter);

                        var buffer        = ReadAttributeBuffer(vertexBuffer, attribute);
                        var numComponents = buffer.Length / vertexBuffer.Count;

                        if (attribute.Name == "BLENDINDICES")
                        {
                            if (!includeJoints)
                            {
                                continue;
                            }

                            var byteBuffer    = buffer.Select(f => (byte)f).ToArray();
                            var rawBufferData = new byte[buffer.Length];
                            System.Buffer.BlockCopy(byteBuffer, 0, rawBufferData, 0, rawBufferData.Length);

                            var bufferView = mesh.LogicalParent.UseBufferView(rawBufferData);
                            var accessor   = mesh.LogicalParent.CreateAccessor();
                            accessor.SetVertexData(bufferView, 0, buffer.Length / 4, DimensionType.VEC4, EncodingType.UNSIGNED_BYTE);

                            primitive.SetVertexAccessor(accessorName, accessor);

                            continue;
                        }

                        if (attribute.Name == "NORMAL" && DrawCall.IsCompressedNormalTangent(drawCall))
                        {
                            var vectors = ToVector4Array(buffer);
                            var(normals, tangents) = DecompressNormalTangents(vectors);
                            primitive.WithVertexAccessor("NORMAL", normals);
                            primitive.WithVertexAccessor("TANGENT", tangents);

                            continue;
                        }

                        if (attribute.Name == "BLENDINDICES")
                        {
                            var byteBuffer = buffer.Select(f => (byte)f).ToArray();
                            var bufferView = mesh.LogicalParent.UseBufferView(byteBuffer);
                            var accessor   = mesh.LogicalParent.CreateAccessor();
                            accessor.SetVertexData(bufferView, 0, buffer.Length / 4, DimensionType.VEC4, EncodingType.UNSIGNED_BYTE);

                            primitive.SetVertexAccessor(accessorName, accessor);

                            continue;
                        }

                        if (attribute.Name == "TEXCOORD" && numComponents != 2)
                        {
                            // We are ignoring some data, but non-2-component UVs cause failures in gltf consumers
                            continue;
                        }

                        switch (numComponents)
                        {
                        case 4:
                        {
                            var vectors = ToVector4Array(buffer);
                            primitive.WithVertexAccessor(accessorName, vectors);
                            break;
                        }

                        case 3:
                        {
                            var vectors = ToVector3Array(buffer);
                            primitive.WithVertexAccessor(accessorName, vectors);
                            break;
                        }

                        case 2:
                        {
                            var vectors = ToVector2Array(buffer);
                            primitive.WithVertexAccessor(accessorName, vectors);
                            break;
                        }

                        case 1:
                        {
                            primitive.WithVertexAccessor(accessorName, buffer);
                            break;
                        }

                        default:
                            throw new NotImplementedException($"Attribute \"{attribute.Name}\" has {numComponents} components");
                        }
                    }

                    // For some reason soruce models can have joints but no weights, check if that is the case
                    var jointAccessor = primitive.GetVertexAccessor("JOINTS_0");
                    if (jointAccessor != null && primitive.GetVertexAccessor("WEIGHTS_0") == null)
                    {
                        // If this occurs, give default weights
                        var defaultWeights = Enumerable.Repeat(Vector4.UnitX, jointAccessor.Count).ToList();
                        primitive.WithVertexAccessor("WEIGHTS_0", defaultWeights);
                    }

                    // Set index buffer
                    var startIndex = (int)drawCall.GetIntegerProperty("m_nStartIndex");
                    var indexCount = (int)drawCall.GetIntegerProperty("m_nIndexCount");
                    var indices    = ReadIndices(indexBuffer, startIndex, indexCount);
                    primitive.WithIndicesAccessor(PrimitiveType.TRIANGLES, indices);

                    // Add material
                    var materialPath = drawCall.GetProperty <string>("m_material");

                    ProgressDialog.SetProgress($"Loading material: {materialPath}");

                    var materialResource = GuiContext.LoadFileByAnyMeansNecessary(materialPath + "_c");

                    if (materialResource == null)
                    {
                        continue;
                    }

                    var renderMaterial = (VMaterial)materialResource.DataBlock;

                    var materialNameTrimmed = Path.GetFileNameWithoutExtension(materialPath);
                    var bestMaterial        = GenerateGLTFMaterialFromRenderMaterial(renderMaterial, model, materialNameTrimmed);
                    primitive.WithMaterial(bestMaterial);
                }
            }

            return(mesh);
        }
Example #9
0
        private Mesh CreateGltfMesh(string meshName, VMesh vmesh, ModelRoot model)
        {
            ProgressDialog.SetProgress($"Creating mesh: {meshName}");

            var data = vmesh.GetData();
            var vbib = vmesh.VBIB;

            var mesh = model.CreateMesh(meshName);

            mesh.Name = meshName;

            foreach (var sceneObject in data.GetArray("m_sceneObjects"))
            {
                foreach (var drawCall in sceneObject.GetArray("m_drawCalls"))
                {
                    var vertexBufferInfo  = drawCall.GetArray("m_vertexBuffers")[0]; // In what situation can we have more than 1 vertex buffer per draw call?
                    var vertexBufferIndex = (int)vertexBufferInfo.GetIntegerProperty("m_hBuffer");
                    var vertexBuffer      = vbib.VertexBuffers[vertexBufferIndex];

                    var indexBufferInfo  = drawCall.GetSubCollection("m_indexBuffer");
                    var indexBufferIndex = (int)indexBufferInfo.GetIntegerProperty("m_hBuffer");
                    var indexBuffer      = vbib.IndexBuffers[indexBufferIndex];

                    // Create one primitive per draw call
                    var primitive = mesh.CreatePrimitive();

                    // Avoid duplicate attribute names
                    var uniqueAttributes = vertexBuffer.Attributes.GroupBy(a => a.Name).Select(g => g.First());

                    // Set vertex attributes
                    foreach (var attribute in uniqueAttributes)
                    {
                        if (AccessorInfo.TryGetValue(attribute.Name, out var accessorInfo))
                        {
                            var buffer = ReadAttributeBuffer(vbib, vertexBuffer, attribute);

                            if (accessorInfo.NumComponents == 4)
                            {
                                var vectors = ToVector4Array(buffer);
                                primitive.WithVertexAccessor(accessorInfo.GltfAccessorName, vectors);
                            }
                            else if (attribute.Name == "NORMAL" && DrawCall.IsCompressedNormalTangent(drawCall))
                            {
                                var vectors = ToVector4Array(buffer);
                                var(normals, tangents) = DecompressNormalTangents(vectors);
                                primitive.WithVertexAccessor("NORMAL", normals);
                                primitive.WithVertexAccessor("TANGENT", tangents);
                            }
                            else if (accessorInfo.NumComponents == 3)
                            {
                                var vectors = ToVector3Array(buffer, true, accessorInfo.Resize);
                                primitive.WithVertexAccessor(accessorInfo.GltfAccessorName, vectors);
                            }
                            else if (accessorInfo.NumComponents == 2)
                            {
                                var vectors = ToVector2Array(buffer);
                                primitive.WithVertexAccessor(accessorInfo.GltfAccessorName, vectors);
                            }
                        }
                    }

                    // Set index buffer
                    var indices = ReadIndices(indexBuffer);

                    // For triangle primitives, the front face has to be in counter-clockwise (CCW) winding order.
                    for (var i = 0; i < indices.Length; i += 3)
                    {
                        var b = indices[i + 2];
                        indices[i + 2] = indices[i + 1];
                        indices[i + 1] = b;
                    }

                    primitive.WithIndicesAccessor(PrimitiveType.TRIANGLES, indices);

                    // Add material
                    var materialPath = drawCall.GetProperty <string>("m_material");

                    ProgressDialog.SetProgress($"Loading material: {materialPath}");

                    var materialResource = GuiContext.LoadFileByAnyMeansNecessary(materialPath + "_c");

                    if (materialResource == null)
                    {
                        continue;
                    }

                    var renderMaterial = (VMaterial)materialResource.DataBlock;

                    var materialNameTrimmed = Path.GetFileNameWithoutExtension(materialPath);
                    var bestMaterial        = GenerateGLTFMaterialFromRenderMaterial(renderMaterial, model, materialNameTrimmed);
                    primitive.WithMaterial(bestMaterial);
                }
            }

            return(mesh);
        }