Example #1
0
 private void SetMaterialColor(Material material, Assimp.Material assimpMat)
 {
     if (assimpMat.HasColorDiffuse)
     {
         material.SetParameter("DiffuseColor", ConvertColor(assimpMat.ColorDiffuse));
     }
 }
Example #2
0
        public MAT3(Assimp.Scene scene, TEX1 textures, SHP1 shapes)
        {
            InitLists();

            for (int i = 0; i < scene.MeshCount; i++)
            {
                Assimp.Material    meshMat     = scene.Materials[scene.Meshes[i].MaterialIndex];
                Materials.Material bmdMaterial = new Material();

                bool hasVtxColor0 = shapes.Shapes[i].AttributeData.CheckAttribute(GXVertexAttribute.Color0);
                int  texIndex     = -1;
                if (meshMat.HasTextureDiffuse)
                {
                    string texName = Path.GetFileNameWithoutExtension(meshMat.TextureDiffuse.FilePath);
                    texIndex = textures.Textures.IndexOf(textures[texName]);
                }

                bmdMaterial.SetUpTev(meshMat.HasTextureDiffuse, hasVtxColor0, texIndex);

                m_Materials.Add(bmdMaterial);
                m_RemapIndices.Add(i);
                m_MaterialNames.Add(meshMat.Name);
            }

            FillMaterialDataBlocks();
        }
Example #3
0
        private void SetLitMaterialColors(Material material, Assimp.Material assimpMat)
        {
            if (assimpMat.HasColorAmbient)
            {
                material.SetParameter("MatAmbient", ConvertColorToVector3(assimpMat.ColorAmbient));
            }

            if (assimpMat.HasColorDiffuse)
            {
                material.SetParameter("MatDiffuse", ConvertColorToVector3(assimpMat.ColorDiffuse));
            }

            if (assimpMat.HasColorEmissive)
            {
                material.SetParameter("MatEmissive", ConvertColorToVector3(assimpMat.ColorEmissive));
            }

            if (assimpMat.HasColorSpecular)
            {
                material.SetParameter("MatSpecular", ConvertColorToVector3(assimpMat.ColorSpecular));
            }

            if (assimpMat.HasShininessStrength)
            {
                material.SetParameter("Shininess", assimpMat.ShininessStrength);
            }

            if (assimpMat.HasOpacity)
            {
                material.SetParameter("Alpha", assimpMat.Opacity);
            }
        }
Example #4
0
        private void exportToAssimp(object sender, EventArgs e)
        {
            Debug.WriteLine("Exporting to assimp");

            if (RenderState.rootObject != null)
            {
                Assimp.AssimpContext ctx = new Assimp.AssimpContext();

                Dictionary <int, int> meshImportStatus = new Dictionary <int, int>();
                Assimp.Scene          aScene           = new Assimp.Scene();
                Assimp.Node           rootNode         = RenderState.rootObject.assimpExport(ref aScene, ref meshImportStatus);
                aScene.RootNode = rootNode;

                //add a single material for now
                Assimp.Material aMat = new Assimp.Material();
                aMat.Name = "testMaterial";
                aScene.Materials.Add(aMat);

                Assimp.ExportFormatDescription[] supported_formats = ctx.GetSupportedExportFormats();
                //Assimp.Scene blenderScene = ctx.ImportFile("SimpleSkin.gltf");
                //ctx.ExportFile(blenderScene, "SimpleSkin.glb", "glb2");
                try
                {
                    ctx.ExportFile(aScene, "test.glb", "glb2");
                    //ctx.ExportFile(aScene, "test.fbx", "fbx");
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
        }
Example #5
0
        public void FillScene(Assimp.Scene scene, TEX1 textures, string fileDir)
        {
            textures.DumpTextures(fileDir);

            foreach (Material mat in m_Materials)
            {
                Assimp.Material assMat = new Assimp.Material();

                if (mat.TextureIndices[0] != -1)
                {
                    int texIndex = mat.TextureIndices[0];
                    //texIndex = m_TexRemapBlock[texIndex];
                    string texPath = Path.Combine(fileDir, textures[texIndex].Name + ".png");

                    Assimp.TextureSlot tex = new Assimp.TextureSlot(texPath, Assimp.TextureType.Diffuse, 0,
                                                                    Assimp.TextureMapping.FromUV, 0, 1.0f, Assimp.TextureOperation.Add,
                                                                    textures[texIndex].WrapS.ToAssImpWrapMode(), textures[texIndex].WrapT.ToAssImpWrapMode(), 0);

                    assMat.AddMaterialTexture(ref tex);
                }

                if (mat.MaterialColors[0] != null)
                {
                    assMat.ColorDiffuse = mat.MaterialColors[0].Value.ToColor4D();
                }

                if (mat.AmbientColors[0] != null)
                {
                    assMat.ColorAmbient = mat.AmbientColors[0].Value.ToColor4D();
                }

                scene.Materials.Add(assMat);
            }
        }
        public static Onyx3D.DefaultMaterial ToOnyx3D(this Assimp.Material material)
        {
            Onyx3D.DefaultMaterial newMaterial = new Onyx3D.DefaultMaterial();

            // TODO - Load the material;

            return(newMaterial);
        }
Example #7
0
        protected Assimp.Material CreateMaterial(Color diffuse, Color specular, Color ambient, string textureName, bool clampU, bool clampV, bool flipU, bool flipV, bool useAlpha)
        {
            var textureFilePath = textureName != null ? $"{textureName}.png" : null;
            var aiMaterial      = new Assimp.Material
            {
                Name              = FormatMaterialName(textureName, Scene.Materials.Count(x => x.TextureDiffuse.FilePath == textureFilePath)),
                ColorDiffuse      = ToAssimp(diffuse),
                ColorSpecular     = ToAssimp(specular),
                ColorAmbient      = ToAssimp(ambient),
                Shininess         = 0,
                ShininessStrength = 0,
                Reflectivity      = 0,
            };

            if (textureName != null)
            {
                aiMaterial.TextureDiffuse = new Assimp.TextureSlot
                {
                    TextureType = Assimp.TextureType.Diffuse,
                    FilePath    = textureFilePath,
                    WrapModeU   =
                        clampU ? Assimp.TextureWrapMode.Clamp :
                        flipU  ? Assimp.TextureWrapMode.Mirror :
                        Assimp.TextureWrapMode.Wrap,
                    WrapModeV =
                        clampV ? Assimp.TextureWrapMode.Clamp :
                        flipV  ? Assimp.TextureWrapMode.Mirror :
                        Assimp.TextureWrapMode.Wrap,
                };

                if (useAlpha)
                {
                    aiMaterial.TextureOpacity = new Assimp.TextureSlot
                    {
                        TextureType = Assimp.TextureType.Opacity,
                        FilePath    = textureFilePath,
                        WrapModeU   =
                            clampU ? Assimp.TextureWrapMode.Clamp :
                            flipU  ? Assimp.TextureWrapMode.Mirror :
                            Assimp.TextureWrapMode.Wrap,
                        WrapModeV =
                            clampV ? Assimp.TextureWrapMode.Clamp :
                            flipV  ? Assimp.TextureWrapMode.Mirror :
                            Assimp.TextureWrapMode.Wrap,
                    };
                }
            }

            return(aiMaterial);
        }
Example #8
0
 private void SetMaterialTexture(Material material, Assimp.Material assimpMat)
 {
     Assimp.TextureSlot diffuseMap = assimpMat.GetTexture(Assimp.TextureType.Diffuse, 0);
     if (!String.IsNullOrEmpty(diffuseMap.FilePath))
     {
         Texture diffuse;
         try {
             diffuse = m_content.LoadRelativeTo <Texture2D>(diffuseMap.FilePath, m_modelResource);// m_content.Load<Texture2D>(diffuseMap.FilePath);
             material.SetParameter("DiffuseMap", diffuse);
         } catch {
             //    diffuse = m_content.Load<Texture2D>("notexture.tebo");
         }
     }
 }
        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);
        }
Example #10
0
        public RwMaterialListNode(RwNode parent, Assimp.Material material)
            : base(RwNodeId.RwMaterialListNode, parent)
        {
            mMaterials = new List <RwMaterial>();

            string textureName = null;

            if (material.HasTextureDiffuse)
            {
                textureName = Path.GetFileNameWithoutExtension(material.TextureDiffuse.FilePath);
            }

            mMaterials.Add(new RwMaterial(material.Name, textureName, this));
            mStructNode = new RwMaterialListStructNode(this);
        }
Example #11
0
        internal Texture2D Load(Assimp.Material mat)
        {
            var tex = mat.TextureDiffuse;

            if (string.IsNullOrEmpty(tex.FilePath))
            {
                return(null);
            }
            if (Path.IsPathRooted(tex.FilePath))
            {
                Debug.LogError("Skipping loading texture from: " + tex.FilePath);
                return(null);
            }

            Texture2D tex1;

            if (textures == null)
            {
                textures = new Dictionary <string, Texture2D>();
            }
            if (textures.TryGetValue(tex.FilePath, out tex1))
            {
                return(tex1);
            }

            try
            {
                int tex_index;
                if (tex.FilePath.StartsWith("*") && tex.FilePath.Length > 1 && int.TryParse(tex.FilePath.Substring(1), out tex_index))
                {
                    tex1 = BuildTextureFromInternal(tex_index);
                }
                else
                {
                    tex1 = BuildTextureFromExternal(tex.FilePath);
                }
            }
            catch (Exception e)
            {
                Debug.LogException(e);
                tex1 = null;
            }
            textures[tex.FilePath] = tex1;
            return(tex1);
        }
