using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Toolbox.Library; using Toolbox.Library.Rendering; using GL_EditorFramework.GL_Core; using GL_EditorFramework.Interfaces; using Bfres.Structs; using OpenTK.Graphics.OpenGL; using OpenTK; namespace FirstPlugin { public class BFRESRenderBase : AbstractGlDrawable, IMeshContainer { public Matrix4 ModelTransform = Matrix4.Identity; // gl buffer objects internal int vbo_position; internal int ibo_elements; public BFRES ResFileNode; public List Meshes { get { List meshes = new List(); for (int m = 0; m < models.Count; m++) { for (int s = 0; s < models[m].shapes.Count; s++) meshes.Add(models[m].shapes[s]); } return meshes; } } private List _models = new List(); public List models { get { return _models; } } internal bool Disposing = false; public void UpdateModelList() { _models.Clear(); foreach (var node in ResFileNode.Nodes) { if (node is BFRESGroupNode && ((BFRESGroupNode)node).Type == BRESGroupType.Models) { foreach (FMDL mdl in ((BFRESGroupNode)node).Nodes) _models.Add(mdl); } } } private void TransformBones() { for (int mdl = 0; mdl < models.Count; mdl++) { for (int b = 0; b < models[mdl].Skeleton.bones.Count; b++) { models[mdl].Skeleton.bones[b].ModelMatrix = ModelTransform; } } } internal void GenerateBuffers() { GL.GenBuffers(1, out vbo_position); GL.GenBuffers(1, out ibo_elements); TransformBones(); UpdateVertexData(); UpdateTextureMaps(); } public void Destroy() { bool buffersWereInitialized = ibo_elements != 0 && vbo_position != 0; if (!buffersWereInitialized) return; GL.DeleteBuffer(vbo_position); GL.DeleteBuffer(ibo_elements); Disposing = true; } public virtual void UpdateVertexData() { } public virtual void UpdateTextureMaps() { if (!Runtime.OpenTKInitialized) return; foreach (BNTX bntx in PluginRuntime.bntxContainers) { if (!bntx.AllGLInitialized) { foreach (var tex in bntx.Textures) { if (tex.Value.RenderableTex != null && !tex.Value.RenderableTex.GLInitialized) tex.Value.LoadOpenGLTexture(); } } } foreach (BFRESGroupNode ftexCont in PluginRuntime.ftexContainers) { foreach (var tex in ftexCont.ResourceNodes) { if (!((FTEX)tex.Value).RenderableTex.GLInitialized) ((FTEX)tex.Value).LoadOpenGLTexture(); } } } public void UpdateSingleMaterialTextureMaps(FMAT mat) { if (!Runtime.OpenTKInitialized) return; foreach (BNTX bntx in PluginRuntime.bntxContainers) { foreach (var t in mat.TextureMaps) { if (bntx.Textures.ContainsKey(t.Name)) { if (!bntx.Textures[t.Name].RenderableTex.GLInitialized) bntx.Textures[t.Name].LoadOpenGLTexture(); } } } LibraryGUI.UpdateViewport(); } public override void Prepare(GL_ControlModern control) { } public override void Prepare(GL_ControlLegacy control) { } public override void Draw(GL_ControlLegacy control, Pass pass) { if (Disposing || pass == Pass.TRANSPARENT) return; bool buffersWereInitialized = ibo_elements != 0 && vbo_position != 0; if (!buffersWereInitialized) GenerateBuffers(); if (!Runtime.OpenTKInitialized) return; Matrix4 mvpMat = control.ModelMatrix * control.CameraMatrix * control.ProjectionMatrix; Matrix4 invertedCamera = Matrix4.Identity; if (invertedCamera.Determinant != 0) invertedCamera = mvpMat.Inverted(); Vector3 lightDirection = new Vector3(0f, 0f, -1f); Vector3 difLightDirection = Vector3.TransformNormal(lightDirection, invertedCamera).Normalized(); GL.Enable(EnableCap.Texture2D); GL.Enable(EnableCap.DepthTest); foreach (var model in models) { foreach (var shape in model.shapes) { if (Runtime.RenderModels && model.Checked && shape.Checked) { var mat = shape.GetMaterial(); List faces = shape.lodMeshes[shape.DisplayLODIndex].getDisplayFace(); GL.Begin(PrimitiveType.Triangles); foreach (var index in faces) { Vertex vert = shape.vertices[index]; float normal = Vector3.Dot(difLightDirection, vert.nrm) * 0.5f + 0.5f; GL.Color3(new Vector3(normal)); GL.TexCoord2(vert.uv0); GL.Vertex3(vert.pos); } GL.End(); } } } GL.Enable(EnableCap.Texture2D); } public void CenterCamera(GL_ControlBase control) { if (!Runtime.FrameCamera) return; var spheres = new List(); for (int mdl = 0; mdl < models.Count; mdl++) { for (int shp = 0; shp < models[mdl].shapes.Count; shp++) { var vertexPositions = models[mdl].shapes[shp].vertices.Select(x => x.pos).Distinct(); spheres.Add(control.GenerateBoundingSphere(vertexPositions)); } } control.FrameSelect(spheres); } public static Vector4 GenerateBoundingSphere(IEnumerable boundingSpheres) { // The initial max/min should be the first point. Vector3 min = boundingSpheres.FirstOrDefault().Xyz - new Vector3(boundingSpheres.FirstOrDefault().W); Vector3 max = boundingSpheres.FirstOrDefault().Xyz + new Vector3(boundingSpheres.FirstOrDefault().W); // Calculate the end points using the center and radius foreach (var sphere in boundingSpheres) { min = Vector3.ComponentMin(min, sphere.Xyz - new Vector3(sphere.W)); max = Vector3.ComponentMax(max, sphere.Xyz + new Vector3(sphere.W)); } return GetBoundingSphereFromSpheres(min, max); } private static Vector4 GetBoundingSphereFromSpheres(Vector3 min, Vector3 max) { Vector3 lengths = max - min; float maxLength = Math.Max(lengths.X, Math.Max(lengths.Y, lengths.Z)); Vector3 center = (max + min) / 2.0f; float radius = maxLength / 2.0f; return new Vector4(center, radius); } public override void Draw(GL_ControlModern control, Pass pass) { } } }