bullet3/Demos/DX11ClothDemo/cloth_renderer.cpp
erwin.coumans 66c349caa6 Remove btSoftBodySolver_CPU.*
Move btSoftBodySolverData.h to src/BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h
Attempt to re-enable MiniCL version of OpenCLClothDemo (cloth-capsule collision still broken)
Add optional OpenCL acceleration to SerializeDemo (just for cloth)
2011-11-11 19:00:26 +00:00

1357 lines
46 KiB
C++

//--------------------------------------------------------------------------------------
// File: BasicHLSL10.cpp
//
// This sample shows a simple example of the Microsoft Direct3D's High-Level
// Shader Language (HLSL) using the Effect interface.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//--------------------------------------------------------------------------------------
#include "DXUT.h"
#include "DXUTcamera.h"
#include "DXUTgui.h"
#include "DXUTsettingsDlg.h"
#include "SDKmisc.h"
#include "SDKMesh.h"
#include "resource.h"
#include "btBulletDynamicsCommon.h"
#include "LinearMath/btHashMap.h"
#include "btDirectComputeSupport.h"
#include "BulletSoftBody/btSoftRigidDynamicsWorld.h"
#include "BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexBuffer_DX11.h"
#include "BulletSoftBody/btSoftBodyHelpers.h"
#include "vectormath/vmInclude.h"
class btDefaultSoftBodySolver;
class btCPUSoftBodySolver;
class btCPUSoftBodyVertexSolver;
class btDX11SoftBodySolver;
class btDX11SIMDAwareSoftBodySolver;
#include "BulletSoftBody/btSoftBodySolvers.h"
#include "BulletSoftBody/btDefaultSoftBodySolver.h"
#include "BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.h"
#include "BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.h"
#include "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h"
#define USE_SIMDAWARE_SOLVER
//#define USE_GPU_SOLVER
#define USE_GPU_COPY
const int numFlags = 5;
const int clothWidth = 40;
const int clothHeight = 60;
float _windAngle = 1.0;//0.4;
float _windStrength = 15;
//#define TABLETEST
#include <fstream>
#include <cmath>
using Vectormath::Aos::Vector3;
class piece_of_cloth;
class btBroadphaseInterface;
class btCollisionShape;
class btOverlappingPairCache;
class btCollisionDispatcher;
class btConstraintSolver;
struct btCollisionAlgorithmCreateFunc;
class btDefaultCollisionConfiguration;
int paused = 0;
float global_shift_x = 0;
float global_shift_y = 0;
float global_shift_z = 0;
namespace BTAcceleratedSoftBody
{
class BulletPhysicsDevice;
class CPUDevice;
class DX11Device;
}
namespace Vectormath
{
namespace Aos
{
class Transform3;
}
}
const float flagSpacing = 30.f;
#include <iostream>
using namespace std;
//--------------------------------------------------------------------------------------
// Global variables
//--------------------------------------------------------------------------------------
CDXUTDialogResourceManager g_DialogResourceManager; // manager for shared resources of dialogs
//CModelViewerCamera g_Camera; // A model viewing camera
CFirstPersonCamera g_Camera; // A model viewing camera
CDXUTDirectionWidget g_LightControl;
CD3DSettingsDlg g_D3DSettingsDlg; // Device settings dialog
CDXUTDialog g_HUD; // manages the 3D
CDXUTDialog g_SampleUI; // dialog for sample specific controls
D3DXMATRIXA16 g_mCenterMesh;
float g_fLightScale;
int g_nNumActiveLights;
int g_nActiveLight;
bool g_bShowHelp = false; // If true, it renders the UI control text
// Direct3D9 resources
CDXUTTextHelper* g_pTxtHelper = NULL;
CDXUTSDKMesh g_Mesh11;
ID3D11InputLayout* g_pVertexLayout11 = NULL;
ID3D11Buffer* g_pVertexBuffer = NULL;
//ID3D11Buffer* g_pIndexBuffer = NULL;
ID3D11VertexShader* g_pVertexShader = NULL;
ID3D11GeometryShader* g_pGeometryShader = NULL;
ID3D11PixelShader* g_pPixelShader = NULL;
ID3D11SamplerState* g_pSamLinear = NULL;
ID3D11RasterizerState *g_pRasterizerState = NULL;
ID3D11RasterizerState *g_pRasterizerStateWF = NULL;
bool g_wireFrame = false;
struct CB_VS_PER_OBJECT
{
D3DXMATRIX m_WorldViewProj;
D3DXMATRIX m_World;
};
UINT g_iCBVSPerObjectBind = 0;
struct CB_PS_PER_OBJECT
{
D3DXVECTOR4 m_vObjectColor;
};
UINT g_iCBPSPerObjectBind = 0;
struct CB_PS_PER_FRAME
{
D3DXVECTOR4 m_vLightDirAmbient;
};
UINT g_iCBPSPerFrameBind = 1;
ID3D11Buffer* g_pcbVSPerObject = NULL;
ID3D11Buffer* g_pcbPSPerObject = NULL;
ID3D11Buffer* g_pcbPSPerFrame = NULL;
ID3D11Device* g_pd3dDevice;
// Create our vertex input layout
const D3D11_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
struct vertex_struct
{
D3DXVECTOR3 Pos;
D3DXVECTOR3 Normal;
D3DXVECTOR2 Texcoord;
};
#include "capsule.h"
#include "cap.h"
#include "cylinder.h"
#include "cloth.h"
//cylinder cyl_1;
//cap cap_1;
btRigidBody *capCollider;
capsule my_capsule;
btAlignedObjectArray<piece_of_cloth> cloths;
//////////////////////////////////////////
// Bullet globals
btAlignedObjectArray<btCollisionShape*> m_collisionShapes;
btBroadphaseInterface* m_broadphase;
btCollisionDispatcher* m_dispatcher;
btConstraintSolver* m_solver;
btDefaultCollisionConfiguration* m_collisionConfiguration;
BTAcceleratedSoftBody::DX11SupportHelper m_dxSupport;
btAlignedObjectArray<btSoftBody *> m_flags;
btSoftRigidDynamicsWorld* m_dynamicsWorld;
btDefaultSoftBodySolver *g_defaultSolver = NULL;
btCPUSoftBodySolver *g_cpuSolver = NULL;
btDX11SoftBodySolver *g_dx11Solver = NULL;
btDX11SIMDAwareSoftBodySolver *g_dx11SIMDSolver = NULL;
btSoftBodySolverOutput *g_softBodyOutput = NULL;
btSoftBodySolver *g_solver = NULL;
// End bullet globals
//////////////////////////////////////////
// Helper to test and add links correctly.
// Records links that have already been generated
static bool testAndAddLink( btAlignedObjectArray<int> &trianglesForLinks, btSoftBody *softBody, int triangle, int *triangleVertexIndexArray, int numVertices, int vertex0, int vertex1, int nonLinkVertex, btSoftBody::Material *structuralMaterial, bool createBendLinks, btSoftBody::Material *bendMaterial )
{
if( trianglesForLinks[ numVertices * vertex0 + vertex1 ] >= 0 && createBendLinks)
{
// Already have link so find other triangle and generate cross link
int otherTriangle = trianglesForLinks[numVertices * vertex0 + vertex1];
int otherIndices[3] = {triangleVertexIndexArray[otherTriangle * 3], triangleVertexIndexArray[otherTriangle * 3 + 1], triangleVertexIndexArray[otherTriangle * 3 + 2]};
int nodeA;
// Test all links of the other triangle against this link. The one that's not part of it is what we want.
if( otherIndices[0] != vertex0 && otherIndices[0] != vertex1 )
nodeA = otherIndices[0];
if( otherIndices[1] != vertex0 && otherIndices[1] != vertex1 )
nodeA = otherIndices[1];
if( otherIndices[2] != vertex0 && otherIndices[2] != vertex1 )
nodeA = otherIndices[2];
softBody->appendLink( nodeA, nonLinkVertex, bendMaterial );
return true;
} else {
// Don't yet have link so create it
softBody->appendLink( vertex0, vertex1, structuralMaterial );
// If we added a new link, set the triangle array
trianglesForLinks[numVertices * vertex0 + vertex1] = triangle;
trianglesForLinks[numVertices * vertex1 + vertex0] = triangle;
return true;
}
}
btSoftBody *createFromIndexedMesh( btVector3 *vertexArray, int numVertices, int *triangleVertexIndexArray, int numTriangles, bool createBendLinks )
{
btSoftBody* softBody = new btSoftBody(&(m_dynamicsWorld->getWorldInfo()), numVertices, vertexArray, 0);
btSoftBody::Material * structuralMaterial = softBody->appendMaterial();
btSoftBody::Material * bendMaterial;
if( createBendLinks )
{
bendMaterial = softBody->appendMaterial();
bendMaterial->m_kLST = 0.7;
} else {
bendMaterial = NULL;
}
structuralMaterial->m_kLST = 1.0;
// List of values for each link saying which triangle is associated with that link
// -1 to start. Once a value is entered we know the "other" triangle
// and can add a link across the link
btAlignedObjectArray<int> triangleForLinks;
triangleForLinks.resize( numVertices * numVertices, -1 );
for( int triangle = 0; triangle < numTriangles; ++triangle )
{
int index[3] = {triangleVertexIndexArray[triangle * 3], triangleVertexIndexArray[triangle * 3 + 1], triangleVertexIndexArray[triangle * 3 + 2]};
softBody->appendFace( index[0], index[1], index[2] );
// Generate the structural links directly from the triangles
testAndAddLink( triangleForLinks, softBody, triangle, triangleVertexIndexArray, numVertices, index[0], index[1], index[2], structuralMaterial, createBendLinks, bendMaterial );
testAndAddLink( triangleForLinks, softBody, triangle, triangleVertexIndexArray, numVertices, index[1], index[2], index[0], structuralMaterial, createBendLinks, bendMaterial );
testAndAddLink( triangleForLinks, softBody, triangle, triangleVertexIndexArray, numVertices, index[2], index[0], index[1], structuralMaterial, createBendLinks, bendMaterial);
}
return softBody;
}
/**
* Create a sequence of flag objects and add them to the world.
*/
void createFlag( int width, int height, btAlignedObjectArray<btSoftBody *> &flags )
{
// First create a triangle mesh to represent a flag
using namespace BTAcceleratedSoftBody;
using Vectormath::Aos::Matrix3;
using Vectormath::Aos::Vector3;
// Allocate a simple mesh consisting of a vertex array and a triangle index array
btIndexedMesh mesh;
mesh.m_numVertices = width*height;
mesh.m_numTriangles = 2*(width-1)*(height-1);
btVector3 *vertexArray = new btVector3[mesh.m_numVertices];
mesh.m_vertexBase = reinterpret_cast<const unsigned char*>(vertexArray);
int *triangleVertexIndexArray = new int[3*mesh.m_numTriangles];
mesh.m_triangleIndexBase = reinterpret_cast<const unsigned char*>(triangleVertexIndexArray);
mesh.m_triangleIndexStride = sizeof(int)*3;
mesh.m_vertexStride = sizeof(Vector3);
// Generate normalised object space vertex coordinates for a rectangular flag
float zCoordinate = 0.0f;
Matrix3 defaultScale(Vector3(5.f, 0.f, 0.f), Vector3(0.f, 20.f, 0.f), Vector3(0.f, 0.f, 1.f));
for( int y = 0; y < height; ++y )
{
float yCoordinate = y*2.0f/float(height) - 1.0f;
for( int x = 0; x < width; ++x )
{
float xCoordinate = x*2.0f/float(width) - 1.0f;
Vector3 vertex(xCoordinate, yCoordinate, zCoordinate);
Vector3 transformedVertex = defaultScale*vertex;
vertexArray[y*width + x] = btVector3(transformedVertex.getX(), transformedVertex.getY(), transformedVertex.getZ() );
}
}
// Generate vertex indices for triangles
for( int y = 0; y < (height-1); ++y )
{
for( int x = 0; x < (width-1); ++x )
{
// Triangle 0
// Top left of square on mesh
{
int vertex0 = y*width + x;
int vertex1 = vertex0 + 1;
int vertex2 = vertex0 + width;
int triangleIndex = 2*y*(width-1) + 2*x;
triangleVertexIndexArray[(mesh.m_triangleIndexStride*triangleIndex)/sizeof(int)] = vertex0;
triangleVertexIndexArray[(mesh.m_triangleIndexStride*triangleIndex+1)/sizeof(int)+1] = vertex1;
triangleVertexIndexArray[(mesh.m_triangleIndexStride*triangleIndex+2)/sizeof(int)+2] = vertex2;
}
// Triangle 1
// Bottom right of square on mesh
{
int vertex0 = y*width + x + 1;
int vertex1 = vertex0 + width;
int vertex2 = vertex1 - 1;
int triangleIndex = 2*y*(width-1) + 2*x + 1;
triangleVertexIndexArray[(mesh.m_triangleIndexStride*triangleIndex)/sizeof(int)] = vertex0;
triangleVertexIndexArray[(mesh.m_triangleIndexStride*triangleIndex)/sizeof(int)+1] = vertex1;
triangleVertexIndexArray[(mesh.m_triangleIndexStride*triangleIndex)/sizeof(int)+2] = vertex2;
}
}
}
float rotateAngleRoundZ = 0.5;
float rotateAngleRoundX = 0.5;
btMatrix3x3 defaultRotate;
defaultRotate[0] = btVector3(cos(rotateAngleRoundZ), sin(rotateAngleRoundZ), 0.f);
defaultRotate[1] = btVector3(-sin(rotateAngleRoundZ), cos(rotateAngleRoundZ), 0.f);
defaultRotate[2] = btVector3(0.f, 0.f, 1.f);
//btMatrix3x3 defaultRotateAndScale( (defaultRotateX*defaultRotate) );
#ifdef TABLETEST
btMatrix3x3 defaultRotateX;
rotateAngleRoundX = 3.141592654/2;
defaultRotateX[0] = btVector3(1.f, 0.f, 0.f);
defaultRotateX[1] = btVector3( 0.f, cos(rotateAngleRoundX), sin(rotateAngleRoundX));
defaultRotateX[2] = btVector3(0.f, -sin(rotateAngleRoundX), cos(rotateAngleRoundX));
btMatrix3x3 defaultRotateAndScale( (defaultRotateX) );
#else
btMatrix3x3 defaultRotateX;
defaultRotateX[0] = btVector3(1.f, 0.f, 0.f);
defaultRotateX[1] = btVector3( 0.f, cos(rotateAngleRoundX), sin(rotateAngleRoundX));
defaultRotateX[2] = btVector3(0.f, -sin(rotateAngleRoundX), cos(rotateAngleRoundX));
btMatrix3x3 defaultRotateAndScale( (defaultRotateX) );
#endif
// Construct the sequence flags applying a slightly different translation to each one to arrange them
// appropriately in the scene.
for( int i = 0; i < numFlags; ++i )
{
float zTranslate = flagSpacing * (i-numFlags/2);
btVector3 defaultTranslate(0.f, 20.f, zTranslate);
btTransform transform( defaultRotateAndScale, defaultTranslate );
btSoftBody *softBody = createFromIndexedMesh( vertexArray, mesh.m_numVertices, triangleVertexIndexArray, mesh.m_numTriangles, true );
for( int i = 0; i < mesh.m_numVertices; ++i )
{
softBody->setMass(i, 10.f/mesh.m_numVertices);
}
#ifndef TABLETEST
// Set the fixed points
softBody->setMass((height-1)*(width), 0.f);
softBody->setMass((height-1)*(width) + width - 1, 0.f);
softBody->setMass((height-1)*width + width/2, 0.f);
#endif
softBody->m_cfg.collisions = btSoftBody::fCollision::CL_SS+btSoftBody::fCollision::CL_RS;
softBody->m_cfg.kLF = 0.0005f;
softBody->m_cfg.kVCF = 0.001f;
softBody->m_cfg.kDP = 0.f;
softBody->m_cfg.kDG = 0.f;
flags.push_back( softBody );
softBody->transform( transform );
softBody->setFriction( 0.8f );
m_dynamicsWorld->addSoftBody( softBody );
}
delete [] vertexArray;
delete [] triangleVertexIndexArray;
}
void updatePhysicsWorld()
{
static int counter = 0;
// Change wind velocity a bit based on a frame counter
if( (counter % 400) == 0 )
{
_windAngle = (_windAngle + 0.05f);
if( _windAngle > (2*3.141) )
_windAngle = 0;
for( int flagIndex = 0; flagIndex < m_flags.size(); ++flagIndex )
{
btSoftBody *cloth = 0;
cloth = m_flags[flagIndex];
float localWind = _windAngle + 0.5*(((float(rand())/RAND_MAX))-0.1);
float xCoordinate = cos(localWind)*_windStrength;
float zCoordinate = sin(localWind)*_windStrength;
cloth->setWindVelocity( btVector3(xCoordinate, 0, zCoordinate) );
}
}
#ifndef TABLETEST
if (capCollider)
{
btVector3 origin( capCollider->getWorldTransform().getOrigin() );
origin.setZ( origin.getZ() + 0.01 );
capCollider->getWorldTransform().setOrigin( origin );
}
#endif
counter++;
}
void initBullet(void)
{
#ifdef USE_GPU_SOLVER
g_dx11Solver = new btDX11SoftBodySolver( g_pd3dDevice, DXUTGetD3D11DeviceContext() );
g_solver = g_dx11Solver;
#ifdef USE_GPU_COPY
g_softBodyOutput = new btSoftBodySolverOutputDXtoDX( g_pd3dDevice, DXUTGetD3D11DeviceContext() );
#else // #ifdef USE_GPU_COPY
g_softBodyOutput = new btSoftBodySolverOutputDXtoCPU;
#endif // #ifdef USE_GPU_COPY
#else
#ifdef USE_SIMDAWARE_SOLVER
g_dx11SIMDSolver = new btDX11SIMDAwareSoftBodySolver( g_pd3dDevice, DXUTGetD3D11DeviceContext() );
g_solver = g_dx11SIMDSolver;
g_softBodyOutput = new btSoftBodySolverOutputDXtoCPU;
#ifdef USE_GPU_COPY
g_softBodyOutput = new btSoftBodySolverOutputDXtoDX( g_pd3dDevice, DXUTGetD3D11DeviceContext() );
#else // #ifdef USE_GPU_COPY
g_softBodyOutput = new btSoftBodySolverOutputDXtoCPU;
#endif // #ifdef USE_GPU_COPY
#else
g_cpuSolver = new btCPUSoftBodySolver;
g_solver = g_cpuSolver;
g_softBodyOutput = new btSoftBodySolverOutputCPUtoCPU;
//g_defaultSolver = new btDefaultSoftBodySolver;
//g_solver = g_defaultSolver;
#endif
#endif
if (g_dx11SIMDSolver)
g_dx11SIMDSolver->setEnableUpdateBounds(true);
if (g_dx11Solver)
g_dx11Solver->setEnableUpdateBounds(true);
// Initialise CPU physics device
//m_collisionConfiguration = new btDefaultCollisionConfiguration();
m_collisionConfiguration = new btSoftBodyRigidBodyCollisionConfiguration();
m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
m_broadphase = new btDbvtBroadphase();
btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver;
m_solver = sol;
m_dynamicsWorld = new btSoftRigidDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration, g_solver);
m_dynamicsWorld->setGravity(btVector3(0,-10,0));
btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.)));
m_collisionShapes.push_back(groundShape);
btTransform groundTransform;
groundTransform.setIdentity();
groundTransform.setOrigin(btVector3(0,-50,0));
m_dynamicsWorld->getWorldInfo().air_density = (btScalar)1.2;
m_dynamicsWorld->getWorldInfo().water_density = 0;
m_dynamicsWorld->getWorldInfo().water_offset = 0;
m_dynamicsWorld->getWorldInfo().water_normal = btVector3(0,0,0);
m_dynamicsWorld->getWorldInfo().m_gravity.setValue(0,-10,0);
#if 0
{
btScalar mass(0.);
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);
btVector3 localInertia(0,0,0);
if (isDynamic)
groundShape->calculateLocalInertia(mass,localInertia);
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia);
btRigidBody* body = new btRigidBody(rbInfo);
//add the body to the dynamics world
m_dynamicsWorld->addRigidBody(body);
}
#endif
#if 0
{
btScalar mass(0.);
//btScalar mass(1.);
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);
btCollisionShape *capsuleShape = new btCapsuleShape(5, 10);
capsuleShape->setMargin( 0.5 );
my_capsule.set_collision_shape(capsuleShape);
btVector3 localInertia(0,0,0);
if (isDynamic)
capsuleShape->calculateLocalInertia(mass,localInertia);
m_collisionShapes.push_back(capsuleShape);
btTransform capsuleTransform;
capsuleTransform.setIdentity();
#ifdef TABLETEST
capsuleTransform.setOrigin(btVector3(0, 10, -11));
const btScalar pi = 3.141592654;
capsuleTransform.setRotation(btQuaternion(0, 0, pi/2));
#else
capsuleTransform.setOrigin(btVector3(0, 20, -10));
const btScalar pi = 3.141592654;
//capsuleTransform.setRotation(btQuaternion(0, 0, pi/2));
capsuleTransform.setRotation(btQuaternion(0, 0, 0));
#endif
btDefaultMotionState* myMotionState = new btDefaultMotionState(capsuleTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,capsuleShape,localInertia);
btRigidBody* body = new btRigidBody(rbInfo);
body->setFriction( 0.8f );
my_capsule.set_collision_object(body);
m_dynamicsWorld->addRigidBody(body);
//cap_1.collisionShape = body;
capCollider = body;
}
#endif
createFlag( clothWidth, clothHeight, m_flags );
// Create output buffer descriptions for ecah flag
// These describe where the simulation should send output data to
for( int flagIndex = 0; flagIndex < m_flags.size(); ++flagIndex )
{
// In this case we have a DX11 output buffer with a vertex at index 0, 8, 16 and so on as well as a normal at 3, 11, 19 etc.
// Copies will be performed GPU-side directly into the output buffer
#ifdef USE_GPU_COPY
btDX11VertexBufferDescriptor *vertexBufferDescriptor = new btDX11VertexBufferDescriptor(DXUTGetD3D11DeviceContext(), cloths[flagIndex].pVB[0], cloths[flagIndex].g_pVB_UAV, 0, 8, 3, 8);
cloths[flagIndex].m_vertexBufferDescriptor = vertexBufferDescriptor;
#else // #ifdef USE_GPU_COPY
btCPUVertexBufferDescriptor *vertexBufferDescriptor = new btCPUVertexBufferDescriptor(cloths[flagIndex].cpu_buffer, 0, 8, 3, 8);
cloths[flagIndex].m_vertexBufferDescriptor = vertexBufferDescriptor;
#endif // #ifdef USE_GPU_COPY
}
g_solver->optimize( m_dynamicsWorld->getSoftBodyArray() );
}
//--------------------------------------------------------------------------------------
// UI control IDs
//--------------------------------------------------------------------------------------
#define IDC_TOGGLEFULLSCREEN 1
#define IDC_TOGGLEREF 3
#define IDC_CHANGEDEVICE 4
#define IDC_PAUSE 5
#define IDC_WIREFRAME 6
//--------------------------------------------------------------------------------------
// Forward declarations
//--------------------------------------------------------------------------------------
bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void* pUserContext );
void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void* pUserContext );
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 );
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 RenderText();
//--------------------------------------------------------------------------------------
// 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 );
_CrtSetReportMode ( _CRT_ERROR, _CRTDBG_MODE_DEBUG);
#endif
// DXUT will create and use the best device (either D3D9 or D3D11)
// that is available on the system depending on which D3D callbacks are set below
// Set DXUT callbacks
DXUTSetCallbackDeviceChanging( ModifyDeviceSettings );
DXUTSetCallbackMsgProc( MsgProc );
DXUTSetCallbackKeyboard( OnKeyboard );
DXUTSetCallbackFrameMove( OnFrameMove );
DXUTSetCallbackD3D11DeviceAcceptable( IsD3D11DeviceAcceptable );
DXUTSetCallbackD3D11DeviceCreated( OnD3D11CreateDevice );
DXUTSetCallbackD3D11SwapChainResized( OnD3D11ResizedSwapChain );
DXUTSetCallbackD3D11FrameRender( OnD3D11FrameRender );
DXUTSetCallbackD3D11SwapChainReleasing( OnD3D11ReleasingSwapChain );
DXUTSetCallbackD3D11DeviceDestroyed( OnD3D11DestroyDevice );
InitApp();
DXUTInit( true, true, NULL ); // Parse the command line, show msgboxes on error, no extra command line params
DXUTSetCursorSettings( true, true ); // Show the cursor and clip it when in full screen
DXUTCreateWindow( L"Cloth Renderer" );
DXUTCreateDevice (D3D_FEATURE_LEVEL_11_0, true, 800, 600 );
DXUTSetMultimonSettings(false);
//DXUTCreateDevice(true, 640, 480);
DXUTMainLoop(); // Enter into the DXUT render loop
return DXUTGetExitCode();
}
//--------------------------------------------------------------------------------------
// Initialize the app
//--------------------------------------------------------------------------------------
void InitApp()
{
D3DXVECTOR3 vLightDir( 1, 0, 0 );
D3DXVec3Normalize( &vLightDir, &vLightDir );
g_LightControl.SetLightDirection( vLightDir );
// Initialize dialogs
g_D3DSettingsDlg.Init( &g_DialogResourceManager );
g_HUD.Init( &g_DialogResourceManager );
g_SampleUI.Init( &g_DialogResourceManager );
g_HUD.SetCallback( OnGUIEvent ); int iY = 10;
g_HUD.AddButton( IDC_TOGGLEFULLSCREEN, L"Toggle full screen", 0, iY, 170, 23 );
g_HUD.AddButton( IDC_TOGGLEREF, L"Toggle REF (F3)", 0, iY += 26, 170, 23, VK_F3 );
g_HUD.AddButton( IDC_CHANGEDEVICE, L"Change device (F2)", 0, iY += 26, 170, 23, VK_F2 );
g_HUD.AddButton( IDC_PAUSE, L"Pause", 0, iY += 26, 170, 23 );
g_HUD.AddButton( IDC_WIREFRAME, L"Wire frame", 0, iY += 26, 170, 23 );
g_SampleUI.SetCallback( OnGUIEvent ); iY = 10;
}
//--------------------------------------------------------------------------------------
// Called right before creating a D3D9 or D3D11 device, allowing the app to modify the device settings as needed
//--------------------------------------------------------------------------------------
bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void* pUserContext )
{
// Uncomment this to get debug information from D3D11
//pDeviceSettings->d3d11.CreateFlags |= D3D11_CREATE_DEVICE_DEBUG;
// 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_D3D11_DEVICE == pDeviceSettings->ver &&
pDeviceSettings->d3d11.DriverType == D3D_DRIVER_TYPE_REFERENCE ) )
{
DXUTDisplaySwitchingToREFWarning( pDeviceSettings->ver );
}
}
return true;
}
//--------------------------------------------------------------------------------------
// 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 );
}
//--------------------------------------------------------------------------------------
// Render the help and statistics text
//--------------------------------------------------------------------------------------
void RenderText()
{
UINT nBackBufferHeight = ( DXUTIsAppRenderingWithD3D9() ) ? DXUTGetD3D9BackBufferSurfaceDesc()->Height :
DXUTGetDXGIBackBufferSurfaceDesc()->Height;
g_pTxtHelper->Begin();
g_pTxtHelper->SetInsertionPos( 2, 0 );
g_pTxtHelper->SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ) );
g_pTxtHelper->DrawTextLine( DXUTGetFrameStats( DXUTIsVsyncEnabled() ) );
g_pTxtHelper->DrawTextLine( DXUTGetDeviceStats() );
// Draw help
if( g_bShowHelp )
{
g_pTxtHelper->SetInsertionPos( 2, nBackBufferHeight - 20 * 6 );
g_pTxtHelper->SetForegroundColor( D3DXCOLOR( 1.0f, 0.75f, 0.0f, 1.0f ) );
g_pTxtHelper->DrawTextLine( L"Controls:" );
g_pTxtHelper->SetInsertionPos( 20, nBackBufferHeight - 20 * 5 );
g_pTxtHelper->DrawTextLine( L"Rotate view: Left mouse button\n"
L"Move camera: W, A, S, and D\n"
L"Rotate light: Right mouse button\n"
L"Zoom camera: Mouse wheel scroll\n" );
g_pTxtHelper->SetInsertionPos( 550, nBackBufferHeight - 20 * 5 );
g_pTxtHelper->DrawTextLine( L"Hide help: F1\n"
L"Quit: ESC\n" );
}
else
{
g_pTxtHelper->SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );
g_pTxtHelper->DrawTextLine( L"Press F1 for help" );
}
g_pTxtHelper->End();
}
//--------------------------------------------------------------------------------------
// 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_D3DSettingsDlg.IsActive() )
{
g_D3DSettingsDlg.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;
g_LightControl.HandleMessages( hWnd, uMsg, wParam, lParam );
// 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( bKeyDown )
{
switch( nChar )
{
case VK_F1:
g_bShowHelp = !g_bShowHelp; break;
}
}
}
//--------------------------------------------------------------------------------------
// 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_D3DSettingsDlg.SetActive( !g_D3DSettingsDlg.IsActive() ); break;
case IDC_PAUSE:
paused = !paused;
break;
case IDC_WIREFRAME:
g_wireFrame = !g_wireFrame;
break;
}
}
//--------------------------------------------------------------------------------------
// 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;
}
//--------------------------------------------------------------------------------------
// Use this until D3DX11 comes online and we get some compilation helpers
//--------------------------------------------------------------------------------------
HRESULT CompileShaderFromFile( WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut )
{
HRESULT hr = S_OK;
// find the file
WCHAR str[MAX_PATH];
V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, szFileName ) );
// open the file
HANDLE hFile = CreateFile( str, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN, NULL );
if( INVALID_HANDLE_VALUE == hFile )
return E_FAIL;
// Get the file size
LARGE_INTEGER FileSize;
GetFileSizeEx( hFile, &FileSize );
// create enough space for the file data
BYTE* pFileData = new BYTE[ FileSize.LowPart ];
if( !pFileData )
return E_OUTOFMEMORY;
// read the data in
DWORD BytesRead;
if( !ReadFile( hFile, pFileData, FileSize.LowPart, &BytesRead, NULL ) )
return E_FAIL;
CloseHandle( hFile );
// Compile the shader
ID3DBlob* pErrorBlob;
hr = D3DCompile( pFileData, FileSize.LowPart, "none", NULL, NULL, szEntryPoint, szShaderModel, D3D10_SHADER_ENABLE_STRICTNESS, 0, ppBlobOut, &pErrorBlob );
delete []pFileData;
if( FAILED(hr) )
{
OutputDebugStringA( (char*)pErrorBlob->GetBufferPointer() );
SAFE_RELEASE( pErrorBlob );
return hr;
}
SAFE_RELEASE( pErrorBlob );
return S_OK;
}
//--------------------------------------------------------------------------------------
// Create any D3D11 resources that aren't dependant on the back buffer
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnD3D11CreateDevice( ID3D11Device* pd3dDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc,
void* pUserContext )
{
g_pd3dDevice = pd3dDevice;
HRESULT hr;
ID3D11DeviceContext* pd3dImmediateContext = DXUTGetD3D11DeviceContext();
V_RETURN( g_DialogResourceManager.OnD3D11CreateDevice( pd3dDevice, pd3dImmediateContext ) );
V_RETURN( g_D3DSettingsDlg.OnD3D11CreateDevice( pd3dDevice ) );
g_pTxtHelper = new CDXUTTextHelper( pd3dDevice, pd3dImmediateContext, &g_DialogResourceManager, 15 );
D3DXVECTOR3 vCenter( 0.25767413f, -28.503521f, 111.00689f);
FLOAT fObjectRadius = 378.15607f;
D3DXMatrixTranslation( &g_mCenterMesh, -vCenter.x, -vCenter.y, -vCenter.z );
D3DXMATRIXA16 m;
D3DXMatrixRotationY( &m, D3DX_PI );
g_mCenterMesh *= m;
D3DXMatrixRotationX( &m, D3DX_PI / 2.0f );
g_mCenterMesh *= m;
// Compile the shaders to a model based on the feature level we acquired
ID3DBlob* pVertexShaderBuffer = NULL;
ID3DBlob* pGeometryShaderBuffer = NULL;
ID3DBlob* pPixelShaderBuffer = NULL;
switch( DXUTGetD3D11DeviceFeatureLevel() )
{
case D3D_FEATURE_LEVEL_11_0:
V_RETURN( CompileShaderFromFile( L"cloth_renderer_VS.hlsl", "VSMain", "vs_5_0" , &pVertexShaderBuffer ) );
V_RETURN( CompileShaderFromFile( L"cloth_renderer_PS.hlsl", "GSMain", "gs_5_0" , &pGeometryShaderBuffer ) );
V_RETURN( CompileShaderFromFile( L"cloth_renderer_PS.hlsl", "PSMain", "ps_5_0" , &pPixelShaderBuffer ) );
break;
}
// Create the shaders
V_RETURN( pd3dDevice->CreateVertexShader( pVertexShaderBuffer->GetBufferPointer(),
pVertexShaderBuffer->GetBufferSize(), NULL, &g_pVertexShader ) );
V_RETURN( pd3dDevice->CreateGeometryShader( pGeometryShaderBuffer->GetBufferPointer(),
pGeometryShaderBuffer->GetBufferSize(), NULL, &g_pGeometryShader ) );
V_RETURN( pd3dDevice->CreatePixelShader( pPixelShaderBuffer->GetBufferPointer(),
pPixelShaderBuffer->GetBufferSize(), NULL, &g_pPixelShader ) );
V_RETURN( pd3dDevice->CreateInputLayout( layout, ARRAYSIZE( layout ), pVertexShaderBuffer->GetBufferPointer(),
pVertexShaderBuffer->GetBufferSize(), &g_pVertexLayout11 ) );
SAFE_RELEASE( pVertexShaderBuffer );
SAFE_RELEASE( pPixelShaderBuffer );
SAFE_RELEASE( pGeometryShaderBuffer );
// Load the mesh
V_RETURN( g_Mesh11.Create( pd3dDevice, L"tiny\\tiny.sdkmesh", true ) );
// Create a sampler state
D3D11_SAMPLER_DESC SamDesc;
SamDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
SamDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
SamDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
SamDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
SamDesc.MipLODBias = 0.0f;
SamDesc.MaxAnisotropy = 1;
SamDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
SamDesc.BorderColor[0] = SamDesc.BorderColor[1] = SamDesc.BorderColor[2] = SamDesc.BorderColor[3] = 0;
SamDesc.MinLOD = 0;
SamDesc.MaxLOD = D3D11_FLOAT32_MAX;
V_RETURN( pd3dDevice->CreateSamplerState( &SamDesc, &g_pSamLinear ) );
// Setup constant buffers
D3D11_BUFFER_DESC Desc;
Desc.Usage = D3D11_USAGE_DYNAMIC;
Desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
Desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
Desc.MiscFlags = 0;
Desc.ByteWidth = sizeof( CB_VS_PER_OBJECT );
V_RETURN( pd3dDevice->CreateBuffer( &Desc, NULL, &g_pcbVSPerObject ) );
Desc.ByteWidth = sizeof( CB_PS_PER_OBJECT );
V_RETURN( pd3dDevice->CreateBuffer( &Desc, NULL, &g_pcbPSPerObject ) );
Desc.ByteWidth = sizeof( CB_PS_PER_FRAME );
V_RETURN( pd3dDevice->CreateBuffer( &Desc, NULL, &g_pcbPSPerFrame ) );
// Setup the camera's view parameters
D3DXVECTOR3 vecEye( 30.0f, 30.0f, -80.0f );
D3DXVECTOR3 vecAt ( 10.0f, 20.0f, -0.0f );
g_Camera.SetViewParams( &vecEye, &vecAt );
cloths.resize(numFlags);
for( int flagIndex = 0; flagIndex < numFlags; ++flagIndex )
{
cloths[flagIndex].create_buffers(clothWidth, clothHeight);
}
initBullet();
std::wstring flagTexsName[] = {
L"atiFlag.bmp",
L"amdFlag.bmp",
};
int numFlagTexs = 2;
WCHAR flagTexs[2][MAX_PATH];
HRESULT res = DXUTFindDXSDKMediaFileCch(flagTexs[0],MAX_PATH, flagTexsName[0].c_str());
res = DXUTFindDXSDKMediaFileCch(flagTexs[1],MAX_PATH, flagTexsName[1].c_str());
for( int flagIndex = 0; flagIndex < numFlags; ++flagIndex )
{
cloths[flagIndex].create_texture(flagTexs[flagIndex % numFlagTexs]);
cloths[flagIndex].x_offset = 0;
cloths[flagIndex].y_offset = 0;
cloths[flagIndex].z_offset = 0;
}
my_capsule.create_buffers(50,40);
my_capsule.create_texture();
//Turn off backface culling
D3D11_RASTERIZER_DESC rsDesc;
ZeroMemory(&rsDesc,sizeof(D3D11_RASTERIZER_DESC) );
rsDesc.CullMode = D3D11_CULL_NONE;
rsDesc.FillMode = D3D11_FILL_SOLID;
hr = pd3dDevice->CreateRasterizerState(&rsDesc, &g_pRasterizerState);
rsDesc.FillMode = D3D11_FILL_WIREFRAME;
hr = pd3dDevice->CreateRasterizerState(&rsDesc, &g_pRasterizerStateWF);
SAFE_RELEASE(pd3dImmediateContext);
return S_OK;
}
//--------------------------------------------------------------------------------------
// 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;
V_RETURN( g_DialogResourceManager.OnD3D11ResizedSwapChain( pd3dDevice, pBackBufferSurfaceDesc ) );
V_RETURN( g_D3DSettingsDlg.OnD3D11ResizedSwapChain( pd3dDevice, pBackBufferSurfaceDesc ) );
// Setup the camera's projection parameters
float fAspectRatio = pBackBufferSurfaceDesc->Width / ( FLOAT )pBackBufferSurfaceDesc->Height;
g_Camera.SetProjParams( D3DX_PI / 4, fAspectRatio, 2.0f, 4000.0f );
// g_Camera.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height );
// g_Camera.SetButtonMasks( MOUSE_MIDDLE_BUTTON, MOUSE_WHEEL, MOUSE_LEFT_BUTTON );
D3DXVECTOR3 vMin = D3DXVECTOR3( -1000.0f, -1000.0f, -1000.0f );
D3DXVECTOR3 vMax = D3DXVECTOR3( 1000.0f, 1000.0f, 1000.0f );
g_Camera.SetRotateButtons(TRUE, FALSE, FALSE);
g_Camera.SetScalers( 0.01f, 30.0f );
g_Camera.SetDrag( true );
g_Camera.SetEnableYAxisMovement( true );
g_Camera.SetClipToBoundary( TRUE, &vMin, &vMax );
g_Camera.FrameMove( 0 );
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 );
//Turn off backface culling
D3D11_RASTERIZER_DESC rsDesc;
ZeroMemory(&rsDesc,sizeof(D3D11_RASTERIZER_DESC) );
rsDesc.CullMode = D3D11_CULL_NONE;
rsDesc.FillMode = D3D11_FILL_SOLID;
//rsDesc.FillMode = D3D11_FILL_WIREFRAME;
ID3D11RasterizerState *pRasterizerState = NULL;
pd3dDevice->CreateRasterizerState(&rsDesc, &pRasterizerState);
DXUTGetD3D11DeviceContext()->RSSetState(pRasterizerState);
SAFE_RELEASE(pRasterizerState);
return S_OK;
}
btClock m_clock;
//--------------------------------------------------------------------------------------
// Render the scene using the D3D11 device
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D11FrameRender( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext, double fTime,
float fElapsedTime, void* pUserContext )
{
//float ms = getDeltaTimeMicroseconds();
btScalar dt = (btScalar)m_clock.getTimeMicroseconds();
m_clock.reset();
///step the simulation
if (m_dynamicsWorld && !paused)
{
m_dynamicsWorld->stepSimulation(dt / 1000000.f);
updatePhysicsWorld();
}
//paused = 1;
///////////////////////////////////////////////////////
HRESULT hr;
// If the settings dialog is being shown, then render it instead of rendering the app's scene
if( g_D3DSettingsDlg.IsActive() )
{
g_D3DSettingsDlg.OnRender( fElapsedTime );
return;
}
// Clear the render target and depth stencil
float ClearColor[4] = { 0.0f, 0.25f, 0.25f, 0.55f };
ID3D11RenderTargetView* pRTV = DXUTGetD3D11RenderTargetView();
pd3dImmediateContext->ClearRenderTargetView( pRTV, ClearColor );
ID3D11DepthStencilView* pDSV = DXUTGetD3D11DepthStencilView();
pd3dImmediateContext->ClearDepthStencilView( pDSV, D3D11_CLEAR_DEPTH, 1.0, 0 );
for( int flagIndex = 0; flagIndex < m_flags.size(); ++flagIndex )
{
g_softBodyOutput->copySoftBodyToVertexBuffer( m_flags[flagIndex], cloths[flagIndex].m_vertexBufferDescriptor );
cloths[flagIndex].draw();
}
my_capsule.draw();
DXUT_BeginPerfEvent( DXUT_PERFEVENTCOLOR, L"HUD / Stats" );
g_HUD.OnRender( fElapsedTime );
g_SampleUI.OnRender( fElapsedTime );
RenderText();
DXUT_EndPerfEvent();
/*
SAFE_RELEASE(pRTV);
SAFE_RELEASE(pDSV);
*/
}
//--------------------------------------------------------------------------------------
// Release D3D11 resources created in OnD3D11ResizedSwapChain
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D11ReleasingSwapChain( void* pUserContext )
{
g_DialogResourceManager.OnD3D11ReleasingSwapChain();
DXUTGetD3D11DeviceContext()->ClearState();
}
//--------------------------------------------------------------------------------------
// Release D3D11 resources created in OnD3D11CreateDevice
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D11DestroyDevice( void* pUserContext )
{
g_DialogResourceManager.OnD3D11DestroyDevice();
g_D3DSettingsDlg.OnD3D11DestroyDevice();
DXUTGetGlobalResourceCache().OnDestroyDevice();
SAFE_DELETE( g_pTxtHelper );
g_Mesh11.Destroy();
SAFE_RELEASE(g_pGeometryShader);
SAFE_RELEASE( g_pVertexLayout11 );
SAFE_RELEASE( g_pVertexBuffer );
SAFE_RELEASE( g_pVertexShader );
SAFE_RELEASE( g_pPixelShader );
SAFE_RELEASE( g_pSamLinear );
SAFE_RELEASE( g_pcbVSPerObject );
SAFE_RELEASE( g_pcbPSPerObject );
SAFE_RELEASE( g_pcbPSPerFrame );
SAFE_RELEASE( g_pRasterizerState );
SAFE_RELEASE( g_pRasterizerStateWF );
for( int flagIndex = 0; flagIndex < numFlags; ++flagIndex )
{
cloths[flagIndex].destroy();
}
my_capsule.destroy();
// Shouldn't need to delete this as it's just a soft body and will be deleted later by the collision object cleanup.
//for( int flagIndex = 0; flagIndex < m_flags.size(); ++flagIndex )
//{
//delete m_flags[flagIndex];
//}
//cleanup in the reverse order of creation/initialization
if( g_defaultSolver )
delete g_defaultSolver;
if( g_cpuSolver )
delete g_cpuSolver;
if( g_dx11Solver )
delete g_dx11Solver;
if( g_dx11SIMDSolver )
delete g_dx11SIMDSolver;
if( g_softBodyOutput )
delete g_softBodyOutput;
for(int i=0; i< m_collisionShapes.size(); i++)
delete m_collisionShapes[i];
//remove the rigidbodies from the dynamics world and delete them
int i;
for (i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--)
{
btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i];
btRigidBody* body = btRigidBody::upcast(obj);
if (body && body->getMotionState())
{
delete body->getMotionState();
}
m_dynamicsWorld->removeCollisionObject( obj );
delete obj;
}
delete m_dynamicsWorld;
delete m_solver;
delete m_broadphase;
delete m_dispatcher;
delete m_collisionConfiguration;
}