Example #12
0
        private void SetMaterialRenderStates(Material material, Assimp.Material assimpMat)
        {
            if (assimpMat.HasTwoSided && assimpMat.HasWireFrame)
            {
                // material.SetRenderState(RasterizerState.CullNoneWireframe);
            }
            else if (assimpMat.HasWireFrame)
            {
                if (m_wireframeOneSidedRS == null)
                {
                    m_wireframeOneSidedRS      = new RasterizerState();
                    m_wireframeOneSidedRS.Fill = FillMode.WireFrame;
                    m_wireframeOneSidedRS.BindRenderState();
                }
                // material.SetRenderState(m_wireframeOneSidedRS);
            }
            else if (assimpMat.HasTwoSided)
            {
                if (m_twoSidedRS == null)
                {
                    m_twoSidedRS      = new RasterizerState();
                    m_twoSidedRS.Cull = CullMode.None;
                    m_twoSidedRS.BindRenderState();
                }
                //  material.SetRenderState(m_twoSidedRS);
            }

            if (assimpMat.HasBlendMode)
            {
                if (assimpMat.BlendMode == Assimp.BlendMode.Additive)
                {
                    //  material.SetRenderState(BlendState.AdditiveBlend);
                }
                else
                {
                    //  material.SetRenderState(BlendState.AlphaBlendNonPremultiplied);
                }
            }
        }
        private TextureProvider[] InitTextures(Assimp.Scene aiScene, string filename)
        {
            var textureProviders = new TextureProvider[aiScene.MaterialCount];
            // Extract the directory part from the file name
            string directory = new FileInfo(filename).DirectoryName;

            // Initialize the materials
            for (uint i = 0; i < aiScene.MaterialCount; i++)
            {
                Assimp.Material material = aiScene.Materials[i];

                if (material.GetTextureCount(Assimp.TextureType.Diffuse) > 0)
                {
                    Assimp.TextureSlot slot     = material.GetTexture(Assimp.TextureType.Diffuse, 0);
                    string             fullname = Path.Combine(directory, slot.FilePath);
                    var provider = new TextureProvider(fullname);
                    textureProviders[i] = provider;
                }
            }

            return(textureProviders);
        }
Example #14
0
        public MAT3(Assimp.Scene scene, TEX1 textures)
        {
            InitLists();

            foreach (Assimp.Mesh mesh in scene.Meshes)
            {
                Assimp.Material    meshMat     = scene.Materials[mesh.MaterialIndex];
                Materials.Material bmdMaterial = new Material();

                if (meshMat.HasTextureDiffuse)
                {
                    bmdMaterial.AddTexGen(TexGenType.Matrix2x4, TexGenSrc.TexCoord0, Materials.Enums.TexMatrix.Identity);
                    bmdMaterial.AddTexMatrix(TexGenType.Matrix3x4, 0, OpenTK.Vector3.Zero, OpenTK.Vector2.One, 0, OpenTK.Vector2.Zero, OpenTK.Matrix4.Identity);

                    string texName = System.IO.Path.GetFileNameWithoutExtension(meshMat.TextureDiffuse.FilePath);
                    bmdMaterial.AddTexIndex(textures.Textures.IndexOf(textures[texName]));

                    bmdMaterial.AddTevStage(SetUpTevStageParametersForTexture());
                }
            }

            FillMaterialDataBlocks();
        }
Example #15
0
        private void SetNormalMapMaterialTextures(Material material, Assimp.Material assimpMat)
        {
            Assimp.TextureSlot diffuseMap  = assimpMat.GetTexture(Assimp.TextureType.Diffuse, 0);
            Assimp.TextureSlot normalMap   = assimpMat.GetTexture(Assimp.TextureType.Normals, 0);
            Assimp.TextureSlot specularMap = assimpMat.GetTexture(Assimp.TextureType.Specular, 0);

            if (!String.IsNullOrEmpty(diffuseMap.FilePath))
            {
                Texture diffuse;
                try {
                    diffuse = m_content.LoadRelativeTo <Texture2D>(diffuseMap.FilePath, m_modelResource); //m_content.Load<Texture2D>(diffuseMap.FilePath);
                    material.SetParameter("DiffuseMap", diffuse);
                } catch {
                    //   diffuse = m_content.Load<Texture2D>("notexture.tebo");
                }
            }

            if (!String.IsNullOrEmpty(normalMap.FilePath))
            {
                try {
                    Texture normal = m_content.LoadRelativeTo <Texture2D>(normalMap.FilePath, m_modelResource); //m_content.Load<Texture2D>(normalMap.FilePath);
                    material.SetParameter("NormalMap", normal);
                } catch {
                    //Default normal map?
                }
            }

            if (!String.IsNullOrEmpty(specularMap.FilePath))
            {
                try {
                    Texture specular = m_content.LoadRelativeTo <Texture2D>(specularMap.FilePath, m_modelResource);//m_content.Load<Texture2D>(specularMap.FilePath);
                    material.SetParameter("SpecularMap", specular);
                } catch {
                    //Default specular map?
                }
            }
        }
Example #16
0
        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);
        }
