SpiderPig Posted February 10, 2023 Share Posted February 10, 2023 In Leadwerks I used to be able to make a player controller and turn off gravity for that entity and just use AddForce() for my own gravity system. I didn't see a problem with doing it this way for rigid bodies, but I never did think it was a good idea for the character controller. Doesn't seem to work in Ultra anyway and in all fairness that's okay because I am going to have to make my own controller I think. I'm going to post a few attempts here and see if I can't finally get this to work the way I want! This used to work in Leadwerks: #include "UltraEngine.h" using namespace UltraEngine; int main(int argc, const char* argv[]) { auto displays = GetDisplays(); auto window = CreateWindow("Ultra Engine", 0, 0, 800, 600, displays[0]); auto framebuffer = CreateFramebuffer(window); auto world = CreateWorld(); auto camera = CreateCamera(world); camera->Move(0, 2, -3); camera->SetClearColor(1, 0, 0); auto light = CreateDirectionalLight(world); light->SetRotation(35, 35, 35); auto floor = CreateBox(world, 100.0f, 0.5f, 100.0f); auto default_font = LoadFont("Fonts\\arial.ttf"); auto ui = CreateInterface(world, default_font, framebuffer->size); ui->SetRenderLayers(2); ui->root->SetColor(0.0f, 0.0f, 0.0f, 0.0f); auto ui_camera = CreateCamera(world, PROJECTION_ORTHOGRAPHIC); ui_camera->SetPosition((float)framebuffer->size.x * 0.5f, (float)framebuffer->size.y * 0.5f, 0); ui_camera->SetRenderLayers(2); ui_camera->SetClearMode(CLEAR_DEPTH); auto m = CreateCylinder(world, 0.5f, 1.8f); m->SetPhysicsMode(PHYSICS_PLAYER); m->SetPosition(0, 5, 0); m->SetMass(1.0f); m->SetGravityMode(false); while (true) { m->AddForce(0.0f, -9.8f, 0.0f); world->Update(); world->Render(framebuffer); } return 0; } Quote Link to comment Share on other sites More sharing options...
Josh Posted February 10, 2023 Share Posted February 10, 2023 1 hour ago, SpiderPig said: ...I am going to have to make my own controller I think. Why? Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
SpiderPig Posted February 10, 2023 Author Share Posted February 10, 2023 I use AddForce() for moving physics bodies toward multiple gravity sources so I need a controller that will respond to that as well as being able to have the up direction dynamically changed. Quote Link to comment Share on other sites More sharing options...
SpiderPig Posted February 11, 2023 Author Share Posted February 11, 2023 The idea here is to switch between a rigid body when physics is needed and a kinematic joint when control is needed. This might end up working but right now the Collide method in the CallbackCollision component is not being called a second time round... If you wait for the player to fall, is_rigid_body will set to False, then hit space to jump, the player will jump and fall again but this time will not trigger the collide method. The component is still attached and is still calling the update method. A bug perhaps or bad coding by me? #include "UltraEngine.h" #include "ComponentSystem.h" using namespace UltraEngine; class Player { public: shared_ptr<World> world = nullptr; shared_ptr<Model> model = nullptr; shared_ptr<Entity> rigid_body, controller_body; shared_ptr<Actor> actor = nullptr; shared_ptr<CollisionCallback> callback = nullptr; shared_ptr<Joint> joint = nullptr; bool is_controlable = false; bool is_rigid_body = false; bool is_airborne = false; Player(shared_ptr<World> world) { this->world = world; model = CreateCylinder(world, 0.5f, 1.8f); model->SetCollider(nullptr); model->SetColor(1, 0, 0); EnableRidgedBody(true); } ~Player() {} void SetPosition(float x, float y, float z) { if (is_rigid_body) { rigid_body->SetPosition(x, y, z); } } void EnableRidgedBody(bool state) { if (state == true) { is_rigid_body = true; is_airborne = true; auto collider = CreateCylinderCollider(0.5f, 1.8f); if (rigid_body == nullptr) { rigid_body = CreatePivot(world); rigid_body->SetShadows(true); rigid_body->SetCollider(collider); rigid_body->SetCollisionType(COLLISION_PLAYER); rigid_body->SetMass(1.0f); actor = CreateActor(rigid_body); callback = actor->AddComponent<CollisionCallback>(); } model->SetParent(rigid_body); } else { is_rigid_body = false; is_airborne = false; model->SetParent(nullptr); model->SetRotation(0.0f, 0.0f, 0.0f); // callback = nullptr; // actor = nullptr; //rigid_body = nullptr; } } void EnableController(bool state) { if (state == true) { is_controlable = true; if (joint == nullptr) { auto pos = model->GetPosition(true); auto col = CreateCylinderCollider(0.5f, 1.8f); controller_body = CreatePivot(world); controller_body->SetShadows(true); controller_body->SetCollider(col); controller_body->SetCollisionType(COLLISION_NONE); controller_body->SetMass(1.0f); controller_body->SetPosition(pos, true); joint = CreateKinematicJoint(pos, controller_body); } model->SetParent(controller_body); } else { // joint = nullptr; // controller_body = nullptr; is_controlable = false; } } void SetInput(float move, float angle) { } void Update() { if (is_airborne == true && callback->collided == true) { auto vel = rigid_body->GetVelocity(true); auto speed_sqr = (vel.x * vel.x) + (vel.y * vel.y) + (vel.z * vel.z); if (speed_sqr < FLT_EPSILON) { callback->collided = false; EnableRidgedBody(false); EnableController(true); } } if (is_controlable == true) { auto target_position = model->GetPosition(true); auto angle = 0.0f; auto up = Vec3(0.0f, 1.0f, 0.0f); auto window = ActiveWindow(); if (window != nullptr) { if (window->KeyDown(KEY_UP)) {} if (window->KeyHit(KEY_SPACE)) { EnableController(false); EnableRidgedBody(true); rigid_body->AddForce(up * 250.0f); } else { joint->SetPose(target_position, Vec3(0.0f)); } } } } }; int main(int argc, const char* argv[]) { auto displays = GetDisplays(); auto window = CreateWindow("Ultra Engine", 0, 0, 1440, 900, displays[0]); auto framebuffer = CreateFramebuffer(window); auto world = CreateWorld(); auto camera = CreateCamera(world); camera->Move(0, 2, -3); camera->SetClearColor(1, 0, 0); auto light = CreateDirectionalLight(world); light->SetRotation(35, 35, 35); auto floor = CreateBox(world, 100.0f, 0.5f, 100.0f); auto default_font = LoadFont("Fonts\\arial.ttf"); auto ui = CreateInterface(world, default_font, framebuffer->size); ui->SetRenderLayers(2); ui->root->SetColor(0.0f, 0.0f, 0.0f, 0.0f); auto ui_camera = CreateCamera(world, PROJECTION_ORTHOGRAPHIC); ui_camera->SetPosition((float)framebuffer->size.x * 0.5f, (float)framebuffer->size.y * 0.5f, 0); ui_camera->SetRenderLayers(2); ui_camera->SetClearMode(CLEAR_DEPTH); auto label = CreateLabel("", 10, 10, 500, 200, ui->root); auto player = make_shared<Player>(world); player->SetPosition(0, 5, 0); while (window->KeyHit(KEY_ESCAPE) == false && window->Closed() == false) { while (PeekEvent()) { ui->ProcessEvent(WaitEvent()); } player->Update(); auto pos = player->model->GetPosition(true); auto rot = player->model->GetRotation(); WString text = "Position : " + String(pos.x) + ", " + String(pos.y) + ", " + String(pos.z) + "\n" + "Rotation : " + String(rot.x) + ", " + String(rot.y) + ", " + String(rot.z) + "\n" + "Rigid Body : " + String(player->is_rigid_body == true ? "True" : "False") + "\n" + "Collide : " + String(player->callback->collided == true ? "True" : "False") + "\n" + "Collision Count : " + String(player->callback->collision_count) + "\n" + "Still Updating : " + String(player->callback->is_updating == true ? "True" : "False"); label->SetText(text); player->callback->is_updating = false; world->Update(); world->Render(framebuffer); } return 0; } Component: #pragma once #include "UltraEngine.h" #include "../ComponentSystem.h" class CollisionCallback : public Component { private: public: bool collided = false, is_updating = false; int collision_count = 0; virtual void Update() { is_updating = true; } virtual void Collide(shared_ptr<Actor> collidedactor, const Vec3& position, const Vec3& normal, const dFloat speed) { collided = true; collision_count++; } }; Quote Link to comment Share on other sites More sharing options...
SpiderPig Posted February 11, 2023 Author Share Posted February 11, 2023 It works flawlessly if I delete the actor and component and then remake them. So I'd say the above post shows a bug in the Collide method. void EnableRidgedBody(bool state) { if (state == true) { is_rigid_body = true; is_airborne = true; auto collider = CreateCylinderCollider(0.5f, 1.8f); if (rigid_body == nullptr) { rigid_body = CreatePivot(world); rigid_body->SetShadows(true); rigid_body->SetCollider(collider); rigid_body->SetCollisionType(COLLISION_PLAYER); rigid_body->SetMass(1.0f); } actor = CreateActor(rigid_body); callback = actor->AddComponent<CollisionCallback>(); model->SetParent(rigid_body); } else { is_rigid_body = false; is_airborne = false; model->SetParent(nullptr); model->SetRotation(0.0f, 0.0f, 0.0f); callback = nullptr; actor = nullptr; } } Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.