Jump to content

Controller Starts with Offset


Go to solution Solved by Josh,

Recommended Posts

Posted

I was seeing issues with setting my player controllers position in game so I tried replicating it the best I could here.  With the setup below, setting the mass causes the height to be offset and the player no longer falls.  I thought I was creating the pivot at a different location from the cylinder but if you hit F5 it shows they are at the same location.  I tried giving the pivot it's own collider, but that did nothing.  I assume PHYSICS_PLAYER has it's own collider anyway.  I also tried removing the floor plane.

EDIT : I solved why it wasn't falling.   Stupid me didn't disable the collider on the 'player' model. ;)

There is still the issue of starting with an offset though.  This is what I was seeing in my larger project.  The position reads as 10 units high however it starts lower than that.  In game I've had to add an arbitrary offset to the players height but that won't do forever.

ControllerOffset_001.thumb.jpg.e20440c3d81655ba4a0f572e1c052f51.jpg

#include "UltraEngine.h"

using namespace UltraEngine;

Vec3 mousepos = Vec3(0.0f);
float move_adjustment = 0.1f;
float move_speed = 1.0f;
float lookspeed = 0.1f;
float looksmoothing = 0.5f;
bool enable_camera = false;

int main(int argc, const char* argv[])
{
    //Get the displays
    auto displays = GetDisplays();

    //Create a window
    auto window = CreateWindow("Ultra Engine", 0, 0, 1280, 720, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR);

    //Create a world
    auto world = CreateWorld();
    world->SetGravity(0.0f, -0.1f, 0.0f);

    //Create a framebuffer
    auto framebuffer = CreateFramebuffer(window);

    //Create a camera
    auto camera = CreateCamera(world);
    camera->SetClearColor(0.125);
    camera->SetFov(70);
    camera->SetPosition(0, 9, -5);

    //Create a light
    auto light = CreateDirectionalLight(world);
    light->SetRotation(35, 45, 0);
    light->SetRange(-10, 10);

    auto floor = CreatePlane(world, 100.0f, 100.0f);

    auto thing = CreateCylinder(world);
    thing->SetColor(1, 0, 0);
    thing->SetPosition(-2.0f, 10.0f, 0.0f);


    auto controller = CreatePivot(world);
    controller->SetPhysicsMode(PHYSICS_PLAYER);
    controller->SetCollisionType(COLLISION_PLAYER);

    auto player = CreateCylinder(world);
    player->SetParent(controller);
    player->SetColor(0, 1, 0);
    player->SetCollider(nullptr);

    controller->SetPosition(2.0f, 10.0f, 0.0f);
    controller->SetMass(1.0f);
    camera->SetParent(controller);

  	//Reads as the set position above, but appears to start at a lower position.  Gravity has been slowed to better see it at startup.
    auto c_pos = controller->GetPosition(true);
    auto p_pos = player->GetPosition(true);
    Print("Controller Position : " + String(c_pos.x) + ", " + String(c_pos.y) + ", " + String(c_pos.z));
    Print("Player Position : " + String(p_pos.x) + ", " + String(p_pos.y) + ", " + String(p_pos.z));

    //Main loop
    while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false)
    {
        if (window->KeyHit(KEY_F2) == true) { camera->SetWireframe(!camera->GetWireframe()); }
        if (window->KeyHit(KEY_F3) == true) { camera->SetDebugPhysicsMode(!camera->GetDebugPhysicsMode()); }
        if (window->KeyHit(KEY_F4) == true) { enable_camera = !enable_camera; }
        if (window->KeyHit(KEY_F5) == true) {
            auto c_pos = controller->GetPosition(true);
            auto p_pos = player->GetPosition(true);

            Print("Controller Position : " + String(c_pos.x) + ", " + String(c_pos.y) + ", " + String(c_pos.z));
            Print("Player Position : " + String(p_pos.x) + ", " + String(p_pos.y) + ", " + String(p_pos.z));
        }

        if (enable_camera) {
            auto _displaySize = window->GetSize();
            float cx = Round((float)_displaySize.x / 2.0f);
            float cy = Round((float)_displaySize.y / 2.0f);

            auto mpos = Vec3(window->GetMousePosition().x, window->GetMousePosition().y, window->GetMousePosition().z);
            window->SetMousePosition(cx, cy);
            mpos = mpos * looksmoothing + mousepos * (1 - looksmoothing);
            auto dx = (mpos.x - cx) * lookspeed;
            auto dy = (mpos.y - cy) * lookspeed;


            auto camrot = camera->GetRotation();
            camrot.x += dy;
            camrot.y += dx;
            camera->SetRotation(camrot);
            mousepos = mpos;

            auto speed = 0.1f;
            if (window->KeyDown(KEY_SHIFT) == true) { speed = speed * 10.0f; }
            if (window->KeyDown(KEY_W) == true) { camera->Move(0, 0, speed); }
            else if (window->KeyDown(KEY_S) == true) { camera->Move(0, 0, -speed); }
            if (window->KeyDown(KEY_A) == true) { camera->Move(-speed, 0, 0); }
            else if (window->KeyDown(KEY_D) == true) { camera->Move(speed, 0, 0); }
        }

        world->Update();
        world->Render(framebuffer);
    }
    return 0;
}

 

  • SpiderPig changed the title to Controller Starts with Offset
  • 2 weeks later...