Example #17
0
        Material ConvertMaterial(string path, Assimp.Material aiMaterial, bool hasTangent)
        {
            Shader     shader    = null;
            BlendFlags blendType = BlendFlags.Solid;

            if (hasTangent)
            {
                if (aiMaterial.HasTextureOpacity)
                {
                    blendType = BlendFlags.AlphaTest;
                    shader    = Resources.Instance.Load <Shader>("Shaders/LitAlphaTest.shader");
                }
                else if (aiMaterial.Opacity < 1)
                {
                    blendType = BlendFlags.AlphaBlend;
                    shader    = Resources.Instance.Load <Shader>("Shaders/LitParticle.shader");
                }
                else
                {
                    shader = Resources.Instance.Load <Shader>("Shaders/LitSolid.shader");
                }
            }
            else
            {
                shader = Resources.Instance.Load <Shader>("Shaders/Basic.shader");
            }

            Material material = new Material(shader);

            material.Name      = aiMaterial.Name;
            material.BlendType = blendType;
            if (aiMaterial.HasTextureDiffuse)
            {
                string  texPath = FileUtil.CombinePath(path, aiMaterial.TextureDiffuse.FilePath);
                Texture tex     = Resources.Instance.Load <Texture>(texPath);
                if (tex != null)
                {
                    material.SetTexture("DiffMap", tex);
                }
                else
                {
                    int idx = texPath.LastIndexOfAny(new[] { '\\', '/' });
                    if (idx != -1)
                    {
                        texPath = texPath.Substring(idx + 1);
                    }

                    tex = Resources.Instance.Load <Texture>(texPath.Replace(".ktx", "_bc3_unorm.ktx"));
                    if (tex != null)
                    {
                        material.SetTexture("DiffMap", tex);
                    }
                }
            }
            else
            {
                if (aiMaterial.HasColorDiffuse)
                {
                    Color c = new Color(aiMaterial.ColorDiffuse[0], aiMaterial.ColorDiffuse[1],
                                        aiMaterial.ColorDiffuse[2], aiMaterial.ColorDiffuse[3] * aiMaterial.Opacity);
                    material.SetTexture("DiffMap", Texture.CreateByColor(c));
                    material.SetShaderParameter("diffuse", c);
                }
                else
                {
                    material.SetTexture("DiffMap", Texture.White);
                }
            }

            if (aiMaterial.HasTextureNormal)
            {
                string  texPath = FileUtil.CombinePath(path, aiMaterial.TextureNormal.FilePath);
                Texture tex     = Resources.Instance.Load <Texture>(texPath);
                if (tex != null)
                {
                    material.SetTexture("NormalMap", tex);
                }
                else
                {
                    tex = Resources.Instance.Load <Texture>(texPath.Replace(".ktx", "_bc3_unorm.ktx"));
                    if (tex != null)
                    {
                        material.SetTexture("NormalMap", tex);
                    }
                }
            }
            else
            {
                material.SetTexture("NormalMap", Texture.Blue);
            }

            if (aiMaterial.HasTextureSpecular)
            {
                string  texPath = FileUtil.CombinePath(path, aiMaterial.TextureSpecular.FilePath);
                Texture tex     = Resources.Instance.Load <Texture>(texPath);
                if (tex != null)
                {
                    material.SetTexture("SpecMap", tex);
                }
                else
                {
                    tex = Resources.Instance.Load <Texture>(texPath.Replace(".ktx", "_bc3_unorm.ktx"));
                    if (tex != null)
                    {
                        material.SetTexture("SpecMap", tex);
                    }
                }
            }
            else
            {
                if (aiMaterial.HasColorSpecular)
                {
                    Color c = new Color(aiMaterial.ColorSpecular[0], aiMaterial.ColorSpecular[1],
                                        aiMaterial.ColorSpecular[2], aiMaterial.Shininess / 255.0f);
                    material.SetTexture("SpecMap", Texture.CreateByColor(c));

                    material.SetShaderParameter("specular", c);
                }
                else
                {
                    material.SetTexture("SpecMap", Texture.Black);
                }
            }

            return(material);
        }
        public static Assimp.Scene AssimpExport(string filePath, AquaObject aqp, AquaNode aqn)
        {
            if (aqp is NGSAquaObject)
            {
                //NGS aqps will give lots of isolated vertices if we don't handle them
                //Since we're not actually altering the data so much as rearranging references, we can just do this
                aqp = aqp.Clone();
                aqp.splitVSETPerMesh();
            }
            Assimp.Scene aiScene = new Assimp.Scene();

            //Create an array to hold references to these since Assimp lacks a way to grab these by order or id
            //We don't need the nodo count in this since they can't be parents
            Assimp.Node[] boneArray = new Assimp.Node[aqn.nodeList.Count];

            //Set up root node
            var root       = aqn.nodeList[0];
            var aiRootNode = new Assimp.Node("RootNode", null);

            aiRootNode.Transform = Assimp.Matrix4x4.Identity;

            aiScene.RootNode = aiRootNode;

            //Assign bones
            for (int i = 0; i < aqn.nodeList.Count; i++)
            {
                var         bn = aqn.nodeList[i];
                Assimp.Node parentNode;
                var         parentTfm = Matrix4x4.Identity;
                if (bn.parentId == -1)
                {
                    parentNode = aiRootNode;
                }
                else
                {
                    parentNode = boneArray[bn.parentId];
                    var pn = aqn.nodeList[bn.parentId];
                    parentTfm = new Matrix4x4(pn.m1.X, pn.m1.Y, pn.m1.Z, pn.m1.W,
                                              pn.m2.X, pn.m2.Y, pn.m2.Z, pn.m2.W,
                                              pn.m3.X, pn.m3.Y, pn.m3.Z, pn.m3.W,
                                              pn.m4.X * 100, pn.m4.Y * 100, pn.m4.Z * 100, pn.m4.W);
                }
                var aiNode = new Assimp.Node($"({i})" + bn.boneName.GetString(), parentNode);

                //Use inverse bind matrix as base
                var bnMat = new Matrix4x4(bn.m1.X, bn.m1.Y, bn.m1.Z, bn.m1.W,
                                          bn.m2.X, bn.m2.Y, bn.m2.Z, bn.m2.W,
                                          bn.m3.X, bn.m3.Y, bn.m3.Z, bn.m3.W,
                                          bn.m4.X * 100, bn.m4.Y * 100, bn.m4.Z * 100, bn.m4.W);
                Matrix4x4.Invert(bnMat, out bnMat);

                //Get local transform
                aiNode.Transform = GetAssimpMat4(bnMat * parentTfm);

                parentNode.Children.Add(aiNode);
                boneArray[i] = aiNode;
            }

            foreach (AquaNode.NODO bn in aqn.nodoList)
            {
                var parentNodo = boneArray[bn.parentId];
                var aiNode     = new Assimp.Node(bn.boneName.GetString(), parentNodo);

                //NODOs are a bit more primitive. We need to generate the matrix for these ones.
                var matrix   = Assimp.Matrix4x4.Identity;
                var rotation = Assimp.Matrix4x4.FromRotationX(bn.eulRot.X) *
                               Assimp.Matrix4x4.FromRotationY(bn.eulRot.Y) *
                               Assimp.Matrix4x4.FromRotationZ(bn.eulRot.Z);

                matrix          *= rotation;
                matrix          *= Assimp.Matrix4x4.FromTranslation(new Assimp.Vector3D(bn.pos.X * 100, bn.pos.Y * 100, bn.pos.Z * 100));
                aiNode.Transform = matrix;

                parentNodo.Children.Add(aiNode);
            }

            //Assign meshes and materials
            foreach (AquaObject.MESH msh in aqp.meshList)
            {
                var vtxl = aqp.vtxlList[msh.vsetIndex];

                //Mesh
                var  aiMeshName       = string.Format("mesh[{4}]_{0}_{1}_{2}_{3}_mesh", msh.mateIndex, msh.rendIndex, msh.shadIndex, msh.tsetIndex, aiScene.Meshes.Count);
                bool hasVertexWeights = aqp.vtxlList[msh.vsetIndex].vertWeightIndices.Count > 0;

                var aiMesh = new Assimp.Mesh(aiMeshName, Assimp.PrimitiveType.Triangle);

                //Vertex face data - PSO2 Actually doesn't do this, it just has per vertex data so we can just map a vertice's data to each face using it
                //It may actually be possible to add this to the previous loop, but my reference didn't so I'm doing it in a separate loop for safety
                //Reference: https://github.com/TGEnigma/Amicitia/blob/master/Source/AmicitiaLibrary/Graphics/RenderWare/RWClumpNode.cs
                //UVs will have dummied data to ensure that if the game arbitrarily writes them, they will still be exported back in the same order
                for (int vertId = 0; vertId < vtxl.vertPositions.Count; vertId++)
                {
                    if (vtxl.vertPositions.Count > 0)
                    {
                        var pos = vtxl.vertPositions[vertId] * 100;
                        aiMesh.Vertices.Add(new Assimp.Vector3D(pos.X, pos.Y, pos.Z));
                    }

                    if (vtxl.vertNormals.Count > 0)
                    {
                        var nrm = vtxl.vertNormals[vertId];
                        aiMesh.Normals.Add(new Assimp.Vector3D(nrm.X, nrm.Y, nrm.Z));
                    }

                    if (vtxl.vertColors.Count > 0)
                    {
                        //Vert colors are bgra
                        var rawClr = vtxl.vertColors[vertId];
                        var clr    = new Assimp.Color4D(clrToFloat(rawClr[2]), clrToFloat(rawClr[1]), clrToFloat(rawClr[0]), clrToFloat(rawClr[3]));
                        aiMesh.VertexColorChannels[0].Add(clr);
                    }

                    if (vtxl.vertColor2s.Count > 0)
                    {
                        //Vert colors are bgra
                        var rawClr = vtxl.vertColor2s[vertId];
                        var clr    = new Assimp.Color4D(clrToFloat(rawClr[2]), clrToFloat(rawClr[1]), clrToFloat(rawClr[0]), clrToFloat(rawClr[3]));
                        aiMesh.VertexColorChannels[1].Add(clr);
                    }

                    if (vtxl.uv1List.Count > 0)
                    {
                        var textureCoordinate   = vtxl.uv1List[vertId];
                        var aiTextureCoordinate = new Assimp.Vector3D(textureCoordinate.X, textureCoordinate.Y, 0f);
                        aiMesh.TextureCoordinateChannels[0].Add(aiTextureCoordinate);
                    }
                    else
                    {
                        var aiTextureCoordinate = new Assimp.Vector3D(0, 0, 0f);
                        aiMesh.TextureCoordinateChannels[0].Add(aiTextureCoordinate);
                    }

                    if (vtxl.uv2List.Count > 0)
                    {
                        var textureCoordinate   = vtxl.uv2List[vertId];
                        var aiTextureCoordinate = new Assimp.Vector3D(textureCoordinate.X, textureCoordinate.Y, 0f);
                        aiMesh.TextureCoordinateChannels[1].Add(aiTextureCoordinate);
                    }
                    else
                    {
                        var aiTextureCoordinate = new Assimp.Vector3D(0, 0, 0f);
                        aiMesh.TextureCoordinateChannels[1].Add(aiTextureCoordinate);
                    }

                    if (vtxl.uv3List.Count > 0)
                    {
                        var textureCoordinate   = vtxl.uv3List[vertId];
                        var aiTextureCoordinate = new Assimp.Vector3D(textureCoordinate.X, textureCoordinate.Y, 0f);
                        aiMesh.TextureCoordinateChannels[2].Add(aiTextureCoordinate);
                    }
                    else
                    {
                        var aiTextureCoordinate = new Assimp.Vector3D(0, 0, 0f);
                        aiMesh.TextureCoordinateChannels[2].Add(aiTextureCoordinate);
                    }

                    if (vtxl.uv4List.Count > 0)
                    {
                        var textureCoordinate   = vtxl.uv4List[vertId];
                        var aiTextureCoordinate = new Assimp.Vector3D(textureCoordinate.X, textureCoordinate.Y, 0f);
                        aiMesh.TextureCoordinateChannels[3].Add(aiTextureCoordinate);
                    }
                    else
                    {
                        var aiTextureCoordinate = new Assimp.Vector3D(0, 0, 0f);
                        aiMesh.TextureCoordinateChannels[3].Add(aiTextureCoordinate);
                    }

                    if (vtxl.vert0x22.Count > 0)
                    {
                        var textureCoordinate   = vtxl.vert0x22[vertId];
                        var aiTextureCoordinate = new Assimp.Vector3D(uvShortToFloat(textureCoordinate[0]), uvShortToFloat(textureCoordinate[1]), 0f);
                        aiMesh.TextureCoordinateChannels[4].Add(aiTextureCoordinate);
                    }
                    else
                    {
                        var aiTextureCoordinate = new Assimp.Vector3D(0, 0, 0f);
                        aiMesh.TextureCoordinateChannels[4].Add(aiTextureCoordinate);
                    }

                    if (vtxl.vert0x23.Count > 0)
                    {
                        var textureCoordinate   = vtxl.vert0x23[vertId];
                        var aiTextureCoordinate = new Assimp.Vector3D(uvShortToFloat(textureCoordinate[0]), uvShortToFloat(textureCoordinate[1]), 0f);
                        aiMesh.TextureCoordinateChannels[5].Add(aiTextureCoordinate);
                    }
                    else
                    {
                        var aiTextureCoordinate = new Assimp.Vector3D(0, 0, 0f);
                        aiMesh.TextureCoordinateChannels[5].Add(aiTextureCoordinate);
                    }

                    if (vtxl.vert0x24.Count > 0)
                    {
                        var textureCoordinate   = vtxl.vert0x24[vertId];
                        var aiTextureCoordinate = new Assimp.Vector3D(uvShortToFloat(textureCoordinate[0]), uvShortToFloat(textureCoordinate[1]), 0f);
                        aiMesh.TextureCoordinateChannels[6].Add(aiTextureCoordinate);
                    }
                    else
                    {
                        var aiTextureCoordinate = new Assimp.Vector3D(0, 0, 0f);
                        aiMesh.TextureCoordinateChannels[6].Add(aiTextureCoordinate);
                    }

                    if (vtxl.vert0x25.Count > 0)
                    {
                        var textureCoordinate   = vtxl.vert0x25[vertId];
                        var aiTextureCoordinate = new Assimp.Vector3D(uvShortToFloat(textureCoordinate[0]), uvShortToFloat(textureCoordinate[1]), 0f);
                        aiMesh.TextureCoordinateChannels[7].Add(aiTextureCoordinate);
                    }
                    else
                    {
                        var aiTextureCoordinate = new Assimp.Vector3D(0, 0, 0f);
                        aiMesh.TextureCoordinateChannels[7].Add(aiTextureCoordinate);
                    }
                }

                //Assimp Bones - Assimp likes to store vertex weights in bones and bones references in meshes
                if (hasVertexWeights)
                {
                    //Get bone palette
                    List <uint> bonePalette;
                    if (aqp.objc.bonePaletteOffset > 0)
                    {
                        bonePalette = aqp.bonePalette;
                    }
                    else
                    {
                        bonePalette = new List <uint>();
                        for (int bn = 0; bn < vtxl.bonePalette.Count; bn++)
                        {
                            bonePalette.Add(vtxl.bonePalette[bn]);
                        }
                    }
                    var aiBoneMap = new Dictionary <int, Assimp.Bone>();

                    //Iterate through vertices
                    for (int vertId = 0; vertId < vtxl.vertWeightIndices.Count; vertId++)
                    {
                        var boneIndices = vtxl.vertWeightIndices[vertId];
                        var boneWeights = Vector4ToFloatArray(vtxl.vertWeights[vertId]);

                        //Iterate through weights
                        for (int wt = 0; wt < 4; wt++)
                        {
                            var boneIndex  = boneIndices[wt];
                            var boneWeight = boneWeights[wt];

                            if (boneWeight == 0.0f)
                            {
                                continue;
                            }

                            if (!aiBoneMap.Keys.Contains(boneIndex))
                            {
                                var aiBone  = new Assimp.Bone();
                                var aqnBone = boneArray[bonePalette[boneIndex]];
                                var rawBone = aqn.nodeList[(int)bonePalette[boneIndex]];

                                aiBone.Name = $"({bonePalette[boneIndex]})" + rawBone.boneName.GetString();
                                aiBone.VertexWeights.Add(new Assimp.VertexWeight(vertId, boneWeight));

                                var invTransform = new Assimp.Matrix4x4(rawBone.m1.X, rawBone.m2.X, rawBone.m3.X, rawBone.m4.X,
                                                                        rawBone.m1.Y, rawBone.m2.Y, rawBone.m3.Y, rawBone.m4.Y,
                                                                        rawBone.m1.Z, rawBone.m2.Z, rawBone.m3.Z, rawBone.m4.Z,
                                                                        rawBone.m1.W, rawBone.m2.W, rawBone.m3.W, rawBone.m4.W);

                                aiBone.OffsetMatrix = invTransform;

                                aiBoneMap[boneIndex] = aiBone;
                            }

                            if (!aiBoneMap[boneIndex].VertexWeights.Any(x => x.VertexID == vertId))
                            {
                                aiBoneMap[boneIndex].VertexWeights.Add(new Assimp.VertexWeight(vertId, boneWeight));
                            }
                        }
                    }

                    //Add the bones to the mesh
                    aiMesh.Bones.AddRange(aiBoneMap.Values);
                }
                else   //Handle rigid meshes
                {
                    var aiBone  = new Assimp.Bone();
                    var aqnBone = boneArray[msh.baseMeshNodeId];

                    // Name
                    aiBone.Name = aqnBone.Name;

                    // VertexWeights
                    for (int i = 0; i < aiMesh.Vertices.Count; i++)
                    {
                        var aiVertexWeight = new Assimp.VertexWeight(i, 1f);
                        aiBone.VertexWeights.Add(aiVertexWeight);
                    }

                    aiBone.OffsetMatrix = Assimp.Matrix4x4.Identity;

                    aiMesh.Bones.Add(aiBone);
                }

                //Faces
                foreach (var face in aqp.strips[msh.vsetIndex].GetTriangles(true))
                {
                    aiMesh.Faces.Add(new Assimp.Face(new int[] { (int)face.X, (int)face.Y, (int)face.Z }));
                }

                //Material
                var             mat        = aqp.mateList[msh.mateIndex];
                var             shaderSet  = AquaObjectMethods.GetShaderNames(aqp, msh.shadIndex);
                var             textureSet = AquaObjectMethods.GetTexListNames(aqp, msh.tsetIndex);
                Assimp.Material mate       = new Assimp.Material();

                mate.ColorDiffuse = new Assimp.Color4D(mat.diffuseRGBA.X, mat.diffuseRGBA.Y, mat.diffuseRGBA.Z, mat.diffuseRGBA.W);
                if (mat.alphaType.GetString().Equals("add"))
                {
                    mate.BlendMode = Assimp.BlendMode.Additive;
                }
                mate.Name = "|[]{}~`!@#$%^&*;:'\"?><,./(" + shaderSet[0] + "," + shaderSet[1] + ")" + "{" + mat.alphaType.GetString() + "}" + mat.matName.GetString();

                //Set textures - PSO2 Texture slots are NOT consistent and depend entirely on the selected shader. As such, slots will be somewhat arbitrary after albedo/diffuse
                for (int i = 0; i < textureSet.Count; i++)
                {
                    switch (i)
                    {
                    case 0:
                        mate.TextureDiffuse = new Assimp.TextureSlot(
                            textureSet[i], Assimp.TextureType.Diffuse, i, Assimp.TextureMapping.FromUV, aqp.tstaList[aqp.tsetList[msh.tsetIndex].tstaTexIDs[i]].modelUVSet, 0,
                            Assimp.TextureOperation.Add, Assimp.TextureWrapMode.Wrap, Assimp.TextureWrapMode.Wrap, 0);
                        break;

                    case 1:
                        mate.TextureSpecular = new Assimp.TextureSlot(
                            textureSet[i], Assimp.TextureType.Specular, i, Assimp.TextureMapping.FromUV, aqp.tstaList[aqp.tsetList[msh.tsetIndex].tstaTexIDs[i]].modelUVSet, 0,
                            Assimp.TextureOperation.Add, Assimp.TextureWrapMode.Wrap, Assimp.TextureWrapMode.Wrap, 0);
                        break;

                    case 2:
                        mate.TextureNormal = new Assimp.TextureSlot(
                            textureSet[i], Assimp.TextureType.Normals, i, Assimp.TextureMapping.FromUV, aqp.tstaList[aqp.tsetList[msh.tsetIndex].tstaTexIDs[i]].modelUVSet, 0,
                            Assimp.TextureOperation.Add, Assimp.TextureWrapMode.Wrap, Assimp.TextureWrapMode.Wrap, 0);
                        break;

                    case 3:
                        mate.TextureLightMap = new Assimp.TextureSlot(
                            textureSet[i], Assimp.TextureType.Lightmap, i, Assimp.TextureMapping.FromUV, aqp.tstaList[aqp.tsetList[msh.tsetIndex].tstaTexIDs[i]].modelUVSet, 0,
                            Assimp.TextureOperation.Add, Assimp.TextureWrapMode.Wrap, Assimp.TextureWrapMode.Wrap, 0);
                        break;

                    case 4:
                        mate.TextureDisplacement = new Assimp.TextureSlot(
                            textureSet[i], Assimp.TextureType.Displacement, i, Assimp.TextureMapping.FromUV, aqp.tstaList[aqp.tsetList[msh.tsetIndex].tstaTexIDs[i]].modelUVSet, 0,
                            Assimp.TextureOperation.Add, Assimp.TextureWrapMode.Wrap, Assimp.TextureWrapMode.Wrap, 0);
                        break;

                    case 5:
                        mate.TextureOpacity = new Assimp.TextureSlot(
                            textureSet[i], Assimp.TextureType.Opacity, i, Assimp.TextureMapping.FromUV, aqp.tstaList[aqp.tsetList[msh.tsetIndex].tstaTexIDs[i]].modelUVSet, 0,
                            Assimp.TextureOperation.Add, Assimp.TextureWrapMode.Wrap, Assimp.TextureWrapMode.Wrap, 0);
                        break;

                    case 6:
                        mate.TextureHeight = new Assimp.TextureSlot(
                            textureSet[i], Assimp.TextureType.Height, i, Assimp.TextureMapping.FromUV, aqp.tstaList[aqp.tsetList[msh.tsetIndex].tstaTexIDs[i]].modelUVSet, 0,
                            Assimp.TextureOperation.Add, Assimp.TextureWrapMode.Wrap, Assimp.TextureWrapMode.Wrap, 0);
                        break;

                    case 7:
                        mate.TextureEmissive = new Assimp.TextureSlot(
                            textureSet[i], Assimp.TextureType.Emissive, i, Assimp.TextureMapping.FromUV, aqp.tstaList[aqp.tsetList[msh.tsetIndex].tstaTexIDs[i]].modelUVSet, 0,
                            Assimp.TextureOperation.Add, Assimp.TextureWrapMode.Wrap, Assimp.TextureWrapMode.Wrap, 0);
                        break;

                    case 8:
                        mate.TextureAmbient = new Assimp.TextureSlot(
                            textureSet[i], Assimp.TextureType.Ambient, i, Assimp.TextureMapping.FromUV, aqp.tstaList[aqp.tsetList[msh.tsetIndex].tstaTexIDs[i]].modelUVSet, 0,
                            Assimp.TextureOperation.Add, Assimp.TextureWrapMode.Wrap, Assimp.TextureWrapMode.Wrap, 0);
                        break;

                    case 9:
                        mate.TextureReflection = new Assimp.TextureSlot(
                            textureSet[i], Assimp.TextureType.Reflection, i, Assimp.TextureMapping.FromUV, aqp.tstaList[aqp.tsetList[msh.tsetIndex].tstaTexIDs[i]].modelUVSet, 0,
                            Assimp.TextureOperation.Add, Assimp.TextureWrapMode.Wrap, Assimp.TextureWrapMode.Wrap, 0);
                        break;

                    default:
                        break;
                    }
                }

                mate.ShadingMode = Assimp.ShadingMode.Phong;


                var meshNodeName = string.Format("mesh[{4}]_{0}_{1}_{2}_{3}#{4}#{5}", msh.mateIndex, msh.rendIndex, msh.shadIndex, msh.tsetIndex, aiScene.Meshes.Count, msh.baseMeshNodeId, msh.baseMeshDummyId);

                // Add mesh to meshes
                aiScene.Meshes.Add(aiMesh);

                // Add material to materials
                aiScene.Materials.Add(mate);

                // MaterialIndex
                aiMesh.MaterialIndex = aiScene.Materials.Count - 1;

                // Set up mesh node and add this mesh's index to it (This tells assimp to export it as a mesh for various formats)
                var meshNode = new Assimp.Node(meshNodeName, aiScene.RootNode);
                meshNode.Transform = Assimp.Matrix4x4.Identity;

                aiScene.RootNode.Children.Add(meshNode);

                meshNode.MeshIndices.Add(aiScene.Meshes.Count - 1);
            }

            return(aiScene);
        }
        public static Assimp.Scene AssimpPRMExport(string filePath, PRMModel prm)
        {
            Assimp.Scene aiScene = new Assimp.Scene();

            //Create an array to hold references to these since Assimp lacks a way to grab these by order or id
            //We don't need the nodo count in this since they can't be parents
            Assimp.Node[] boneArray = new Assimp.Node[2];

            //Set up root node
            var aiRootNode = new Assimp.Node("RootNode", null);

            aiRootNode.Transform = Assimp.Matrix4x4.Identity;

            boneArray[0]     = aiRootNode;
            aiScene.RootNode = aiRootNode;

            //Set up single child node
            var aiNode = new Assimp.Node(Path.GetFileNameWithoutExtension(filePath) + "_node", aiRootNode);

            //Use inverse bind matrix as base

            //Get local transform
            aiNode.Transform = aiRootNode.Transform;

            aiRootNode.Children.Add(aiNode);
            boneArray[1] = aiNode;

            //Mesh
            string aiMeshName = Path.GetFileNameWithoutExtension(filePath);

            var aiMesh = new Assimp.Mesh(aiMeshName, Assimp.PrimitiveType.Triangle);

            //Vertex face data - PSO2 Actually doesn't do this, it just has per vertex data so we can just map a vertice's data to each face using it
            //It may actually be possible to add this to the previous loop, but my reference didn't so I'm doing it in a separate loop for safety
            //Reference: https://github.com/TGEnigma/Amicitia/blob/master/Source/AmicitiaLibrary/Graphics/RenderWare/RWClumpNode.cs
            for (int vertId = 0; vertId < prm.vertices.Count; vertId++)
            {
                var prmVert = prm.vertices[vertId];

                var pos = prmVert.pos * 100;
                aiMesh.Vertices.Add(new Assimp.Vector3D(pos.X, pos.Y, pos.Z));

                var nrm = prmVert.normal;
                aiMesh.Normals.Add(new Assimp.Vector3D(nrm.X, nrm.Y, nrm.Z));

                //Vert colors are bgra
                var rawClr = prmVert.color;
                var clr    = new Assimp.Color4D(clrToFloat(rawClr[2]), clrToFloat(rawClr[1]), clrToFloat(rawClr[0]), clrToFloat(rawClr[3]));
                aiMesh.VertexColorChannels[0].Add(clr);

                var uv1   = prmVert.uv1;
                var aiUV1 = new Assimp.Vector3D(uv1.X, uv1.Y, 0f);
                aiMesh.TextureCoordinateChannels[0].Add(aiUV1);


                var uv2   = prmVert.uv2;
                var aiUV2 = new Assimp.Vector3D(uv2.X, uv2.Y, 0f);
                aiMesh.TextureCoordinateChannels[1].Add(aiUV2);
            }

            //Handle rigid meshes
            {
                var aiBone  = new Assimp.Bone();
                var aqnBone = boneArray[0];

                // Name
                aiBone.Name = aiNode.Name;

                // VertexWeights
                for (int i = 0; i < aiMesh.Vertices.Count; i++)
                {
                    var aiVertexWeight = new Assimp.VertexWeight(i, 1f);
                    aiBone.VertexWeights.Add(aiVertexWeight);
                }

                aiBone.OffsetMatrix = Assimp.Matrix4x4.Identity;

                aiMesh.Bones.Add(aiBone);
            }

            //Faces
            foreach (var face in prm.faces)
            {
                aiMesh.Faces.Add(new Assimp.Face(new int[] { (int)face.X, (int)face.Y, (int)face.Z }));
            }

            //Material
            Assimp.Material mate = new Assimp.Material();

            mate.ColorDiffuse = new Assimp.Color4D(1, 1, 1, 1);
            mate.Name         = aiMeshName + "_material";

            mate.ShadingMode = Assimp.ShadingMode.Phong;

            var meshNodeName = Path.GetFileNameWithoutExtension(filePath);

            // Add mesh to meshes
            aiScene.Meshes.Add(aiMesh);

            // Add material to materials
            aiScene.Materials.Add(mate);

            // MaterialIndex
            aiMesh.MaterialIndex = aiScene.Materials.Count - 1;

            // Set up mesh node and add this mesh's index to it (This tells assimp to export it as a mesh for various formats)
            var meshNode = new Assimp.Node(meshNodeName, aiScene.RootNode);

            meshNode.Transform = Assimp.Matrix4x4.Identity;

            aiScene.RootNode.Children.Add(meshNode);

            meshNode.MeshIndices.Add(aiScene.Meshes.Count - 1);


            return(aiScene);
        }
