feat(part): added aabb calculation

This commit is contained in:
maelstrom 2025-03-29 23:05:35 +01:00
parent 18a1cc79df
commit 3fc20fcd4e
7 changed files with 130 additions and 8 deletions

20
assets/shaders/ghost.fs Normal file
View file

@ -0,0 +1,20 @@
#version 330 core
in vec3 vPos;
in vec3 vNormal;
out vec4 FragColor;
#define NR_POINT_LIGHTS 4
uniform vec3 viewPos;
uniform float transparency;
uniform vec3 color;
// Main
void main() {
FragColor = vec4(color, 1) * (1-transparency);
}

18
assets/shaders/ghost.vs Normal file
View file

@ -0,0 +1,18 @@
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
out vec3 vPos;
out vec3 vNormal;
uniform mat4 model;
uniform mat3 normalMatrix;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0);
vPos = vec3(model * vec4(aPos, 1.0));
vNormal = normalMatrix * aNormal;
}

View file

@ -25,6 +25,7 @@ Data::Vector3::operator glm::vec3() const { return vector; };
Data::Vector3::operator rp::Vector3() const { return rp::Vector3(X(), Y(), Z()); };
// Operators
Data::Vector3 Data::Vector3::operator *(float scale) const {
return Data::Vector3(this->X() * scale, this->Y() * scale, this->Z() * scale);
}
@ -33,6 +34,11 @@ Data::Vector3 Data::Vector3::operator /(float scale) const {
return Data::Vector3(this->X() / scale, this->Y() / scale, this->Z() / scale);
}
// Component-wise
Data::Vector3 Data::Vector3::operator *(Data::Vector3 other) const {
return Data::Vector3(this->X() * other.X(), this->Y() * other.Y(), this->Z() * other.Z());
}
Data::Vector3 Data::Vector3::operator +(Data::Vector3 other) const {
return Data::Vector3(this->X() + other.X(), this->Y() + other.Y(), this->Z() + other.Z());
}

View file

