Skip to content

Dvelopment : Custom Model File Format (Rendering)

KillzXGaming edited this page Mar 24, 2020 · 3 revisions

A template for model rendering.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Toolbox.Library;
using Toolbox.Library.IO;
using Toolbox.Library.Rendering;
using Toolbox.Library.Forms;
using OpenTK;
using GL_EditorFramework.GL_Core;
using OpenTK.Graphics.OpenGL;

namespace FirstPlugin
{
    public class MDL : TreeNodeFile, IFileFormat
    {
        public FileType FileType { get; set; } = FileType.Model;

        public bool CanSave { get; set; }
        public string[] Description { get; set; } = new string[] { "MDL" };
        public string[] Extension { get; set; } = new string[] { "*.mdl" };
        public string FileName { get; set; }
        public string FilePath { get; set; }
        public IFileInfo IFileInfo { get; set; }

        public bool Identify(System.IO.Stream stream)
        {
            using (var reader = new Toolbox.Library.IO.FileReader(stream, true))
            {
                return reader.CheckSignature(4, "MDL3");
            }
        }

        public Type[] Types
        {
            get
            {
                List<Type> types = new List<Type>();
                return types.ToArray();
            }
        }

        //Check for the viewport in the object editor
        //This is attached to it to load multiple file formats within the object editor to the viewer
        Viewport viewport
        {
            get
            {
                var editor = LibraryGUI.GetObjectEditor();
                return editor.GetViewport();
            }
            set
            {
                var editor = LibraryGUI.GetObjectEditor();
                editor.LoadViewport(value);
            }
        }

        bool DrawablesLoaded = false;
        public override void OnClick(TreeView treeView)
        {
            //Make sure opengl is enabled
            if (Runtime.UseOpenGL)
            {
                //Open the viewport
                if (viewport == null)
                {
                    viewport = new Viewport(ObjectEditor.GetDrawableContainers());
                    viewport.Dock = DockStyle.Fill;
                }

                //Make sure to load the drawables only once so set it to true!
                if (!DrawablesLoaded)
                {
                    ObjectEditor.AddContainer(DrawableContainer);
                    DrawablesLoaded = true;
                }

                //Reload which drawable to display
                viewport.ReloadDrawables(DrawableContainer);
                LibraryGUI.LoadEditor(viewport);

                viewport.Text = Text;
            }
        }

        public MDL_Renderer Renderer;

        public DrawableContainer DrawableContainer = new DrawableContainer();

        public void Load(System.IO.Stream stream)
        {
            CanSave = true;

            //Set renderer
            //Load it to a drawables list
            Renderer = new MDL_Renderer();
            DrawableContainer.Name = FileName;
            DrawableContainer.Drawables.Add(Renderer);

            //Lets make a new skeleton too
            STSkeleton skeleton = new STSkeleton();

            //Note the bone class will be rewritten soon to be a bit better
            STBone bone = new STBone(skeleton); //Add the skeleton as a paramater
            bone.RotationType = STBone.BoneRotationType.Euler;
            bone.Position = new Vector3(5,0,0);
            bone.Scale = new Vector3(1, 1, 1);
            bone.Rotation =new Vector4(0, 0.5f, 0, 1);
            bone.parentIndex = -1;
            skeleton.bones.Add(bone);

            //Update the skeleton bone matrices
            skeleton.reset();
            skeleton.update();

            //Create a renderable object for our mesh
            var renderedMesh = new GenericRenderedObject();
            renderedMesh.ImageKey = "mesh";
            renderedMesh.SelectedImageKey = "mesh";
            renderedMesh.Checked = true;

            //Load vertices
            for (int v = 0; v < 100; v++)
            {
                Vertex vert = new Vertex();
                vert.pos = new Vector3(1,5,1);
                vert.nrm = new Vector3(1, 0, 1);
                vert.uv0 = new Vector2(1, 0);
                renderedMesh.vertices.Add(vert);
            }

            ushort[] Indices = new ushort[] { 0, 1, 2, 3, 4, 5, 6 };

            //Faces are stored in polygon groups allowing to specifically map materials to certain groups
            renderedMesh.PolygonGroups = new List<STGenericPolygonGroup>();
            var polygonGroup = new STGenericPolygonGroup();

            for (int f = 0; f < Indices.Length; f++)
            {
                polygonGroup.faces.AddRange(new int[3]
                {
                           Indices[f++],
                           Indices[f++],
                           Indices[f]
                });
            }

            renderedMesh.PolygonGroups.Add(polygonGroup);
            renderedMesh.Text = $"Mesh 0";
            Nodes.Add(renderedMesh);
            Renderer.Meshes.Add(renderedMesh);
        }
        public void Unload()
        {

        }
        public byte[] Save()
        {
            return null;
        }

        public class MaterialTextureMap : STGenericMatTexture
        {
            //The index of a texture
            //Some formats will map them by index, some by name, some by a hash, it's up to how the user handles it
            public int TextureIndex { get; set; }
        }

        public class MDL_Renderer : GenericModelRenderer
        {
            //A list of textures to display on the model
            public List<STGenericTexture> TextureList = new List<STGenericTexture>();

            public override void OnRender(GLControl control)
            {
                //Here we can add things on each frame rendered
            }

            //Render data to display by per material and per mesh
            public override void SetRenderData(STGenericMaterial mat, ShaderProgram shader, STGenericObject m)
            {
            }

            //Custom bind texture method
            public override int BindTexture(STGenericMatTexture tex, ShaderProgram shader)
            {
                //By default we bind to the default texture to use
                //This will be used if no texture is found
                GL.ActiveTexture(TextureUnit.Texture0 + tex.textureUnit + 1);
                GL.BindTexture(TextureTarget.Texture2D, RenderTools.defaultTex.RenderableTex.TexID);

                string activeTex = tex.Name;

                //We want to cast our custom texture map class to get any custom properties we may need
                //If you don't need any custom way of mapping, you can just stick with the generic one
                var matTexture = (MaterialTextureMap)tex;

                //Go through our texture maps in the material and see if the index matches
                foreach (var texture in TextureList)
                {
                    if (TextureList.IndexOf(texture) == matTexture.TextureIndex)
                    {
                        BindGLTexture(tex, shader, TextureList[matTexture.TextureIndex]);
                        return tex.textureUnit + 1;
                    }

                    //You can also check if the names match
                    if (texture.Text == tex.Name)
                    {
                        BindGLTexture(tex, shader, TextureList[matTexture.TextureIndex]);
                        return tex.textureUnit + 1;
                    }
                }

                //Return our texture uint id. 
                return tex.textureUnit + 1;
            }
        }
    }
}

`