Example #20
0
        private void ParseMaterials(Assimp.Scene scene)
        {
            Assimp.Material[] materials = scene.Materials;

            //Should always have the default material at least
            m_materials = new Material[materials.Length];
            bool hasNormals      = false;
            bool hasTangentBasis = false;
            bool hasTexCoords    = false;
            bool hasVertexColors = false;

            //TODO: Incorporate user-defined materials

            for (int i = 0; i < materials.Length; i++)
            {
                Assimp.Material material = materials[i];
                Material        mat;
                hasNormals      = false;
                hasTangentBasis = false;
                hasTexCoords    = false;
                hasVertexColors = false;

                foreach (MeshMaterialInfo info in m_meshMatInfo)
                {
                    if (info.MaterialIndex == i)
                    {
                        if (info.HasNormals)
                        {
                            hasNormals = true;
                        }
                        if (info.HasTangentBasis)
                        {
                            hasTangentBasis = true;
                        }
                        if (info.HasTexCoords)
                        {
                            hasTexCoords = true;
                        }
                        if (info.HasVertexColors)
                        {
                            hasVertexColors = true;
                        }
                    }
                }

                if (hasNormals && m_loaderParams.PreferLitMaterials)
                {
                    if (hasTexCoords && hasTangentBasis)
                    {
                        if (hasVertexColors)
                        {
                            mat = m_content.Load <Material>("NormalMapVertColor.tem").Clone();
                        }
                        else
                        {
                            mat = m_content.Load <Material>("NormalMap.tem").Clone();
                        }
                        SetNormalMapMaterialTextures(mat, material); //Normal map textures + diffuse
                    }
                    else
                    {
                        if (hasTexCoords)
                        {
                            if (hasVertexColors)
                            {
                                mat = m_content.Load <Material>("LitBasicVertColorTexture.tem");
                            }
                            else
                            {
                                mat = m_content.Load <Material>("LitBasicTexture.tem").Clone();
                            }
                            SetMaterialTexture(mat, material); //Difuse texture
                        }
                        else
                        {
                            if (hasVertexColors)
                            {
                                mat = m_content.Load <Material>("LitBasicVertColor.tem").Clone();
                            }
                            else
                            {
                                mat = m_content.Load <Material>("LitBasicColor.tem").Clone();
                            }
                        }
                    }
                    SetLitMaterialColors(mat, material); //Common lit color parameters
                }
                else
                {
                    if (hasTexCoords)
                    {
                        if (hasVertexColors)
                        {
                            mat = m_content.Load <Material>("BasicVertColorTexture.tem");
                        }
                        else
                        {
                            mat = m_content.Load <Material>("BasicTexture.tem").Clone();
                        }
                        SetMaterialTexture(mat, material); //Difuse texture
                    }
                    else
                    {
                        if (hasVertexColors)
                        {
                            mat = m_content.Load <Material>("BasicVertColor.tem").Clone();
                        }
                        else
                        {
                            mat = m_content.Load <Material>("BasicColor.tem").Clone();
                        }
                    }
                    SetMaterialColor(mat, material); //Common unlit color parameters
                }

                SetMaterialRenderStates(mat, material);

                if (material.HasName)
                {
                    mat.Name = material.Name;
                }
                m_materials[i] = mat;
            }
        }
