3D Car Game (trying it once more)

The Partridge Family were neither partridges nor a family. Discuss.
User avatar
bshivam2001
Posts: 214
Joined: July 27th, 2013, 6:57 am
Location: India

3D Car Game (trying it once more)

Post by bshivam2001 » June 14th, 2014, 2:11 pm

Hi Guys,
I have been away from programming since 3 months. I had downloaded addicting games and was busy playing them. But I got bored of it soon. So I started my first 3d project. Last time I was unable to change the eye and target of the cam without touching the up vector. Now I think that was pretty simple. But I don't know what values to put in the function to make the cam follow the back of the car. Here's the project.....check out the Update function in Game.cpp to find these functions.
Attachments
3D Game.rar
(922.95 KiB) Downloaded 231 times
'If you can't make it good, at least make it look good'

engi
Posts: 161
Joined: April 7th, 2014, 6:00 am
Location: Brazil

Re: 3D Car Game (trying it once more)

Post by engi » June 14th, 2014, 7:55 pm

Hey, nice job!
Awesome project, really cool car mesh too.. I will be taking a look at your code, in particular the graphics pipeline.

One thing I've noticed : it seems you cant turn the car when you reverse it, or is this intended?

As for the camera you can just store the position of the car and the direction it's moving, then you just look in the direction the car is moving towards and set the camera position behind the car.
You won't have to worry about up vectors while the car moving on a plane.

If you need any help with the camera, just let me know!
Cheers :D
0x5f3759df

User avatar
bshivam2001
Posts: 214
Joined: July 27th, 2013, 6:57 am
Location: India

Re: 3D Car Game (trying it once more)

Post by bshivam2001 » June 16th, 2014, 12:09 pm

it seems you cant turn the car when you reverse it, or is this intended?
No, I don't know why does this happen. But if you observe, the car turns slowly.
you just look in the direction the car is moving towards and set the camera position behind the car.
Exactly what Im trying to do. But I cant seem to find the 'behind' of the car. Moreover I do not have working functions for setting the position and target of the cam. Maybe you could put in the working code and give me??
And thanks!
'If you can't make it good, at least make it look good'

engi
Posts: 161
Joined: April 7th, 2014, 6:00 am
Location: Brazil

Re: 3D Car Game (trying it once more)

Post by engi » June 16th, 2014, 12:37 pm

Ok, but you will need to modify this code to make it work properly, the idea with this class is to keep track of the camera and generate a view matrix when you call Update(), you will probably want to replace GLM with something else since you're working with DirectX :)

Camera.h

Code: Select all

class Camera
{
private:
    glm::vec3 vecPos;
    glm::vec3 vecRight;
    glm::vec3 vecUp;
    glm::vec3 vecViewDir;
    float rotateX;
    float rotateY;
    float rotateZ;

    glm::mat4 view;

public:
    explicit Camera(glm::vec3& pos, glm::vec3& lookdir);
    ~Camera();

    void Move(glm::vec3 direction, float speed);
    // Rotation
    void RotateX(float theta);
    void RotateY(float theta);
    void RotateZ(float theta);
    // Movement
    void Forward(float speed);
    void Sideward(float speed);
    void Upward(float speed);

    // Get the updated matrix
    const glm::mat4& GetView() const;

    // Getters
    const glm::vec3& GetPosition() const;
    const glm::vec3& GetDirection() const;

    void Update();
};
Camera.cpp

Code: Select all

#include "Camera.h"
#include "LinearAlgebra.h"

#define PI180 1.5707963267948966192313216916398f

Camera::Camera(glm::vec3& pos, glm::vec3& lookdir)
{
    if (glm::length(pos) <= std::numeric_limits<float>::epsilon()) pos.x = 0.01f;

    vecPos = pos;

    glm::mat3 base = LinearAlgebra::GenerateOrthonormalBase(lookdir);

    vecViewDir = glm::normalize(-base[0]);
    vecRight = glm::normalize(-base[1]);
    vecUp = glm::normalize(-base[2]);

    rotateX = rotateY = rotateZ = 0.0f;
}

Camera::~Camera()
{}

void Camera::Move(glm::vec3 direction, float speed)
{
    vecPos = vecPos + direction * speed;
}

void Camera::RotateX(float theta)
{
    rotateX += theta;

    //Rotate viewdir around the up vector:
    vecViewDir = glm::normalize(vecViewDir*glm::cos<float>(theta * PI180)
                                - vecRight*glm::sin<float>(theta * PI180));

    //now compute the new RightVector (by cross product)
    vecRight = glm::cross(vecViewDir, vecUp);
}

