feat: Migrated Part to Instance class

This commit is contained in:
maelstrom 2025-01-17 09:24:18 +01:00
parent a6b3247c0c
commit 1daed5bb83
15 changed files with 159 additions and 91 deletions

View file

@ -5,10 +5,10 @@
#include <glm/ext/quaternion_trigonometric.hpp>
#include <glm/ext/vector_float3.hpp>
#include <glm/gtc/quaternion.hpp>
#include <memory>
#include <stdio.h>
#include <vector>
#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<Part> 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> part = std::dynamic_pointer_cast<Part>(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);
}
}

View file

@ -4,7 +4,6 @@
#include <QMouseEvent>
#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);
}
}

View file

@ -1,14 +1,17 @@
#ifndef MAINGLWIDGET_H
#define MAINGLWIDGET_H
#include "objects/part.h"
#include "qevent.h"
#include <QOpenGLWidget>
#include <QWidget>
#include <memory>
class MainGLWidget : public QOpenGLWidget {
public:
MainGLWidget(QWidget *parent = nullptr);
void updateCycle();
std::shared_ptr<Part> lastPart;
protected:
void initializeGL() override;

View file

@ -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();

View file

@ -1,6 +1,8 @@
// TEMPORARY COMMON DATA FOR DIFFERENT INTERNAL COMPONENTS
#include "common.h"
#include <memory>
Camera camera(glm::vec3(0.0, 0.0, 3.0));
std::vector<Part> parts;
//std::vector<Part> parts;
std::shared_ptr<Workspace> workspace = Workspace::New();

View file

@ -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<Part> parts;
extern std::shared_ptr<Workspace> workspace;

View file

@ -28,6 +28,9 @@ public:
void SetParent(std::optional<std::shared_ptr<Instance>> newParent);
std::optional<std::shared_ptr<Instance>> GetParent();
inline const std::vector<std::shared_ptr<Instance>> GetChildren() { return children; }
// Utility functions
inline void AddChild(std::shared_ptr<Instance> object) { children.push_back(object); }
};
typedef std::shared_ptr<Instance> InstanceRef;

View file

@ -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) {
}

View file

@ -2,13 +2,41 @@
#include "base.h"
#include <memory>
#include <glm/glm.hpp>
#include <glm/ext.hpp>
#include "../rendering/material.h"
#include <reactphysics3d/reactphysics3d.h>
namespace rp = reactphysics3d;
// For easy construction from C++. Maybe should be removed?
struct PartConstructParams {
glm::vec3 position;
glm::quat rotation = glm::identity<glm::quat>();
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::quat>();
glm::vec3 scale;
Material material;
bool anchored = false;
rp::RigidBody* rigidBody = nullptr;
Part();
Part(PartConstructParams params);
static inline std::shared_ptr<Part> New() { return std::make_shared<Part>(); };
static inline std::shared_ptr<Part> New(PartConstructParams params) { return std::make_shared<Part>(params); };
static inline InstanceRef CreateGeneric() { return std::make_shared<Part>(); };
virtual InstanceType* GetClass() override;
};

16
src/objects/workspace.cpp Normal file
View file

@ -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_) {
}

16
src/objects/workspace.h Normal file
View file

@ -0,0 +1,16 @@
#pragma once
#include "base.h"
#include <memory>
class Workspace : public Instance {
//private:
public:
static InstanceType* TYPE;
Workspace();
static inline std::shared_ptr<Workspace> New() { return std::make_shared<Workspace>(); };
static inline InstanceRef Create() { return std::make_shared<Workspace>(); };
virtual InstanceType* GetClass() override;
};

View file

@ -1,20 +0,0 @@
#pragma once
#include <glm/ext/matrix_transform.hpp>
#include <glm/fwd.hpp>
#include <glm/gtc/quaternion.hpp>
#include <reactphysics3d/body/RigidBody.h>
#include "rendering/material.h"
namespace rp = reactphysics3d;
struct Part {
glm::vec3 position;
glm::quat rotation = glm::identity<glm::quat>();
glm::vec3 scale;
Material material;
bool anchored = false;
rp::RigidBody* rigidBody = nullptr;
void syncTransforms();
};

View file

@ -1,6 +1,7 @@
#include <cstdio>
#include <glm/ext/matrix_float3x3.hpp>
#include <glm/gtc/quaternion.hpp>
#include <memory>
#include <reactphysics3d/collision/shapes/BoxShape.h>
#include <reactphysics3d/collision/shapes/CollisionShape.h>
#include <reactphysics3d/components/RigidBodyComponents.h>
@ -10,16 +11,14 @@
#include <reactphysics3d/memory/DefaultAllocator.h>
#include <reactphysics3d/memory/MemoryAllocator.h>
#include <reactphysics3d/reactphysics3d.h>
#include <vector>
#include "../part.h"
#include "../common.h"
#include "../objects/part.h"
#include "util.h"
#include "simulation.h"
namespace rp = reactphysics3d;
extern std::vector<Part> 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> 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> part = std::dynamic_pointer_cast<Part>(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());
}
}

View file

@ -1,7 +1,8 @@
#pragma once
#include "../part.h"
#include "../objects/part.h"
#include <memory>
void simulationInit();
void syncPartPhysics(Part& part);
void syncPartPhysics(std::shared_ptr<Part> part);
void physicsStep(float deltaTime);

View file

@ -7,13 +7,15 @@
#include <glm/ext/matrix_transform.hpp>
#include <glm/glm.hpp>
#include <glm/trigonometric.hpp>
#include <memory>
#include <vector>
#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<Part> 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> part = std::dynamic_pointer_cast<Part>(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);