Example #21
0
        internal static Mesh3D LoadFromFileSUB(Device device, Assimp.Scene pScene, InputElement[] ieLayout, List <SceneObject> meshArr)
        {
            string sourceTextures = ConfigurationSettings.AppSettings["SourceTextures"];

            int iVBufferSize = 0;
            int iIBufferSize = 0;

            foreach (SceneObject so in meshArr)
            {
                iVBufferSize += (int)so.pMesh.VertexCount;
                iIBufferSize += (int)so.pMesh.FaceCount * 3;
            }


            MeshInputElements10.sNormalMesh[] tVertex = new MeshInputElements10.sNormalMesh[iVBufferSize];
            //short[] tIndex = new short[iIBufferSize];
            uint[] tIndex = new uint[iIBufferSize];
            MeshAttributeRange[] tAttibutes = new MeshAttributeRange[meshArr.Count];
            MeshNode[]           nodes      = new MeshNode[meshArr.Count];
            string[]             tTextures  = new string[meshArr.Count];

            // Monitor global poisition in the vertex, index and attribute buffers.
            int iAttribute    = 0;
            int iBVertex      = 0;
            int iBIndex       = 0;
            int prevVertCount = 0;

            foreach (SceneObject so in meshArr)
            {
                MeshNode n = new MeshNode();
                n.attributeId     = iAttribute;
                n.nodeName        = so.nodeName;
                n.parentNodeName  = so.parentNodeName;
                n.transform       = toDXMat(so.transform);
                nodes[iAttribute] = n;


                MeshAttributeRange pAttrib = new MeshAttributeRange();
                pAttrib.Id          = iAttribute;
                pAttrib.VertexStart = iBVertex;
                pAttrib.FaceStart   = iBIndex / 3;

                Assimp.Material mat = pScene.Materials[so.pMesh.MaterialIndex];
                if (mat.GetTextureCount(Assimp.TextureType.Diffuse) > 0)
                {
                    string inputFilePath = mat.GetTexture(Assimp.TextureType.Diffuse, 0).FilePath.Replace("\\\\", "\\");
                    string inputFileName = Path.GetFileName(inputFilePath);
                    string ext           = Path.GetExtension(inputFileName);
                    string subFolder     = inputFilePath.Replace(sourceTextures, "").Split('\\')[1];
                    string diffOutFile   = subFolder + "\\" + inputFileName.Replace(ext, ".dds");
                    tTextures[iAttribute] = diffOutFile;
                }

                // Copy verticies.
                int iMeshVerts = (int)so.pMesh.VertexCount;
                for (int iVertex = 0; iVertex < iMeshVerts; ++iVertex)
                {
                    tVertex[iVertex + iBVertex] = getVert(so, iVertex);
                }

                // Increment the vertex count by the number of verticies we just looped over.
                iBVertex += iMeshVerts;

                // Copy indicies.
                int iMeshFaces = (int)so.pMesh.FaceCount;
                for (int iFace = 0; iFace < iMeshFaces; ++iFace)
                {
                    uint[] tIndices = so.pMesh.Faces[iFace].Indices;
                    //tIndex[iBIndex++] = Convert.ToInt16(tIndices[0] + (iAttribute == 0 ? 0 : prevVertCount));
                    //tIndex[iBIndex++] = Convert.ToInt16(tIndices[1] + (iAttribute == 0 ? 0 : prevVertCount));
                    //tIndex[iBIndex++] = Convert.ToInt16(tIndices[2] + (iAttribute == 0 ? 0 : prevVertCount));
                    tIndex[iBIndex++] = Convert.ToUInt32(tIndices[0] + (iAttribute == 0 ? 0 : prevVertCount));
                    tIndex[iBIndex++] = Convert.ToUInt32(tIndices[1] + (iAttribute == 0 ? 0 : prevVertCount));
                    tIndex[iBIndex++] = Convert.ToUInt32(tIndices[2] + (iAttribute == 0 ? 0 : prevVertCount));
                }

                // Increment the face count by the number of faces we just looped over.
                prevVertCount += iMeshVerts;


                pAttrib.FaceCount      = iMeshFaces;
                pAttrib.VertexCount    = iMeshVerts;
                tAttibutes[iAttribute] = pAttrib;
                iAttribute++;
            }

            Mesh3D gm     = new Mesh3D();
            Mesh   output = new Mesh(device, ieLayout, ieLayout[0].SemanticName, iVBufferSize, iIBufferSize / 3, MeshFlags.Has32BitIndices);

            output.SetAttributeTable(tAttibutes);

            DataStream verts = new DataStream(iVBufferSize * Marshal.SizeOf(typeof(MeshInputElements10.sNormalMesh)), true, true);
            //DataStream indicies = new DataStream(iIBufferSize * Marshal.SizeOf(typeof(short)), true, true);
            DataStream indicies = new DataStream(iIBufferSize * Marshal.SizeOf(typeof(uint)), true, true);

            verts.WriteRange(tVertex);
            indicies.WriteRange(tIndex);


            verts.Position    = 0;
            indicies.Position = 0;

            output.SetVertexData(0, verts);
            output.SetIndexData(indicies, iIBufferSize);
            output.Commit();
            verts.Dispose();
            indicies.Dispose();

            gm.attrTable     = tAttibutes;
            gm.meshObj       = output;
            gm.NumAttributes = meshArr.Count;
            gm.materials     = tTextures;
            gm.nodes         = nodes;

            if (pScene.HasAnimations)
            {
                gm.animations = new List <Mesh3DAnimation>();
                foreach (Assimp.Animation a in pScene.Animations)
                {
                    Mesh3DAnimation anim = new Mesh3DAnimation();
                    anim.animName = a.Name;
                    anim.duration = a.DurationInTicks;
                    anim.channels = new AnimationChannel[a.NodeAnimationChannelCount];

                    int x = 0;
                    foreach (Assimp.NodeAnimationChannel c in a.NodeAnimationChannels)
                    {
                        if (c == null)
                        {
                            continue;
                        }

                        AnimationChannel ac = new AnimationChannel();
                        ac.nodeName = c.NodeName;
                        ac.animKeys = new AnimationKey[c.RotationKeyCount];
                        for (int i = 0; i < c.PositionKeys.Length; i++)
                        {
                            double      time = 0;
                            SceneObject sObj = meshArr[0];
                            foreach (SceneObject so in meshArr)
                            {
                                if (so.nodeName == c.NodeName)
                                {
                                    sObj = so;
                                    break;
                                }
                            }

                            time = c.PositionKeys[i].Time;
                            Matrix  mat            = toDXMat(sObj.transform);
                            Vector3 rotationCenter = new Vector3(mat.M41, mat.M42, mat.M43);
                            mat.Invert();
                            Vector3 pos = Vector3.TransformCoordinate(toDX(c.PositionKeys[i].Value), mat);


                            Matrix matAnim = Matrix.Transformation(Vector3.Zero, Quaternion.Identity, new Vector3(1, 1, 1), rotationCenter, toDX(c.RotationKeys[i].Value), pos);


                            AnimationKey ak = new AnimationKey();
                            ak.animMat     = matAnim;
                            ak.time        = time;
                            ac.animKeys[i] = ak;
                        }

                        anim.channels[x++] = ac;
                    }

                    gm.animations.Add(anim);
                }
            }



            return(gm);
        }
