diff --git a/core/src/enum/part.h b/core/src/enum/part.h new file mode 100644 index 0000000..ec27a88 --- /dev/null +++ b/core/src/enum/part.h @@ -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; +}; \ No newline at end of file diff --git a/core/src/objects/part/basepart.cpp b/core/src/objects/part/basepart.cpp index 1cc7604..3cd1163 100644 --- a/core/src/objects/part/basepart.cpp +++ b/core/src/objects/part/basepart.cpp @@ -155,6 +155,10 @@ float BasePart::GetSurfaceParamB(Vector3 face) { return 0; // Unreachable } +Vector3 BasePart::GetEffectiveSize() { + return size; +} + bool BasePart::checkJointContinuity(std::shared_ptr otherPart) { // Make sure that the two parts don't depend on one another diff --git a/core/src/objects/part/basepart.h b/core/src/objects/part/basepart.h index bec89f9..39c700b 100644 --- a/core/src/objects/part/basepart.h +++ b/core/src/objects/part/basepart.h @@ -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; diff --git a/core/src/objects/part/part.cpp b/core/src/objects/part/part.cpp index 83c6e6f..795dbb1 100644 --- a/core/src/objects/part/part.cpp +++ b/core/src/objects/part/part.cpp @@ -1,24 +1,42 @@ #include "part.h" +#include "enum/part.h" #include "physics/util.h" +#include 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(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; + } \ No newline at end of file diff --git a/core/src/objects/part/part.h b/core/src/objects/part/part.h index 851abec..b267969 100644 --- a/core/src/objects/part/part.h +++ b/core/src/objects/part/part.h @@ -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 New() { return std::make_shared(); }; static inline std::shared_ptr New(PartConstructParams params) { return std::make_shared(params); }; static inline std::shared_ptr Create() { return std::make_shared(); }; diff --git a/core/src/partassembly.cpp b/core/src/partassembly.cpp index a1a1a4d..83eefbb 100644 --- a/core/src/partassembly.cpp +++ b/core/src/partassembly.cpp @@ -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() || parts[0]->CastTo().expect()->shape != PartType::Ball)) { parts[0]->size = newSize; parts[0]->UpdateProperty("Size"); sendPropertyUpdatedSignal(parts[0], "Size", Variant(parts[0]->size)); diff --git a/core/src/rendering/renderer.cpp b/core/src/rendering/renderer.cpp index c27d717..b0e08df 100644 --- a/core/src/rendering/renderer.cpp +++ b/core/src/rendering/renderer.cpp @@ -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 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 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 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->CastTo().expect()->shape : PartType::Block; if (part->IsA()) { 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);