void Camera::RotateY(float theta)
{
    rotateY += theta;

    //Rotate viewdir around the right vector:
    vecViewDir = glm::normalize(vecViewDir * glm::cos<float>(theta * PI180)
                                + vecUp * glm::sin<float>(theta * PI180));

    // Up vector will be the cross product of our adjusted vectors
    vecUp = glm::cross(vecViewDir, vecRight) * (-1.0f);
}

void Camera::RotateZ(float theta)
{
    rotateZ += theta;

    //Rotate viewdir around the right vector:
    vecRight = glm::normalize(vecRight * glm::cos<float>(theta * PI180)
                              + vecUp * glm::sin<float>(theta * PI180));

    //now compute the new UpVector (by cross product)
    vecUp = glm::cross(vecViewDir, vecRight) * (-1.0f);
}

void Camera::Forward(float speed)
{
    vecPos += (vecViewDir*-speed);
}

void Camera::Sideward(float speed)
{
    vecPos += (vecRight*speed);
}

void Camera::Upward(float speed)
{
    vecPos += (vecUp*speed);
}

const glm::mat4& Camera::GetView() const
{
    return view;
}

const glm::vec3& Camera::GetPosition() const
{
    return vecPos;
}

const glm::vec3& Camera::GetDirection() const
{
    return vecViewDir;
}

void Camera::Update()
{
    // The point at which the camera looks:
    glm::vec3 vecViewPoint = vecPos + vecViewDir;

    // Updating the view matrix
    view = glm::lookAt<float>(vecPos, vecViewPoint, vecUp);
}

The generate orthonormal base's code:

Code: Select all

glm::mat3 LinearAlgebra::GenerateOrthonormalBase(glm::vec3& u)
{
    // There are infinite solutions for a zero vector, using NAN will make the error apparent and thus more likely to be caught
    if (u.x == 0.0 && u.y == 0.0 && u.z == 0.0)
        return {
        glm::vec3(NAN, NAN, NAN),
        glm::vec3(NAN, NAN, NAN),
        glm::vec3(NAN, NAN, NAN)
    };

    glm::vec3 *v;
    if (u.y == 0.0) v = &glm::vec3(-u.z, 0.0, u.x);
    else if (u.z == 0.0) v = &glm::vec3(-u.y, u.x, 0);
    else v = &glm::vec3(0, -u.z, u.y);
    glm::vec3 w = glm::cross<float>(u, *v);

    return {
        glm::normalize(u),
        glm::normalize(*v),
        glm::normalize(w)
    };
}
Some notes:
You will probably want to replace glm::mat3 with an equivalent 3x3 matrix
Same for glm::vec3

glm::cross is the cross product of two vectors
glm::normalize will get the direction of the vector (unit vector)
glm::lookAt should be equivalent to D3DXMatrixLookAtLH
glm::length returns the length of the vector

Then again it might be easier to just download GLM and use it, up to you though :)
0x5f3759df

User avatar
bshivam2001
Posts: 214
Joined: July 27th, 2013, 6:57 am
Location: India

Re: 3D Car Game (trying it once more)

Post by bshivam2001 » June 16th, 2014, 2:42 pm

You know I m really a kid n I dont understand much of vectors. I do programming as a hobby. Could u implement the camera stuff??? Then I'd mention ur name in credits too. Well GLM is a math library. there is no harm using dx and glm together....
'If you can't make it good, at least make it look good'

engi
Posts: 161
Joined: April 7th, 2014, 6:00 am
Location: Brazil

Re: 3D Car Game (trying it once more)

Post by engi » June 16th, 2014, 7:20 pm

As long as you don't mind using GLM with DirectX it's simple enough..

Sorry, but this is as much as I will spoon-feed, besides since you will be using GLM there is no need to modify anything you just need to add the include files and convert the GLM matrix to a D3D matrix ;)

If you need more help I'm willing to help, but try to get it working on your own first, tackling challenges is the way to improve.

Good luck.
0x5f3759df

User avatar
LuisR14
Posts: 1248
Joined: May 23rd, 2013, 3:52 pm
Location: USA
Contact:

Re: 3D Car Game (trying it once more)

Post by LuisR14 » June 17th, 2014, 6:54 am