Example #22
0
        public void ExportToDae(string path)
        {
            var atomicSectors = new List <RwAtomicSector>();

            void RecursivelyFindAtomicSectors(RwNode node)
            {
                if (node.Id == RwNodeId.RwAtomicSector)
                {
                    atomicSectors.Add(( RwAtomicSector )node);
                }

                foreach (var child in node.Children)
                {
                    RecursivelyFindAtomicSectors(child);
                }
            }

            RecursivelyFindAtomicSectors(this);

            if (atomicSectors.Count == 0)
            {
                return;
            }

            var aiScene = new Assimp.Scene();

            for (var i = 0; i < Materials.Count; i++)
            {
                var material   = Materials[i];
                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{i}";
                if (material.IsTextured)
                {
                    aiMaterial.Name = material.TextureReferenceNode.Name;
                }

                aiMaterial.ShadingMode = Assimp.ShadingMode.Phong;
                aiScene.Materials.Add(aiMaterial);
            }

            for (var i = 0; i < atomicSectors.Count; i++)
            {
                var atomicSector = atomicSectors[i];
                var header       = atomicSector.Header;
                if (header.VertexCount == 0)
                {
                    continue;
                }

                foreach (var materialGroup in header.Triangles.GroupBy(x => x.MatId))
                {
                    var materialId = materialGroup.Key;

                    var aiMesh = new Assimp.Mesh($"AtomicSector{i}_Material{materialId}", Assimp.PrimitiveType.Triangle);
                    aiMesh.MaterialIndex = materialId;

                    foreach (var triangle in materialGroup)
                    {
                        var pos1 = header.Positions[triangle.A];
                        var pos2 = header.Positions[triangle.B];
                        var pos3 = header.Positions[triangle.C];

                        aiMesh.Vertices.Add(new Assimp.Vector3D(pos1.X, pos1.Y, pos1.Z));
                        aiMesh.Vertices.Add(new Assimp.Vector3D(pos2.X, pos2.Y, pos2.Z));
                        aiMesh.Vertices.Add(new Assimp.Vector3D(pos3.X, pos3.Y, pos3.Z));

                        if (header.TextureCoordinateChannels != null && header.TextureCoordinateChannels.Length > 0)
                        {
                            var tex1 = header.TextureCoordinateChannels[0][triangle.A];
                            var tex2 = header.TextureCoordinateChannels[0][triangle.B];
                            var tex3 = header.TextureCoordinateChannels[0][triangle.C];

                            aiMesh.TextureCoordinateChannels[0].Add(new Assimp.Vector3D(tex1.X, 1f - tex1.Y, 0));
                            aiMesh.TextureCoordinateChannels[0].Add(new Assimp.Vector3D(tex2.X, 1f - tex2.Y, 0));
                            aiMesh.TextureCoordinateChannels[0].Add(new Assimp.Vector3D(tex3.X, 1f - tex3.Y, 0));
                        }

                        if (header.Colors != null && header.Colors.Length > 0)
                        {
                            var color1 = header.Colors[triangle.A];
                            var color2 = header.Colors[triangle.B];
                            var color3 = header.Colors[triangle.C];

                            aiMesh.VertexColorChannels[0].Add(new Assimp.Color4D((float)color1.R / 255f, ( float )color1.G / 255f, ( float )color1.B / 255f, ( float )color1.A / 255f));
                            aiMesh.VertexColorChannels[0].Add(new Assimp.Color4D(( float )color2.R / 255f, ( float )color2.G / 255f, ( float )color2.B / 255f, ( float )color2.A / 255f));
                            aiMesh.VertexColorChannels[0].Add(new Assimp.Color4D(( float )color3.R / 255f, ( float )color3.G / 255f, ( float )color3.B / 255f, ( float )color3.A / 255f));
                        }
                    }

                    for (int j = 0; j < aiMesh.VertexCount; j += 3)
                    {
                        aiMesh.Faces.Add(new Assimp.Face(new[] { j, j + 1, j + 2 }));
                    }

                    aiScene.Meshes.Add(aiMesh);
                }
            }

            aiScene.RootNode = new Assimp.Node("RootNode");
            aiScene.RootNode.MeshIndices.AddRange(Enumerable.Range(0, aiScene.Meshes.Count));

            var aiContext = new Assimp.AssimpContext();

            aiContext.ExportFile(aiScene, path, "collada",
                                 Assimp.PostProcessSteps.GenerateSmoothNormals | Assimp.PostProcessSteps.JoinIdenticalVertices |
                                 Assimp.PostProcessSteps.ImproveCacheLocality);
        }
