1
\$\begingroup\$

I'm trying to follow this guys method for steering a basic car. Link.

It's the first example I can sort of get my head around and I'm trying to convert it to a working 3D version.

To get some scope, I've rendered a cube in OpenGL which represents a car and I'm using GLM for matrix manipulation.

Even though I'm trying to get a 3D example working, I'm only using 2D controls; the X axis for left/right and Z axis for forwards/backwards.

For clarity, I have shown all the vectors as vec.x, vec.y, vec.z. note that not much happens with the vec.y as for the time being the car stays level on the X Z plane. (like top-down games but in 3D environment).

I'm getting some strange responses on screen and I can't see why. I can only assume I've misunderstood where some of the code belongs.

These are my variables etc:

glm::vec3 carLocation(0,0,0);   //location of car
float carHeading    = 0.0f;     //direction car facing
float carSpeed      = 0.5f;     //speed of car
float steeringAngle = 0.0f;     //angle of front wheel
float wheelBase;                //length of car
glm::vec3 frontWheel;           //vec 3 representing front wheel
glm::vec3 backWheel;            //vec 3 representing back wheel
glm::vec3 sincos_Calc;          //vec 3 representing sin/cos calculation

This is my function to render the car and manipulate it:

void renderMovingCube(){
glUseProgram(movingCubeShader.handle());
GLuint matrixLoc4MovingCube = glGetUniformLocation(movingCubeShader.handle(), "ProjectionMatrix");  
glUniformMatrix4fv(matrixLoc4MovingCube, 1, GL_FALSE, &ProjectionMatrix[0][0]);

    glm::mat4 viewMatrixMovingCube;
    viewMatrixMovingCube = glm::lookAt(camOrigin, camLookingAt, camNormalXYZ);

        //set values
        wheelBase = 12;                     //car dim X;
        sincos_Calc.x = cos(carHeading);    //adjust X coord
        sincos_Calc.y = 0;                  //car stays on Y plane
        sincos_Calc.z = sin(carHeading);    //adjust Z coord

        //step 1
        frontWheel.x = (carLocation.x + (wheelBase/2)) * sincos_Calc.x;
        frontWheel.y = 0;
        frontWheel.z = (carLocation.z + (wheelBase/2)) * sincos_Calc.z;
        backWheel.x  = (carLocation.x - (wheelBase/2)) * sincos_Calc.x;
        backWheel.y  = 0;
        backWheel.z  = (carLocation.z - (wheelBase/2)) * sincos_Calc.z;

    //location of car
    ModelViewMatrix = glm::translate(viewMatrixMovingCube,carLocation);

    ModelViewMatrix = glm::translate(ModelViewMatrix,  glm::vec3(0,-48,0));
    ModelViewMatrix = glm::rotate(ModelViewMatrix, steeringAngle, glm::vec3(0,1,0));//manually turn

    glUniformMatrix4fv(glGetUniformLocation(movingCubeShader.handle(), "ModelViewMatrix"), 1, GL_FALSE, &ModelViewMatrix[0][0]); //pass matrix to shader
movingCube.render();        //car
glUseProgram(0);            //turn off the current shader
}

This is my key input:

void keyboard(){
if (FORWARD) //W key
{
    //step 2
    backWheel.x += carSpeed*sincos_Calc.x;
    backWheel.y += 0;
    backWheel.z += carSpeed*sincos_Calc.z;
    frontWheel.x += carSpeed*(cos(carHeading+steeringAngle));
    frontWheel.y += 0;
    frontWheel.z += carSpeed*(sin(carHeading+steeringAngle));

    //step 3
    carLocation.x = (frontWheel.x+backWheel.x)/2;
    carLocation.y = 0;
    carLocation.z = (frontWheel.z+backWheel.z)/2;
    carHeading = atan2((frontWheel.z-backWheel.z), (frontWheel.x-backWheel.x));

    cout<< glm::to_string(carLocation) << endl;
    BACKWARD = false;  
}
if (ROT_LEFT){ //A key
    steeringAngle +=0.5f;
    ROT_LEFT = false;  
}
if (ROT_RIGHT){ //D key
    steeringAngle -=0.5f;
    ROT_RIGHT = false; 
}
}

I've been trying for days to get this to work and done so much googling and SO'ing to avoid posting this but I'm still have problems with it.

My aim is to have my cube moving forwards/backwards and steering/turing like a car, described in the link above.

Am I even remotely heading in the right direct? I'm not quite sure why Step 2 overwrites step 1, I feel this is why I'm going wrong...

Have I converted the vecs from vec2's to vec3's correctly? and Are my "steps" in the right locations? Thanks.

\$\endgroup\$
1
\$\begingroup\$

First, You are doing the step 1 wrongly. You should add the (sin, cos) direction scaled by half whellBase instead of scalling the entire result. So, the first line of this step should be:

frontWheel.x = carLocation.x + wheelBase/2*sincos_Calc.x;

instead of

frontWheel.x = (carLocation.x + (wheelBase/2)) * sincos_Calc.x;

The same applies for frontWheel.z and backWheel.

Second, I don't know if your glUniformMatrix4fv calls will work properly. It seems by your code that you are using a multidimensional matrix, but OpenGL uses monodimensional matrices as transformations. See this tutorial.

Third, I think your glm::rotate should take into consideration the car heading too:

ModelViewMatrix = glm::rotate(ModelViewMatrix, carHeading + steeringAngle, glm::vec3(0,1,0));//manually turn

As a final tip, don't mix rendering, input and game update. Rendering and input should be encapsulated by their proper classes and the update should be encapsulated by a function of the game object at least.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.