⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 carobject.cpp

📁 3D赛车游戏源代码-用Visual Studio 2005
💻 CPP
字号:
#include "StdAfx.h"
#include "CarObject.h"
#include "../model/Model.h"
#include "../model/TriMesh.h"
#include "OGLutil.h"
#include "../res/ModelLoadManager.h"
#include "QuadTree.h"
#include "SceneManager.h"

using namespace std;


CCarObject::CCarObject()
{
	m_pCarBodyModel     = NULL;
	m_pWheelModel       = NULL;
	m_fMoveSpeed        = 0.0f;
	m_fTurnSpeed        = 0.0f;
	m_fMaxMoveSpeed     = 0.0f;
	m_fTurnRadian       = 0.0f;
	m_fWheelRollRadian  = 0.0f;
	m_fWheelTurnRadian  = 0.0f;
	m_eCurState = ECarState_Begin;
}

CCarObject::~CCarObject()
{
}

void CCarObject::BuildObjectBox()
{
	// 现在只计算车身。

	if (m_pCarBodyModel != NULL)
	{
		m_boxObjectBox.Empty();
		int iTriMeshCount = m_pCarBodyModel->GetPartCount();

		for (int i=0; i<iTriMeshCount; ++i)
		{
			TriMesh* mesh = m_pCarBodyModel->GetPartMesh(i);
			m_boxObjectBox.Add(mesh->GetBoundingBox());
		}
	}
}

void CCarObject::LoadWheelPosition(const char *filename)
{
	ifstream inf(filename);
	
	for (int i = 0; i < WHEEL_COUNT; ++i)
	{
		inf >> m_posWheel[i].x >> m_posWheel[i].y >> m_posWheel[i].z;
	}
}

void CCarObject::LoadModels(const char *filename)
{
	char szPathName[64];
	char szFileName[128];
	bool bHasPath = false;
	char* ptr = strrchr(filename, '/');

	if (ptr == NULL)
	{
		ptr = strrchr(filename, '\\');
	}

	if (ptr == NULL)
	{
		szPathName[0] = '\0';
	}
	else
	{
		int len = static_cast<int>(ptr - filename);
		strncpy(szPathName, filename, len);
		szPathName[len] = '/';
		szPathName[len+1] = '\0';
	}

	m_pCarBodyModel = g_ModelLoadManager.LoadModel(filename);
	strcpy(szFileName, szPathName);
	strcat(szFileName, "Wheel.3ds");
	m_pWheelModel = g_ModelLoadManager.LoadModel(szFileName);
	strcpy(szFileName, szPathName);
	strcat(szFileName, "car.cfg");

	LoadWheelPosition(szFileName);
	BuildObjectBox();
}

void CCarObject::RenderObject()
{
	assert(m_pCarBodyModel != NULL && m_pWheelModel != NULL);

	g_Renderer.PushModelViewMatrix();
	g_Renderer.MulMatrix(m_mxTransformObjToWorld.m);
	m_pCarBodyModel->Render();

	CMatrix44F mat;

	// 前面两个车轮还要有转弯的角度
	for (int i=0; i<2; ++i)
	{
		g_Renderer.PushModelViewMatrix();
		mat.SetupTranslation(m_posWheel[i]);
		mat.Rotate(3, m_fWheelTurnRadian);
		mat.Rotate(1, m_fWheelRollRadian);
		g_Renderer.MulMatrix(mat.m);
		m_pWheelModel->Render();
		g_Renderer.PopModelViewMatrix();
	}

	for (int i=2; i<WHEEL_COUNT; ++i)
	{
		g_Renderer.PushModelViewMatrix();
		mat.SetupTranslation(m_posWheel[i]);
		mat.Rotate(1, m_fWheelRollRadian);
		g_Renderer.MulMatrix(mat.m);
		m_pWheelModel->Render();
		g_Renderer.PopModelViewMatrix();
	}

	// 调试画出物体的局部盒子
	//g_Renderer.RenderBox(m_boxObjectBox.min, m_boxObjectBox.max);

	g_Renderer.PopModelViewMatrix();

	// 调试画出物体的世界盒子
	//g_Renderer.RenderBox(m_boxWorldBox.min, m_boxWorldBox.max);
}

void CCarObject::Update()
{
	Move();
	Animate();
	m_fMoveSpeed -= 0.0014f;

	// 如果在没有跑道的地方,阻力会更大一些
	CQuadTree *pTree = m_pSceneManager->GetQuadTree();

	if (pTree->FindTri(GetPosition()) == NULL)
	{
		m_fMoveSpeed -= (0.2f * m_fMoveSpeed + 0.0032f) ;
	}

	if (m_fMoveSpeed < 0.0f)
	{
		m_fMoveSpeed = 0.0f;
	}
}

void CCarObject::Animate()
{
	m_fWheelRollRadian -= m_fMoveSpeed;
}

void CCarObject::Move()
{
	if (m_fWheelTurnRadian > 0.0f)
	{
		m_fTurnRadian = m_fTurnSpeed * 0.8f;
		m_fWheelTurnRadian -= m_fTurnSpeed * 0.8f;

		if (m_fWheelTurnRadian < 0.f)
		{
			m_fWheelTurnRadian = 0.f;
		}
	}
	else if (m_fWheelTurnRadian < 0.0f)
	{
		m_fTurnRadian = -m_fTurnSpeed * 0.8f;
		m_fWheelTurnRadian += m_fTurnSpeed * 0.8f;

		if (m_fWheelTurnRadian > 0.f)
		{
			m_fWheelTurnRadian = 0.f;
		}
	}

	m_mxTransformObjToWorld.Rotate(3, m_fTurnRadian);
	m_mxTransformObjToWorld.Translate(Vector3(0.0f, m_fMoveSpeed, 0.0f));
	SetTransform(m_mxTransformObjToWorld);

	m_fTurnRadian = 0.0f;
}