hehe, trying to get this problem out again huh :p (long time lol)
always available, always on, about ~10 years c/c++, java[script], win32/directx api, [x]html/css/php/some asp/sql experience. (all self taught)
Knows English, Spanish and Japanese.
[url=irc://irc.freenode.net/#pchili]irc://irc.freenode.net/#pchili[/url] [url=irc://luisr14.no-ip.org/#pchili]alt[/url] -- join up if ever want real-time help or to just chat :mrgreen: --

George_99
Posts: 25
Joined: December 4th, 2013, 2:58 pm

Re: 3D Car Game (trying it once more)

Post by George_99 » June 18th, 2014, 9:00 am

i get this error when trying to run it : 1>------ Build started: Project: Chili DirectX Framework, Configuration: Debug Win32 ------
1>Project file contains ToolsVersion="12.0", which is not supported by this version of MSBuild. Treating the project as if it had ToolsVersion="4.0".
1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Platforms\Win32\Microsoft.Cpp.Win32.Targets(511,5): error MSB8008: Specified platform toolset (v120) is not installed or invalid. Please make sure that a supported PlatformToolset value is selected.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

User avatar
LuisR14
Posts: 1248
Joined: May 23rd, 2013, 3:52 pm
Location: USA
Contact:

Re: 3D Car Game (trying it once more)

Post by LuisR14 » June 18th, 2014, 11:10 am

it just means that you gotta run it on vs13 (you can edit in project settings to use vs12 or vs10 instead, tho if code uses features that is only supported in vs13 then you'd have to modify it ...)
always available, always on, about ~10 years c/c++, java[script], win32/directx api, [x]html/css/php/some asp/sql experience. (all self taught)
Knows English, Spanish and Japanese.
[url=irc://irc.freenode.net/#pchili]irc://irc.freenode.net/#pchili[/url] [url=irc://luisr14.no-ip.org/#pchili]alt[/url] -- join up if ever want real-time help or to just chat :mrgreen: --

L1FeMaKeR
Posts: 32
Joined: September 16th, 2013, 4:45 pm

Re: 3D Car Game (trying it once more)

Post by L1FeMaKeR » June 18th, 2014, 11:18 am

This is what I do for my 3rd-Person Camera:

Code: Select all

else if (m_CamType == CAMTYPE_3RDPERSON)
	{ 
		assert(!(m_SnapTarget == nullptr));
		const D3DXVECTOR3 SnapDir = *m_SnapTarget->GetDirection();
		const D3DXVECTOR3 SnapUp = *m_SnapTarget->GetUp();;
		const D3DXVECTOR3 SnapRight = *m_SnapTarget->GetRight();
		const D3DXVECTOR3 SnapPos = *m_SnapTarget->GetPos();
		D3DXVECTOR3 CamVecDir = *m_SnapTarget->GetDirection();
		D3DXVECTOR3 CamVecUp = *m_SnapTarget->GetUp();
		D3DXVECTOR3 CamVecRight = *m_SnapTarget->GetRight();

		// 1st: Rotate the CameraVector
		// 1.1. Rotate Local Up/Down
		D3DXMATRIX Temp;
		//D3DXMatrixRotationAxis(&Temp, &CamVecRight, D3DXToRadian(m_OffsetRot.x));
		D3DXMatrixRotationAxis(&Temp, &SnapRight, D3DXToRadian(m_OffsetRot.x));
		D3DXVec3TransformCoord(&CamVecDir, &CamVecDir, &Temp);
		D3DXVec3Normalize(&CamVecDir, &CamVecDir);
		D3DXVec3TransformCoord(&CamVecUp, &CamVecUp, &Temp);
		D3DXVec3Normalize(&CamVecUp, &CamVecUp);
		D3DXVec3TransformCoord(&CamVecRight, &CamVecRight, &Temp);
		D3DXVec3Normalize(&CamVecRight, &CamVecRight);

		// 1.2. Rotate Global Left/Right
		//D3DXMatrixRotationAxis(&Temp, &CamVecUp, D3DXToRadian(m_OffsetRot.y));
		D3DXMatrixRotationAxis(&Temp, &SnapUp, D3DXToRadian(m_OffsetRot.y));
		D3DXVec3TransformCoord(&CamVecDir, &CamVecDir, &Temp);
		D3DXVec3Normalize(&CamVecDir, &CamVecDir);
		D3DXVec3TransformCoord(&CamVecUp, &CamVecUp, &Temp);
		D3DXVec3Normalize(&CamVecUp, &CamVecUp);
		D3DXVec3TransformCoord(&CamVecRight, &CamVecRight, &Temp);
		D3DXVec3Normalize(&CamVecRight, &CamVecRight);

		// 1.3 Rotate Local Tilt
		D3DXMatrixRotationAxis(&Temp, &CamVecDir, D3DXToRadian(m_OffsetRot.z));
		//D3DXMatrixRotationAxis(&Temp, &SnapDir, D3DXToRadian(m_OffsetRot.z));
		D3DXVec3TransformCoord(&CamVecDir, &CamVecDir, &Temp);
		D3DXVec3Normalize(&CamVecDir, &CamVecDir);
		D3DXVec3TransformCoord(&CamVecUp, &CamVecUp, &Temp);
		D3DXVec3Normalize(&CamVecUp, &CamVecUp);
		D3DXVec3TransformCoord(&CamVecRight, &CamVecRight, &Temp);
		D3DXVec3Normalize(&CamVecRight, &CamVecRight);

		// 2nd: Calculate New Camera Pos
		m_Pos = SnapPos - (m_OffsetDist * CamVecDir);

		// 3rd: Calculate new Camera Local Vectors
		m_Target = CamVecDir;
		m_Up = CamVecUp;
		m_Right = CamVecRight;

		// 4th: Do Vector regeneration
		D3DXVec3Normalize(&m_Target, &m_Target);
		D3DXVec3Cross(&m_Right, &m_Up, &m_Target);
		D3DXVec3Normalize(&m_Right, &m_Right);
		D3DXVec3Cross(&m_Up, &m_Target, &m_Right);
		D3DXVec3Normalize(&m_Up, &m_Up);

		// 5th: update viewmatrix
		m_ViewMatrix._11 = m_Right.x;
		m_ViewMatrix._12 = m_Up.x;
		m_ViewMatrix._13 = m_Target.x;
		m_ViewMatrix._21 = m_Right.y;
		m_ViewMatrix._22 = m_Up.y;
		m_ViewMatrix._23 = m_Target.y;
		m_ViewMatrix._31 = m_Right.z;
		m_ViewMatrix._32 = m_Up.z;
		m_ViewMatrix._33 = m_Target.z;
		m_ViewMatrix._41 = -D3DXVec3Dot(&m_Pos, &m_Right);
		m_ViewMatrix._42 = -D3DXVec3Dot(&m_Pos, &m_Up);
		m_ViewMatrix._43 = -D3DXVec3Dot(&m_Pos, &m_Target);

		// 6th: set transform
		m_pDirect3DDevice->SetTransform(D3DTS_VIEW, &m_ViewMatrix);

	}
It's not that complicated.
First I make const copys of the local-vectors of the snaptarget (in your case it would be the car).
http://puu.sh/9yR9j/0ad170ed2d.jpg
The Up-Vector always points upwards the car (e.g. when you jump you would technically move along the local Up-Vector).
The Direction Vector always points in the direction your car is facing.
The RightVector always points to the right (if you strafe in an ego-shooter you would always move along the local RightVector of the Character). You Need local Vectors of the Car to work. It is important, that you rotate these vectors with your car.

You may have seen those local vectors in 3D Programms:
http://puu.sh/9yS29/8125da5d33.png
Those "Gizmos" used in those programm are the same as the three local Vectors (Up, Right, Direction).

The 3 CamVec Vectors will be the endresult I will use in the end to calculate the new viewmatrix.

1st I rotate the CamVec vectors in three different directions. What I do is rotating around the three Vectors of the Car (the const copys!). If you change the m_OffsetRot Vector you can freely rotate the Camera around the Target.
http://puu.sh/9yRyH/3af46614a4.jpg
It may look like this, after all rotation stuff.
In your racing game, you may want to set the OffsetRot Vector once (normally you can't rotate the cam freely around the car).

2nd part:
ONE IMPORTANT THING!: Those Local Vectors are "Unitlength Vectors". That means they ALWAYS should have a length of 1 (chili called them x^(x-hat) and y^(y-hat) in the 2D world). Then If I multiply the vector with a scalar (normal number), the Vector will always have the length of the scalar! (like multiplying with 1).
To Calculate the CamPos I stretch the Camera Direction Vector by a certain Length (called OffsetDist(ance)) and subtract it from the Snappos (in your case Car). This means the resulting Cameraposition will be perfectly behind the Camera Direction Vector. And because we rotatet these Vectors freely it could be anything around the car.
http://puu.sh/9yRJl/4db4c19a14.jpg

In the 3rd Part I Use The CamVec Vectors and set them as the three Camera Vectors (which you use to create the Viewmatrix). This way the Camera will always look at the Car.

4th is very important. When rotate the camera you will get little rounding errors. They are small, but the more you have moved the camera the bigger those errors will become. And in the End the Camera might not work probably after some time. You ALWAYS need to do this when you rotate any object, that has local-vectors (so basically every object).

5th is another possibility to create a new viewmatrix (if you want you can use the D3DX-Helper functions to create one, my version is not necessary).

6th: Set the new Viewmatrix.

You have to do this every frame (or even better everytime, the 3rd-Person Target has moved!)

Hopefully this could help a little bit :D

Post Reply