DanielChappuis / reactphysics3d

Open source C++ physics engine library in 3D
http://www.reactphysics3d.com
zlib License
1.54k stars 223 forks source link

Dynamic body behaves weirdly unless created at origin #256

Closed anugentc closed 2 years ago

anugentc commented 2 years ago

Hello, I have a very strange problem. So when I create a cube dynamic rigidbody that is centered at the origin, everything works amazingly. If the static floor is inside it, it will pop out. If the body is above the floor, it will fall and act normally.

good

So it works fine when the cube is at the origin, yet when I move it any amount anywhere on creation, it behaves weirdly. It looks like it bumps into invisible walls and sinks through the floor. It also seems to have a rocking motion when it rests, almost like it's swinging.

bad

This happens in any direction, x, y, or z. It could be something with my quaternions but I'm not sure. IDK if there is something obvious I'm missing, but I've been stuck on it for a while, and any help is appreciated!

The code is a bit sloppy since I'm not too well organized, apologies

rp3d::PhysicsCommon common;

    rp3d::PhysicsWorld::WorldSettings settings;
    settings.defaultVelocitySolverNbIterations = 20; 
    settings.gravity = rp3d::Vector3(0, -9.8, 0); 
    settings.isSleepingEnabled = false;

    rp3d::PhysicsWorld* world;
    world = common.createPhysicsWorld(settings);

    rp3d::Vector3 start(20.0f,0.0f,10.0f);
    rp3d::Vector3 end(20.0f,0.0f,-10.0f);
    rp3d::Ray ray(start,end);

    rp3d::Vector3 Position(0.0f, 2.0f, 0.0f);   //<-      ===Setting this at 2 gives me problems===
    rp3d::Quaternion Orientation = reactphysics3d::Quaternion::identity();
    rp3d::Transform Transform(Position, Orientation);

    const rp3d::Vector3 halfExtents(1.0,1.0,1.0); 
    rp3d::BoxShape* boxShape = common.createBoxShape(halfExtents);
    rp3d::Collider* collider; 
    testBody = world->createRigidBody(Transform);
    testBody->setType(rp3d::BodyType::DYNAMIC);
    testBody->setMass(10.0f);
    collider = testBody->addCollider(boxShape, Transform); 

    rp3d::Vector3 p2(0.0f,-4.0f,0.0f);
    rp3d::Quaternion o2 = reactphysics3d::Quaternion::identity();
    rp3d::Transform t2(p2, o2);

    const rp3d::Vector3 h2(50.0, 6.0, 50.0); 
    rp3d::BoxShape* b2 = common.createBoxShape(h2);
    rp3d::Collider* c2; 
    groundBody = world->createRigidBody(t2);
    groundBody->setType(rp3d::BodyType::STATIC);
    c2 = groundBody->addCollider(b2, t2); 

    ResourceManager::LoadShader("shaders/2d.vert", "shaders/common.frag", nullptr, "sprite");
    glm::mat4 projection = glm::ortho(0.0f, static_cast<GLfloat>(width), static_cast<GLfloat>(height), 0.0f, -1.0f, 1.0f);
    ResourceManager::GetShader("sprite").Use().SetInteger("image", 0);
    ResourceManager::GetShader("sprite").SetMatrix4("projection", projection);
    ResourceManager::LoadTexture("textures/crosshair.png", GL_TRUE, "crosshair");
    Shader shader = ResourceManager::GetShader("sprite");
    SpriteRenderer* Renderer = new SpriteRenderer(shader, 2);

    ResourceManager::LoadShader("shaders/3d.vert", "shaders/common.frag", nullptr, "scene");
    ResourceManager::GetShader("scene").Use().SetInteger("image", 0);
    ResourceManager::LoadTexture("textures/clover.jpg", GL_FALSE, "ground");
    ResourceManager::LoadTexture("textures/dice.jpg", GL_FALSE, "test");
    ResourceManager::LoadTexture("textures/sky.jpg", GL_FALSE, "sky");
    Shader sceneShader = ResourceManager::GetShader("scene");
    SpriteRenderer* Renderer3d = new SpriteRenderer(sceneShader, 3);

    Texture2D crosshair = ResourceManager::GetTexture("crosshair");
    Texture2D ground = ResourceManager::GetTexture("ground");
    Texture2D test = ResourceManager::GetTexture("test");
    Texture2D sky = ResourceManager::GetTexture("sky");

    // A new Renderer of 3d scene is needed

    while(!glfwWindowShouldClose(window))
    {

        frame++;

        float currentFrame = glfwGetTime();
        deltaTime = currentFrame - lastFrame;
        lastFrame = currentFrame;

        accumulator += deltaTime;

        processInput(window);

        glClearColor(0.49f, 0.75f, 0.93f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        // glClear(GL_COLOR_BUFFER_BIT);

        reactphysics3d::Vector3 tmp; float a;

        testBody->getTransform().getOrientation().getRotationAngleAxis(a, tmp);

        const rp3d::Transform& transform = testBody->getTransform();
        const rp3d::Vector3& position = transform.getPosition();
        const rp3d:: Quaternion rot = testBody->getTransform().getOrientation();

        /* glm::vec3 pos = glm::vec3(testBody->getTransform().getPosition().x,
            testBody->getTransform().getPosition().y,
            testBody->getTransform().getPosition().z); */

        //glm::quat rotationz = glm::quat(testBody->getTransform().getOrientation().w, testBody->getTransform().getOrientation().x, 
            //testBody->getTransform().getOrientation().y, testBody->getTransform().getOrientation().z);

        glm::mat4 view = camera.GetViewMatrix();
        glm::mat4 proj = glm::perspective(glm::radians(camera.Zoom), (float)width/height, 0.1f, 1000.0f);
        // glm::mat4 proj = glm::ortho(0.0f, static_cast<GLfloat>(width), static_cast<GLfloat>(height), 0.0f, -1.0f, 1.0f);

        Renderer3d->DrawSprite(ground, glm::vec3(0, -2, 0), glm::vec3(1,1,1), 0, glm::vec3(0.0f, 1.0f, 0.0f), view, proj,0);
        //Renderer3d->DrawSprite(sky, glm::vec3(0, 80, 0), glm::vec3(100,100,100), 0, glm::vec3(1.0f, 1.0f, 1.0f), view, proj,1);

        Renderer3d->DrawSprite(test, glm::vec3(position.x, position.y, position.z), glm::vec3(1,1,1), a,glm::quat(rot.w,rot.x,rot.y,rot.z), view, proj,2);

        Renderer->DrawSprite(crosshair, glm::vec2(width/2-40, height/2-40), glm::vec2(80, 80));

        //world->raycast(ray, &rp3d::RaycastCallback);

        num+=.001;
        glfwSwapBuffers(window);
        glfwPollEvents();

        if(testBody->getTransform().getPosition().y < -50){
            testBody->setLinearVelocity(rp3d::Vector3(0.0f,0.0f,0.0f));
            testBody->setAngularVelocity(rp3d::Vector3(0.0f,0.0f,0.0f));
            testBody->setTransform(Transform);
        }

        while(accumulator >= timeStep){

            world->update(timeStep);
            accumulator -= timeStep;
        }

    }
anugentc commented 2 years ago

NEVERMIND! I'm an idiot. What I was doing was assigning the transform for the collision object as the transform from the rigidbody itself. That's why it only worked at the origin, since the collisionbody needed to be transform::identity(). Guess that's what I get for not reading the docs closely enough lol. Closing this now.

DanielChappuis commented 2 years ago

Hello. Ok perfect. I am glad that you have found the issue. Sorry, I didn't have the time yet to look into it.