diff --git a/client/src/main.cpp b/client/src/main.cpp index 68df237..42bd0b0 100644 --- a/client/src/main.cpp +++ b/client/src/main.cpp @@ -5,10 +5,10 @@ #include #include #include +#include #include -#include -#include "part.h" +#include "objects/part.h" #include "rendering/renderer.h" #include "physics/simulation.h" #include "camera.h" @@ -25,6 +25,8 @@ void mouseCallback(GLFWwindow* window, double xpos, double ypos); // void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); void mouseButtonCallback(GLFWwindow* window, int button, int action, int mods); +std::shared_ptr lastPart; + int main() { glfwSetErrorCallback(errorCatcher); @@ -41,7 +43,7 @@ int main() { renderInit(window); // Baseplate - parts.push_back(Part { + workspace->AddChild(Part::New({ .position = glm::vec3(0, -5, 0), .rotation = glm::vec3(0), .scale = glm::vec3(512, 1.2, 512), @@ -51,10 +53,9 @@ int main() { .shininess = 32.0f, }, .anchored = true, - }); - syncPartPhysics(parts.back()); + })); - parts.push_back(Part { + workspace->AddChild(lastPart = Part::New({ .position = glm::vec3(0), .rotation = glm::vec3(0), .scale = glm::vec3(4, 1.2, 2), @@ -63,8 +64,13 @@ int main() { .specular = glm::vec3(0.5f, 0.5f, 0.5f), .shininess = 32.0f, } - }); - syncPartPhysics(parts.back()); + })); + + for (InstanceRef inst : workspace->GetChildren()) { + if (inst->GetClass()->className != "Part") continue; + std::shared_ptr part = std::dynamic_pointer_cast(inst); + syncPartPhysics(part); + } float lastTime = glfwGetTime(); do { @@ -109,16 +115,16 @@ void processInput(GLFWwindow* window) { float shiftFactor = (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) ? -0.5 : 0.5; shiftFactor *= deltaTime; if (glfwGetKey(window, GLFW_KEY_X) == GLFW_PRESS) { - parts.back().rotation *= glm::angleAxis(shiftFactor, glm::vec3(1, 0, 0)); - syncPartPhysics(parts.back()); + lastPart->rotation *= glm::angleAxis(shiftFactor, glm::vec3(1, 0, 0)); + syncPartPhysics(lastPart); } if (glfwGetKey(window, GLFW_KEY_Y) == GLFW_PRESS) { - parts.back().rotation *= glm::angleAxis(shiftFactor, glm::vec3(0, 1, 0)); - syncPartPhysics(parts.back()); + lastPart->rotation *= glm::angleAxis(shiftFactor, glm::vec3(0, 1, 0)); + syncPartPhysics(lastPart); } if (glfwGetKey(window, GLFW_KEY_Z) == GLFW_PRESS) { - parts.back().rotation *= glm::angleAxis(shiftFactor, glm::vec3(0, 0, 1)); - syncPartPhysics(parts.back()); + lastPart->rotation *= glm::angleAxis(shiftFactor, glm::vec3(0, 0, 1)); + syncPartPhysics(lastPart); } } } @@ -153,7 +159,7 @@ void mouseButtonCallback(GLFWwindow* window, int button, int action, int mods) { void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) { if (key == GLFW_KEY_F && action == GLFW_PRESS) { - parts.push_back(Part { + workspace->AddChild(lastPart = Part::New({ .position = camera.cameraPos + camera.cameraFront * glm::vec3(3), .rotation = glm::vec3(0), .scale = glm::vec3(1, 1, 1), @@ -162,36 +168,36 @@ void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods .specular = glm::vec3(0.5f, 0.5f, 0.5f), .shininess = 32.0f, } - }); - syncPartPhysics(parts.back()); + })); + syncPartPhysics(lastPart); } float shiftFactor = (mods & GLFW_MOD_SHIFT) ? -0.2 : 0.2; if (mode == 0) { if (key == GLFW_KEY_X && action == GLFW_PRESS) { - parts.back().position.x += shiftFactor; - syncPartPhysics(parts.back()); + lastPart->position.x += shiftFactor; + syncPartPhysics(lastPart); } if (key == GLFW_KEY_Y && action == GLFW_PRESS) { - parts.back().position.y += shiftFactor; - syncPartPhysics(parts.back()); + lastPart->position.y += shiftFactor; + syncPartPhysics(lastPart); } if (key == GLFW_KEY_Z && action == GLFW_PRESS) { - parts.back().position.z += shiftFactor; - syncPartPhysics(parts.back()); + lastPart->position.z += shiftFactor; + syncPartPhysics(lastPart); } } else if (mode == 1) { if (key == GLFW_KEY_X && action == GLFW_PRESS) { - parts.back().scale.x += shiftFactor; - syncPartPhysics(parts.back()); + lastPart->scale.x += shiftFactor; + syncPartPhysics(lastPart); } if (key == GLFW_KEY_Y && action == GLFW_PRESS) { - parts.back().scale.y += shiftFactor; - syncPartPhysics(parts.back()); + lastPart->scale.y += shiftFactor; + syncPartPhysics(lastPart); } if (key == GLFW_KEY_Z && action == GLFW_PRESS) { - parts.back().scale.z += shiftFactor; - syncPartPhysics(parts.back()); + lastPart->scale.z += shiftFactor; + syncPartPhysics(lastPart); } } diff --git a/editor/mainglwidget.cpp b/editor/mainglwidget.cpp index 23b470c..0427a3a 100644 --- a/editor/mainglwidget.cpp +++ b/editor/mainglwidget.cpp @@ -4,7 +4,6 @@ #include #include "GLFW/glfw3.h" -#include "part.h" #include "qcursor.h" #include "qevent.h" #include "qnamespace.h" @@ -81,7 +80,7 @@ void MainGLWidget::keyPressEvent(QKeyEvent* evt) { else if (evt->key() == Qt::Key_D) moveX = -1; if (evt->key() == Qt::Key_F) { - parts.push_back(Part { + workspace->AddChild(lastPart = Part::New({ .position = camera.cameraPos + camera.cameraFront * glm::vec3(3), .rotation = glm::vec3(0), .scale = glm::vec3(1, 1, 1), @@ -90,8 +89,8 @@ void MainGLWidget::keyPressEvent(QKeyEvent* evt) { .specular = glm::vec3(0.5f, 0.5f, 0.5f), .shininess = 32.0f, } - }); - syncPartPhysics(parts.back()); + })); + syncPartPhysics(lastPart); } } diff --git a/editor/mainglwidget.h b/editor/mainglwidget.h index 03932d7..1824780 100644 --- a/editor/mainglwidget.h +++ b/editor/mainglwidget.h @@ -1,14 +1,17 @@ #ifndef MAINGLWIDGET_H #define MAINGLWIDGET_H +#include "objects/part.h" #include "qevent.h" #include #include +#include class MainGLWidget : public QOpenGLWidget { public: MainGLWidget(QWidget *parent = nullptr); void updateCycle(); + std::shared_ptr lastPart; protected: void initializeGL() override; diff --git a/editor/mainwindow.cpp b/editor/mainwindow.cpp index 8543287..2888898 100644 --- a/editor/mainwindow.cpp +++ b/editor/mainwindow.cpp @@ -11,6 +11,7 @@ #include "common.h" #include "physics/simulation.h" +#include "objects/part.h" #include "wayland-pointer-constraints-unstable-v1-client-protocol.h" @@ -25,7 +26,7 @@ MainWindow::MainWindow(QWidget *parent) simulationInit(); // Baseplate - parts.push_back(Part { + workspace->AddChild(ui->mainWidget->lastPart = Part::New({ .position = glm::vec3(0, -5, 0), .rotation = glm::vec3(0), .scale = glm::vec3(512, 1.2, 512), @@ -35,10 +36,10 @@ MainWindow::MainWindow(QWidget *parent) .shininess = 32.0f, }, .anchored = true, - }); - syncPartPhysics(parts.back()); + })); + syncPartPhysics(ui->mainWidget->lastPart); - parts.push_back(Part { + workspace->AddChild(ui->mainWidget->lastPart = Part::New({ .position = glm::vec3(0), .rotation = glm::vec3(0), .scale = glm::vec3(4, 1.2, 2), @@ -47,8 +48,8 @@ MainWindow::MainWindow(QWidget *parent) .specular = glm::vec3(0.5f, 0.5f, 0.5f), .shininess = 32.0f, } - }); - syncPartPhysics(parts.back()); + })); + syncPartPhysics(ui->mainWidget->lastPart); } static std::chrono::time_point lastTime = std::chrono::steady_clock::now(); diff --git a/src/common.cpp b/src/common.cpp index 8803d6c..a0f8d13 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -1,6 +1,8 @@ // TEMPORARY COMMON DATA FOR DIFFERENT INTERNAL COMPONENTS #include "common.h" +#include Camera camera(glm::vec3(0.0, 0.0, 3.0)); -std::vector parts; +//std::vector parts; +std::shared_ptr workspace = Workspace::New(); \ No newline at end of file diff --git a/src/common.h b/src/common.h index b52fa65..efd0d50 100644 --- a/src/common.h +++ b/src/common.h @@ -1,8 +1,8 @@ #pragma once -#include "part.h" +#include "objects/workspace.h" #include "camera.h" // TEMPORARY COMMON DATA FOR DIFFERENT INTERNAL COMPONENTS extern Camera camera; -extern std::vector parts; +extern std::shared_ptr workspace; \ No newline at end of file diff --git a/src/objects/base/instance.h b/src/objects/base/instance.h index 4830698..e979184 100644 --- a/src/objects/base/instance.h +++ b/src/objects/base/instance.h @@ -28,6 +28,9 @@ public: void SetParent(std::optional> newParent); std::optional> GetParent(); inline const std::vector> GetChildren() { return children; } + + // Utility functions + inline void AddChild(std::shared_ptr object) { children.push_back(object); } }; typedef std::shared_ptr InstanceRef; diff --git a/src/objects/part.cpp b/src/objects/part.cpp index e881a8d..3459581 100644 --- a/src/objects/part.cpp +++ b/src/objects/part.cpp @@ -1,4 +1,5 @@ #include "part.h" +#include "base/instance.h" static InstanceType TYPE_ { .super = Instance::TYPE, @@ -14,3 +15,7 @@ InstanceType* Part::GetClass() { Part::Part(): Instance(&TYPE_) { } + +Part::Part(PartConstructParams params): Instance(&TYPE_), position(params.position), rotation(params.rotation), + scale(params.scale), material(params.material), anchored(params.anchored) { +} \ No newline at end of file diff --git a/src/objects/part.h b/src/objects/part.h index 06a282b..c4aed5b 100644 --- a/src/objects/part.h +++ b/src/objects/part.h @@ -2,13 +2,41 @@ #include "base.h" #include +#include +#include +#include "../rendering/material.h" +#include + +namespace rp = reactphysics3d; + +// For easy construction from C++. Maybe should be removed? +struct PartConstructParams { + glm::vec3 position; + glm::quat rotation = glm::identity(); + glm::vec3 scale; + Material material; + + bool anchored = false; +}; class Part : public Instance { public: static InstanceType* TYPE; + // TODO: Switch these over to our dedicated datatypes + glm::vec3 position; + glm::quat rotation = glm::identity(); + glm::vec3 scale; + Material material; + + bool anchored = false; + rp::RigidBody* rigidBody = nullptr; + Part(); + Part(PartConstructParams params); + static inline std::shared_ptr New() { return std::make_shared(); }; + static inline std::shared_ptr New(PartConstructParams params) { return std::make_shared(params); }; static inline InstanceRef CreateGeneric() { return std::make_shared(); }; virtual InstanceType* GetClass() override; }; \ No newline at end of file diff --git a/src/objects/workspace.cpp b/src/objects/workspace.cpp new file mode 100644 index 0000000..594d4b2 --- /dev/null +++ b/src/objects/workspace.cpp @@ -0,0 +1,16 @@ +#include "workspace.h" + +static InstanceType TYPE_ { + .super = Instance::TYPE, + .className = "Workspace", + .constructor = &Workspace::Create, +}; + +InstanceType* Workspace::TYPE = &TYPE_; + +InstanceType* Workspace::GetClass() { + return &TYPE_; +} + +Workspace::Workspace(): Instance(&TYPE_) { +} diff --git a/src/objects/workspace.h b/src/objects/workspace.h new file mode 100644 index 0000000..11a1e09 --- /dev/null +++ b/src/objects/workspace.h @@ -0,0 +1,16 @@ +#pragma once + +#include "base.h" +#include + +class Workspace : public Instance { +//private: +public: + static InstanceType* TYPE; + + Workspace(); + + static inline std::shared_ptr New() { return std::make_shared(); }; + static inline InstanceRef Create() { return std::make_shared(); }; + virtual InstanceType* GetClass() override; +}; \ No newline at end of file diff --git a/src/part.h b/src/part.h deleted file mode 100644 index b1a349e..0000000 --- a/src/part.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include "rendering/material.h" - -namespace rp = reactphysics3d; - -struct Part { - glm::vec3 position; - glm::quat rotation = glm::identity(); - glm::vec3 scale; - Material material; - - bool anchored = false; - rp::RigidBody* rigidBody = nullptr; - - void syncTransforms(); -}; \ No newline at end of file diff --git a/src/physics/simulation.cpp b/src/physics/simulation.cpp index 7343e14..1c43769 100644 --- a/src/physics/simulation.cpp +++ b/src/physics/simulation.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -10,16 +11,14 @@ #include #include #include -#include -#include "../part.h" +#include "../common.h" +#include "../objects/part.h" #include "util.h" #include "simulation.h" namespace rp = reactphysics3d; -extern std::vector parts; - rp::PhysicsCommon physicsCommon; rp::PhysicsWorld* world; @@ -29,35 +28,39 @@ void simulationInit() { world->setGravity(rp::Vector3(0, -196.2, 0)); } -void syncPartPhysics(Part& part) { +void syncPartPhysics(std::shared_ptr part) { glm::mat4 rotMat = glm::mat4(1.0f); - rp::Transform transform(glmToRp(part.position), glmToRp(part.rotation)); - if (!part.rigidBody) { - part.rigidBody = world->createRigidBody(transform); + rp::Transform transform(glmToRp(part->position), glmToRp(part->rotation)); + if (!part->rigidBody) { + part->rigidBody = world->createRigidBody(transform); } else { - part.rigidBody->setTransform(transform); + part->rigidBody->setTransform(transform); } - rp::BoxShape* shape = physicsCommon.createBoxShape(glmToRp(part.scale * glm::vec3(0.5f))); + rp::BoxShape* shape = physicsCommon.createBoxShape(glmToRp(part->scale * glm::vec3(0.5f))); - if (part.rigidBody->getNbColliders() > 0) { - part.rigidBody->removeCollider(part.rigidBody->getCollider(0)); + if (part->rigidBody->getNbColliders() > 0) { + part->rigidBody->removeCollider(part->rigidBody->getCollider(0)); } - if (part.rigidBody->getNbColliders() == 0) - part.rigidBody->addCollider(shape, rp::Transform()); - part.rigidBody->setType(part.anchored ? rp::BodyType::STATIC : rp::BodyType::DYNAMIC); + if (part->rigidBody->getNbColliders() == 0) + part->rigidBody->addCollider(shape, rp::Transform()); + part->rigidBody->setType(part->anchored ? rp::BodyType::STATIC : rp::BodyType::DYNAMIC); } void physicsStep(float deltaTime) { // Step the simulation a few steps world->update(deltaTime / 2); - for (Part& part : parts) { - const rp::Transform& transform = part.rigidBody->getTransform(); - part.position = rpToGlm(transform.getPosition()); + // Naive implementation. Parts are only considered so if they are just under Workspace + // TODO: Add list of tracked parts in workspace based on their ancestry using inWorkspace property of Instance + for (InstanceRef obj : workspace->GetChildren()) { + if (obj->GetClass()->className != "Part") continue; // TODO: Replace this with a .IsA call instead of comparing the class name directly + std::shared_ptr part = std::dynamic_pointer_cast(obj); + const rp::Transform& transform = part->rigidBody->getTransform(); + part->position = rpToGlm(transform.getPosition()); // part.rotation = glm::eulerAngles(rpToGlm(transform.getOrientation())); - part.rotation = rpToGlm(transform.getOrientation()); + part->rotation = rpToGlm(transform.getOrientation()); } } \ No newline at end of file diff --git a/src/physics/simulation.h b/src/physics/simulation.h index d103cc3..f9d4f0a 100644 --- a/src/physics/simulation.h +++ b/src/physics/simulation.h @@ -1,7 +1,8 @@ #pragma once -#include "../part.h" +#include "../objects/part.h" +#include void simulationInit(); -void syncPartPhysics(Part& part); +void syncPartPhysics(std::shared_ptr part); void physicsStep(float deltaTime); \ No newline at end of file diff --git a/src/rendering/renderer.cpp b/src/rendering/renderer.cpp index f42ca5e..480d4df 100644 --- a/src/rendering/renderer.cpp +++ b/src/rendering/renderer.cpp @@ -7,13 +7,15 @@ #include #include #include +#include #include #include "shader.h" #include "mesh.h" #include "defaultmeshes.h" #include "../camera.h" -#include "../part.h" +#include "../common.h" +#include "../objects/part.h" #include "skybox.h" #include "surface.h" #include "texture3d.h" @@ -23,7 +25,6 @@ Shader *shader = NULL; Shader *skyboxShader = NULL; extern Camera camera; -extern std::vector parts; Skybox* skyboxTexture = NULL; Texture3D* studsTexture = NULL; @@ -100,16 +101,20 @@ void renderParts() { // Pass in the camera position shader->set("viewPos", camera.cameraPos); - for (Part part : parts) { + // TODO: Same as todo in src/physics/simulation.cpp + for (InstanceRef inst : workspace->GetChildren()) { + if (inst->GetClass()->className != "Part") continue; + std::shared_ptr part = std::dynamic_pointer_cast(inst); + glm::mat4 model = glm::mat4(1.0f); - model = glm::translate(model, part.position); - model = model * glm::mat4_cast(part.rotation); - model = glm::scale(model, part.scale); + model = glm::translate(model, part->position); + model = model * glm::mat4_cast(part->rotation); + model = glm::scale(model, part->scale); shader->set("model", model); - shader->set("material", part.material); + shader->set("material", part->material); glm::mat3 normalMatrix = glm::mat3(glm::transpose(glm::inverse(model))); shader->set("normalMatrix", normalMatrix); - shader->set("texScale", part.scale); + shader->set("texScale", part->scale); CUBE_MESH->bind(); glDrawArrays(GL_TRIANGLES, 0, 36);