0
Dvelopment : Custom Model File Format (Rendering)
KillzXGaming edited this page 2020-03-24 18:59:39 -04:00
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;
}
}
}
}
`