Ejemplo n.º 1
0
void Camera::moveCam()
{
	XMVECTOR tempRight = XMLoadFloat3(&mRight);
	XMVECTOR tempUp = XMLoadFloat3(&mUp);
	XMVECTOR tempPosition = XMLoadFloat3(&mPosition);
	XMVECTOR tempForward = XMLoadFloat3(&mLook);
	



	//set the camera to look at the character
	camTarget = playerPosition;






	XMVECTOR tempTarget = XMLoadFloat3(&camTarget);

	tempTarget = XMVectorSetY(tempTarget,10);


	
	//rotate camera around the character
	camRotationMatrix = XMMatrixRotationRollPitchYaw(-camPitch, camYaw, 0);
	tempPosition = XMVector3TransformNormal(PlayerForward, camRotationMatrix);
	tempPosition = XMVector3Normalize(tempPosition);


	tempPosition = (tempPosition * -50) + tempTarget;
		
	tempPosition = XMVectorSetY(tempPosition, 30.0f);

	tempForward = XMVector3Normalize(tempTarget - tempPosition);	// Get forward vector based on target
	tempForward = XMVectorSetY(tempForward, 0.0f);	// set forwards y component to 0 so it lays only on

	tempForward= XMVector3Normalize(tempForward);

	tempRight = XMVectorSet(XMVectorGetZ(-tempForward), 0.0f, XMVectorGetX(tempForward), 0.0f);

	tempUp = XMVector3Normalize(XMVector3Cross(XMVector3Normalize(tempPosition - tempTarget), tempRight));



	XMStoreFloat3(&mRight, tempRight);
	XMStoreFloat3(&mUp, tempUp);
	XMStoreFloat3(&mPosition, tempPosition);
	XMStoreFloat3(&mLook, tempForward);

	XMMATRIX tempView = XMLoadFloat4x4(&mView);


	tempView = XMMatrixLookAtLH(tempPosition, tempTarget, tempUp);

	XMStoreFloat4x4(&mView, tempView);

	///////////mising some code maybe
}
Ejemplo n.º 2
0
void Graphics::exe_cam_curr_pos(uint32_t const _i_zad) {
	XMVECTOR _v = XMVectorSet(cam.v.x, 0.0f, cam.v.z, 0.0f);
	XMVECTOR _dl_v = XMVector3LengthEst(_v);
	if(XMVectorGetX(_dl_v) != 0.0f) {
		_v = XMVector3Rotate(_v, XMLoadFloat4(&cam.quat));
		_v = XMVectorSetY(_v, 0.0f);
		XMVECTOR _v_modul = XMVectorAbs(_v);
		_v = _v / (XMVectorGetX(_v_modul) + XMVectorGetZ(_v_modul)) * _dl_v;
	}
	_v = XMVectorSetY(_v, cam.v.y);
	XMStoreFloat3(&cam.pos, XMLoadFloat3(&cam.pos) + _v);
	task.erase(_i_zad);
}
Ejemplo n.º 3
0
void		CFVec4::SetXY( CFVec2Arg fv2Source )
{
	const XMVECTOR& v2V = *reinterpret_cast<const XMVECTOR*>( &fv2Source );
	XMVECTOR& v4V = *reinterpret_cast<XMVECTOR*>(this);

	v4V = XMVectorSetX( v4V, XMVectorGetX( v2V ) );
	v4V = XMVectorSetY( v4V, XMVectorGetY( v2V ) );
}
Ejemplo n.º 4
0
void		CFVec4::SetXYZ( CFVec3Arg fv3Source )
{
	const XMVECTOR& v3V = *reinterpret_cast<const XMVECTOR*>( &fv3Source );
	XMVECTOR& v4V = *reinterpret_cast<XMVECTOR*>(this);

	v4V = XMVectorSetX( v4V, XMVectorGetX( v3V ) );
	v4V = XMVectorSetY( v4V, XMVectorGetY( v3V ) );
	v4V = XMVectorSetZ( v4V, XMVectorGetZ( v3V ) );
}
Ejemplo n.º 5
0
void		CFVec4::Y( FLOAT32 fVal )
{
	XMVECTOR& V4 = *reinterpret_cast<XMVECTOR*>(this);
	V4 = XMVectorSetY( V4, fVal );
}
Ejemplo n.º 6
0
void		CFVec4::YAdd( FLOAT32 fVal )
{
	XMVECTOR& v4V = *reinterpret_cast<XMVECTOR*>(this);
	
	v4V = XMVectorSetY( v4V, XMVectorGetY( v4V ) + fVal );
}
Ejemplo n.º 7
0
void Frustum::CreateFrustum(float screenDepth, XMMATRIX viewMatrix, XMMATRIX projMatrix)
{
	float zMinimum, r;
	XMFLOAT4X4 projMatrixFloat;
	XMFLOAT4X4 frustumMatrix;
	XMStoreFloat4x4(&projMatrixFloat, projMatrix);

	// Calculate the minimum Z distance in the frustum.
	zMinimum = -projMatrixFloat._43 / projMatrixFloat._33;
	r = screenDepth / (screenDepth - zMinimum);
	projMatrixFloat._33 = r;
	projMatrixFloat._43 = -r * zMinimum;

	XMMATRIX updatedProjMatrix = XMLoadFloat4x4(&projMatrixFloat);

	//Create the frustum from the viewMatrix and updated projectionMatrix
	XMStoreFloat4x4(&frustumMatrix, XMMatrixMultiply(viewMatrix, updatedProjMatrix)); ;

	//Calculate near plane of frustum
	XMVectorSetX(this->planes[0], frustumMatrix._14 + frustumMatrix._13);
	XMVectorSetY(this->planes[0], frustumMatrix._24 + frustumMatrix._23);
	XMVectorSetZ(this->planes[0], frustumMatrix._34 + frustumMatrix._33);
	XMVectorSetW(this->planes[0], frustumMatrix._44 + frustumMatrix._43);
	this->planes[0] = XMPlaneNormalize(this->planes[0]);
	//this->planes[0] = XMVector3Normalize(this->planes[0]);

	//Calculate far plane of frustum
	XMVectorSetX(this->planes[1], frustumMatrix._14 - frustumMatrix._13);
	XMVectorSetY(this->planes[1], frustumMatrix._24 - frustumMatrix._23);
	XMVectorSetZ(this->planes[1], frustumMatrix._34 - frustumMatrix._33);
	XMVectorSetW(this->planes[1], frustumMatrix._44 - frustumMatrix._43);
	this->planes[1] = XMPlaneNormalize(this->planes[1]);
	//this->planes[1] = XMVector3Normalize(this->planes[1]);

	//Calculate left plane of frustum
	XMVectorSetX(this->planes[2], frustumMatrix._14 + frustumMatrix._11);
	XMVectorSetY(this->planes[2], frustumMatrix._24 + frustumMatrix._21);
	XMVectorSetZ(this->planes[2], frustumMatrix._34 + frustumMatrix._31);
	XMVectorSetW(this->planes[2], frustumMatrix._44 + frustumMatrix._41);
	this->planes[2] = XMPlaneNormalize(this->planes[2]);
	//this->planes[2] = XMVector3Normalize(this->planes[2]);

	//Calculate right plane of frustum
	XMVectorSetX(this->planes[3], frustumMatrix._14 - frustumMatrix._11);
	XMVectorSetY(this->planes[3], frustumMatrix._24 - frustumMatrix._21);
	XMVectorSetZ(this->planes[3], frustumMatrix._34 - frustumMatrix._31);
	XMVectorSetW(this->planes[3], frustumMatrix._44 - frustumMatrix._41);
	this->planes[3] = XMPlaneNormalize(this->planes[3]);
	//this->planes[3] = XMVector3Normalize(this->planes[3]);

	//Calculate top plane of frustum
	XMVectorSetX(this->planes[4], frustumMatrix._14 - frustumMatrix._12);
	XMVectorSetY(this->planes[4], frustumMatrix._24 - frustumMatrix._22);
	XMVectorSetZ(this->planes[4], frustumMatrix._34 - frustumMatrix._32);
	XMVectorSetW(this->planes[4], frustumMatrix._44 - frustumMatrix._42);
	this->planes[4] = XMPlaneNormalize(this->planes[4]);
	//this->planes[4] = XMVector3Normalize(this->planes[4]);

	//Calculate bottom plane of frustum
	XMVectorSetX(this->planes[5], frustumMatrix._14 + frustumMatrix._12);
	XMVectorSetY(this->planes[5], frustumMatrix._24 + frustumMatrix._22);
	XMVectorSetZ(this->planes[5], frustumMatrix._34 + frustumMatrix._32);
	XMVectorSetW(this->planes[5], frustumMatrix._44 + frustumMatrix._42);
	this->planes[5] = XMPlaneNormalize(this->planes[5]);
	//this->planes[5] = XMVector3Normalize(this->planes[5]);

	/*for (int i = 0; i < 6; i++) {
		float denom = 1.0f / XMVectorGetX(XMVector3Length(this->planes[i]));
		XMVectorSetX(this->planes[i], XMVectorGetX(this->planes[i]) * denom);
		XMVectorSetY(this->planes[i], XMVectorGetY(this->planes[i]) * denom);
		XMVectorSetZ(this->planes[i], XMVectorGetZ(this->planes[i]) * denom);
		XMVectorSetW(this->planes[i], XMVectorGetW(this->planes[i]) * denom);
	}*/

	return;
}
Ejemplo n.º 8
0
void GameOverState::Init()
{
	auto o = System::GetOptions();
	float width = (float)o->GetScreenResolutionWidth();
	float height = (float)o->GetScreenResolutionHeight();
	auto i = System::GetInput();
	auto c = _controller;
	auto a = System::GetInstance()->GetAudio();
	a->PlayBGMusic(L"mamb.wav", 0.5f);
	XMFLOAT4 TextColor = XMFLOAT4(41.0f / 255.0f, 127.0f / 255.0f, 185.0f / 255.0f, 1.0f);
	XMFLOAT4 ScoreTextColor = XMFLOAT4(17.0f / 255.0f, 166.0f / 255.0f, 67.0f / 255.0f, 1.0f);

	//==========================
	//====	High Score Text	====
	//==========================

	float widthPercentOfDefault = (1.0f / 1920.0f) * width;
	float heightPercentOfDefault = (1.0f / 1080.0f) * height;

	Entity scoreOverlay = _builder->CreateOverlay(XMFLOAT3(0.0f, 0.0f, 0.0f), 550.0f*widthPercentOfDefault, 350.0f*heightPercentOfDefault, "Assets/Textures/GameOverOverlay.png");

	float fontSize = 40 * widthPercentOfDefault;

	//High Score
	Entity textHighScore = _builder->CreateLabel(XMFLOAT3(0.0f, 0.0f, 0.0f),
		"Statistics",
		fontSize,
		ScoreTextColor,
		125.0f,
		25.0f,
		"");
	_builder->Text()->ChangeFontSize(textHighScore, (uint)(fontSize*1.5f));
	_builder->Transform()->SetPosition(textHighScore, XMFLOAT3(550.0f*widthPercentOfDefault / 2 - _builder->Text()->GetLength(textHighScore) / 2, 0.0f, 0.0f));
	_builder->Transform()->BindChild(scoreOverlay, textHighScore);

	//Light High Score
	Entity totalLightHighScoreText = _builder->CreateLabel(XMFLOAT3(0.0f, 0.0f, 0.0f),
		"Light Collected:",
		fontSize,
		ScoreTextColor,
		125.0f,
		25.0f,
		"");
	_builder->Text()->ChangeFontSize(totalLightHighScoreText, (uint)(fontSize*0.55f));
	_builder->Transform()->SetPosition(totalLightHighScoreText, XMFLOAT3(0.0f, fontSize*1.5f + fontSize * 0 + 10.0f * 1 * heightPercentOfDefault, 0.0f));
	_builder->Transform()->BindChild(scoreOverlay, totalLightHighScoreText);

	Entity totalLightCollectedText = _builder->CreateLabel(XMFLOAT3(0.0f, 0.0f, 0.0f),
		std::to_string(_thePlayer->GetTotalLightCollected()),
		fontSize,
		ScoreTextColor,
		125.0f,
		25.0f,
		"");
	_builder->Text()->ChangeFontSize(totalLightCollectedText, (uint)(fontSize*0.55f));
	_builder->Transform()->SetPosition(totalLightCollectedText, XMFLOAT3(560.0f*widthPercentOfDefault / 2, fontSize*1.5f + fontSize * 0 + 10.0f * 1 * heightPercentOfDefault, 0.0f));
	_builder->Transform()->BindChild(scoreOverlay, totalLightCollectedText);


	//Shots Fired
	Entity totalShotsFiredHighScoreText = _builder->CreateLabel(XMFLOAT3(0.0f, 0.0f, 0.0f),
		"Shots Fired:",
		fontSize,
		ScoreTextColor,
		125.0f,
		25.0f,
		"");
	_builder->Text()->ChangeFontSize(totalShotsFiredHighScoreText, (uint)(fontSize*0.55f));
	_builder->Transform()->SetPosition(totalShotsFiredHighScoreText, XMFLOAT3(0.0f, fontSize*1.5f + fontSize * 1 + 10.0f * 2 * heightPercentOfDefault, 0.0f));
	_builder->Transform()->BindChild(scoreOverlay, totalShotsFiredHighScoreText);

	Entity totalShotsFiredText = _builder->CreateLabel(XMFLOAT3(0.0f, 0.0f, 0.0f),
		std::to_string(_thePlayer->GetShotsFired()),
		fontSize,
		ScoreTextColor,
		125.0f,
		25.0f,
		"");
	_builder->Text()->ChangeFontSize(totalShotsFiredText, (uint)(fontSize*0.55f));
	_builder->Transform()->SetPosition(totalShotsFiredText, XMFLOAT3(560.0f*widthPercentOfDefault / 2, fontSize*1.5f + fontSize * 1 + 10.0f * 2 * heightPercentOfDefault, 0.0f));
	_builder->Transform()->BindChild(scoreOverlay, totalShotsFiredText);


	//Shots Connected
	Entity totalShotsConnectedHighScoreText = _builder->CreateLabel(XMFLOAT3(0.0f, 0.0f, 0.0f),
		"Shots Hitting:",
		fontSize,
		ScoreTextColor,
		125.0f,
		25.0f,
		"");
	_builder->Text()->ChangeFontSize(totalShotsConnectedHighScoreText, (uint)(fontSize*0.55f));
	_builder->Transform()->SetPosition(totalShotsConnectedHighScoreText, XMFLOAT3(0.0f, fontSize*1.5f + fontSize * 2 + 10.0f * 3 * heightPercentOfDefault, 0.0f));
	_builder->Transform()->BindChild(scoreOverlay, totalShotsConnectedHighScoreText);

	Entity totalShotsConnectedText = _builder->CreateLabel(XMFLOAT3(0.0f, 0.0f, 0.0f),
		std::to_string(_thePlayer->GetShotsConnected()),
		fontSize,
		ScoreTextColor,
		125.0f,
		25.0f,
		"");
	_builder->Text()->ChangeFontSize(totalShotsConnectedText, (uint)(fontSize*0.55f));
	_builder->Transform()->SetPosition(totalShotsConnectedText, XMFLOAT3(560.0f*widthPercentOfDefault / 2, fontSize*1.5f + fontSize * 2 + 10.0f * 3 * heightPercentOfDefault, 0.0f));
	_builder->Transform()->BindChild(scoreOverlay, totalShotsConnectedText);


	//Hit Chance
	Entity totalHitChanceHighScoreText = _builder->CreateLabel(XMFLOAT3(0.0f, 0.0f, 0.0f),
		"Hit Percent:",
		fontSize,
		ScoreTextColor,
		125.0f,
		25.0f,
		"");
	_builder->Text()->ChangeFontSize(totalHitChanceHighScoreText, (uint)(fontSize*0.55f));
	_builder->Transform()->SetPosition(totalHitChanceHighScoreText, XMFLOAT3(0.0f, fontSize*1.5f + fontSize * 3 + 10.0f * 4 * heightPercentOfDefault, 0.0f));
	_builder->Transform()->BindChild(scoreOverlay, totalHitChanceHighScoreText);
	float value = _thePlayer->GetHitPercent();
	int intValue = static_cast<int>(value);
	Entity totalHitPercentText = _builder->CreateLabel(XMFLOAT3(0.0f, 0.0f, 0.0f),
		std::to_string(intValue) + "." + std::to_string(static_cast<int>((value-(float)intValue)*100))+ "%",
		fontSize,
		ScoreTextColor,
		125.0f,
		25.0f,
		"");
	_builder->Text()->ChangeFontSize(totalHitPercentText, (uint)(fontSize*0.55f));
	_builder->Transform()->SetPosition(totalHitPercentText, XMFLOAT3(560.0f*widthPercentOfDefault / 2, fontSize*1.5f + fontSize * 3 + 10.0f * 4 * heightPercentOfDefault, 0.0f));
	_builder->Transform()->BindChild(scoreOverlay, totalHitPercentText);


	//Enemies Defeated
	Entity totalEnemiesDefeatedScoreText = _builder->CreateLabel(XMFLOAT3(0.0f, 0.0f, 0.0f),
		"Enemies Defeated:",
		fontSize,
		ScoreTextColor,
		125.0f,
		25.0f,
		"");
	_builder->Text()->ChangeFontSize(totalEnemiesDefeatedScoreText, (uint)(fontSize*0.55f));
	_builder->Transform()->SetPosition(totalEnemiesDefeatedScoreText, XMFLOAT3(0.0f, fontSize*1.5f + fontSize * 4 + 10.0f * 5 * heightPercentOfDefault, 0.0f));
	_builder->Transform()->BindChild(scoreOverlay, totalEnemiesDefeatedScoreText);

	Entity totalEnemiesDefeatedText = _builder->CreateLabel(XMFLOAT3(0.0f, 0.0f, 0.0f),
		std::to_string(_thePlayer->GetEnemiesDefeated()),
		fontSize,
		ScoreTextColor,
		125.0f,
		25.0f,
		"");
	_builder->Text()->ChangeFontSize(totalEnemiesDefeatedText, (uint)(fontSize*0.75f));
	_builder->Transform()->SetPosition(totalEnemiesDefeatedText, XMFLOAT3(560.0f*widthPercentOfDefault / 2, fontSize*1.5f + fontSize * 4 + 10.0f * 5 * heightPercentOfDefault, 0.0f));
	_builder->Transform()->BindChild(scoreOverlay, totalEnemiesDefeatedText);



	//Set the overlay, and all it's childrens', positions.
	_builder->Transform()->SetPosition(scoreOverlay, XMFLOAT3(width - 550.0f*widthPercentOfDefault, height - 350.0f*heightPercentOfDefault, 0.0f));


	//==========================
	//====		Buttons		====
	//==========================


	// Start game button
	Entity b1 = _builder->CreateButton(
		XMFLOAT3(50.0f, height - 230.0f, 0.0f),
		"New Game",
		fontSize,
		TextColor,
		"",
		[i, a]()
	{
		a->PlaySoundEffect(L"menuclick.wav", 1);
		ChangeStateTo(StateChange(new GameState()));
	});

	//Options button
	Entity b5 = _builder->CreateButton(
		XMFLOAT3(50.0f, height - 180.0f, 0.0f),
		"Main Menu",
		fontSize,
		TextColor,
		"",
		[i, a]()
	{
		a->PlaySoundEffect(L"menuclick.wav", 1);
		ChangeStateTo(StateChange(new MenuState));
	});


	// Exit button
	Entity b2 = _builder->CreateButton(
		XMFLOAT3(50.0f, height - 130.0f, 0.0f),
		"Exit",
		fontSize,
		TextColor,
		"",
		[a]() {
		a->PlaySoundEffect(L"menuclick.wav", 1);
		ExitApplication;
	});

	//==========================
	//====	Background		====
	//==========================

	// Game Over text
	_builder->CreateLabel(
		XMFLOAT3(width / 2.0f - 100.0f, 25.0f, 0.0f),
		"Game Over",
		fontSize,
		TextColor,
		250.0f,
		45.0f,
		"");

	_altar = _builder->CreateObject(
		XMVectorSet(1.5f, 0.0f, 1.0f, 1.0f),
		XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f),
		XMVectorSet(0.5f, 0.5f, 0.5f, 0.0f),
		"Assets/Models/Altar.arf",
		"Assets/Textures/Altar_Albedo.png",
		"Assets/Textures/Altar_NM.png",
		"Assets/Textures/default_displacement.png",
		"Assets/Textures/Altar_Roughness.png");
	_builder->Material()->SetMaterialProperty(_altar, "ParallaxBias", -0.05f, "Shaders/GBuffer.hlsl");
	_builder->Material()->SetMaterialProperty(_altar, "ParallaxScaling", 0.12f, "Shaders/GBuffer.hlsl");


	_builder->Bounding()->CreateBoundingSphere(_altar, 2.0f);

	_altarCenterLight = _builder->EntityC().Create();
	_builder->Light()->BindPointLight(_altarCenterLight, XMFLOAT3(0.0f, 0.0f, 0.0f), 3.0f, XMFLOAT3(0.0f, 0.25f, 0.35f), 10.0f);
	_builder->Light()->ChangeLightBlobRange(_altarCenterLight, 1.0f);
	_builder->Transform()->CreateTransform(_altarCenterLight);
	_builder->Transform()->SetPosition(_altarCenterLight, XMFLOAT3(0.0f, 1.4f, 0.0f));
	_builder->Transform()->BindChild(_altar, _altarCenterLight);

	for (int i = 0; i < _numAltarBolts; ++i)
	{
		_altarBolts[i] = _builder->EntityC().Create();
		_builder->Light()->BindPointLight(_altarBolts[i], XMFLOAT3(0.0f, 0.0f, 0.0f), 1.0f, XMFLOAT3(0.35f, 1.0f, 0.25f), 5.0f);
		_builder->Light()->ChangeLightBlobRange(_altarBolts[i], 0.3f);
		_builder->Lightning()->CreateLightningBolt(_altarBolts[i], _altarCenterLight);
		_builder->Lightning()->SetScale(_altarBolts[i], XMFLOAT2(0.4f, 0.4f));
		_builder->Transform()->CreateTransform(_altarBolts[i]);
		_builder->Transform()->BindChild(_altarCenterLight, _altarBolts[i]);

		float angle = XM_2PI / _numAltarBolts;
		_builder->Transform()->SetPosition(_altarBolts[i], XMFLOAT3(1.5f * sinf(i * angle), 0.0f, 1.5f * cosf(i * angle)));

		_altarBoltAngle[i] = i * angle;
	}

	_builder->Transform()->SetPosition(_altar, XMFLOAT3(0.0f, 0.0f, 0.0f));


	_controller->BindEventHandler(_altar, EventManager::Type::Object);
	_controller->BindEvent(_altar, EventManager::EventType::Update,
		[this]()
	{
		_builder->Transform()->RotateYaw(_altarCenterLight, _gameTimer.DeltaTime() * 25.0f);
		static float animDeltaTime = 0;
		animDeltaTime += _gameTimer.DeltaTime();
		bool resetAnimTime = false;
		for (int i = 0; i < _numAltarBolts; ++i)
		{
			_altarBoltAngle[i] += _gameTimer.DeltaTime() * XM_PIDIV2 + _gameTimer.DeltaTime()*XM_PI * (i / 6);
			if (_altarBoltAngle[i] >= XM_2PI)
				_altarBoltAngle[i] -= XM_2PI;

			XMVECTOR pos = _builder->Transform()->GetPosition(_altarBolts[i]);
			_builder->Transform()->SetPosition(_altarBolts[i], XMVectorSetY(pos, 0.8f * sinf(_altarBoltAngle[i])));

			if (animDeltaTime >= 0.02f)
			{
				resetAnimTime = true;
				_builder->Lightning()->Animate(_altarBolts[i]);
			}
		}

		if (resetAnimTime)
			animDeltaTime -= 0.02f;

	});

	Entity camera = _builder->CreateCamera(XMVectorSet(0.0f, 1.0f, -3.0f, 0.0f));
	_builder->Transform()->SetRotation(camera, XMFLOAT3(0.0f, 0.0f, 0.0f));



	//==========================
	//====		Update		====
	//==========================

	_controller->BindEvent(b2, EventManager::EventType::Update, [i, this]()
	{
		if (i->IsKeyPushed(VK_ESCAPE))
		{
			ExitApplication;
		}
		if (i->IsKeyPushed('1'))
		{
			ChangeStateTo(StateChange(new GameState()));
		}
		if (i->IsKeyPushed('2'))
		{
			ChangeStateTo(StateChange(new MenuState()));
		}
	}
	);

}
//--------------------------------------------------------------------------------------
// Handles mouse input
//--------------------------------------------------------------------------------------
void CALLBACK OnMouse( bool bLeftButtonDown, bool bRightButtonDown, bool bMiddleButtonDown, bool bSideButton1Down, bool bSideButton2Down, int nMouseWheelDelta, int xPos, int yPos, void* pUserContext )
{
    if( g_bDrawTerrain )
    {
        if( bRightButtonDown )
        {
            if( g_pInspectionTexture != NULL )
            {
                g_pInspectionTexture = NULL;
            }
            else
            {
                g_pInspectionTexture = g_pTerrainView->GetInspectionTexture();
            }
            g_InspectionSliceIndex = 0;
        }
        return;
    }

    static BOOL MouseDragging = FALSE;
    static XMFLOAT4 DragMouseCursorPos( 0, 0, 0, 0 );
    static XMFLOAT4 DragCameraPos( 0, 0, 0, 0 );

    // vMousePos is the mouse cursor's location on the Z far and near planes in homogenous space
    XMVECTOR vMousePosFar = XMVectorSet( ( (FLOAT)xPos - g_HalfClientWidthPixels ) / g_HalfClientWidthPixels, ( (FLOAT)yPos - g_HalfClientHeightPixels ) / -g_HalfClientHeightPixels, 1, 1 );

    XMMATRIX matView = XMLoadFloat4x4A( &g_matView );
    XMMATRIX matViewProj = matView * XMLoadFloat4x4A( &g_matProjection );
    XMVECTOR vDet;
    XMMATRIX matInvViewProj = XMMatrixInverse( &vDet, matViewProj );

    // vMouseWorldPos is the location in world space of the mouse cursor on the near plane
    XMVECTOR vMouseWorldPosFar = XMVector3TransformCoord( vMousePosFar, matInvViewProj );

    XMVECTOR vCameraPosWorld = XMLoadFloat4A( &g_CameraPos );

    const XMVECTOR vPlaneNormal = XMVectorSet( 0, 1, 0, 0 );
    const XMVECTOR vPlaneDistance = XMVectorZero();

    XMVECTOR vCameraToMouseWorldFar = vMouseWorldPosFar - vCameraPosWorld;

    XMVECTOR t = ( vPlaneDistance - XMVector3Dot( vPlaneNormal, vCameraPosWorld ) ) / XMVector3Dot( vPlaneNormal, vCameraToMouseWorldFar );
    XMVECTOR vMouseCursorWorld = vCameraPosWorld + t * vCameraToMouseWorldFar;

    if( bLeftButtonDown )
    {
        if( !MouseDragging )
        {
            MouseDragging = TRUE;
            XMStoreFloat4( &DragMouseCursorPos, vMouseCursorWorld );
            XMStoreFloat4( &DragCameraPos, vCameraPosWorld );
        }
        else
        {
            XMVECTOR vDragPos = XMLoadFloat4( &DragMouseCursorPos );
            XMVECTOR vCameraDelta = vMouseCursorWorld - vDragPos;

            vCameraPosWorld -= vCameraDelta;

            XMStoreFloat4A( &g_CameraPos, vCameraPosWorld );
            UpdateViewMatrix();
            XMStoreFloat4( &DragCameraPos, vCameraPosWorld );
        }
    }
    else if( MouseDragging )
    {
        MouseDragging = FALSE;
    }

    if( bRightButtonDown )
    {
        ID3D11TiledTexture2D* pCurrentTexture = g_pInspectionTexture;
        g_pInspectionTexture = NULL;

        UINT SceneObjectCount = (UINT)g_SceneObjects.size();
        for( UINT i = 0; i < SceneObjectCount; ++i )
        {
            const SceneObject* pSO = g_SceneObjects[i];
            FLOAT X = pSO->matWorld._41;
            FLOAT Y = pSO->matWorld._43;

            FLOAT DeltaX = fabsf( X - XMVectorGetX( vMouseCursorWorld ) );
            FLOAT DeltaY = fabsf( Y - XMVectorGetZ( vMouseCursorWorld ) );
            if( DeltaX <= 0.5f && DeltaY <= 0.5f )
            {
                g_pInspectionTexture = pSO->Textures[0].pTexture;
                break;
            }
        }

        if( g_pInspectionTexture != pCurrentTexture )
        {
            g_InspectionSliceIndex = 0;
        }
    }

    if( nMouseWheelDelta != 0 )
    {
        const FLOAT LogMoveSpeed = 0.05f * ( (FLOAT)nMouseWheelDelta / 120.0f );

        FLOAT CameraY = XMVectorGetY( vCameraPosWorld );
        float LogYPos = logf( CameraY );
        LogYPos -= LogMoveSpeed;
        
        vCameraPosWorld = XMVectorSetY( vCameraPosWorld, max( 0.001f, expf( LogYPos ) ) );
        XMStoreFloat4A( &g_CameraPos, vCameraPosWorld );
        UpdateViewMatrix();
    }
}