From aafbe087547c69590df61be14bc36e46d186a008 Mon Sep 17 00:00:00 2001
From: Joseph Walton-Rivers <joseph@walton-rivers.uk>
Date: Mon, 18 Apr 2022 14:45:56 +0100
Subject: [PATCH] start work on porting model rendering over to the new API

---
 fggl/gfx/ogl4/models.cpp            | 104 ++++++++++++++++++++++++++++
 include/fggl/ecs3/prototype/world.h |   8 +--
 include/fggl/gfx/ogl/types.hpp      |   1 -
 include/fggl/gfx/ogl4/canvas.hpp    |   4 +-
 include/fggl/gfx/ogl4/models.hpp    |  17 ++++-
 5 files changed, 126 insertions(+), 8 deletions(-)
 create mode 100644 fggl/gfx/ogl4/models.cpp

diff --git a/fggl/gfx/ogl4/models.cpp b/fggl/gfx/ogl4/models.cpp
new file mode 100644
index 0000000..b752d30
--- /dev/null
+++ b/fggl/gfx/ogl4/models.cpp
@@ -0,0 +1,104 @@
+/*
+ * ${license.title}
+ * Copyright (C) 2022 ${license.owner}
+ * ${license.mailto}
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+//
+// Created by webpigeon on 18/04/22.
+//
+
+#include "fggl/gfx/ogl4/models.hpp"
+#include "fggl/gfx/camera.hpp"
+#include <spdlog/spdlog.h>
+
+namespace fggl::gfx::ogl4 {
+
+	void StaticModelRenderer::resolveModels(ecs3::World &world) {
+		// FIXME: this needs something reactive or performance will suck.
+		auto renderables = world.findMatching<StaticModel>();
+
+		for (auto& renderable : renderables){
+			auto currModel = world.get<StaticModel>( renderable );
+			if ( currModel != nullptr ){
+				continue;
+			}
+
+			// no active model, we need to resolve/load one.
+		}
+	}
+
+	void StaticModelRenderer::renderModelsForward(const ecs3::World &world) {
+
+		// fetch cameras we will need to render with
+		auto cameras = world.findMatching<gfx::Camera>();
+
+		// if there are no cameras, we can't do anything...
+		if ( cameras.size() == 0) {
+			spdlog::warn("asked to render static models, but there were no cameras");
+			return;
+		}
+
+		float deltaTime = 0.0f;
+
+		// perform a rendering pass for each camera (will usually only be one...)
+		for ( auto& cameraEnt : cameras ){
+
+			//TODO should be cliping this to only visible objects
+
+			// enable required OpenGL state
+			glEnable( GL_CULL_FACE );
+			glCullFace( GL_BACK );
+
+			// enable depth testing
+			glEnable( GL_DEPTH_TEST );
+
+			// set-up camera matrices
+			auto* const camTransform = world.get<math::Transform>(cameraEnt);
+			auto* const camComp = world.get<gfx::Camera>(cameraEnt);
+
+			math::mat4 projectionMatrix = glm::perspective(camComp->fov, camComp->aspectRatio, camComp->nearPlane, camComp->farPlane);
+			math::mat4 viewMatrix = glm::lookAt( camTransform->origin(), camComp->target, camTransform->up() );
+
+			// TODO lighting needs to not be this...
+			math::vec3 lightPos{1.0f, 1.0f, 1.0f};
+			math::mat4 modelMatrix(1.0f);
+
+			auto renderables = world.findMatching<StaticModel>();
+			for ( const auto& entity : renderables ){
+				auto* transform = world.get<math::Transform>(entity);
+				StaticModel* model = world.get<StaticModel>(entity);
+
+				// grouping by shader would mean we only need to send the model matrix...
+				// TODO clean shader API
+				auto shader = model->pipeline;
+				shader->use();
+				shader->setUniformMtx(shader->uniform("model"), &modelMatrix, 1);
+				shader->setUniformMtx(shader->uniform("view"), &viewMatrix, 1);
+				shader->setUniformMtx(shader->uniform("projection"), &projectionMatrix, 1);
+
+				auto vao = model->vao;
+
+				// TODO support primitive restart/fans/etc...
+				auto elements = model->elements.get();
+				vao->drawElements( *elements, model->drawType, model->elementCount);
+			}
+
+		}
+	}
+
+}
diff --git a/include/fggl/ecs3/prototype/world.h b/include/fggl/ecs3/prototype/world.h
index 97e2d10..26dba7a 100644
--- a/include/fggl/ecs3/prototype/world.h
+++ b/include/fggl/ecs3/prototype/world.h
@@ -54,7 +54,7 @@ namespace fggl::ecs3::prototype {
 			}
 
 			template<typename C>
-			C *get() {
+			C *get() const {
 				void *ptr = m_components.at(Component<C>::typeID());
 				return (C *) ptr;
 			}
@@ -71,7 +71,7 @@ namespace fggl::ecs3::prototype {
 				return comps;
 			}
 
-			bool hasComponents(std::vector<component_type_t> &Cs) {
+			bool hasComponents(std::vector<component_type_t> &Cs) const {
 				for (auto c : Cs) {
 					if (m_components.find(c) == m_components.end()) {
 						return false;
@@ -145,7 +145,7 @@ namespace fggl::ecs3::prototype {
 			}
 
 			template<typename... Cs>
-			std::vector<entity_t> findMatching() {
+			std::vector<entity_t> findMatching() const {
 				// construct the key
 				std::vector<ecs::component_type_t> key;
 				(key.push_back(Component<Cs>::typeID()), ...);
@@ -200,7 +200,7 @@ namespace fggl::ecs3::prototype {
 			}
 
 			template<typename C>
-			C *get(entity_t entity_id) {
+			C *get(entity_t entity_id) const {
 				try {
 					auto &entity = m_entities.at(entity_id);
 					try {
diff --git a/include/fggl/gfx/ogl/types.hpp b/include/fggl/gfx/ogl/types.hpp
index 45d8cf6..5bc8897 100644
--- a/include/fggl/gfx/ogl/types.hpp
+++ b/include/fggl/gfx/ogl/types.hpp
@@ -60,7 +60,6 @@ namespace fggl::gfx::ogl {
 			void use();
 
 			Location uniform(const std::string_view& name) const;
-			Location uniform(const std::string& name) const;
 
 			// primatives
 			void setUniformF(Location name, GLfloat value);
diff --git a/include/fggl/gfx/ogl4/canvas.hpp b/include/fggl/gfx/ogl4/canvas.hpp
index 8ace79c..6908867 100644
--- a/include/fggl/gfx/ogl4/canvas.hpp
+++ b/include/fggl/gfx/ogl4/canvas.hpp
@@ -17,8 +17,8 @@ namespace fggl::gfx::ogl4 {
 
 		private:
 			ogl::VertexArray m_vao;
-			ogl::Buffer<ogl::BufType::ARRAY> m_vertexList;
-			ogl::Buffer<ogl::BufType::ELEMENT_ARRAY> m_indexList;
+			ogl::ArrayBuffer m_vertexList;
+			ogl::ElementBuffer m_indexList;
 	};
 
 } // namespace fggl::gfx::ogl4
diff --git a/include/fggl/gfx/ogl4/models.hpp b/include/fggl/gfx/ogl4/models.hpp
index baabd39..8ae6fa1 100644
--- a/include/fggl/gfx/ogl4/models.hpp
+++ b/include/fggl/gfx/ogl4/models.hpp
@@ -9,10 +9,23 @@
 #include <unordered_map>
 
 #include "fggl/gfx/ogl/backend.hpp"
+#include "fggl/gfx/ogl/types.hpp"
 #include "fggl/ecs3/ecs.hpp"
 
 namespace fggl::gfx::ogl4 {
 
+	struct StaticModel {
+		constexpr static const char name[] = "StaticModel";
+
+		std::shared_ptr<ogl::Shader> pipeline;
+		std::shared_ptr<ogl::VertexArray> vao;
+
+		// element data
+		std::shared_ptr<ogl::ElementBuffer> elements;
+		ogl::Primative drawType;
+		std::size_t elementCount;
+	};
+
 	class StaticModelRenderer {
 		public:
 			StaticModelRenderer() = default;
@@ -40,7 +53,9 @@ namespace fggl::gfx::ogl4 {
 			 */
 			void renderModelsForward(const ecs3::World& world);
 
-			std::unordered_map<std::string, std::shared_ptr<gfx::Shader>> m_shaders;
+			ogl::VertexArray m_vao;
+			ogl::ArrayBuffer m_vertexList;
+			ogl::ElementBuffer m_indexList;
 	};
 
 }
-- 
GitLab