From 14ed96161dc7ad99f9d8fe85a5c42d814951e675 Mon Sep 17 00:00:00 2001 From: Dane Johnson Date: Tue, 26 Jan 2021 16:42:28 -0600 Subject: [PATCH] Begin refactor, add documentation --- CMakeLists.txt | 50 +++------------- core/CMakeLists.txt | 84 +++++++++++++++++++++++++++ core/Node.cpp | 47 +++++++++------ core/Node.h | 93 ++++++++++++++++++++++++++++-- core/Scripting/Lua.cpp | 1 + core/Scripting/Lua.h | 3 +- core/Scripting/ScriptingLanguage.h | 2 +- core/Shaders/Shader.h | 6 +- core/Shaders/SkyboxShader.h | 2 +- core/Util.h | 2 +- core/couch.cpp | 11 ++-- demo/main.lua | 31 +++++----- roadmap.md | 16 +++-- scripting/CMakeLists.txt | 22 +++++++ thirdparty/CMakeLists.txt | 9 +-- 15 files changed, 274 insertions(+), 105 deletions(-) create mode 100644 core/CMakeLists.txt create mode 100644 scripting/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b438ef..b39097b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,56 +2,20 @@ cmake_minimum_required(VERSION 3.13) project(Couch) set(CMAKE_MODULE_PATH, ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR/cmake.}) -## Find OPENGL packages -find_package(OpenGL REQUIRED) -find_package(GLEW REQUIRED) -find_package(glfw3 3.3 REQUIRED) - -## Find SWIG -find_package(SWIG REQUIRED) - -## Find Bullet -find_package(Bullet REQUIRED) -include_directories(${BULLET_INCLUDE_DIRS}) - -## Find Lua -find_package(Lua REQUIRED) - -file(GLOB_RECURSE sources core/*.cpp core/*.h) - add_compile_definitions(LUA_SCRIPTING) -add_executable(couch ${sources}) -include_directories(core) -if(NOT WIN32) - target_link_libraries(couch glfw) -endif() -target_link_libraries(couch OpenGL::GL) -target_link_libraries(couch GLEW::GLEW) -target_link_libraries(couch ${LUA_LIBRARIES}) -target_link_libraries(couch ${BULLET_LIBRARIES}) +add_executable(couch core/couch.cpp) -include(UseSWIG) -set_property(SOURCE scripting/couch.i PROPERTY CPLUSPLUS ON) -if (NOT WIN32) -swig_add_library(couchlua - TYPE SHARED - LANGUAGE lua - SOURCES scripting/couch.i scripting/lua/helpers.i) -else() - swig_add_library(couchlua - TYPE STATIC - LANGUAGE lua - SOURCES scripting/couch.i scripting/lua/helpers.i) -endif() +add_subdirectory(core) +target_link_libraries(couch couchlib) -target_link_libraries(couchlua ${LUA_LIBRARIES}) +add_subdirectory(scripting) target_link_libraries(couch couchlua) add_subdirectory(thirdparty) add_subdirectory(shaders) -add_dependencies(couch shader_headers) -target_include_directories(couch +add_dependencies(couchlib shader_headers) +target_include_directories(couchlib PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/shaders/") if(WIN32) @@ -60,4 +24,4 @@ if(WIN32) set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++") endif(WIN32) -install(TARGETS couch couchlua) +install(TARGETS couch couchlib couchlua) diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt new file mode 100644 index 0000000..d1b3727 --- /dev/null +++ b/core/CMakeLists.txt @@ -0,0 +1,84 @@ +project(Couch) + +## Find OPENGL packages +find_package(OpenGL REQUIRED) +find_package(GLEW REQUIRED) +find_package(glfw3 3.3 REQUIRED) + +## Find Bullet +find_package(Bullet REQUIRED) + +## Find Lua +find_package(Lua REQUIRED) + +add_library(couchlib SHARED) +target_sources(couchlib PUBLIC + Camera.h + Camera.cpp + CollisionShape.h + CollisionShape.cpp + constants.h + Index.h + Index.cpp + Input.h + Input.cpp + Light.h + Light.cpp + Material.h + Material.cpp + Mesh.h + Mesh.cpp + Node.h + Node.cpp + Rigidbody.h + Rigidbody.cpp + Screen.h + Screen.cpp + Skybox.h + Skybox.cpp + Spatial.h + Spatial.cpp + Transform.h + Transform.cpp + types.h + types.cpp + Util.h + Util.cpp + Vertex.h + Vertex.cpp + World.h + World.cpp + Scripting/Lua.h + Scripting/Lua.cpp + Scripting/ScriptingLanguage.h + Scripting/ScriptingLanguage.cpp + Shaders/FlatShader.h + Shaders/FlatShader.cpp + Shaders/ScreenShader.h + Shaders/ScreenShader.cpp + Shaders/Shader.h + Shaders/Shader.cpp + Shaders/SkyboxShader.h + Shaders/SkyboxShader.cpp) + +target_include_directories(couchlib + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}) + +target_include_directories(couchlib + PUBLIC + ${BULLET_INCLUDE_DIRS}) + +if(NOT WIN32) + target_link_libraries(couchlib glfw) +endif() +target_link_libraries(couchlib OpenGL::GL) +target_link_libraries(couchlib GLEW::GLEW) +target_link_libraries(couchlib ${LUA_LIBRARIES}) +target_link_libraries(couchlib ${BULLET_LIBRARIES}) + +## Add documentation +find_package(Doxygen REQUIRED + OPTIONAL_COMPONENTS dot mscgen dia) +doxygen_add_docs(Node.h) + diff --git a/core/Node.cpp b/core/Node.cpp index 263cb6c..ff0bbe5 100644 --- a/core/Node.cpp +++ b/core/Node.cpp @@ -1,18 +1,37 @@ #include "Node.h" #include "Util.h" +void NodeList::Append(Node *node) { + if (this->isPrefabList and not node->isPrefab) { + Util::Die("Attempt to add instanced node to prefab list!"); + } + if (node->isPrefab and not this->isPrefabList) { + Util::Die("Attempt to add prefab node to instanced list!"); + } + push_back(node); +} + +bool NodeList::IsPrefabList() { + return isPrefabList; +} + Name Node::GetType() const {return "Node";} -Node *Node::root = {Node().Instance()}; +bool Node::IsPrefab() { + return isPrefab; +} + +NodeList Node::GetChildren() { + return children; +} + +void Node::AddChild(Node *child) { + children.Append(child); +} + Node *Node::GetRoot() { return root; } -bool Node::IsDrawable() const { - return false; -} -bool Node::IsTransformable() const { - return false; -} Node* Node::Create() { return new Node; @@ -23,13 +42,13 @@ Node* Node::Duplicate() { } Node* Node::Instance() { - if (not this->isPrefab) { + if (not isPrefab) { Util::Die("Attempt to instance an instanced node!"); } Node* instance = Duplicate(); instance->isPrefab = false; - instance->children = NodeList(); instance->children.isPrefabList = false; + // Instance the children to the instanced list for (Node *child : children) { instance->children.Append(child->Instance()); } @@ -37,12 +56,4 @@ Node* Node::Instance() { return instance; } -void NodeList::Append(Node *node) { - if (this->isPrefabList and not node->isPrefab) { - Util::Die("Attempt to add instanced node to prefab list!"); - } - if (node->isPrefab and not this->isPrefabList) { - Util::Die("Attempt to add prefab node to instanced list!"); - } - push_back(node); -} +Node *Node::root = {Node().Instance()}; diff --git a/core/Node.h b/core/Node.h index ad6b4b9..13aa358 100644 --- a/core/Node.h +++ b/core/Node.h @@ -1,3 +1,26 @@ +/** + @file + @author Dane Johnson + + @section LICENSE + + Couch Copyright (C) 2021 Dane Johnson + This program comes with ABSOLUTELY NO WARRANTY; without event the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public LICENSE for details at + https://www.gnu.org/licenses/gpl-3.0.html + + This is free software, and you are welcome to redistribute it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + @section DESCRIPTION + + Node is the parent class for all classes that would be in the scene + tree. The root of the scene tree is always a node. +*/ + #ifndef NODE_H #define NODE_H @@ -6,26 +29,84 @@ #include "types.h" class Node; // Forwards declare +/** + A list of nodes, tagged as either a list of prefabs + or a list of instanced nodes. +*/ class NodeList : public std::vector { public: + /** + Add a node to this list, will check if it is a prefab + or an instance. + @param node The node to add + */ void Append(Node *node); + /** + Whether or not this is a list of prefabs + @returns true if this is a prefab list, + false if it is an instanced list. + */ + bool IsPrefabList(); private: bool isPrefabList = true; friend class Node; }; +/** + The parent class for any object that will go into the scene tree +*/ class Node { public: - NodeList children; - static Node *GetRoot(); - virtual bool IsDrawable() const; - virtual void Draw() {}; - virtual bool IsTransformable() const; virtual Name GetType() const; + + /** + Whether or not this object is a prefab, that is, if it is + an object being set up to be instanced one or more times. + The alternative to being a prefab is being instanced, in which + case it will be drawn, added to the physics system, etc. + @return true if the object is a prefab, false if it is instanced. + */ + bool IsPrefab(); + /** + Returns the children of this node + @return The list of children + */ + NodeList GetChildren(); + /** + Adds a node to this nodes list of children + @param child The node to add + */ + void AddChild(Node *child); + + /** + Gets the root of the game scene tree + @return The root node + */ + static Node *GetRoot(); + /** + Allocates a new "default" version of this node. + @return A reference to the node. + */ + virtual Node* Create(); - virtual Node* Instance(); + /** + Copies the properties of this node to a newly allocated node, + created via @ref Create. Subclasses should override this to copy + additional class attributes + @return A reference to the duplicate + */ virtual Node* Duplicate(); + /** + Creates an instanced version of this node, by calling @ref Duplicate. + Subclasses should override this to perform neccesary tasks for + instantiation, i.e. adding a physic object to the physics world. + Any children of this node will also be instanced. + @return an instanced version of this node. + */ + virtual Node* Instance(); + private: + NodeList children; static Node *root; bool isPrefab = true; friend class NodeList; diff --git a/core/Scripting/Lua.cpp b/core/Scripting/Lua.cpp index 25aa53e..da41237 100644 --- a/core/Scripting/Lua.cpp +++ b/core/Scripting/Lua.cpp @@ -1,4 +1,5 @@ #include "Lua.h" +#include "../Util.h" #ifdef LUA_SCRIPTING diff --git a/core/Scripting/Lua.h b/core/Scripting/Lua.h index 7ce0913..d19392f 100644 --- a/core/Scripting/Lua.h +++ b/core/Scripting/Lua.h @@ -1,8 +1,7 @@ #ifndef LUA_H #define LUA_H -#include "Input.h" -#include "Util.h" +#include "../Input.h" #ifdef LUA_SCRIPTING // Lua includes diff --git a/core/Scripting/ScriptingLanguage.h b/core/Scripting/ScriptingLanguage.h index 2b7a45f..5491900 100644 --- a/core/Scripting/ScriptingLanguage.h +++ b/core/Scripting/ScriptingLanguage.h @@ -1,7 +1,7 @@ #ifndef SCRIPTINGLANGUAGE_H #define SCRIPTINGLANGUAGE_H -#include "types.h" +#include "../types.h" class ScriptingLanguage { public: diff --git a/core/Shaders/Shader.h b/core/Shaders/Shader.h index 1048565..619dd73 100644 --- a/core/Shaders/Shader.h +++ b/core/Shaders/Shader.h @@ -3,9 +3,9 @@ #include -#include "types.h" -#include "Material.h" -#include "Light.h" +#include "../types.h" +#include "../Material.h" +#include "../Light.h" class Shader { public: diff --git a/core/Shaders/SkyboxShader.h b/core/Shaders/SkyboxShader.h index 2c7ec29..2a555c2 100644 --- a/core/Shaders/SkyboxShader.h +++ b/core/Shaders/SkyboxShader.h @@ -2,7 +2,7 @@ #define SKYBOXSHADER_H #include "Shader.h" -#include "Skybox.h" +#include "../Skybox.h" class SkyboxShader : public Shader { public: diff --git a/core/Util.h b/core/Util.h index 9335e61..1f9ecd1 100644 --- a/core/Util.h +++ b/core/Util.h @@ -20,7 +20,7 @@ namespace Util { return dynamic_cast(root); } - for (Node *child : root->children) { + for (Node *child : root->GetChildren()) { T* res = FindNodeByType(child, type); if (res) { return res; diff --git a/core/couch.cpp b/core/couch.cpp index 06b011b..2db11e5 100644 --- a/core/couch.cpp +++ b/core/couch.cpp @@ -41,8 +41,8 @@ const int height = 600; Node *root; void render(Node *curr, Shader *shader, Matrix model) { - if (curr->IsTransformable()) { - Spatial *spatial = dynamic_cast(curr); + Spatial *spatial = dynamic_cast(curr); + if (spatial) { model = glm::rotate(model, spatial->transform.rotation.x, Vector3(1.0f, 0.0f, 0.0f)); model = glm::rotate(model, spatial->transform.rotation.y, Vector3(0.0f, 1.0f, 0.0f)); model = glm::rotate(model, spatial->transform.rotation.z, Vector3(0.0f, 0.0f, 1.0f)); @@ -51,11 +51,12 @@ void render(Node *curr, Shader *shader, Matrix model) { shader->UpdateModel(model); shader->UpdateNormal(glm::mat3(glm::transpose(glm::inverse(model)))); } - if (curr->IsDrawable()) { - Mesh *mesh = dynamic_cast(curr); + + Mesh *mesh = dynamic_cast(curr); + if (mesh) { mesh->Draw(shader); } - for (Node *child : curr->children) { + for (Node *child : curr->GetChildren()) { render(child, shader, model); } } diff --git a/demo/main.lua b/demo/main.lua index a1043f1..dc01f5a 100644 --- a/demo/main.lua +++ b/demo/main.lua @@ -38,7 +38,8 @@ function init() light.ambient = 0.2 light.diffuse = 1.0 light.specular = 0.1 - couch.Node.GetRoot().children:Append(light:Instance()) + print(couch.Node.GetRoot().GetChildren) + couch.Node.GetRoot():AddChild(light:Instance()) local skybox = couch.Skybox.FromFiles( "skybox/px.png", @@ -48,7 +49,7 @@ function init() "skybox/pz.png", "skybox/nz.png" ) - couch.Node.GetRoot().children:Append(skybox:Instance()) + couch.Node.GetRoot():AddChild(skybox:Instance()) local physics_ball_prefab = couch.Rigidbody() local physics_ball_mesh = couch.Mesh.FromFile("ball.obj") @@ -56,10 +57,10 @@ function init() material.ambient = BLUE material.diffuse = BLUE physics_ball_mesh:SetMaterial(0, material) - physics_ball_prefab.children:Append(physics_ball_mesh); + physics_ball_prefab:AddChild(physics_ball_mesh); physics_ball_prefab.transform.position = couch.Vector3(0.0, 30.0, -10.0) physics_ball = physics_ball_prefab:Instance() - couch.Node.GetRoot().children:Append(physics_ball) + couch.Node.GetRoot():AddChild(physics_ball) make_ground() @@ -73,10 +74,10 @@ function init() character_body.mass = 1.0 character_body:SetCollisionShape(couch.CapsuleCollisionShape(1.0, 1.0)) character_body:SetCharacter(true) - character_body.children:Append(character_prefab) + character_body:AddChild(character_prefab) character_body.transform.position = couch.Vector3(0.0, 3.0, 0.0) character = character_body:Instance() - couch.Node.GetRoot().children:Append(character) + couch.Node.GetRoot():AddChild(character) local cube_prefab = couch.Mesh.FromFile("cube.obj") material = cube_prefab:GetMaterial(0) @@ -86,21 +87,21 @@ function init() local orbiter = couch.Mesh.FromFile("ball.obj") orbiter.transform.scale = orbiter.transform.scale * 0.25; orbiter.transform:Translate(1.0, 0.0, 0.0) - cube_prefab.children:Append(orbiter) + cube_prefab:AddChild(orbiter) cube = cube_prefab:Instance() - couch.Node.GetRoot().children:Append(cube) + couch.Node.GetRoot():AddChild(cube) local ball_prefab = couch.Mesh.FromFile("ball.obj") material = ball_prefab:GetMaterial(0) ball_prefab:SetMaterial(0, material) ball = ball_prefab:Instance() - couch.Node.GetRoot().children:Append(ball) + couch.Node.GetRoot():AddChild(ball) ball.transform:Translate(0.0, 3.0, 0.0) local trough_prefab = couch.TexturedMesh("trough.obj", "wood_lowres.png") trough = trough_prefab:Instance() - couch.Node.GetRoot().children:Append(trough) + couch.Node.GetRoot():AddChild(trough) trough.transform:Translate(10.0, 0.0, 0.0) local scaffold_prefab = couch.TexturedMesh("scaffold.obj", "grate_floor_lowres.png", "railing.png") @@ -114,7 +115,7 @@ function init() material = scaffold:GetMaterial(1) material.alphaScissor = 0.1 scaffold:SetMaterial(1, material) - couch.Node.GetRoot().children:Append(scaffold) + couch.Node.GetRoot():AddChild(scaffold) scaffold.transform:Translate(-3.0, 3.0, 0.0) local barn_prefab = couch.TexturedMesh("barn.obj", "paintedwood.jpg", "barnroof_lowres.png", "wood_lowres.png") @@ -125,7 +126,7 @@ function init() material = barn:GetMaterial(1) material.cullBack = false barn:SetMaterial(1, material) - couch.Node.GetRoot().children:Append(barn) + couch.Node.GetRoot():AddChild(barn) barn.transform:Translate(-15.0, 0.0, 0.0) end @@ -192,20 +193,20 @@ function make_ground() ground_prefab.transform.scale = couch.Vector3(3.0, 1.0, 3.0) ground = couch.Spatial():Instance() - couch.Node.GetRoot().children:Append(ground) + couch.Node.GetRoot():AddChild(ground) -- Add a collisionshape local ground_shape_prefab = couch.Rigidbody() ground_shape_prefab.mass = 0.0 ground_shape_prefab:SetCollisionShape(couch.BoxCollisionShape(180.0, 1.0, 180.0)) ground_shape_prefab.transform:Translate(0.0, -2.5, 0.0) - ground.children:Append(ground_shape_prefab:Instance()) + ground:AddChild(ground_shape_prefab:Instance()) for x = -20, 20, 1 do for z = -20, 20, 1 do local piece = ground_prefab:Instance() piece.transform.position = couch.Vector3(6.0 * x, -2.0, 6.0 * z) - ground.children:Append(piece) + ground:AddChild(piece) end end end diff --git a/roadmap.md b/roadmap.md index 600f69d..f6a7bd6 100644 --- a/roadmap.md +++ b/roadmap.md @@ -71,7 +71,15 @@ to revert (shitty animation support). There are a number of systems I want to ad ## Physics Yeah sure let's do physics -- [ ] Static, Kinematic and Rigidbodies -- [ ] Collision areas -- [ ] Ray tracing -- [ ] Axis pinning +- [X] Static, Kinematic and Rigidbodies +- [X] Collision areas +- [X] Ray tracing +- [X] Axis pinning + +## Great Refactor +Things are starting to smell, here's what I need to do +- [ ] Replace all public attributes with accessors (on classes) +- [ ] Seperate prefabs from instances +- [ ] Combine related files (shaders) +- [ ] Create a testing suite +- [ ] Have exceptions thrown to Lua if generated from a user program diff --git a/scripting/CMakeLists.txt b/scripting/CMakeLists.txt new file mode 100644 index 0000000..dd78bfd --- /dev/null +++ b/scripting/CMakeLists.txt @@ -0,0 +1,22 @@ +include(UseSWIG) +set_property(SOURCE couch.i PROPERTY CPLUSPLUS ON) +set_property(SOURCE couch.i PROPERTY USE_TARGET_INCLUDE_DIRECTORIES ON) + +if (NOT WIN32) +swig_add_library(couchlua + TYPE SHARED + LANGUAGE lua + SOURCES couch.i lua/helpers.i) +else() + swig_add_library(couchlua + TYPE STATIC + LANGUAGE lua + SOURCES couch.i lua/helpers.i) +endif() + +target_include_directories(couchlua PRIVATE "${PROJECT_SOURCE_DIR}/core") + +swig_link_libraries(couchlua + PRIVATE + couchlib + ${LUA_LIBRARIES}) diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index ea39b72..3576076 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -1,15 +1,12 @@ project(Couch) - ## STB (image) -target_include_directories(couch - PUBLIC stb) -target_include_directories(couchlua +target_include_directories(couchlib PUBLIC stb) ## ASSIMP set(ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT FALSE CACHE BOOL "Turn off all assimp importers") set(ASSIMP_BUILD_OBJ_IMPORTER ON CACHE BOOL "Turn on wavefront importer") add_subdirectory(assimp) -target_link_libraries(couch assimp::assimp) -target_link_libraries(couchlua assimp::assimp) +target_link_libraries(couchlib assimp::assimp) +