Posted

The center of the controller is at the foot. The center of a cylinder model is its center. The cylinder model will be offset from the controller pivot by the cylinder height divided by two. Does this address your issue?

#include "UltraEngine.h"

using namespace UltraEngine;

Vec3 mousepos = Vec3(0.0f);
float move_adjustment = 0.1f;
float move_speed = 1.0f;
float lookspeed = 0.1f;
float looksmoothing = 0.5f;
bool enable_camera = false;

int main(int argc, const char* argv[])
{
    //Get the displays
    auto displays = GetDisplays();

    //Create a window
    auto window = CreateWindow("Ultra Engine", 0, 0, 1280, 720, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR);

    //Create a world
    auto world = CreateWorld();
    world->SetGravity(0.0f, -0.1f, 0.0f);

    //Create a framebuffer
    auto framebuffer = CreateFramebuffer(window);

    //Create a camera
    auto camera = CreateCamera(world);
    camera->SetClearColor(0.125);
    camera->SetFov(70);
    camera->SetPosition(0, 2, -5);

    //Create a light
    auto light = CreateDirectionalLight(world);
    light->SetRotation(35, 45, 0);
    light->SetRange(-10, 10);

    auto floor = CreateBox(world, 100.0f, 1, 100.0f);

    auto thing = CreateCylinder(world);
    thing->SetColor(1, 0, 0);
    thing->SetPosition(-2.0f, 10.0f, 0.0f);


    auto controller = CreatePivot(world);
    controller->SetPhysicsMode(PHYSICS_PLAYER);
    controller->SetCollisionType(COLLISION_PLAYER);

    auto player = CreateCylinder(world);
    player->SetParent(controller);
    player->SetPosition(0, 0.5, 0);
    player->SetColor(0, 1, 0);
    player->SetCollider(nullptr);

    controller->SetPosition(2.0f, 10.0f, 0.0f);
    controller->SetMass(1.0f);
    //camera->SetParent(controller);

    //Reads as the set position above, but appears to start at a lower position.  Gravity has been slowed to better see it at startup.
    auto c_pos = controller->GetPosition(true);
    auto p_pos = player->GetPosition(true);
    Print("Controller Position : " + String(c_pos.x) + ", " + String(c_pos.y) + ", " + String(c_pos.z));
    Print("Player Position : " + String(p_pos.x) + ", " + String(p_pos.y) + ", " + String(p_pos.z));

    //Main loop
    while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false)
    {
        if (window->KeyHit(KEY_F2) == true) { camera->SetWireframe(!camera->GetWireframe()); }
        if (window->KeyHit(KEY_F3) == true) { camera->SetDebugPhysicsMode(!camera->GetDebugPhysicsMode()); }
        if (window->KeyHit(KEY_F4) == true) { enable_camera = !enable_camera; }
        if (window->KeyHit(KEY_F5) == true) {
            auto c_pos = controller->GetPosition(true);
            auto p_pos = player->GetPosition(true);

            Print("Controller Position : " + String(c_pos.x) + ", " + String(c_pos.y) + ", " + String(c_pos.z));
            Print("Player Position : " + String(p_pos.x) + ", " + String(p_pos.y) + ", " + String(p_pos.z));
        }

        if (enable_camera) {
            auto _displaySize = window->GetSize();
            float cx = Round((float)_displaySize.x / 2.0f);
            float cy = Round((float)_displaySize.y / 2.0f);

            auto mpos = Vec3(window->GetMousePosition().x, window->GetMousePosition().y, window->GetMousePosition().z);
            window->SetMousePosition(cx, cy);
            mpos = mpos * looksmoothing + mousepos * (1 - looksmoothing);
            auto dx = (mpos.x - cx) * lookspeed;
            auto dy = (mpos.y - cy) * lookspeed;


            auto camrot = camera->GetRotation();
            camrot.x += dy;
            camrot.y += dx;
            camera->SetRotation(camrot);
            mousepos = mpos;

            auto speed = 0.1f;
            if (window->KeyDown(KEY_SHIFT) == true) { speed = speed * 10.0f; }
            if (window->KeyDown(KEY_W) == true) { camera->Move(0, 0, speed); }
            else if (window->KeyDown(KEY_S) == true) { camera->Move(0, 0, -speed); }
            if (window->KeyDown(KEY_A) == true) { camera->Move(-speed, 0, 0); }
            else if (window->KeyDown(KEY_D) == true) { camera->Move(speed, 0, 0); }
        }

        world->Update();
        world->Render(framebuffer);
    }
    return 0;
}

 

  • Thanks 1