Example #23
0
        public void SetUpTev(bool hasTexture, bool hasVtxColor, int texIndex, string texName, Assimp.Material meshMat)
        {
            Flag = 1;
            // Set up channel control 0 to use vertex colors, if they're present
            if (hasVtxColor)
            {
                AddChannelControl(J3DColorChannelId.Color0, false, ColorSrc.Vertex, LightId.None, DiffuseFn.None, J3DAttenuationFn.None_0, ColorSrc.Register);
                AddChannelControl(J3DColorChannelId.Alpha0, false, ColorSrc.Vertex, LightId.None, DiffuseFn.None, J3DAttenuationFn.None_0, ColorSrc.Register);
            }
            else
            {
                AddChannelControl(J3DColorChannelId.Color0, false, ColorSrc.Register, LightId.None, DiffuseFn.Clamp, J3DAttenuationFn.Spec, ColorSrc.Register);
                AddChannelControl(J3DColorChannelId.Alpha0, false, ColorSrc.Register, LightId.None, DiffuseFn.Clamp, J3DAttenuationFn.Spec, ColorSrc.Register);
            }

            // These settings are common to all the configurations we can use
            TevStageParameters stageParams = new TevStageParameters
            {
                ColorInD   = CombineColorInput.Zero,
                ColorOp    = TevOp.Add,
                ColorBias  = TevBias.Zero,
                ColorScale = TevScale.Scale_1,
                ColorClamp = true,
                ColorRegId = TevRegisterId.TevPrev,

                AlphaInD   = CombineAlphaInput.Zero,
                AlphaOp    = TevOp.Add,
                AlphaBias  = TevBias.Zero,
                AlphaScale = TevScale.Scale_1,
                AlphaClamp = true,
                AlphaRegId = TevRegisterId.TevPrev
            };

            if (hasTexture)
            {
                // Generate texture stuff
                AddTexGen(TexGenType.Matrix2x4, TexGenSrc.Tex0, Enums.TexMatrix.Identity);
                AddTexMatrix(TexGenType.Matrix3x4, 0, OpenTK.Vector3.Zero, OpenTK.Vector2.One, 0, OpenTK.Vector2.Zero, OpenTK.Matrix4.Identity);
                AddTevOrder(TexCoordId.TexCoord0, TexMapId.TexMap0, GXColorChannelId.Color0A0);
                AddTexIndex(texIndex);

                // Texture + Vertex Color
                if (hasVtxColor)
                {
                    stageParams.ColorInA = CombineColorInput.Zero;
                    stageParams.ColorInB = CombineColorInput.RasColor;
                    stageParams.ColorInC = CombineColorInput.TexColor;
                    stageParams.AlphaInA = CombineAlphaInput.Zero;
                    stageParams.AlphaInB = CombineAlphaInput.RasAlpha;
                    stageParams.AlphaInC = CombineAlphaInput.TexAlpha;
                }
                // Texture alone
                else
                {
                    stageParams.ColorInA = CombineColorInput.TexColor;
                    stageParams.ColorInB = CombineColorInput.Zero;
                    stageParams.ColorInC = CombineColorInput.Zero;
                    stageParams.AlphaInA = CombineAlphaInput.TexAlpha;
                    stageParams.AlphaInB = CombineAlphaInput.Zero;
                    stageParams.AlphaInC = CombineAlphaInput.Zero;
                }
            }
            // No texture!
            else
            {
                AddTevOrder(TexCoordId.Null, TexMapId.Null, GXColorChannelId.Color0A0);

                // No vertex colors either, so make sure there's a material color to use instead
                if (!hasVtxColor)
                {
                    if (meshMat.HasColorDiffuse)   // Use model's diffuse color
                    {
                        Assimp.Color4D color = meshMat.ColorDiffuse;
                        MaterialColors[0] = new Color(color.R, color.G, color.B, color.A);
                    }
                    else   // Otherwise default to white
                    {
                        MaterialColors[0] = new Color(1, 1, 1, 1);
                    }

                    AddChannelControl(J3DColorChannelId.Color0, false, ColorSrc.Register, LightId.None, DiffuseFn.None, J3DAttenuationFn.None_0, ColorSrc.Register);
                    AddChannelControl(J3DColorChannelId.Alpha0, false, ColorSrc.Register, LightId.None, DiffuseFn.None, J3DAttenuationFn.None_0, ColorSrc.Register);
                }

                // Set up TEV to use the material color we just set
                stageParams.ColorInA = CombineColorInput.RasColor;
                stageParams.ColorInB = CombineColorInput.Zero;
                stageParams.ColorInC = CombineColorInput.Zero;
                stageParams.AlphaInA = CombineAlphaInput.RasAlpha;
                stageParams.AlphaInB = CombineAlphaInput.Zero;
                stageParams.AlphaInC = CombineAlphaInput.Zero;
            }

            AddTevStage(stageParams);
        }
Example #24
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);
        }
Example #25
0
        public static Assimp.Scene CreateAssimpScene(this IGeometryModel model, Assimp.AssimpContext context, string formatId)
        {
            var scale = ModelViewerPlugin.Settings.GeometryScale;

            //either Assimp or collada has issues when there is a name conflict
            const string bonePrefix = "~";
            const string geomPrefix = "-";
            const string scenPrefix = "$";

            var scene = new Assimp.Scene();

            scene.RootNode = new Assimp.Node($"{scenPrefix}{model.Name}");

            //Assimp is Y-up in inches by default - this forces it to export as Z-up in meters
            scene.RootNode.Transform = (CoordinateSystem.HaloCEX * ModelViewerPlugin.Settings.AssimpScale).ToAssimp4x4();

            #region Nodes
            var allNodes = new List <Assimp.Node>();
            foreach (var node in model.Nodes)
            {
                var result = new Assimp.Node($"{bonePrefix}{node.Name}");

                var q   = new System.Numerics.Quaternion(node.Rotation.X, node.Rotation.Y, node.Rotation.Z, node.Rotation.W);
                var mat = System.Numerics.Matrix4x4.CreateFromQuaternion(q);
                mat.Translation  = new System.Numerics.Vector3(node.Position.X * scale, node.Position.Y * scale, node.Position.Z * scale);
                result.Transform = mat.ToAssimp4x4();

                allNodes.Add(result);
            }

            for (int i = 0; i < model.Nodes.Count; i++)
            {
                var node = model.Nodes[i];
                if (node.ParentIndex >= 0)
                {
                    allNodes[node.ParentIndex].Children.Add(allNodes[i]);
                }
                else
                {
                    scene.RootNode.Children.Add(allNodes[i]);
                }
            }
            #endregion

            var meshLookup = new List <int>();

            #region Meshes
            for (int i = 0; i < model.Meshes.Count; i++)
            {
                var geom = model.Meshes[i];
                if (geom.Submeshes.Count == 0)
                {
                    meshLookup.Add(-1);
                    continue;
                }

                meshLookup.Add(scene.MeshCount);

                foreach (var sub in geom.Submeshes)
                {
                    var m = new Assimp.Mesh($"mesh{i:D3}");

                    var indices = geom.Indicies.Skip(sub.IndexStart).Take(sub.IndexLength);

                    var minIndex  = indices.Min();
                    var maxIndex  = indices.Max();
                    var vertCount = maxIndex - minIndex + 1;

                    if (geom.IndexFormat == IndexFormat.TriangleStrip)
                    {
                        indices = indices.Unstrip();
                    }

                    indices = indices.Select(x => x - minIndex);
                    var vertices = geom.Vertices.Skip(minIndex).Take(vertCount);

                    if (geom.BoundsIndex >= 0)
                    {
                        vertices = vertices.Select(v => (IVertex) new CompressedVertex(v, model.Bounds[geom.BoundsIndex.Value]));
                    }

                    int vIndex     = -1;
                    var boneLookup = new Dictionary <int, Assimp.Bone>();
                    foreach (var v in vertices)
                    {
                        vIndex++;

                        if (v.Position.Count > 0)
                        {
                            m.Vertices.Add(v.Position[0].ToAssimp3D(scale));

                            //some Halo shaders use position W as the colour alpha - add it to a colour channel to preserve it
                            //also assimp appears to have issues exporting obj when a colour channel exists so only do this for collada
                            if (formatId == "collada" && v.Color.Count == 0 && !float.IsNaN(v.Position[0].W))
                            {
                                m.VertexColorChannels[0].Add(new Assimp.Color4D {
                                    R = v.Position[0].W
                                });
                            }
                        }

                        if (v.Normal.Count > 0)
                        {
                            m.Normals.Add(v.Normal[0].ToAssimp3D());
                        }

                        if (v.TexCoords.Count > 0)
                        {
                            m.TextureCoordinateChannels[0].Add(v.TexCoords[0].ToAssimpUV());
                        }

                        if (geom.VertexWeights == VertexWeights.None && !geom.NodeIndex.HasValue)
                        {
                            continue;
                        }

                        #region Vertex Weights
                        var weights = new List <Tuple <int, float> >(4);

                        if (geom.NodeIndex.HasValue)
                        {
                            weights.Add(Tuple.Create <int, float>(geom.NodeIndex.Value, 1));
                        }
                        else if (geom.VertexWeights == VertexWeights.Skinned)
                        {
                            var ind = v.BlendIndices[0];
                            var wt  = v.BlendWeight[0];

                            if (wt.X > 0)
                            {
                                weights.Add(Tuple.Create((int)ind.X, wt.X));
                            }
                            if (wt.Y > 0)
                            {
                                weights.Add(Tuple.Create((int)ind.Y, wt.Y));
                            }
                            if (wt.Z > 0)
                            {
                                weights.Add(Tuple.Create((int)ind.Z, wt.Z));
                            }
                            if (wt.W > 0)
                            {
                                weights.Add(Tuple.Create((int)ind.W, wt.W));
                            }
                        }

                        foreach (var val in weights)
                        {
                            Assimp.Bone b;
                            if (boneLookup.ContainsKey(val.Item1))
                            {
                                b = boneLookup[val.Item1];
                            }
                            else
                            {
                                var t = model.Nodes[val.Item1].OffsetTransform;
                                t.M41 *= scale;
                                t.M42 *= scale;
                                t.M43 *= scale;

                                b = new Assimp.Bone
                                {
                                    Name         = bonePrefix + model.Nodes[val.Item1].Name,
                                    OffsetMatrix = t.ToAssimp4x4()
                                };

                                m.Bones.Add(b);
                                boneLookup.Add(val.Item1, b);
                            }

                            b.VertexWeights.Add(new Assimp.VertexWeight(vIndex, val.Item2));
                        }
                        #endregion
                    }

                    m.SetIndices(indices.ToArray(), 3);
                    m.MaterialIndex = sub.MaterialIndex;

                    scene.Meshes.Add(m);
                }
            }
            #endregion

            #region Regions
            foreach (var reg in model.Regions)
            {
                var regNode = new Assimp.Node($"{geomPrefix}{reg.Name}");
                foreach (var perm in reg.Permutations)
                {
                    var meshStart = meshLookup[perm.MeshIndex];
                    if (meshStart < 0)
                    {
                        continue;
                    }

                    var permNode = new Assimp.Node($"{geomPrefix}{perm.Name}");
                    if (perm.TransformScale != 1 || !perm.Transform.IsIdentity)
                    {
                        permNode.Transform = Assimp.Matrix4x4.FromScaling(new Assimp.Vector3D(perm.TransformScale)) * perm.Transform.ToAssimp4x4(scale);
                    }

                    var meshCount = Enumerable.Range(perm.MeshIndex, perm.MeshCount).Sum(i => model.Meshes[i].Submeshes.Count);
                    permNode.MeshIndices.AddRange(Enumerable.Range(meshStart, meshCount));

                    regNode.Children.Add(permNode);
                }

                if (regNode.ChildCount > 0)
                {
                    scene.RootNode.Children.Add(regNode);
                }
            }
            #endregion

            #region Materials
            foreach (var mat in model.Materials)
            {
                var m = new Assimp.Material {
                    Name = mat?.Name ?? "unused"
                };

                //prevent max from making every material super shiny
                m.ColorEmissive = m.ColorReflective = m.ColorSpecular = new Assimp.Color4D(0, 0, 0, 1);
                m.ColorDiffuse  = m.ColorTransparent = new Assimp.Color4D(1);

                //max only seems to care about diffuse
                var dif = mat?.Submaterials.FirstOrDefault(s => s.Usage == MaterialUsage.Diffuse);
                if (dif != null)
                {
                    var suffix   = dif.Bitmap.SubmapCount > 1 ? "[0]" : string.Empty;
                    var filePath = $"{dif.Bitmap.Name}{suffix}.{ModelViewerPlugin.Settings.MaterialExtension}";

                    //collada spec says it requires URI formatting, and Assimp doesn't do it for us
                    //for some reason "new Uri(filePath, UriKind.Relative)" doesnt change the slashes, have to use absolute uri
                    if (formatId == FormatId.Collada)
                    {
                        filePath = new Uri("X:\\", UriKind.Absolute).MakeRelativeUri(new Uri(System.IO.Path.Combine("X:\\", filePath))).ToString();
                    }

                    m.TextureDiffuse = new Assimp.TextureSlot
                    {
                        BlendFactor = 1,
                        FilePath    = filePath,
                        TextureType = Assimp.TextureType.Diffuse
                    };
                }

                scene.Materials.Add(m);
            }
            #endregion

            return(scene);
        }