@ -35,6 +35,7 @@ namespace Data {
inline float Z() const { return vector.z; }
inline float Magnitude() const { return glm::length(vector); }
inline Data::Vector3 Unit() const { return glm::normalize(vector); }
inline Data::Vector3 Abs() const { return glm::abs(vector); }
Data::Vector3 Cross(Data::Vector3) const;
float Dot(Data::Vector3) const;
@ -42,6 +43,7 @@ namespace Data {
// Operators
Data::Vector3 operator *(float) const;
Data::Vector3 operator /(float) const;
Data::Vector3 operator *(Data::Vector3) const; // Component-wise
Data::Vector3 operator +(Data::Vector3) const;
Data::Vector3 operator -(Data::Vector3) const;
Data::Vector3 operator -() const;

View file

@ -9,6 +9,8 @@
#include <optional>
#include "physics/simulation.h"
using Data::Vector3;
// template <typename T, typename U>
// constexpr FieldCodec fieldCodecOf() {
// return FieldCodec {
@ -25,7 +27,7 @@ constexpr FieldCodec cframePositionCodec() {
return FieldCodec {
.write = [](Data::Variant source, void* destination) {
Data::CFrame* cframe = static_cast<Data::CFrame*>(destination);
*cframe = cframe->Rotation() + source.get<Data::Vector3>();
*cframe = cframe->Rotation() + source.get<Vector3>();
},
.read = [](void* source) -> Data::Variant {
return *static_cast<Data::CFrame*>(source);
@ -37,7 +39,7 @@ constexpr FieldCodec cframeRotationCodec() {
return FieldCodec {
.write = [](Data::Variant source, void* destination) {
Data::CFrame* cframe = static_cast<Data::CFrame*>(destination);
*cframe = Data::CFrame::FromEulerAnglesXYZ(source.get<Data::Vector3>()) + cframe->Position();
*cframe = Data::CFrame::FromEulerAnglesXYZ(source.get<Vector3>()) + cframe->Position();
},
.read = [](void* source) -> Data::Variant {
return static_cast<Data::CFrame*>(source)->ToEulerAnglesXYZ();
@ -71,13 +73,13 @@ Part::Part(PartConstructParams params): Instance(&TYPE), cframe(Data::CFrame(par
.updateCallback = memberFunctionOf(&Part::onUpdated, this)
}}, { "Position", {
.backingField = &cframe,
.type = &Data::Vector3::TYPE,
.type = &Vector3::TYPE,
.codec = cframePositionCodec(),
.updateCallback = memberFunctionOf(&Part::onUpdated, this),
.flags = PropertyFlags::PROP_NOSAVE
}}, { "Rotation", {
.backingField = &cframe,
.type = &Data::Vector3::TYPE,
.type = &Vector3::TYPE,
.codec = cframeRotationCodec(),
.updateCallback = memberFunctionOf(&Part::onUpdated, this),
.flags = PropertyFlags::PROP_NOSAVE
@ -88,8 +90,8 @@ Part::Part(PartConstructParams params): Instance(&TYPE), cframe(Data::CFrame(par
.updateCallback = memberFunctionOf(&Part::onUpdated, this),
}}, { "Size", {
.backingField = &size,
.type = &Data::Vector3::TYPE,
.codec = fieldCodecOf<Data::Vector3, glm::vec3>(),
.type = &Vector3::TYPE,
.codec = fieldCodecOf<Vector3, glm::vec3>(),
.updateCallback = memberFunctionOf(&Part::onUpdated, this)
}}, { "Color", {
.backingField = &color,
@ -122,4 +124,32 @@ void Part::OnParentUpdated(std::optional<std::shared_ptr<Instance>> oldParent, s
void Part::onUpdated(std::string property) {
syncPartPhysics(std::dynamic_pointer_cast<Part>(this->shared_from_this()));
}
// Expands provided extents to fit point
static void expandMaxExtents(Vector3* min, Vector3* max, Vector3 point) {
*min = Vector3(glm::min(min->X(), point.X()), glm::min(min->Y(), point.Y()), glm::min(min->Z(), point.Z()));
*max = Vector3(glm::max(max->X(), point.X()), glm::max(max->Y(), point.Y()), glm::max(max->Z(), point.Z()));
}
static Vector3 verts[8] {
{-1, -1, -1},
{-1, -1, 1},
{-1, 1, -1},
{-1, 1, 1},
{1, -1, -1},
{1, -1, 1},
{1, 1, -1},
{1, 1, 1},
};
Vector3 Part::GetAABB() {
Vector3 min(0, 0, 0);
Vector3 max(0, 0, 0);
for (Vector3 vert : verts) {
Vector3 worldVert = this->cframe.Rotation() * ((Data::Vector3)this->size * vert);
expandMaxExtents(&min, &max, worldVert);
}
return (min - max).Abs() / 2;
}

View file

@ -48,4 +48,7 @@ public:
virtual const InstanceType* GetClass() override;
inline Data::Vector3 position() { return cframe.Position(); }
// Calculate size of axis-aligned bounding box
Data::Vector3 GetAABB();
};

View file

@ -29,6 +29,7 @@ Shader* shader = NULL;
Shader* skyboxShader = NULL;
Shader* handleShader = NULL;
Shader* identityShader = NULL;
Shader* ghostShader = NULL;
extern Camera camera;
Skybox* skyboxTexture = NULL;
Texture3D* studsTexture = NULL;
@ -63,6 +64,7 @@ void renderInit(GLFWwindow* window, int width, int height) {
skyboxShader = new Shader("assets/shaders/skybox.vs", "assets/shaders/skybox.fs");
handleShader = new Shader("assets/shaders/handle.vs", "assets/shaders/handle.fs");
identityShader = new Shader("assets/shaders/identity.vs", "assets/shaders/identity.fs");
ghostShader = new Shader("assets/shaders/ghost.vs", "assets/shaders/ghost.fs");
}
void renderParts() {
@ -126,7 +128,7 @@ void renderParts() {
sorted[distance] = part;
} else {
glm::mat4 model = part->cframe;
if (part->name == "camera") model = camera.getLookAt();
// if (part->name == "camera") model = camera.getLookAt();
model = glm::scale(model, part->size);
shader->set("model", model);
shader->set("material", Material {
@ -149,7 +151,7 @@ void renderParts() {
for (std::map<float, std::shared_ptr<Part>>::reverse_iterator it = sorted.rbegin(); it != sorted.rend(); it++) {
std::shared_ptr<Part> part = it->second;
glm::mat4 model = part->cframe;
if (part->name == "camera") model = camera.getLookAt();
// if (part->name == "camera") model = camera.getLookAt();
model = glm::scale(model, part->size);
shader->set("model", model);
shader->set("material", Material {
@ -256,6 +258,45 @@ void renderHandles() {
}
}
void renderAABB() {
glDepthMask(GL_TRUE);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CW);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Use shader
ghostShader->use();
// view/projection transformations
glm::mat4 projection = glm::perspective(glm::radians(45.f), (float)viewportWidth / (float)viewportHeight, 0.1f, 1000.0f);
glm::mat4 view = camera.getLookAt();
ghostShader->set("projection", projection);
ghostShader->set("view", view);
// Pass in the camera position
ghostShader->set("viewPos", camera.cameraPos);
ghostShader->set("transparency", 0.5f);
ghostShader->set("color", glm::vec3(1.f, 0.f, 0.f));
// Sort by nearest
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 = Data::CFrame::IDENTITY + part->cframe.Position();
printf("AABB is supposedly (%f, %f, %f)\n", part->GetAABB().X(), part->GetAABB().Y(), part->GetAABB().Z());
model = glm::scale(model, (glm::vec3)part->GetAABB());
ghostShader->set("model", model);
glm::mat3 normalMatrix = glm::mat3(glm::transpose(glm::inverse(model)));
ghostShader->set("normalMatrix", normalMatrix);
CUBE_MESH->bind();
glDrawArrays(GL_TRIANGLES, 0, CUBE_MESH->vertexCount);
}
}
void render(GLFWwindow* window) {
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@ -263,6 +304,8 @@ void render(GLFWwindow* window) {
renderSkyBox();
renderHandles();
renderParts();
// TODO: Make this a debug flag
// renderAABB();
}
void setViewport(int width, int height) {