My job is to make tools you love, with the features you want, and performance you can't live without.

Posted

Ah that makes sense.  It didn't solve it though.

In your example if you raise the cameras height to 8 you'll be able to see the green player cylinder still starts a few units below the other cylinder even though the console output says there now only 0.5 units apart.

Posted

I think this is due to the fact that Vulkan takes a while to initialize, and the physics simulation is running updates many times before the first frame is rendered.

My job is to make tools you love, with the features you want, and performance you can't live without.

Posted

Is it possible for me to start physics when I want to rather than it being automatic?  I could load all aspects of the game and then after a few frames are rendered start the physics thread.

Posted

Yes, you can wait until the EVENT_STARTRENDERER event occurs before calling World::Update.

  • Thanks 1

My job is to make tools you love, with the features you want, and performance you can't live without.

Posted

I added this before the main loop and it didn't help.  I get about 4k iterations before the loop finishes.

//WHAT FOR THE RENDERER TO START BEFORE STARTING THE GAME
bool started = false;
int it = 0;
while (started == false) {
    world->Render(framebuffer);
    while (PeekEvent()) {
        auto event = WaitEvent();
        if (event.id == EVENT_STARTRENDERER) {
            started = true;
            break;
        }
        it++;
    }
    it++;
}

//Main loop
...

 

Posted

It's also possible that the first frame might take a long time to render, maybe? Try setting it so world:Update only gets called if a key is down.

My job is to make tools you love, with the features you want, and performance you can't live without.

Posted

Yes that made a difference.  I removed the pre-loop check and put the world update into a key hit check.

if (window->KeyHit(KEY_SPACE)) {
    world->Update();
}
world->Render(framebuffer);

Upon loading it is slightly offset up, I believe that's the 0.5 offset.

Offset_001.thumb.jpg.4c1a3e6798edf49ad3cd4b5e085b11bd.jpg

After two key hits the cylinder snaps instantly to the lower position.

Offset_002.thumb.jpg.6cd328b3b26d4969fd91a78a9edf9bfe.jpg

Posted

I don't think so.  The position readout seems to be accurate but the fact that it jumps down like that as soon as it starts updating shouldn't happen I think.  It should start falling slowly from the higher position.

Posted

Okay I got it working.  The physics mode should be set AFTER setting the desired position.  Is this correct or is it a bug?

#include "UltraEngine.h"

using namespace UltraEngine;

Vec3 mousepos = Vec3(0.0f);
float move_adjustment = 0.1f;
float move_speed = 1.0f;
float lookspeed = 0.1f;
float looksmoothing = 0.5f;
bool enable_camera = false;

int main(int argc, const char* argv[])
{
    //Get the displays
    auto displays = GetDisplays();

    //Create a window
    auto window = CreateWindow("Ultra Engine", 0, 0, 1280, 720, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR);

    //Create a world
    auto world = CreateWorld();
    world->SetGravity(0.0f, -0.1f, 0.0f);

    //Create a framebuffer
    auto framebuffer = CreateFramebuffer(window);

    //Create a camera
    auto camera = CreateCamera(world);
    camera->SetClearColor(0.125);
    camera->SetFov(70);
    camera->SetPosition(0, 10, -5);

    //Create a light
    auto light = CreateDirectionalLight(world);
    light->SetRotation(35, 45, 0);
    light->SetRange(-10, 10);

    auto floor = CreateBox(world, 100.0f, 1, 100.0f);

    auto thing = CreateCylinder(world);
    thing->SetColor(1, 0, 0);
    thing->SetPosition(-2.0f, 10.0f, 0.0f);


    auto controller = CreatePivot(world);
    controller->SetCollisionType(COLLISION_PLAYER);
  	//controller->SetPhysicsMode(PHYSICS_PLAYER);

    auto player = CreateCylinder(world);
    player->SetParent(controller);
    player->SetPosition(0, 0.0, 0);
    player->SetColor(0, 1, 0);
    player->SetCollider(nullptr);

    controller->SetPosition(2.0f, 10.0f, 0.0f);
    controller->SetMass(1.0f);
    //camera->SetParent(controller);

    controller->SetPhysicsMode(PHYSICS_PLAYER);
    

    //Reads as the set position above, but appears to start at a lower position.  Gravity has been slowed to better see it at startup.
    auto c_pos = controller->GetPosition(true);
    auto p_pos = player->GetPosition(true);
    auto l_pos = player->GetPosition();
    Print("Controller Position : " + String(c_pos.x) + ", " + String(c_pos.y) + ", " + String(c_pos.z));
    Print("Player Global Position : " + String(p_pos.x) + ", " + String(p_pos.y) + ", " + String(p_pos.z));
    Print("Player Local Position : " + String(l_pos.x) + ", " + String(l_pos.y) + ", " + String(l_pos.z));

   /* bool started = false;
    int it = 0;
    while (started == false) {
        world->Render(framebuffer);
        while (PeekEvent()) {
            auto event = WaitEvent();
            if (event.id == EVENT_STARTRENDERER) {
                started = true;
                break;
            }
            it++;
        }
        it++;
    }*/

    //Main loop
    while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false)
    {

        if (window->KeyHit(KEY_F2) == true) { camera->SetWireframe(!camera->GetWireframe()); }
        if (window->KeyHit(KEY_F3) == true) { camera->SetDebugPhysicsMode(!camera->GetDebugPhysicsMode()); }
        if (window->KeyHit(KEY_F4) == true) { enable_camera = !enable_camera; }
        if (window->KeyHit(KEY_F5) == true) {
            auto c_pos = controller->GetPosition(true);
            auto p_pos = player->GetPosition(true);

            Print("Controller Position : " + String(c_pos.x) + ", " + String(c_pos.y) + ", " + String(c_pos.z));
            Print("Player Position : " + String(p_pos.x) + ", " + String(p_pos.y) + ", " + String(p_pos.z));
        }

        if (enable_camera) {
            auto _displaySize = window->GetSize();
            float cx = Round((float)_displaySize.x / 2.0f);
            float cy = Round((float)_displaySize.y / 2.0f);

            auto mpos = Vec3(window->GetMousePosition().x, window->GetMousePosition().y, window->GetMousePosition().z);
            window->SetMousePosition(cx, cy);
            mpos = mpos * looksmoothing + mousepos * (1 - looksmoothing);
            auto dx = (mpos.x - cx) * lookspeed;
            auto dy = (mpos.y - cy) * lookspeed;


            auto camrot = camera->GetRotation();
            camrot.x += dy;
            camrot.y += dx;
            camera->SetRotation(camrot);
            mousepos = mpos;

            auto speed = 0.1f;
            if (window->KeyDown(KEY_SHIFT) == true) { speed = speed * 10.0f; }
            if (window->KeyDown(KEY_W) == true) { camera->Move(0, 0, speed); }
            else if (window->KeyDown(KEY_S) == true) { camera->Move(0, 0, -speed); }
            if (window->KeyDown(KEY_A) == true) { camera->Move(-speed, 0, 0); }
            else if (window->KeyDown(KEY_D) == true) { camera->Move(speed, 0, 0); }
        }

        //if (window->KeyDown(KEY_SPACE)) {
            world->Update();
        //}
        world->Render(framebuffer);
    }
    return 0;
}

 

  • Solution
Posted

You are correct, this is a bug. I am compiling a new build for you now...

  • Thanks 1

My job is to make tools you love, with the features you want, and performance you can't live without.

  • Josh locked this topic
Guest
This topic is now closed to further replies.
×
×
  • Create New...