feat(part): added balls

This commit is contained in:
maelstrom 2025-07-15 10:30:07 +02:00
parent 8b789fc9b6
commit c944c0cb09
7 changed files with 61 additions and 11 deletions

14
core/src/enum/part.h Normal file
View file

@ -0,0 +1,14 @@
#pragma once
#include "datatypes/enum.h"
#include "enum/annotation.h"
enum class DEF_ENUM PartType {
Ball = 0,
Block = 1,
};
namespace EnumType {
extern const Enum PartType;
};

View file

@ -155,6 +155,10 @@ float BasePart::GetSurfaceParamB(Vector3 face) {
return 0; // Unreachable
}
Vector3 BasePart::GetEffectiveSize() {
return size;
}
bool BasePart::checkJointContinuity(std::shared_ptr<BasePart> otherPart) {
// Make sure that the two parts don't depend on one another

View file

@ -122,6 +122,7 @@ public:
inline SurfaceType GetSurfaceFromFace(NormalId face) { return surfaceFromFace(face); }
float GetSurfaceParamA(Vector3 face);
float GetSurfaceParamB(Vector3 face);
virtual Vector3 GetEffectiveSize();
~BasePart() override;

View file

@ -1,24 +1,42 @@
#include "part.h"
#include "enum/part.h"
#include "physics/util.h"
#include <glm/common.hpp>
Part::Part(): BasePart(&TYPE) {
_lastShape = shape;
_lastSize = size;
}
Part::Part(PartConstructParams params): BasePart(&TYPE, params) {
_lastShape = shape;
_lastSize = size;
}
void Part::updateCollider(rp::PhysicsCommon* common) {
rp::BoxShape* shape = common->createBoxShape(glmToRp(size * glm::vec3(0.5f)));
rp::CollisionShape* physShape;
if (shape == PartType::Ball) {
physShape = common->createSphereShape(glm::min(size.X(), size.Y(), size.Z()) * 0.5f);
} else if (shape == PartType::Block) {
physShape = common->createBoxShape(glmToRp(size * glm::vec3(0.5f)));
}
// Recreate the rigidbody if the shape changes
if (rigidBody->getNbColliders() > 0
&& dynamic_cast<rp::BoxShape*>(rigidBody->getCollider(0)->getCollisionShape())->getHalfExtents() != shape->getHalfExtents()) {
if (rigidBody->getNbColliders() > 0 && (_lastShape != shape || _lastSize != size)) {
// TODO: This causes Touched to get called twice. Fix this.
rigidBody->removeCollider(rigidBody->getCollider(0));
rigidBody->addCollider(shape, rp::Transform());
rigidBody->addCollider(physShape, rp::Transform());
}
if (rigidBody->getNbColliders() == 0)
rigidBody->addCollider(shape, rp::Transform());
rigidBody->addCollider(physShape, rp::Transform());
_lastShape = shape;
_lastSize = size;
}
Vector3 Part::GetEffectiveSize() {
return shape == PartType::Ball ? (Vector3)glm::vec3(glm::min(size.X(), size.Y(), size.Z())) : size;
}

View file

@ -1,11 +1,14 @@
#pragma once
#include "basepart.h"
#include "enum/part.h"
#include "objects/annotation.h"
class DEF_INST Part : public BasePart {
AUTOGEN_PREAMBLE
PartType _lastShape;
Vector3 _lastSize;
protected:
void updateCollider(rp::PhysicsCommon* common) override;
@ -13,6 +16,10 @@ public:
Part();
Part(PartConstructParams params);
DEF_PROP_(on_update=onUpdated) PartType shape = PartType::Block;
Vector3 GetEffectiveSize() override;
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 std::shared_ptr<Instance> Create() { return std::make_shared<Part>(); };

View file

@ -90,7 +90,7 @@ void PartAssembly::TransformBy(CFrame transform) {
}
void PartAssembly::Scale(Vector3 newSize, bool scaleUp) {
if (parts.size() == 1) {
if (parts.size() == 1 && (!parts[0]->IsA<Part>() || parts[0]->CastTo<Part>().expect()->shape != PartType::Ball)) {
parts[0]->size = newSize;
parts[0]->UpdateProperty("Size");
sendPropertyUpdatedSignal(parts[0], "Size", Variant(parts[0]->size));

View file

@ -18,6 +18,7 @@
#include "datatypes/cframe.h"
#include "datatypes/color3.h"
#include "datatypes/vector.h"
#include "enum/part.h"
#include "handles.h"
#include "math_helper.h"
#include "objects/hint.h"
@ -124,8 +125,8 @@ void renderInit(int width, int height) {
static void renderPart(std::shared_ptr<BasePart> part) {
glm::mat4 model = part->cframe;
// if (part->name == "camera") model = camera.getLookAt();
model = glm::scale(model, (glm::vec3)part->size);
Vector3 size = part->GetEffectiveSize();
model = glm::scale(model, (glm::vec3)size);
shader->set("model", model);
shader->set("material", Material {
.diffuse = part->color,
@ -134,7 +135,7 @@ static void renderPart(std::shared_ptr<BasePart> part) {
});
glm::mat3 normalMatrix = glm::mat3(glm::transpose(glm::inverse(model)));
shader->set("normalMatrix", normalMatrix);
shader->set("texScale", part->size);
shader->set("texScale", size);
shader->set("transparency", part->transparency);
shader->set("surfaces[" + std::to_string(NormalId::Right) + "]", (int)part->rightSurface);
@ -144,11 +145,16 @@ static void renderPart(std::shared_ptr<BasePart> part) {
shader->set("surfaces[" + std::to_string(NormalId::Bottom) + "]", (int)part->bottomSurface);
shader->set("surfaces[" + std::to_string(NormalId::Front) + "]", (int)part->frontSurface);
PartType shape = part->IsA<Part>() ? part->CastTo<Part>().expect()->shape : PartType::Block;
if (part->IsA<WedgePart>()) {
glFrontFace(GL_CCW);
WEDGE_MESH->bind();
glDrawArrays(GL_TRIANGLES, 0, WEDGE_MESH->vertexCount);
} else {
} else if (shape == PartType::Ball) { // Part
glFrontFace(GL_CCW);
SPHERE_MESH->bind();
glDrawArrays(GL_TRIANGLES, 0, SPHERE_MESH->vertexCount);
} else if (shape == PartType::Block) {
glFrontFace(GL_CW);
CUBE_MESH->bind();
glDrawArrays(GL_TRIANGLES, 0, CUBE_MESH->vertexCount);