void CCarObject::TurnLeft()
{
	m_fWheelTurnRadian += m_fTurnSpeed;
	//m_mxTransformObjToWorld.Rotate(3, m_fTurnSpeed);
	//SetTransform(m_mxTransformObjToWorld);
}

void CCarObject::TurnRight()
{
	m_fWheelTurnRadian -= m_fTurnSpeed;
	//m_mxTransformObjToWorld.Rotate(3, -m_fTurnSpeed);
	//SetTransform(m_mxTransformObjToWorld);
}


//-------------------------------------------------------------------------------
// 车子与车子的碰撞检测,true为发生碰撞,否则没有
//-------------------------------------------------------------------------------
bool CollisionCheck(const CCarObject &car1, const CCarObject &car2)
{
	const AABB3& box1 = car1.GetWorldBox();
	const AABB3& box2 = car2.GetWorldBox();

	if (IntersectAABBs(box1, box2))
	{
		const AABB3& oBox = car2.GetObjectBox();
		Vector3 vSize = (oBox.max - oBox.min) * 0.5f;
		CMatrix44F mat1 = car1.GetTransformWorldToObj();
		mat1 *= car2.GetTransformObjToWorld();

		if (car1.GetObjectBox().IntersectOBB(vSize, mat1))
		{
			return true;
		}
	}

	return false;
}

//-------------------------------------------------------------------------------
// 车子与车子的碰撞响应
//-------------------------------------------------------------------------------
bool OnCollision(CCarObject &car1, CCarObject &car2)
{
	// 点乘
#define DOT_PRODUCT(ux,uy,vx,vy) ((ux)*(vx) + (uy)*(vy))

	Vector3 pos1, pos2; // 车子的位置
	Vector3 vel1, vel2;	// Z轴即为车子面向的方向

	pos1 = car1.GetPosition();
	pos2 = car2.GetPosition();

	car1.GetTransformObjToWorld().GetRow(1, &vel1);
	car2.GetTransformObjToWorld().GetRow(1, &vel2);
	vel1 *= car1.GetMoveSpeed();
	vel2 *= car2.GetMoveSpeed();

	// 就算a->b的法线向量
	float nabx = pos2.x - pos1.x;
	float naby = pos2.y - pos1.y;
	float length = sqrt(nabx*nabx + naby*naby);

	// 计算反应的坐标系的坐标轴,这个是法线轴
	nabx /= length;
	naby /= length;

	// 计算垂直法线轴的切线轴,简单地逆时针旋转90度
	float tabx =  -naby;
	float taby =  nabx;

	// a球在切线方向上初始速度的投影长度
	float vait = DOT_PRODUCT(vel1.x, vel1.y, tabx, taby);

	// a球在法线方向上初始速度的投影长度
	float vain = DOT_PRODUCT(vel1.x, vel1.y, nabx, naby);

	// b球在切线方向上初始速度的投影长度
	float vbit = DOT_PRODUCT(vel2.x, vel2.y, tabx, taby);

	// b球在法线方向上初始速度的投影长度
	float vbin = DOT_PRODUCT(vel2.x, vel2.y, nabx, naby);

	float ma = 1.2f;
	float mb = 1.2f;

	float vafn = (mb*vbin*(0.6f+1.f) + vain*(ma - 0.6f*mb)) / (ma + mb);
	float vbfn = (ma*vain*(0.6f+1.f) - vbin*(ma - 0.6f*mb)) / (ma + mb);

	// 幸运的,切线反向的速度和原来一样
	float vaft = vait;
	float vbft = vbit;

	// 就这样,宝贝!
	// 最终速度的向量如下:
	// object a (vafn, vaft)
	// object b (vbfn, vbft)    

	// 最后问题是我们在n-t坐标系中!我们需要转换回原来的x-y坐标系中,基本上我们
	// 需要计算相对于n-t坐标轴的x分量的和,已经相对于n-t坐标轴的y分量的和,因为
	// n-t轴相对于原来的x-y坐标系可能同时有x和y分量。

	float xfa = vafn*nabx + vaft*tabx;
	float yfa = vafn*naby + vaft*taby;

	float xfb = vbfn*nabx + vbft*tabx;
	float yfb = vbfn*naby + vbft*taby;

	vel1.x = xfa, vel1.y = yfa;
	vel2.x = xfb, vel2.y = yfb;

	float speed1 = VectorMag(vel1);
	float speed2 = VectorMag(vel2);

	vel1.Normalize();
	vel2.Normalize();

	CMatrix44F mat1 = car1.GetTransformObjToWorld();
	CMatrix44F mat2 = car2.GetTransformObjToWorld();

	mat1.SetRow(1, vel1);
	mat2.SetRow(1, vel2);

	Vector3 vZ1(0.f, 0.f, 1.f);
	Vector3 vZ2(0.f, 0.f, 1.f);

	Vector3 vX1 = CrossProduct(vel1, vZ1);
	Vector3 vX2 = CrossProduct(vel2, vZ2);

	mat1.SetRow(0, vX1);
	mat2.SetRow(0, vX2);

	car1.SetTransform(mat1);
	car2.SetTransform(mat2);

	car1.SetMoveSpeed(speed1);
	car2.SetMoveSpeed(speed2);
	return true;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -