#include <windows.h>
#include <d3d11.h>
#include <d3dx11.h>
#include <d3dcompiler.h>
#include <xnamath.h>
#include <vector>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <cstdint>
#include "resource.h"
#include <map>
#include <list>
#include "DXUT/Core/dxut.h"
#include "DXUTmisc.h"
#include "DXUTcamera.h"
#include "DXUTgui.h"
#include "DXUTsettingsDlg.h"
#include "SDKmisc.h"
#include <algorithm>
#include "Effects11/Inc/d3dx11effect.h"
#include "ntx/NTX.h"
#include "debug.h"
#include "SpriteRenderer.h"
#include "Mesh.h"
#include "T3d.h"
// Convenience macros for safe effect variable retrieval
#define SAFE_GET_PASS(Technique, name, var) {assert(Technique!=NULL); var = Technique->GetPassByName( name ); assert(var->IsValid());}
#define SAFE_GET_TECHNIQUE(effect, name, var) {assert(effect!=NULL); var = effect->GetTechniqueByName( name ); assert(var->IsValid());}
#define SAFE_GET_SCALAR(effect, name, var) {assert(effect!=NULL); var = effect->GetVariableByName( name )->AsScalar(); assert(var->IsValid());}
#define SAFE_GET_VECTOR(effect, name, var) {assert(effect!=NULL); var = effect->GetVariableByName( name )->AsVector(); assert(var->IsValid());}
#define SAFE_GET_MATRIX(effect, name, var) {assert(effect!=NULL); var = effect->GetVariableByName( name )->AsMatrix(); assert(var->IsValid());}
#define SAFE_GET_SAMPLER(effect, name, var) {assert(effect!=NULL); var = effect->GetVariableByName( name )->AsSampler(); assert(var->IsValid());}
#define SAFE_GET_RESOURCE(effect, name, var) {assert(effect!=NULL); var = effect->GetVariableByName( name )->AsShaderResource(); assert(var->IsValid());}
// Help macros
#define DEG2RAD( a ) ( (a) * D3DX_PI / 180.f )
using namespace std;
//--------------------------------------------------------------------------------------
// Global variables
//--------------------------------------------------------------------------------------
// Camera
struct CAMERAPARAMS {
float m_Fovy;
float m_Aspect;
float m_NearPlane;
float m_FarPlane;
} g_CameraParams;
float g_CameraMoveScaler = 1000.f;
float g_CameraRotateScaler = 0.01f;
CFirstPersonCamera g_Camera; // A first person camera
// User Interface
CDXUTDialogResourceManager g_DialogResourceManager; // manager for shared resources of dialogs
CD3DSettingsDlg g_SettingsDlg; // Device settings dialog
CDXUTTextHelper* g_TxtHelper = NULL;
CDXUTDialog g_HUD; // dialog for standard controls
CDXUTDialog g_SampleUI; // dialog for sample specific controls
// A D3DX rendering effect
ID3DX11Effect* g_Effect = NULL; // The whole rendering effect
ID3DX11EffectTechnique* g_Technique = NULL; // One technique to render the effect
ID3DX11EffectPass* g_Pass0 = NULL; // One rendering pass of the technique
ID3DX11EffectMatrixVariable* g_WorldEV = NULL; // World matrix effect variable
ID3DX11EffectMatrixVariable* g_WorldViewProjectionEV = NULL; // WorldViewProjection matrix effect variable
ID3DX11EffectShaderResourceVariable* g_DiffuseEV = NULL; // Effect variable for the diffuse color texture
ID3DX11EffectVectorVariable* g_LightDirEV = NULL; // Light direction in object space
ID3DX11EffectShaderResourceVariable* g_HeightEV = NULL;
ID3DX11EffectShaderResourceVariable* g_NormalEV = NULL;
ID3DX11EffectScalarVariable* g_TerrainResEV = NULL;
ID3DX11EffectScalarVariable* g_TerrainQuadResEV = NULL;
ID3DX11EffectShaderResourceVariable* g_SpecularEV = NULL;
ID3DX11EffectShaderResourceVariable* g_GlowEV = NULL;
ID3DX11EffectMatrixVariable* g_WorldViewEV = NULL;
ID3DX11EffectMatrixVariable* g_WorldViewNormalsEV = NULL;
ID3DX11EffectVectorVariable* g_LightDirViewEV = NULL;
ID3DX11EffectPass* g_Pass1_Mesh = NULL;
// Background color
D3DXVECTOR4 g_ClearColor;
// Terrain meta information
struct PtfHeader{
int16_t magicNumber; // Must be 0x00DA
int16_t version; // Must be 1
int32_t heightSize; // Height data size
int32_t colorSize; // Color data size
int32_t normalSize; // Normal data size
} g_TerrainHeader;
struct Spawn {
float spawntime;
float hMin;
float hMax;
float innerRadius;
float outerRadius;
float borderRadius;
};
struct Object{
string name;
float scale;
float translationX;
float translationY;
float translationZ;
float rotationX;
float rotationY;
float rotationZ;
};
struct Gun
{
float projectileSpeed;
float cooldown;
float damage;
float particleMass;
int textureIndex;
float radius;
float spawnPoint;
float cooldownLeft;
bool firing;
};
struct Projectile
{
float lifetime;
float Speed;
D3DXVECTOR3 pos;
D3DXVECTOR3 dir;
};
struct ExplosionParticleSettings
{
int texIndex;
int maxNumber;
int minNumber;
float maxLifeTime;
float minLifeTime;
float maxSpeed;
float minSpeed;
float maxRadius;
float minRadius;
};
struct ExplosionParticle
{
float timePassed;
float lifetime;
float speed;
float radius;
D3DXVECTOR3 pos;
D3DXVECTOR3 dir;
};
struct EnemyType{
int hitpoints;
int boundingSize;
int speed;
string meshname;
string name;
float scale;
float translationX;
float translationY;
float translationZ;
float rotationX;
float rotationY;
float rotationZ;
};
struct EnemyInstance {
string typeName;
int speed;
int remainingHitpoints;
D3DXVECTOR3 pos;
D3DXVECTOR3 vel;
};
struct explosionStandard{
int number;
int texIndex;
float duration;
};
struct Explosion {
float timePassed;
D3DXVECTOR3 pos;
};
char g_TerrainPath[MAX_PATH] = { '\0' };
int g_TerrainResolution;
int g_TerrainNumVertices = 3;
int g_TerrainNumTriangles = 1;
float g_TerrainWidth = 1000.0f;
float g_TerrainDepth = 1000.0f;
float g_TerrainHeight = 400.0f;
bool g_TerrainSpinning = true;
float g_TerrainSpinSpeed = 0.0f;
D3DXMATRIX g_TerrainWorld; // object- to world-space transformation
// Terrain rendering resources
ID3D11Buffer* g_TerrainHeightBuf = NULL;
ID3D11ShaderResourceView* g_TerrainHeightSRV = NULL;
ID3D11Texture2D* g_TerrainNormalTex = NULL;
ID3D11ShaderResourceView* g_TerrainNormalSRV = NULL;
ID3D11Texture2D* g_TerrainDiffuseTex = NULL; // The terrain's material color for diffuse lighting
ID3D11ShaderResourceView* g_TerrainDiffuseSRV = NULL; // Describes the structure of the diffuse texture to the shader stages
//Meshs/Objects
ID3D11InputLayout* g_MeshInputLayout = NULL;
map<string, Mesh*> g_Meshes;
map<string, EnemyType> g_EnemyTypes;
list <string> enemytypes;
vector<Object> CockpitObjects;
vector<Object> GroundObjects;
vector<unsigned short> terrainHeights;
list<EnemyInstance> g_Enemies;
Spawn spawn;
float g_SpawnTimer = 0.0f;
//Sprites
SpriteRenderer* g_SpriteRenderer;
vector<Sprite> textureFilenames;
vector<Projectile> g_Projectiles_Gatling;
vector<Projectile> g_Projectiles_Plasma;
list<Explosion> g_Explosions;
explosionStandard g_explStandard;
ExplosionParticleSettings eps;
list<ExplosionParticle> g_explParticles;
//Guns
Gun Gatling;
Gun Plasma;
// Scene information
D3DXVECTOR4 g_LightDir;
// General meta data
char g_DebugTexPath[MAX_PATH] = { '\0' };
// General resources
ID3D11ShaderResourceView* g_DebugSRV = NULL;
//--------------------------------------------------------------------------------------
// UI control IDs
//--------------------------------------------------------------------------------------
#define IDC_TOGGLEFULLSCREEN 1
#define IDC_TOGGLEREF 2
#define IDC_CHANGEDEVICE 3
#define IDC_TOGGLESPIN 4
#define IDC_RELOAD_SHADERS 101
//--------------------------------------------------------------------------------------
// Forward declarations
//--------------------------------------------------------------------------------------
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing,
void* pUserContext );
void CALLBACK OnKeyboard( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext );
void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext );
void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void* pUserContext );
bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void* pUserContext );
bool CALLBACK IsD3D11DeviceAcceptable( const CD3D11EnumAdapterInfo *AdapterInfo, UINT Output, const CD3D11EnumDeviceInfo *DeviceInfo,
DXGI_FORMAT BackBufferFormat, bool bWindowed, void* pUserContext );
HRESULT CALLBACK OnD3D11CreateDevice( ID3D11Device* pd3dDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc,
void* pUserContext );
HRESULT CALLBACK OnD3D11ResizedSwapChain( ID3D11Device* pd3dDevice, IDXGISwapChain* pSwapChain,
const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext );
void CALLBACK OnD3D11ReleasingSwapChain( void* pUserContext );
void CALLBACK OnD3D11DestroyDevice( void* pUserContext );
void CALLBACK OnD3D11FrameRender( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext, double fTime,
float fElapsedTime, void* pUserContext );
void InitApp();
void DeinitApp();
void RenderText();
void ReleaseShader();
HRESULT ReloadShader(ID3D11Device* pd3dDevice);
//--------------------------------------------------------------------------------------
// Entry point to the program. Initializes everything and goes into a message processing
// loop. Idle time is used to render the scene.
//--------------------------------------------------------------------------------------
int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow )
{
// Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif
// Old Direct3D Documentation:
// Start > All Programs > Microsoft DirectX SDK (June 2010) > Windows DirectX Graphics Documentation
// DXUT Documentaion:
// Start > All Programs > Microsoft DirectX SDK (June 2010) > DirectX Documentation for C++ : The DirectX Software Development Kit > Programming Guide > DXUT
// New Direct3D Documentaion (just for reference, use old documentation to find explanations):
// http://msdn.microsoft.com/en-us/library/windows/desktop/hh309466%28v=vs.85%29.aspx
// Set DXUT callbacks
DXUTSetCallbackMsgProc( MsgProc );
DXUTSetCallbackKeyboard( OnKeyboard );
DXUTSetCallbackFrameMove( OnFrameMove );
DXUTSetCallbackDeviceChanging( ModifyDeviceSettings );
DXUTSetCallbackD3D11DeviceAcceptable( IsD3D11DeviceAcceptable );
DXUTSetCallbackD3D11DeviceCreated( OnD3D11CreateDevice );
DXUTSetCallbackD3D11SwapChainResized( OnD3D11ResizedSwapChain );
DXUTSetCallbackD3D11SwapChainReleasing( OnD3D11ReleasingSwapChain );
DXUTSetCallbackD3D11DeviceDestroyed( OnD3D11DestroyDevice );
DXUTSetCallbackD3D11FrameRender( OnD3D11FrameRender );
InitApp();
DXUTInit( true, true, NULL ); // Parse the command line, show msgboxes on error, no extra command line params
DXUTSetCursorSettings( true, true );
DXUTCreateWindow( L"TerrainViewer" ); // You may change the title
DXUTCreateDevice( D3D_FEATURE_LEVEL_10_0, true, 1280, 720 );
DXUTMainLoop(); // Enter into the DXUT render loop
DXUTShutdown();
DeinitApp();
return DXUTGetExitCode();
}
//--------------------------------------------------------------------------------------
// Initialize the app
//--------------------------------------------------------------------------------------
void InitApp()
{
char MeshName[MAX_PATH] = {'\0'};
char T3dPath[MAX_PATH]={'\0'};
char DiffusePath[MAX_PATH] = {'\0'};
char SpecularPath[MAX_PATH] = {'\0'};
char GlowPath[MAX_PATH] = {'\0'};
string name;
string meshname;
float scale;
float translationX, translationY, translationZ;
float rotationX, rotationY, rotationZ;
HRESULT hr;
WCHAR path[MAX_PATH];
// Parse the config file
V(DXUTFindDXSDKMediaFileCch(path, MAX_PATH, L"game.cfg"));
ifstream stream(path);
if(!stream) {
MessageBoxA (NULL, "Fatal Error: game.cfg not found.",
"Missing file", MB_ICONERROR | MB_OK);
return;
}
std::string var;
while(!stream.eof())
{
stream >> var;
if ( var.compare("DebugTexPath") ==0 ) stream >> g_DebugTexPath;
if ( var.compare("Spinning") ==0 ) stream >> g_TerrainSpinning;
if ( var.compare("SpinSpeed") ==0 ) stream >> g_TerrainSpinSpeed;
if ( var.compare("BackgroundColor")==0 ) stream >> g_ClearColor.x >> g_ClearColor.y >> g_ClearColor.z >> g_ClearColor.w;
// BEGIN: Assignment 3.2.1
if( var.compare("TerrainPath") ==0) stream >> g_TerrainPath;
if( var.compare("TerrainWidth") ==0) stream >> g_TerrainWidth;
if( var.compare("TerrainDepth") ==0) stream >> g_TerrainDepth;
if( var.compare("TerrainHeight") ==0) stream >> g_TerrainHeight;
if(var.compare("Mesh") == 0){
stream >> MeshName >>T3dPath >> DiffusePath >> SpecularPath >> GlowPath;
g_Meshes[MeshName] = new Mesh(T3dPath, DiffusePath, SpecularPath, GlowPath);
}
if (var.compare("CockpitObject") == 0)
{
stream>>name>>scale>>rotationX>>rotationY>>rotationZ>>translationX>>translationY>>translationZ;
Object co;
co.name = name;
co.scale = scale;
co.rotationX = rotationX;
co.rotationY = rotationY;
co.rotationZ = rotationZ;
co.translationX = translationX;
co.translationY = translationY;
co.translationZ = translationZ;
CockpitObjects.push_back(co);
}
if(var.compare("GroundObject") == 0)
{
stream>>name>>scale>>rotationX>>rotationY>>rotationZ>>translationX>>translationY>>translationZ;
Object go;
go.name = name;
go.scale = scale;
go.rotationX = rotationX;
go.rotationY = rotationY;
go.rotationZ = rotationZ;
go.translationX = translationX;
go.translationY = translationY;
go.translationZ = translationZ;
GroundObjects.push_back(go);
}
if(var.compare("EnemyType") == 0)
{
EnemyType et;
stream>>et.name>>et.hitpoints>>et.boundingSize>>et.speed>>et.meshname>>et.scale>>et.rotationX>>et.rotationY>>et.rotationZ>>et.translationX>>et.translationY>>et.translationZ;
enemytypes.push_back(et.name);
g_EnemyTypes[et.name] = et;
}
if (var.compare("Spawn") == 0)
{
stream>>spawn.spawntime>>spawn.hMin>>spawn.hMax>>spawn.innerRadius>>spawn.outerRadius>>spawn.borderRadius;
}
if(var.compare("Gatling") == 0) stream>>Gatling.projectileSpeed>>Gatling.cooldown>>Gatling.damage>>Gatling.particleMass>>Gatling.textureIndex>>Gatling.radius>>Gatling.spawnPoint;
if(var.compare("Plasma") == 0) stream>>Plasma.projectileSpeed>>Plasma.cooldown>>Plasma.damage>>Plasma.particleMass>>Plasma.textureIndex>>Plasma.radius>>Plasma.spawnPoint;
if(var.compare("Sprite") == 0)
{
Sprite s;
stream>>s.filenameP>>s.min>>s.max;
textureFilenames.push_back(s);
}
if(var.compare("Explosion") == 0) stream>>g_explStandard.texIndex>>g_explStandard.duration>>g_explStandard.number;
if(var.compare("ExplosionParticleSettings") == 0)stream>>eps.maxNumber>>eps.minNumber>>eps.maxLifeTime>>eps.minLifeTime>>eps.maxSpeed>>eps.minSpeed>>eps.maxRadius>>eps.minRadius>>eps.texIndex;
Gatling.firing = false;
Gatling.cooldownLeft = 0.f;
Plasma.firing = false;
Plasma.cooldownLeft = 0.f;
// TODO: Parse the additional information in the config file into the variables:
// g_TerrainPath, g_TerrainWidth, g_TerrainDepth and g_TerrainHeight
// HINT: the operator '>>' converts the next word in 'stream' into the format of
// its right hand side and is really flexible
// END: Assignment 3.2.1
}
stream.close();
// Intialize the user interface
g_SettingsDlg.Init( &g_DialogResourceManager );
g_HUD.Init( &g_DialogResourceManager );
g_SampleUI.Init( &g_DialogResourceManager );
g_HUD.SetCallback( OnGUIEvent );
int iY = 30;
int iYo = 26;
g_HUD.AddButton( IDC_TOGGLEFULLSCREEN, L"Toggle full screen", 0, iY, 170, 22 );
g_HUD.AddButton( IDC_TOGGLEREF, L"Toggle REF (F3)", 0, iY += iYo, 170, 22, VK_F3 );
g_HUD.AddButton( IDC_CHANGEDEVICE, L"Change device (F2)", 0, iY += iYo, 170, 22, VK_F2 );
g_HUD.AddButton (IDC_RELOAD_SHADERS, L"Reload shaders (F5)", 0, iY += 24, 170, 22, VK_F5);
g_SampleUI.SetCallback( OnGUIEvent ); iY = 10;
iY += 24;
g_SampleUI.AddCheckBox( IDC_TOGGLESPIN, L"Toggle Spinning", 0, iY += 24, 125, 22, g_TerrainSpinning );
g_SpriteRenderer = new SpriteRenderer(textureFilenames);
}
void DeinitApp()
{
SAFE_DELETE(g_Meshes["Cockpit"]);
SAFE_DELETE(g_Meshes["GatlingGunBase"]);
SAFE_DELETE(g_Meshes["GatlingGunTop"]);
SAFE_DELETE(g_Meshes["PlasmaGunBase"]);
SAFE_DELETE(g_Meshes["PlasmaGunTop"]);
SAFE_DELETE(g_Meshes["Barracks"]);
SAFE_DELETE(g_Meshes["Tree"]);
SAFE_DELETE(g_Meshes["Amy"]);
SAFE_DELETE(g_Meshes["Lup"]);
SAFE_DELETE(g_Meshes["Juf"]);
SAFE_DELETE(g_SpriteRenderer);
}
//--------------------------------------------------------------------------------------
// Render the help and statistics text. This function uses the ID3DXFont interface for
// efficient text rendering.
//--------------------------------------------------------------------------------------
void RenderText()
{
g_TxtHelper->Begin();
g_TxtHelper->SetInsertionPos( 5, 5 );
g_TxtHelper->SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ) );
g_TxtHelper->DrawTextLine( DXUTGetFrameStats(true)); //DXUTIsVsyncEnabled() ) );
g_TxtHelper->DrawTextLine( DXUTGetDeviceStats() );
g_TxtHelper->End();
}
float getHeightAtPoint(float x, float y) {
int k = min(g_TerrainResolution - 1, (0.5f + x / g_TerrainWidth) * g_TerrainResolution);
int t = min(g_TerrainResolution - 1, (0.5f - y / g_TerrainDepth) * g_TerrainResolution);
return g_TerrainHeight * terrainHeights[(int)(k + g_TerrainResolution * t)] / (float)UINT16_MAX;
}
//--------------------------------------------------------------------------------------
// Reject any D3D11 devices that aren't acceptable by returning false
//--------------------------------------------------------------------------------------
bool CALLBACK IsD3D11DeviceAcceptable( const CD3D11EnumAdapterInfo *AdapterInfo, UINT Output, const CD3D11EnumDeviceInfo *DeviceInfo,
DXGI_FORMAT BackBufferFormat, bool bWindowed, void* pUserContext )
{
return true;
}
//--------------------------------------------------------------------------------------
// Specify the initial device settings
//--------------------------------------------------------------------------------------
bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void* pUserContext )
{
// For the first device created if its a REF device, optionally display a warning dialog box
static bool s_bFirstTime = true;
if( s_bFirstTime )
{
s_bFirstTime = false;
if( ( DXUT_D3D9_DEVICE == pDeviceSettings->ver && pDeviceSettings->d3d9.DeviceType == D3DDEVTYPE_REF ) ||
( DXUT_D3D11_DEVICE == pDeviceSettings->ver &&
pDeviceSettings->d3d11.DriverType == D3D_DRIVER_TYPE_REFERENCE ) )
{
DXUTDisplaySwitchingToREFWarning( pDeviceSettings->ver );
}
}
//// Enable anti aliasing
//pDeviceSettings->d3d11.sd.SampleDesc.Count = 4;
//pDeviceSettings->d3d11.sd.SampleDesc.Quality = 1;
return true;
}
//--------------------------------------------------------------------------------------
// Create any D3D11 resources that aren't dependant on the back buffer
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnD3D11CreateDevice( ID3D11Device* pd3dDevice,
const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext )
{
HRESULT hr;
ID3D11DeviceContext* pd3dImmediateContext = DXUTGetD3D11DeviceContext(); // http://msdn.microsoft.com/en-us/library/ff476891%28v=vs.85%29
V_RETURN( g_DialogResourceManager.OnD3D11CreateDevice( pd3dDevice, pd3dImmediateContext ) );
V_RETURN( g_SettingsDlg.OnD3D11CreateDevice( pd3dDevice ) );
g_TxtHelper = new CDXUTTextHelper( pd3dDevice, pd3dImmediateContext, &g_DialogResourceManager, 15 );
V_RETURN( ReloadShader(pd3dDevice) );
errno_t error;
WCHAR path[MAX_PATH];
stringstream ss;
wstringstream wss;
// Load the debug texture and create a shader resource view
wss.str(L""); wss << g_DebugTexPath;
V(DXUTFindDXSDKMediaFileCch( path, MAX_PATH, wss.str().c_str()));
if (hr != S_OK) {
ss.str();
ss << "Could not find '" << g_DebugTexPath << "'";
MessageBoxA (NULL, ss.str().c_str(), "Missing file", MB_ICONERROR | MB_OK);
return hr;
}
V(D3DX11CreateShaderResourceViewFromFile(pd3dDevice, path, NULL, NULL, &g_DebugSRV, &hr));
if (hr != S_OK) {
ss.str();
ss << "Could not load texture '" << g_DebugTexPath << "'";
MessageBoxA (NULL, ss.str().c_str(), "Invalid texture", MB_ICONERROR | MB_OK);
return hr;
}
// Find the terrain file
wss.str(L""); wss << g_TerrainPath;
V(DXUTFindDXSDKMediaFileCch( path, MAX_PATH, wss.str().c_str()));
if (hr != S_OK) {
ss.str();
ss << "Could not find '" << g_TerrainPath << "'";
MessageBoxA (NULL, ss.str().c_str(), "Missing file", MB_ICONERROR | MB_OK);
return hr;
}
// Open the terrain file
FILE* file;
error = _wfopen_s(&file, path, L"rb");
if (file == nullptr) {
ss.str();
ss << "Could not open '" << g_TerrainPath << "'";
MessageBoxA (NULL, ss.str().c_str(), "File error", MB_ICONERROR | MB_OK);
return E_FAIL;
}
// Read the terrain header
{
auto r = fread (&g_TerrainHeader, sizeof (g_TerrainHeader), 1, file);
if (r != 1) {
MessageBoxA (NULL, "Could not read the header.",
"Invalid terrain file", MB_ICONERROR | MB_OK);
return E_FAIL;
}
}
// Check the magic number
if (g_TerrainHeader.magicNumber != 0x00DA) {
MessageBoxA (NULL, "The magic number is incorrect.",
"Invalid terrain file header", MB_ICONERROR | MB_OK);
return E_FAIL;
}
// Check the version
if (g_TerrainHeader.version != 1) {
MessageBoxA (NULL, "The header version is incorrect.",
"Invalid terrain file header", MB_ICONERROR | MB_OK);
return E_FAIL;
}
// Calculate the terrain resolution from the height size
g_TerrainResolution = (int)sqrt(g_TerrainHeader.heightSize / 2.0); // Assume a square terrain
g_TerrainNumVertices = g_TerrainResolution * g_TerrainResolution;
g_TerrainNumTriangles = 2 * (g_TerrainResolution - 1) * (g_TerrainResolution - 1) ;
assert((g_TerrainHeader.heightSize / 2) == g_TerrainNumVertices);
// Read the terrain heights
//std::vector<unsigned short> terrainHeights;
terrainHeights.resize(g_TerrainNumVertices);
{
if (g_TerrainHeader.heightSize != (int)::fread (&terrainHeights[0], sizeof(BYTE), g_TerrainHeader.heightSize, file)) {
MessageBoxA(NULL, "Error while reading height data.",
"Invalid terrain file", MB_ICONERROR | MB_OK);
return E_FAIL;
}
}
// Read the terrain color texture for diffuse lighting
std::vector<unsigned char> terrainDiffuseNtx;
terrainDiffuseNtx.resize(g_TerrainHeader.colorSize);
{
const auto requestedSize = terrainDiffuseNtx.size();
if (requestedSize != fread (&terrainDiffuseNtx[0], sizeof(unsigned char), requestedSize, file)) {
MessageBoxA (NULL, "Error while reading color data.",
"Invalid terrain file", MB_ICONERROR | MB_OK);
return E_FAIL;
}
}
// Read the terrain normal texture
std::vector<unsigned char> terrainNormalNtx;
terrainNormalNtx.resize(g_TerrainHeader.normalSize);
{
const auto requestedSize = terrainNormalNtx.size();
if (requestedSize != fread (&terrainNormalNtx[0], sizeof(unsigned char), requestedSize, file)) {
MessageBoxA (NULL, "Error while reading color data.",
"Invalid terrain file", MB_ICONERROR | MB_OK);
return E_FAIL;
}
}
fclose(file);
// Initialize the camera
D3DXVECTOR3 Eye( 0.0f, terrainHeights[g_TerrainResolution*g_TerrainResolution/2+g_TerrainResolution/2]/UINT16_MAX * g_TerrainHeight + 200, 0 );
D3DXVECTOR3 At( 0.0f, 0.0f, 0.0f );
g_Camera.SetViewParams( &Eye, &At ); // http://msdn.microsoft.com/en-us/library/windows/desktop/bb206342%28v=vs.85%29.aspx
g_Camera.SetScalers( g_CameraRotateScaler, g_CameraMoveScaler );
/*int iVB = 0; // You can use this variable as index into the vertex buffer ( terrainVB[iVB++] = ... )
float snx = (g_TerrainHeight * (g_TerrainResolution - 1)) / (g_TerrainWidth * 2.0f);
float sny = (g_TerrainHeight * (g_TerrainResolution - 1)) / (g_TerrainDepth * 2.0f);
for(int v = 0; v < g_TerrainResolution; v++) {
for(int u = 0; u < g_TerrainResolution; u++) {
// Retrieve the height
float height = terrainHeights[u + v * g_TerrainResolution] / 65535.f; // [0, 1]
// Calculate the normal
float heightL = terrainHeights[max(0, u - 1) + v * g_TerrainResolution] / 65535.f;
float heightR = terrainHeights[min(g_TerrainResolution - 1, u + 1) + v * g_TerrainResolution] / 65535.f;
float heightU = terrainHeights[u + max(0, v - 1) * g_TerrainResolution] / 65535.f;
float heightD = terrainHeights[u + min(g_TerrainResolution - 1, v + 1) * g_TerrainResolution] / 65535.f;
D3DXVECTOR3 n(snx * (heightL - heightR), sny * (heightU - heightD), 1.f);
D3DXVec3Normalize(&n, &n);
}
}*/
// BEGIN: Assignment 4.2.6
D3D11_SUBRESOURCE_DATA id;
id.pSysMem = &terrainHeights[0];
id.SysMemPitch = sizeof(unsigned short);
id.SysMemSlicePitch = 0;
D3D11_BUFFER_DESC bd;
bd.BindFlags = D3D11_BIND_SHADER_RESOURCE;
bd.ByteWidth = g_TerrainNumVertices * id.SysMemPitch;
bd.CPUAccessFlags = 0;
bd.MiscFlags = 0;
bd.Usage = D3D11_USAGE_DEFAULT;
pd3dDevice->CreateBuffer(&bd, &id, &g_TerrainHeightBuf);
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
srvDesc.Format = DXGI_FORMAT_R16_UNORM;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
srvDesc.Buffer.FirstElement = 0;
srvDesc.Buffer.NumElements = g_TerrainResolution * g_TerrainResolution;
V_RETURN(pd3dDevice->CreateShaderResourceView(g_TerrainHeightBuf, &srvDesc, &g_TerrainHeightSRV));
// END: Assignment 4.2.6
D3D11_TEXTURE2D_DESC tex2DDesc;
std::vector<std::vector<unsigned char>> textureData;
std::vector<D3D11_SUBRESOURCE_DATA> subresourceData;
bool sRgb;
LoadNtx(terrainDiffuseNtx, &tex2DDesc, textureData, subresourceData, sRgb );
pd3dDevice->CreateTexture2D(&tex2DDesc, &subresourceData[0], &g_TerrainDiffuseTex);
pd3dDevice->CreateShaderResourceView(g_TerrainDiffuseTex, NULL, &g_TerrainDiffuseSRV);
LoadNtx(terrainNormalNtx, &tex2DDesc, textureData, subresourceData, sRgb);
pd3dDevice->CreateTexture2D(&tex2DDesc, &subresourceData[0], &g_TerrainNormalTex);
pd3dDevice->CreateShaderResourceView(g_TerrainNormalTex, NULL,&g_TerrainNormalSRV);
g_Meshes["Cockpit"]->CreateResources(pd3dDevice);
g_Meshes["GatlingGunBase"]->CreateResources(pd3dDevice);
g_Meshes["GatlingGunTop"]->CreateResources(pd3dDevice);
g_Meshes["PlasmaGunBase"]->CreateResources(pd3dDevice);
g_Meshes["PlasmaGunTop"]->CreateResources(pd3dDevice);
g_Meshes["Barracks"]->CreateResources(pd3dDevice);
g_Meshes["Tree"]->CreateResources(pd3dDevice);
g_Meshes["Amy"]->CreateResources(pd3dDevice);
g_Meshes["Lup"]->CreateResources(pd3dDevice);
g_Meshes["Juf"]->CreateResources(pd3dDevice);
g_SpriteRenderer->CreateResources(pd3dDevice);
T3d::CreateT3dInputLayout(pd3dDevice, g_Pass1_Mesh, &g_MeshInputLayout);
return S_OK;
}
//--------------------------------------------------------------------------------------
// Release D3D11 resources created in OnD3D11CreateDevice
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D11DestroyDevice( void* pUserContext )
{
g_DialogResourceManager.OnD3D11DestroyDevice();
g_SettingsDlg.OnD3D11DestroyDevice();
DXUTGetGlobalResourceCache().OnDestroyDevice();
SAFE_RELEASE( g_DebugSRV );
// Assignment 3.2.4
// TODO: Release the index buffer
// Assignment 3.2.5
// TODO: Release the terrain's shader resource view and texture
SAFE_RELEASE(g_TerrainDiffuseTex);
SAFE_RELEASE(g_TerrainDiffuseSRV);
SAFE_RELEASE(g_TerrainNormalTex);
SAFE_RELEASE(g_TerrainNormalSRV);
SAFE_RELEASE(g_TerrainHeightBuf);
SAFE_RELEASE(g_TerrainHeightSRV);
SAFE_RELEASE(g_MeshInputLayout);
SAFE_DELETE( g_TxtHelper );
g_Meshes["Cockpit"]->ReleaseResources();
g_Meshes["GatlingGunBase"]->ReleaseResources();
g_Meshes["GatlingGunTop"]->ReleaseResources();
g_Meshes["PlasmaGunBase"]->ReleaseResources();
g_Meshes["PlasmaGunTop"]->ReleaseResources();
g_Meshes["Barracks"]->ReleaseResources();
g_Meshes["Tree"]->ReleaseResources();
g_Meshes["Amy"]->ReleaseResources();
g_Meshes["Lup"]->ReleaseResources();
g_Meshes["Juf"]->ReleaseResources();
g_SpriteRenderer->ReleaseResources();
ReleaseShader();
}
//--------------------------------------------------------------------------------------
// Create any D3D11 resources that depend on the back buffer
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnD3D11ResizedSwapChain( ID3D11Device* pd3dDevice, IDXGISwapChain* pSwapChain,
const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext )
{
HRESULT hr;
// Intialize the user interface
V_RETURN( g_DialogResourceManager.OnD3D11ResizedSwapChain( pd3dDevice, pBackBufferSurfaceDesc ) );
V_RETURN( g_SettingsDlg.OnD3D11ResizedSwapChain( pd3dDevice, pBackBufferSurfaceDesc ) );
g_HUD.SetLocation( pBackBufferSurfaceDesc->Width - 170, 0 );
g_HUD.SetSize( 170, 170 );
g_SampleUI.SetLocation( pBackBufferSurfaceDesc->Width - 170, pBackBufferSurfaceDesc->Height - 300 );
g_SampleUI.SetSize( 170, 300 );
// Initialize the camera
g_CameraParams.m_Aspect = pBackBufferSurfaceDesc->Width / ( FLOAT )pBackBufferSurfaceDesc->Height;
g_CameraParams.m_Fovy = 0.785398;
g_CameraParams.m_NearPlane = 1.f;
g_CameraParams.m_FarPlane = 2000.f;
g_Camera.SetProjParams(g_CameraParams.m_Fovy, g_CameraParams.m_Aspect, g_CameraParams.m_NearPlane, g_CameraParams.m_FarPlane);
g_Camera.SetEnablePositionMovement(false);
g_Camera.SetRotateButtons(true, false, false);
g_Camera.SetScalers( g_CameraRotateScaler, g_CameraMoveScaler );
g_Camera.SetDrag( true );
return S_OK;
}
//--------------------------------------------------------------------------------------
// Release D3D11 resources created in OnD3D11ResizedSwapChain
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D11ReleasingSwapChain( void* pUserContext )
{
g_DialogResourceManager.OnD3D11ReleasingSwapChain();
}
//--------------------------------------------------------------------------------------
// Loads the effect from file
// and retrieves all dependent variables
//--------------------------------------------------------------------------------------
HRESULT ReloadShader(ID3D11Device* pd3dDevice)
{
assert(pd3dDevice != NULL);
HRESULT hr;
ReleaseShader();
WCHAR path[MAX_PATH];
stringstream ss;
wstringstream wss;
// Find and load the rendering effect
V_RETURN(DXUTFindDXSDKMediaFileCch(path, MAX_PATH, L"game.fxo"));
ifstream is(path, ios_base::binary);
is.seekg(0, ios_base::end);
streampos pos = is.tellg();
is.seekg(0, ios_base::beg);
vector<char> effectBuffer((unsigned int)pos);
is.read(&effectBuffer[0], pos);
is.close();
V_RETURN(D3DX11CreateEffectFromMemory((const void*)&effectBuffer[0], effectBuffer.size(), 0, pd3dDevice, &g_Effect));
assert(g_Effect->IsValid());
// Obtain the effect technique
SAFE_GET_TECHNIQUE(g_Effect, "Render", g_Technique);
// Obtain the effect pass
SAFE_GET_PASS(g_Technique, "P0", g_Pass0);
SAFE_GET_PASS(g_Technique, "P1_Mesh", g_Pass1_Mesh);
// Obtain the effect variables
SAFE_GET_RESOURCE(g_Effect, "g_Diffuse", g_DiffuseEV);
SAFE_GET_MATRIX(g_Effect, "g_World", g_WorldEV);
SAFE_GET_MATRIX(g_Effect, "g_WorldViewProjection", g_WorldViewProjectionEV);
SAFE_GET_VECTOR(g_Effect, "g_LightDir", g_LightDirEV);
SAFE_GET_RESOURCE(g_Effect, "g_Height", g_HeightEV);
SAFE_GET_RESOURCE(g_Effect, "g_Normal", g_NormalEV);
SAFE_GET_SCALAR(g_Effect, "g_TerrainRes", g_TerrainResEV);
SAFE_GET_SCALAR(g_Effect, "g_TerrainQuadRes", g_TerrainQuadResEV);
SAFE_GET_RESOURCE(g_Effect, "g_Specular", g_SpecularEV);
SAFE_GET_RESOURCE(g_Effect, "g_Glow", g_GlowEV);
SAFE_GET_MATRIX(g_Effect, "g_WorldView", g_WorldViewEV);
SAFE_GET_MATRIX(g_Effect, "g_WorldViewNormals", g_WorldViewNormalsEV);
SAFE_GET_VECTOR(g_Effect, "g_LightDirView", g_LightDirViewEV);
g_SpriteRenderer->ReloadShader(pd3dDevice);
return S_OK;
}
//--------------------------------------------------------------------------------------
// Release resources created in ReloadShader
//--------------------------------------------------------------------------------------
void ReleaseShader()
{
SAFE_RELEASE( g_Effect );
g_SpriteRenderer->ReleaseShader();
}
//--------------------------------------------------------------------------------------
// Handle messages to the application
//--------------------------------------------------------------------------------------
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing,
void* pUserContext )
{
// Pass messages to dialog resource manager calls so GUI state is updated correctly
*pbNoFurtherProcessing = g_DialogResourceManager.MsgProc( hWnd, uMsg, wParam, lParam );
if( *pbNoFurtherProcessing )
return 0;
// Pass messages to settings dialog if its active
if( g_SettingsDlg.IsActive() )
{
g_SettingsDlg.MsgProc( hWnd, uMsg, wParam, lParam );
return 0;
}
// Give the dialogs a chance to handle the message first
*pbNoFurtherProcessing = g_HUD.MsgProc( hWnd, uMsg, wParam, lParam );
if( *pbNoFurtherProcessing )
return 0;
*pbNoFurtherProcessing = g_SampleUI.MsgProc( hWnd, uMsg, wParam, lParam );
if( *pbNoFurtherProcessing )
return 0;
// Use the mouse weel to control the movement speed
if(uMsg == WM_MOUSEWHEEL) {
int zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
g_CameraMoveScaler *= (1 + zDelta / 500.0f);
if (g_CameraMoveScaler < 0.1f)
g_CameraMoveScaler = 0.1f;
g_Camera.SetScalers(g_CameraRotateScaler, g_CameraMoveScaler);
}
// Pass all remaining windows messages to camera so it can respond to user input
g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam );
return 0;
}
//--------------------------------------------------------------------------------------
// Handle key presses
//--------------------------------------------------------------------------------------
void CALLBACK OnKeyboard( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext )
{
if(nChar == 32)
{
if(bKeyDown) Gatling.firing = true;
}
if(nChar == 13)
{
if(bKeyDown) Plasma.firing = true;
}
}
//--------------------------------------------------------------------------------------
// Handles the GUI events
//--------------------------------------------------------------------------------------
void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext )
{
switch( nControlID )
{
case IDC_TOGGLEFULLSCREEN:
DXUTToggleFullScreen(); break;
case IDC_TOGGLEREF:
DXUTToggleREF(); break;
case IDC_CHANGEDEVICE:
g_SettingsDlg.SetActive( !g_SettingsDlg.IsActive() ); break;
case IDC_TOGGLESPIN:
g_TerrainSpinning = g_SampleUI.GetCheckBox( IDC_TOGGLESPIN )->GetChecked();
break;
case IDC_RELOAD_SHADERS:
ReloadShader(DXUTGetD3D11Device ());
break;
}
}
//--------------------------------------------------------------------------------------
// Handle updates to the scene. This is called regardless of which D3D API is used
//--------------------------------------------------------------------------------------
void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void* pUserContext )
{
// Update the camera's position based on user input
g_Camera.FrameMove( fElapsedTime );
D3DXMATRIX mTmp;
list<string>::iterator it;
g_SpawnTimer -= fElapsedTime;
if(g_SpawnTimer < 0)
{
g_SpawnTimer = spawn.spawntime;
EnemyInstance e;
D3DXVECTOR3 direction;
int i = rand()%enemytypes.size();
it = enemytypes.begin();
std::advance(it, i);
e.typeName = *it;
e.remainingHitpoints = (g_EnemyTypes[e.typeName]).hitpoints;
e.speed = g_EnemyTypes[e.typeName].speed;
float randVal = (float) rand() / (float) RAND_MAX;
float a = randVal * D3DX_PI*2;
e.pos.x = spawn.outerRadius * (sin(a), cos(a));
e.pos.z = spawn.outerRadius*(cos(a), sin(a));
e.pos.y = randVal*(spawn.hMax*g_TerrainHeight - spawn.hMin*g_TerrainHeight) + spawn.hMin*g_TerrainHeight;
randVal = (float) rand() / (float) RAND_MAX;
a = randVal * D3DX_PI*2;
direction.x = spawn.innerRadius * (sin(a), cos(a));
direction.z = spawn.innerRadius * (cos(a), sin(a));
direction.y = e.pos.y;
D3DXVECTOR3 helpvec = direction - e.pos;
D3DXVec3Normalize(&helpvec,&helpvec);
e.vel = (D3DXVECTOR3)(e.speed * helpvec);
g_Enemies.push_back(e);
}
Gatling.cooldownLeft -= fElapsedTime;
if(Gatling.firing)
{
if(Gatling.cooldownLeft <= 0.f)
{
Projectile pro;
pro.Speed = Gatling.projectileSpeed;
pro.lifetime = 0.f;
pro.dir = *g_Camera.GetWorldAhead();
D3DXMATRIX world = *g_Camera.GetWorldMatrix();
D3DXVECTOR3 Spawn;
Spawn.x = Gatling.spawnPoint;
Spawn.y = 0.5;
Spawn.z = 7;
D3DXVec3TransformCoord(&pro.pos,&Spawn,&world);
g_Projectiles_Gatling.push_back(pro);
Gatling.cooldownLeft = Gatling.cooldown;
Gatling.firing = false;
}
}
/*D3DXVECTOR4 lightDirView;
D3DXVec4Transform(&lightDirView, &g_LightDir, &viewTransformation);
D3DXVec3Normalize((D3DXVECTOR3*)&lightDirView, (D3DXVECTOR3*)&lightDirView);*/
Plasma.cooldownLeft -= fElapsedTime;
if(Plasma.firing)
{
if(Plasma.cooldownLeft <= 0.f)
{
Projectile pro;
pro.lifetime = 0.f;
pro.Speed = Plasma.projectileSpeed;
pro.dir = *g_Camera.GetWorldAhead();
D3DXMATRIX world = *g_Camera.GetWorldMatrix();
D3DXVECTOR3 Spawn;
Spawn.x = Plasma.spawnPoint;
Spawn.y = 0.5;
Spawn.z = 7;
D3DXVec3TransformCoord(&pro.pos,&Spawn,&world);
g_Projectiles_Plasma.push_back(pro);
Plasma.cooldownLeft = Plasma.cooldown;
Plasma.firing = false;
}
}
for(int i = 0; i < g_Projectiles_Gatling.size(); i++)
{
if(g_Projectiles_Gatling[i].lifetime > 5.f)
{
Projectile helper;
helper = g_Projectiles_Gatling[g_Projectiles_Gatling.size()-1];
g_Projectiles_Gatling[g_Projectiles_Gatling.size()-1] = g_Projectiles_Gatling[i];
g_Projectiles_Gatling[i] = helper;
g_Projectiles_Gatling.resize(g_Projectiles_Gatling.size()-1);
i--;
}
else
{
g_Projectiles_Gatling[i].lifetime += fElapsedTime;
g_Projectiles_Gatling[i].dir.y = g_Projectiles_Gatling[i].dir.y - Gatling.particleMass * fElapsedTime;
g_Projectiles_Gatling[i].pos.x = g_Projectiles_Gatling[i].pos.x + g_Projectiles_Gatling[i].dir.x * Gatling.projectileSpeed * fElapsedTime;
g_Projectiles_Gatling[i].pos.z = g_Projectiles_Gatling[i].pos.z + g_Projectiles_Gatling[i].dir.z * Gatling.projectileSpeed * fElapsedTime;
g_Projectiles_Gatling[i].pos.y = g_Projectiles_Gatling[i].pos.y + g_Projectiles_Gatling[i].dir.y * Gatling.projectileSpeed * fElapsedTime;
}
}
for(int i = 0; i < g_Projectiles_Plasma.size() ; i++)
{
if(g_Projectiles_Plasma[i].lifetime > 7.f)
{
Projectile helper;
helper = g_Projectiles_Plasma[g_Projectiles_Plasma.size()-1];
g_Projectiles_Plasma[g_Projectiles_Plasma.size()-1] = g_Projectiles_Plasma[i];
g_Projectiles_Plasma[i] = helper;
g_Projectiles_Plasma.resize(g_Projectiles_Plasma.size()-1);
i--;
}
else
{
g_Projectiles_Plasma[i].lifetime += fElapsedTime;
g_Projectiles_Plasma[i].pos.x = g_Projectiles_Plasma[i].pos.x + g_Projectiles_Plasma[i].dir.x * Plasma.projectileSpeed * fElapsedTime;
g_Projectiles_Plasma[i].pos.z = g_Projectiles_Plasma[i].pos.z + g_Projectiles_Plasma[i].dir.z * Plasma.projectileSpeed * fElapsedTime;
g_Projectiles_Plasma[i].pos.y = g_Projectiles_Plasma[i].pos.y + g_Projectiles_Plasma[i].dir.y * (Plasma.projectileSpeed - Plasma.particleMass * fElapsedTime) * fElapsedTime;
}
}
for(int i = 0; i < g_Projectiles_Plasma.size(); i++)
{
for(auto it = g_Enemies.begin(); it != g_Enemies.end(); )
{
if(D3DXVec3Length(&((*it).pos - g_Projectiles_Plasma[i].pos)) < (g_EnemyTypes[(*it).typeName]).boundingSize + Plasma.radius)
{
Projectile helper;
helper = g_Projectiles_Plasma[g_Projectiles_Plasma.size()-1];
g_Projectiles_Plasma[g_Projectiles_Plasma.size()-1] = g_Projectiles_Plasma[i];
g_Projectiles_Plasma[i] = helper;
g_Projectiles_Plasma.resize(g_Projectiles_Plasma.size()-1);
i--;
(*it).remainingHitpoints -= Plasma.damage;
if((*it).remainingHitpoints <= 0)
{
Explosion et;
et.pos = (*it).pos + (*it).vel;
et.timePassed = 0;
g_Explosions.push_back(et);
int number;
number = eps.minNumber + (rand()%(eps.maxNumber-eps.minNumber));
for(int i = 0; i<number; i++)
{
ExplosionParticle ep;
ep.lifetime = eps.minLifeTime +(rand()%int(eps.maxLifeTime*100-eps.minLifeTime*100))/100.f;
ep.pos = et.pos;
ep.timePassed = 0;
ep.radius = eps.minRadius + (rand()%int(eps.maxRadius*100-eps.minRadius*100))/100.f;
ep.speed = eps.minSpeed + (rand()%int(eps.maxSpeed-eps.minSpeed));
D3DXVECTOR3 dir;
float alpha = rand()%180;
float beta = rand()%360;
dir.x = sin(alpha) * cos(beta);
dir.y = sin(alpha) * sin(beta);
dir.z = cos(alpha);
ep.dir = dir;
g_explParticles.push_back(ep);
}
auto it_remove = it;
it++;
g_Enemies.erase(it_remove);
}
break;
}
it++;
}
}
for(int i = 0; i <g_Projectiles_Gatling.size();i++)
{
for(auto it = g_Enemies.begin(); it != g_Enemies.end(); )
{
if(D3DXVec3Length(&((*it).pos - g_Projectiles_Gatling[i].pos)) < (g_EnemyTypes[(*it).typeName]).boundingSize + Gatling.radius)
{
Projectile helper;
helper = g_Projectiles_Gatling[g_Projectiles_Gatling.size()-1];
g_Projectiles_Gatling[g_Projectiles_Gatling.size()-1] = g_Projectiles_Gatling[i];
g_Projectiles_Gatling[i] = helper;
g_Projectiles_Gatling.resize(g_Projectiles_Gatling.size()-1);
i--;
(*it).remainingHitpoints -= Gatling.damage;
if((*it).remainingHitpoints <= 0)
{
Explosion et;
et.pos = (*it).pos + (*it).vel;
et.timePassed = 0;
g_Explosions.push_back(et);
int number;
number = eps.minNumber + (rand()%(eps.maxNumber-eps.minNumber));
for(int i = 0; i<number; i++)
{
ExplosionParticle ep;
ep.lifetime = eps.minLifeTime +(rand()%int(eps.maxLifeTime*100-eps.minLifeTime*100))/100.f;
ep.pos = et.pos;
ep.timePassed = 0;
ep.radius = eps.minRadius + (rand()%int(eps.maxRadius*100-eps.minRadius*100))/100.f;
ep.speed = eps.minSpeed + (rand()%int(eps.maxSpeed-eps.minSpeed));
D3DXVECTOR3 dir;
float alpha = rand()%180;
float beta = rand()%360;
dir.x = sin(alpha) * cos(beta);
dir.y = sin(alpha) * sin(beta);
dir.z = cos(alpha);
ep.dir = dir;
g_explParticles.push_back(ep);
}
auto it_remove = it;
it++;
g_Enemies.erase(it_remove);
}
break;
}
it++;
}
}
for(auto it = g_explParticles.begin(); it != g_explParticles.end();)
{
(*it).timePassed += fElapsedTime/(*it).lifetime;
(*it).pos.x = (*it).pos.x + (*it).dir.x * (*it).speed * fElapsedTime;
(*it).pos.z = (*it).pos.z + (*it).dir.z * (*it).speed * fElapsedTime;
(*it).pos.y = (*it).pos.y + (*it).dir.y * (*it).speed * fElapsedTime;
if((*it).timePassed >= 1)
{
auto it_remove = it;
it++;
g_explParticles.erase(it_remove);
break;
}
it++;
}
for(auto it = g_Explosions.begin(); it != g_Explosions.end();)
{
(*it).timePassed += fElapsedTime/g_explStandard.duration;
if((*it).timePassed >= 1.f)
{
auto it_remove = it;
it++;
g_Explosions.erase(it_remove);
break;
}
it++;
}
for(auto it = g_Enemies.begin(); it != g_Enemies.end(); )
{
if (D3DXVec3Length(&(*it).pos)>spawn.borderRadius)
{
auto it_remove = it;
it++;
g_Enemies.erase(it_remove);
}
else
{
(*it).pos += fElapsedTime * (*it).vel;
it++;
}
}
// Initialize the terrain world matrix
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb206365%28v=vs.85%29.aspx
// Set origin to (0.5, 0.5, 0)
D3DXMatrixTranslation(&g_TerrainWorld, -0.5f, -0.5f, 0.f); // Assume: x, y and z are in [0,1]
// Scale to terrain extents
D3DXMatrixScaling(&mTmp, g_TerrainWidth, g_TerrainDepth, g_TerrainHeight);
g_TerrainWorld = g_TerrainWorld * mTmp;
// Since "up" is z-axis in object space, but y-axis in world space, we rotate around the x-axis
D3DXMatrixRotationX( &mTmp, DEG2RAD( -90.0f ) );
g_TerrainWorld *= mTmp;
if( g_TerrainSpinning ) {
D3DXMatrixRotationY( &mTmp, g_TerrainSpinSpeed * DEG2RAD((float)fTime) );
g_TerrainWorld *= mTmp; // Rotate around world-space "up" axis
}
g_LightDir = D3DXVECTOR4(1, 1, -1, 0); // Direction to the directional light in world space
// Transform the light vector to terrain object space
//D3DXMATRIX invWorld;
//D3DXMatrixInverse(&invWorld, NULL, &g_TerrainWorld);
//D3DXVec4Transform(&g_LightDir, &g_LightDir, &invWorld);
//D3DXVec3Normalize((D3DXVECTOR3*)&g_LightDir, (D3DXVECTOR3*)&g_LightDir); // Normalize the light direction
}
//--------------------------------------------------------------------------------------
// Render the scene using the D3D11 device
//--------------------------------------------------------------------------------------
bool compare(SpriteVertex i, SpriteVertex j)
{
return (D3DXVec3Dot(&i.Position,g_Camera.GetWorldAhead())>D3DXVec3Dot(&j.Position, g_Camera.GetWorldAhead()));
}
void CALLBACK OnD3D11FrameRender( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext, double fTime,
float fElapsedTime, void* pUserContext )
{
HRESULT hr;
D3DXMATRIX inverseTerrainWorldDir;
D3DXVECTOR4 lightDirObj;
D3DXMatrixTranspose(&inverseTerrainWorldDir,&g_TerrainWorld);
D3DXVec4Transform(&lightDirObj, &g_LightDir, &inverseTerrainWorldDir);
D3DXVec3Normalize((D3DXVECTOR3*)&lightDirObj, (D3DXVECTOR3*)&lightDirObj);
// If the settings dialog is being shown, then render it instead of rendering the app's scene
if( g_SettingsDlg.IsActive() )
{
g_SettingsDlg.OnRender( fElapsedTime );
return;
}
ID3D11RenderTargetView* pRTV = DXUTGetD3D11RenderTargetView();
pd3dImmediateContext->ClearRenderTargetView( pRTV, g_ClearColor );
if(g_Effect == NULL) {
g_TxtHelper->Begin();
g_TxtHelper->SetInsertionPos( 5, 5 );
g_TxtHelper->SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ) );
g_TxtHelper->DrawTextLine( L"SHADER ERROR" );
g_TxtHelper->End();
return;
}
vector<SpriteVertex> SpriteVector;
for(int i = 0; i < g_Projectiles_Gatling.size();i++)
{
SpriteVertex s;
s.Position = g_Projectiles_Gatling[i].pos;
s.Radius = Gatling.radius;
s.TextureIndex = Gatling.textureIndex;
SpriteVector.push_back(s);
}
for(int i = 0; i < g_Projectiles_Plasma.size();i++)
{
SpriteVertex s;
s.Position = g_Projectiles_Plasma[i].pos;
s.Radius = Plasma.radius;
s.TextureIndex = Plasma.textureIndex;
SpriteVector.push_back(s);
}
for(auto it = g_Explosions.begin(); it != g_Explosions.end(); it++)
{
SpriteVertex s;
s.Position = (*it).pos;
s.Radius = 85;
s.TextureIndex = g_explStandard.texIndex;
s.t = (*it).timePassed;
SpriteVector.push_back(s);
}
for(auto it = g_explParticles.begin(); it != g_explParticles.end(); it++)
{
SpriteVertex s;
s.Position = (*it).pos;
s.Radius = (*it).radius;
s.TextureIndex = eps.texIndex;
s.t = (*it).timePassed;
SpriteVector.push_back(s);
}
sort(SpriteVector.begin(),SpriteVector.end(),compare);
// Clear the depth stencil
ID3D11DepthStencilView* pDSV = DXUTGetD3D11DepthStencilView();
pd3dImmediateContext->ClearDepthStencilView( pDSV, D3D11_CLEAR_DEPTH, 1.0, 0 );
//
// Update variables that change once per frame
//
D3DXMATRIX const * view = g_Camera.GetViewMatrix(); // http://msdn.microsoft.com/en-us/library/windows/desktop/bb206342%28v=vs.85%29.aspx
D3DXMATRIX const * proj = g_Camera.GetProjMatrix(); // http://msdn.microsoft.com/en-us/library/windows/desktop/bb147302%28v=vs.85%29.aspx
D3DXMATRIX worldViewProj = g_TerrainWorld * (*view) * (*proj);
g_WorldEV->SetMatrix( ( float* )&g_TerrainWorld );
g_WorldViewProjectionEV->SetMatrix( ( float* )&worldViewProj );
g_LightDirEV->SetFloatVector( ( float* )lightDirObj );
// Set input layout
pd3dImmediateContext->IASetInputLayout( NULL );
// Bind the terrain vertex buffer to the input assembler stage
ID3D11Buffer* vbs[] = { NULL, };
unsigned int strides[] = { 0, }, offsets[] = { 0, };
pd3dImmediateContext->IASetVertexBuffers(0, 1, vbs, strides, offsets);
// Tell the input assembler stage which primitive topology to use
pd3dImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
// Assignment 3.2.4
// TODO: Bind the terrain index buffer to the input assembler stage
//pd3dImmediateContext->IASetIndexBuffer(NULL,DXGI_FORMAT_R32_UINT, 0 );
// Assignment 3.2.5
// TODO: Bind the SRV of the terrain diffuse texture to the effect variable
// (instead of the SRV of the debug texture)
V(g_DiffuseEV->SetResource( g_TerrainDiffuseSRV));
V(g_NormalEV->SetResource(g_TerrainNormalSRV));
V(g_HeightEV->SetResource(g_TerrainHeightSRV));
g_TerrainResEV->SetInt(g_TerrainResolution);
g_TerrainQuadResEV->SetInt(g_TerrainResolution-1);
// Apply the rendering pass in order to submit the necessary render state changes to the device
g_Pass0->Apply(0, pd3dImmediateContext);
// Draw
// Assignment 3.2.6
// TODO: Use DrawIndexed to draw the terrain geometry using as shared vertex list
// (instead of drawing only the vertex buffer)
pd3dImmediateContext->Draw(g_TerrainNumTriangles*3, 0);
pd3dImmediateContext->IASetInputLayout(g_MeshInputLayout);
pd3dImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
unsigned int stride[] = {sizeof(T3dVertex),};
D3DXMATRIX mTrans, mScale, mRotX, mRotY, mRotZ;
for(int i = 0; i < CockpitObjects.size(); i++)
{
V(g_DiffuseEV->SetResource(g_Meshes[CockpitObjects[i].name]->GetDiffuseSRV()));
V(g_SpecularEV->SetResource(g_Meshes[CockpitObjects[i].name]->GetSpecularSRV()));
V(g_GlowEV->SetResource(g_Meshes[CockpitObjects[i].name]->GetGlowSRV()));
ID3D11Buffer* vBS[] ={g_Meshes[CockpitObjects[i].name]->GetVertexBuffer(),};
pd3dImmediateContext->IASetVertexBuffers(0, 1, vBS,stride, offsets);
pd3dImmediateContext->IASetIndexBuffer(g_Meshes[CockpitObjects[i].name]->GetIndexBuffer(), g_Meshes[CockpitObjects[i].name]->GetIndexFormat(),0);
D3DXMatrixRotationX(&mRotX, CockpitObjects[i].rotationX*(D3DX_PI/180.0));
D3DXMatrixRotationY(&mRotY,CockpitObjects[i].rotationY*(D3DX_PI/180.0));
D3DXMatrixRotationZ(&mRotZ,CockpitObjects[i].rotationZ*(D3DX_PI/180.0));
D3DXMatrixScaling(&mScale, CockpitObjects[i].scale, CockpitObjects[i].scale, CockpitObjects[i].scale);
D3DXMatrixTranslation(&mTrans, CockpitObjects[i].translationX, CockpitObjects[i].translationY, CockpitObjects[i].translationZ);
D3DXMATRIX worldView = mScale * mRotX * mRotY * mRotZ * mTrans;
worldViewProj = worldView * (*g_Camera.GetProjMatrix());
D3DXMATRIX worldViewNormals;
D3DXMatrixInverse(&worldViewNormals,NULL,&worldViewProj);
D3DXMatrixTranspose(&worldViewNormals,&worldViewNormals);
g_WorldViewEV ->SetMatrix(worldView);
g_WorldViewNormalsEV ->SetMatrix(worldViewNormals);
g_WorldViewProjectionEV ->SetMatrix(worldViewProj);
D3DXMATRIX viewTransformation;
D3DXMatrixInverse(&viewTransformation, NULL, view);
D3DXMatrixTranspose(&viewTransformation,&viewTransformation);
D3DXVECTOR4 lightDirView;
D3DXVec4Transform(&lightDirView, &g_LightDir, &viewTransformation);
D3DXVec3Normalize((D3DXVECTOR3*)&lightDirView, (D3DXVECTOR3*)&lightDirView);
g_LightDirViewEV->SetFloatVector((float*)&lightDirView);
g_Pass1_Mesh ->Apply(0, pd3dImmediateContext);
pd3dImmediateContext->DrawIndexed(g_Meshes[CockpitObjects[i].name]->GetIndexCount(), 0, 0);
}
for(int i = 0; i < GroundObjects.size(); i++)
{
V(g_DiffuseEV->SetResource(g_Meshes[GroundObjects[i].name]->GetDiffuseSRV()));
V(g_SpecularEV->SetResource(g_Meshes[GroundObjects[i].name]->GetSpecularSRV()));
V(g_GlowEV->SetResource(g_Meshes[GroundObjects[i].name]->GetGlowSRV()));
ID3D11Buffer* vBS[] ={g_Meshes[GroundObjects[i].name]->GetVertexBuffer(),};
pd3dImmediateContext->IASetVertexBuffers(0, 1, vBS,stride, offsets);
pd3dImmediateContext->IASetIndexBuffer(g_Meshes[GroundObjects[i].name]->GetIndexBuffer(), g_Meshes[GroundObjects[i].name]->GetIndexFormat(),0);
D3DXMatrixRotationX(&mRotX, GroundObjects[i].rotationX*(D3DX_PI/180.0));
D3DXMatrixRotationY(&mRotY,GroundObjects[i].rotationY*(D3DX_PI/180.0));
D3DXMatrixRotationZ(&mRotZ,GroundObjects[i].rotationZ*(D3DX_PI/180.0));
D3DXMatrixScaling(&mScale, GroundObjects[i].scale, GroundObjects[i].scale, GroundObjects[i].scale);
D3DXMatrixTranslation(&mTrans, GroundObjects[i].translationX, GroundObjects[i].translationY, getHeightAtPoint(GroundObjects[i].translationX,GroundObjects[i].translationY) + 10);
D3DXMATRIX worldView = mScale * mRotX * mRotY * mRotZ * mTrans * (*g_Camera.GetViewMatrix());
worldViewProj = worldView * (*g_Camera.GetProjMatrix());
D3DXMATRIX worldViewNormals;
D3DXMatrixInverse(&worldViewNormals,NULL,&worldViewProj);
D3DXMatrixTranspose(&worldViewNormals,&worldViewNormals);
g_WorldViewEV ->SetMatrix(worldView);
g_WorldViewNormalsEV ->SetMatrix(worldViewNormals);
g_WorldViewProjectionEV ->SetMatrix(worldViewProj);
D3DXMATRIX viewTransformation;
D3DXMatrixInverse(&viewTransformation, NULL, view);
D3DXMatrixTranspose(&viewTransformation,&viewTransformation);
D3DXVECTOR4 lightDirView;
D3DXVec4Transform(&lightDirView, &g_LightDir, &viewTransformation);
D3DXVec3Normalize((D3DXVECTOR3*)&lightDirView, (D3DXVECTOR3*)&lightDirView);
g_LightDirViewEV->SetFloatVector((float*)&lightDirView);
g_Pass1_Mesh ->Apply(0, pd3dImmediateContext);
pd3dImmediateContext->DrawIndexed(g_Meshes[GroundObjects[i].name]->GetIndexCount(), 0, 0);
}
for(auto it = g_Enemies.begin(); it != g_Enemies.end(); it++)
{
V(g_DiffuseEV->SetResource(g_Meshes[g_EnemyTypes[(*it).typeName].meshname]->GetDiffuseSRV()));
V(g_SpecularEV->SetResource(g_Meshes[g_EnemyTypes[(*it).typeName].meshname]->GetSpecularSRV()));
V(g_GlowEV->SetResource(g_Meshes[g_EnemyTypes[(*it).typeName].meshname]->GetGlowSRV()));
ID3D11Buffer* vBS[] ={g_Meshes[g_EnemyTypes[(*it).typeName].meshname]->GetVertexBuffer(),};
pd3dImmediateContext->IASetVertexBuffers(0, 1, vBS,stride, offsets);
pd3dImmediateContext->IASetIndexBuffer(g_Meshes[g_EnemyTypes[(*it).typeName].meshname]->GetIndexBuffer(), g_Meshes[g_EnemyTypes[(*it).typeName].meshname]->GetIndexFormat(),0);
D3DXMatrixRotationX(&mRotX, g_EnemyTypes[(*it).typeName].rotationX*(D3DX_PI/180.0));
D3DXMatrixRotationY(&mRotY,g_EnemyTypes[(*it).typeName].rotationY*(D3DX_PI/180.0));
D3DXMatrixRotationZ(&mRotZ,g_EnemyTypes[(*it).typeName].rotationZ*(D3DX_PI/180.0));
D3DXMatrixScaling(&mScale, g_EnemyTypes[(*it).typeName].scale, g_EnemyTypes[(*it).typeName].scale, g_EnemyTypes[(*it).typeName].scale);
D3DXMatrixTranslation(&mTrans, g_EnemyTypes[(*it).typeName].translationX, g_EnemyTypes[(*it).typeName].translationY, getHeightAtPoint(g_EnemyTypes[(*it).typeName].translationX,g_EnemyTypes[(*it).typeName].translationY) + 10);
D3DXVECTOR3 d = (*it).vel;
D3DXVec3Normalize(&d,&d);
D3DXMATRIX mAnim;
mAnim = D3DXMATRIX (d.x,d.y,d.z,0,
0,1,0,0,
-d.z,d.y,d.x,0,
(*it).pos.x,(*it).pos.y,(*it).pos.z,1);
D3DXMATRIX worldView = mScale * mRotX * mRotY * mRotZ * mTrans * mAnim * (*g_Camera.GetViewMatrix()) ;
worldViewProj = worldView * (*g_Camera.GetProjMatrix());
D3DXMATRIX worldViewNormals;
D3DXMatrixInverse(&worldViewNormals,NULL,&worldViewProj);
D3DXMatrixTranspose(&worldViewNormals,&worldViewNormals);
g_WorldViewEV ->SetMatrix(worldView);
g_WorldViewNormalsEV ->SetMatrix(worldViewNormals);
g_WorldViewProjectionEV ->SetMatrix(worldViewProj);
D3DXMATRIX viewTransformation;
D3DXMatrixInverse(&viewTransformation, NULL, view);
D3DXMatrixTranspose(&viewTransformation,&viewTransformation);
D3DXVECTOR4 lightDirView;
D3DXVec4Transform(&lightDirView, &g_LightDir, &viewTransformation);
D3DXVec3Normalize((D3DXVECTOR3*)&lightDirView, (D3DXVECTOR3*)&lightDirView);
g_LightDirViewEV->SetFloatVector((float*)&lightDirView);
g_Pass1_Mesh ->Apply(0, pd3dImmediateContext);
pd3dImmediateContext->DrawIndexed(g_Meshes[g_EnemyTypes[(*it).typeName].meshname]->GetIndexCount(), 0, 0);
}
g_SpriteRenderer->RenderSprites(pd3dDevice,SpriteVector,g_Camera);
DXUT_BeginPerfEvent( DXUT_PERFEVENTCOLOR, L"HUD / Stats" );
g_HUD.OnRender( fElapsedTime );
g_SampleUI.OnRender( fElapsedTime );
RenderText();
DXUT_EndPerfEvent();
static DWORD dwTimefirst = GetTickCount();
if ( GetTickCount() - dwTimefirst > 5000 )
{
OutputDebugString( DXUTGetFrameStats( DXUTIsVsyncEnabled() ) );
OutputDebugString( L"\n" );
dwTimefirst = GetTickCount();
}
}