Example #26
0
        public MaterialBinding(Shader shader, ResourceManager resourceManager, Assimp.Material material)
        {
            if (shader == null)
            {
                throw new ArgumentNullException(nameof(shader));
            }

            if (resourceManager == null)
            {
                throw new ArgumentNullException(nameof(resourceManager));
            }

            resource = material ?? throw new ArgumentNullException(nameof(material));
            bind     = EmptyAction;

            if (resource.HasBumpScaling)
            {
                BindUniform(ref bind, shader, ShaderConstants.BumpScaling, resource.BumpScaling);
            }
            if (resource.HasColorAmbient)
            {
                BindUniform(ref bind, shader, ShaderConstants.ColorAmbient, material.ColorAmbient);
            }
            if (resource.HasColorDiffuse)
            {
                BindUniform(ref bind, shader, ShaderConstants.ColorDiffuse, material.ColorDiffuse);
            }
            if (resource.HasColorEmissive)
            {
                BindUniform(ref bind, shader, ShaderConstants.ColorEmissive, material.ColorEmissive);
            }
            if (resource.HasColorReflective)
            {
                BindUniform(ref bind, shader, ShaderConstants.ColorReflective, material.ColorReflective);
            }
            if (resource.HasColorSpecular)
            {
                BindUniform(ref bind, shader, ShaderConstants.ColorSpecular, material.ColorSpecular);
            }
            if (resource.HasColorTransparent)
            {
                BindUniform(ref bind, shader, ShaderConstants.ColorTransparent, material.ColorTransparent);
            }
            if (resource.HasOpacity)
            {
                BindUniform(ref bind, shader, ShaderConstants.Opacity, material.Opacity);
            }
            if (resource.HasReflectivity)
            {
                BindUniform(ref bind, shader, ShaderConstants.Reflectivity, material.Reflectivity);
            }
            if (resource.HasShininess)
            {
                BindUniform(ref bind, shader, ShaderConstants.Shininess, material.Shininess);
            }
            if (resource.HasShininessStrength)
            {
                BindUniform(ref bind, shader, ShaderConstants.ShininessStrength, material.ShininessStrength);
            }

            var textures = resource.GetAllMaterialTextures();

            for (int i = 0; i < textures.Length; i++)
            {
                BindUniform(ref bind, shader, textures[i], i, resourceManager);
            }
        }
Example #27
0
        public static Assimp.Scene ToAssimpScene(RWScene scene)
        {
            Assimp.Scene aiScene = new Assimp.Scene();

            int drawCallIdx = 0;
            int materialIdx = 0;
            int totalSplitIdx = 0;
            List<int> meshStartIndices = new List<int>();
            foreach (RWDrawCall drawCall in scene.DrawCalls)
            {
                meshStartIndices.Add(totalSplitIdx);
                var mesh = scene.Meshes[drawCall.MeshIndex];
                var node = scene.Nodes[drawCall.NodeIndex];

                int splitIdx = 0;
                foreach (RWMeshMaterialSplit split in mesh.MaterialSplitData.MaterialSplits)
                {
                    Assimp.Mesh aiMesh = new Assimp.Mesh(Assimp.PrimitiveType.Triangle);
                    aiMesh.Name = string.Format("DrawCall{0}_Split{1}", drawCallIdx.ToString("00"), splitIdx.ToString("00"));
                    aiMesh.MaterialIndex = split.MaterialIndex + materialIdx;

                    // get split indices
                    int[] indices = split.Indices;
                    if (mesh.MaterialSplitData.PrimitiveType == RWPrimitiveType.TriangleStrip)
                        indices = MeshUtilities.ToTriangleList(indices, true);

                    // pos & nrm
                    for (int i = 0; i < indices.Length; i++)
                    {
                        if (mesh.HasVertices)
                        {
                            var vert = Vector3.Transform(mesh.Vertices[indices[i]], node.WorldTransform);
                            aiMesh.Vertices.Add(vert.ToAssimpVector3D());
                        }
                        if (mesh.HasNormals)
                        {
                            var nrm = Vector3.TransformNormal(mesh.Normals[indices[i]], node.WorldTransform);
                            aiMesh.Normals.Add(nrm.ToAssimpVector3D());
                        }
                    }

                    // tex coords
                    if (mesh.HasTexCoords)
                    {
                        for (int i = 0; i < mesh.TextureCoordinateChannelCount; i++)
                        {
                            List<Assimp.Vector3D> texCoordChannel = new List<Assimp.Vector3D>();

                            for (int j = 0; j < indices.Length; j++)
                            {
                                texCoordChannel.Add(mesh.TextureCoordinateChannels[i][indices[j]].ToAssimpVector3D(0));
                            }

                            aiMesh.TextureCoordinateChannels[i] = texCoordChannel;
                        }
                    }

                    // colors
                    if (mesh.HasColors)
                    {
                        List<Assimp.Color4D> vertColorChannel = new List<Assimp.Color4D>();

                        for (int i = 0; i < indices.Length; i++)
                        {
                            var color = mesh.Colors[indices[i]];
                            vertColorChannel.Add(new Assimp.Color4D(color.R / 255f, color.G / 255f, color.B / 255f, color.A / 255f));
                        }

                        aiMesh.VertexColorChannels[0] = vertColorChannel;
                    }

                    // generate temporary face indices
                    int[] tempIndices = new int[aiMesh.VertexCount];
                    for (int i = 0; i < aiMesh.VertexCount; i++)
                        tempIndices[i] = i;

                    aiMesh.SetIndices(tempIndices, 3);

                    // add the mesh to the list
                    aiScene.Meshes.Add(aiMesh);

                    splitIdx++;
                }

                totalSplitIdx += splitIdx;

                foreach (RWMaterial mat in mesh.Materials)
                {
                    Assimp.Material aiMaterial = new Assimp.Material();
                    aiMaterial.AddProperty(new Assimp.MaterialProperty(Assimp.Unmanaged.AiMatKeys.NAME, "Material" + (materialIdx++).ToString("00")));

                    if (mat.IsTextured)
                    {
                        aiMaterial.AddProperty(new Assimp.MaterialProperty(Assimp.Unmanaged.AiMatKeys.TEXTURE_BASE, mat.TextureReference.ReferencedTextureName + ".png", Assimp.TextureType.Diffuse, 0));
                    }

                    aiScene.Materials.Add(aiMaterial);
                }

                drawCallIdx++;
            }

            // store node lookup
            Dictionary<RWSceneNode, Assimp.Node> nodeLookup = new Dictionary<RWSceneNode, Assimp.Node>();

            // first create the root node
            var rootNode = new Assimp.Node("SceneRoot");
            rootNode.Transform = scene.Nodes[0].Transform.ToAssimpMatrix4x4();
            nodeLookup.Add(scene.Nodes[0], rootNode);

            for (int i = 1; i < scene.Nodes.Count - 1; i++)
            {
                var node = scene.Nodes[i];
                string name = node.BoneMetadata.BoneNameID.ToString();

                var aiNode = new Assimp.Node(name);
                aiNode.Transform = node.Transform.ToAssimpMatrix4x4();

                // get the associated meshes for this node
                var drawCalls = scene.DrawCalls.FindAll(dc => dc.NodeIndex == i);
                foreach (var drawCall in drawCalls)
                {
                    for (int j = 0; j < scene.Meshes[drawCall.MeshIndex].MaterialCount; j++)
                    {
                        aiNode.MeshIndices.Add(meshStartIndices[scene.DrawCalls.IndexOf(drawCall)] + j);
                    }
                }

                nodeLookup[node.Parent].Children.Add(aiNode);
                nodeLookup.Add(node, aiNode);
            }

            aiScene.RootNode = rootNode;

            return aiScene;
        }