#ifndef DRAWINGUTILITIESCLASS_h #define DRAWINGUTILITIESCLASS_h // DirectXEffects #include // DXUT includes #include #include // DirectXTK includes #include "Effects.h" #include "VertexTypes.h" #include "PrimitiveBatch.h" #include "GeometricPrimitive.h" #include "ScreenGrab.h" // AntTweakBar includes #include "AntTweakBar.h" // vector mat quat #include "util/vectorbase.h" #include "util/matrixbase.h" #include "util/quaternion.h" using namespace DirectX; using namespace GamePhysics; class DrawingUtilitiesClass{ public: ID3D11Device* g_ppd3Device; ID3D11DeviceContext* g_pd3dImmediateContext; // Effect corresponding to "effect.fx" ID3DX11Effect* g_pEffect; // Tweak bar TwBar* g_pTweakBar; // DXUT camera // NOTE: CModelViewerCamera does not only manage the standard view transformation/camera position // (CModelViewerCamera::GetViewMatrix()), but also allows for model rotation // (CModelViewerCamera::GetWorldMatrix()). // Look out for CModelViewerCamera::SetButtonMasks(...). CModelViewerCamera g_camera; // DirectXTK effect, input layout and primitive batch for position/color vertices // (for drawing multicolored & unlit primitives) BasicEffect* g_pEffectPositionColor; ID3D11InputLayout* g_pInputLayoutPositionColor; PrimitiveBatch* g_pPrimitiveBatchPositionColor; // DirectXTK effect, input layout and primitive batch for position/normal vertices // (for drawing unicolor & oriented & lit primitives) BasicEffect* g_pEffectPositionNormal; ID3D11InputLayout* g_pInputLayoutPositionNormal; PrimitiveBatch* g_pPrimitiveBatchPositionNormal; BasicEffect* g_pEffectPositionNormalColor; ID3D11InputLayout* g_pInputLayoutPositionNormalColor; PrimitiveBatch* g_pPrimitiveBatchPositionNormalColor; // DirectXTK simple geometric primitives std::unique_ptr g_pSphere; std::unique_ptr g_pTeapot; // Constructor DrawingUtilitiesClass(){ g_pTweakBar = nullptr; } void init(ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext) { g_pd3dImmediateContext = pd3dImmediateContext; g_ppd3Device = pd3dDevice; // Create DirectXTK geometric primitives for later usage g_pSphere = GeometricPrimitive::CreateGeoSphere(g_pd3dImmediateContext, 2.0f, 2, false); g_pTeapot = GeometricPrimitive::CreateTeapot(g_pd3dImmediateContext, 1.5f, 8, false); // Create effect, input layout and primitive batch for position/color vertices (DirectXTK) { // Effect g_pEffectPositionColor = new BasicEffect(pd3dDevice); g_pEffectPositionColor->SetVertexColorEnabled(true); // triggers usage of position/color vertices // Input layout void const* shaderByteCode; size_t byteCodeLength; g_pEffectPositionColor->GetVertexShaderBytecode(&shaderByteCode, &byteCodeLength); pd3dDevice->CreateInputLayout(VertexPositionColor::InputElements, VertexPositionColor::InputElementCount, shaderByteCode, byteCodeLength, &g_pInputLayoutPositionColor); // Primitive batch g_pPrimitiveBatchPositionColor = new PrimitiveBatch(pd3dImmediateContext); } // Create effect, input layout and primitive batch for position/normal vertices (DirectXTK) { // Effect g_pEffectPositionNormal = new BasicEffect(pd3dDevice); g_pEffectPositionNormal->EnableDefaultLighting(); // triggers usage of position/normal vertices g_pEffectPositionNormal->SetPerPixelLighting(true); // Input layout void const* shaderByteCode; size_t byteCodeLength; g_pEffectPositionNormal->GetVertexShaderBytecode(&shaderByteCode, &byteCodeLength); pd3dDevice->CreateInputLayout(VertexPositionNormal::InputElements, VertexPositionNormal::InputElementCount, shaderByteCode, byteCodeLength, &g_pInputLayoutPositionNormal); // Primitive batch g_pPrimitiveBatchPositionNormal = new PrimitiveBatch(pd3dImmediateContext); } // Create effect, input layout and primitive batch for position/normal/color vertices (DirectXTK) { // Effect g_pEffectPositionNormalColor = new BasicEffect(pd3dDevice); g_pEffectPositionNormalColor->SetPerPixelLighting(true); g_pEffectPositionNormalColor->EnableDefaultLighting(); // triggers usage of position/normal/color vertices g_pEffectPositionNormalColor->SetVertexColorEnabled(true); // triggers usage of position/normal/color vertices // Input layout void const* shaderByteCode; size_t byteCodeLength; g_pEffectPositionNormalColor->GetVertexShaderBytecode(&shaderByteCode, &byteCodeLength); pd3dDevice->CreateInputLayout(VertexPositionNormalColor::InputElements, VertexPositionNormalColor::InputElementCount, shaderByteCode, byteCodeLength, &g_pInputLayoutPositionNormalColor); // Primitive batch g_pPrimitiveBatchPositionNormalColor = new PrimitiveBatch(pd3dImmediateContext); } } void destroy(){ SAFE_DELETE (g_pPrimitiveBatchPositionColor); SAFE_RELEASE(g_pInputLayoutPositionColor); SAFE_DELETE (g_pEffectPositionColor); SAFE_DELETE (g_pPrimitiveBatchPositionNormal); SAFE_RELEASE(g_pInputLayoutPositionNormal); SAFE_DELETE (g_pEffectPositionNormal); SAFE_DELETE (g_pPrimitiveBatchPositionNormalColor); SAFE_RELEASE(g_pInputLayoutPositionNormalColor); SAFE_DELETE (g_pEffectPositionNormalColor); g_pSphere.reset(); g_pTeapot.reset(); SAFE_RELEASE(g_pEffect); TwDeleteBar(g_pTweakBar); g_pTweakBar = nullptr; TwTerminate(); } // Draw the edges of the bounding box [-0.5;0.5]?rotated with the cameras model tranformation. // (Drawn as line primitives using a DirectXTK primitive batch) void DrawBoundingBox(ID3D11DeviceContext* pd3dImmediateContext) { // Setup position/color effect g_pEffectPositionColor->SetWorld(g_camera.GetWorldMatrix()); g_pEffectPositionColor->Apply(pd3dImmediateContext); pd3dImmediateContext->IASetInputLayout(g_pInputLayoutPositionColor); // Draw g_pPrimitiveBatchPositionColor->Begin(); // Lines in x direction (red color) for (int i=0; i<4; i++) { g_pPrimitiveBatchPositionColor->DrawLine( VertexPositionColor(XMVectorSet(-0.5f, (float)(i%2)-0.5f, (float)(i/2)-0.5f, 1), Colors::Red), VertexPositionColor(XMVectorSet( 0.6f, (float)(i%2)-0.5f, (float)(i/2)-0.5f, 1), Colors::Red) ); } // Lines in y direction for (int i=0; i<4; i++) { g_pPrimitiveBatchPositionColor->DrawLine( VertexPositionColor(XMVectorSet((float)(i%2)-0.5f, -0.5f, (float)(i/2)-0.5f, 1), Colors::Green), VertexPositionColor(XMVectorSet((float)(i%2)-0.5f, 0.6f, (float)(i/2)-0.5f, 1), Colors::Green) ); } // Lines in z direction for (int i=0; i<4; i++) { g_pPrimitiveBatchPositionColor->DrawLine( VertexPositionColor(XMVectorSet((float)(i%2)-0.5f, (float)(i/2)-0.5f, -0.5f, 1), Colors::Blue), VertexPositionColor(XMVectorSet((float)(i%2)-0.5f, (float)(i/2)-0.5f, 0.6f, 1), Colors::Blue) ); } g_pPrimitiveBatchPositionColor->End(); } // Draw a large, square plane at y=-1 with a checkerboard pattern // (Drawn as multiple quads, i.e. triangle strips, using a DirectXTK primitive batch) void DrawFloor(ID3D11DeviceContext* pd3dImmediateContext) { // Setup position/normal/color effect g_pEffectPositionNormalColor->SetWorld(XMMatrixIdentity()); g_pEffectPositionNormalColor->SetEmissiveColor(Colors::Black); g_pEffectPositionNormalColor->SetDiffuseColor(0.8f * Colors::White); g_pEffectPositionNormalColor->SetSpecularColor(0.4f * Colors::White); g_pEffectPositionNormalColor->SetSpecularPower(1000); g_pEffectPositionNormalColor->Apply(pd3dImmediateContext); pd3dImmediateContext->IASetInputLayout(g_pInputLayoutPositionNormalColor); // Draw 4*n*n quads spanning x = [-n;n], y = -1, z = [-n;n] const float n = 4; XMVECTOR normal = XMVectorSet(0, 1,0,0); XMVECTOR planecenter = XMVectorSet(0,-1,0,0); g_pPrimitiveBatchPositionNormalColor->Begin(); for (float z = -n; z < n; z++) { for (float x = -n; x < n; x++) { // Quad vertex positions XMVECTOR pos[] = { XMVectorSet(x , -1, z+1, 0), XMVectorSet(x+1, -1, z+1, 0), XMVectorSet(x+1, -1, z , 0), XMVectorSet(x , -1, z , 0) }; // Color checkerboard pattern (white & gray) XMVECTOR color = ((int(z + x) % 2) == 0) ? XMVectorSet(1,1,1,1) : XMVectorSet(0.6f,0.6f,0.6f,1); // Color attenuation based on distance to plane center float attenuation[] = { 1.0f - XMVectorGetX(XMVector3Length(pos[0] - planecenter)) / n, 1.0f - XMVectorGetX(XMVector3Length(pos[1] - planecenter)) / n, 1.0f - XMVectorGetX(XMVector3Length(pos[2] - planecenter)) / n, 1.0f - XMVectorGetX(XMVector3Length(pos[3] - planecenter)) / n }; g_pPrimitiveBatchPositionNormalColor->DrawQuad( VertexPositionNormalColor(pos[0], normal, attenuation[0] * color), VertexPositionNormalColor(pos[1], normal, attenuation[1] * color), VertexPositionNormalColor(pos[2], normal, attenuation[2] * color), VertexPositionNormalColor(pos[3], normal, attenuation[3] * color) ); } } g_pPrimitiveBatchPositionNormalColor->End(); } void updateScreenSize(int width, int height) { // Update camera parameters g_camera.SetWindow(width, height); g_camera.SetProjParams(XM_PI / 4.0f, float(width) / float(height), 0.1f, 100.0f); // Inform AntTweakBar about back buffer resolution change TwWindowSize(width,height); } void update(float fElapsedTime) { // Move camera g_camera.FrameMove(fElapsedTime); // Update effects with new view + proj transformations g_pEffectPositionColor->SetView (g_camera.GetViewMatrix()); g_pEffectPositionColor->SetProjection (g_camera.GetProjMatrix()); g_pEffectPositionNormal->SetView (g_camera.GetViewMatrix()); g_pEffectPositionNormal->SetProjection(g_camera.GetProjMatrix()); g_pEffectPositionNormalColor->SetView(g_camera.GetViewMatrix()); g_pEffectPositionNormalColor->SetProjection(g_camera.GetProjMatrix()); } void setUpLighting(Vec3 EmissiveColor, Vec3 SpecularColor, float SpecularPower, Vec3 DiffuseColor) { XMVECTOR c1 = EmissiveColor.toDirectXVector(); XMVECTOR c2 = SpecularColor.toDirectXVector(); XMVECTOR c3 = DiffuseColor.toDirectXVector(); g_pEffectPositionNormal->SetEmissiveColor(c1); g_pEffectPositionNormal->SetSpecularColor(c2); g_pEffectPositionNormal->SetSpecularPower(SpecularPower); g_pEffectPositionNormal->SetDiffuseColor(c3); } void drawSphere(Vec3 pos, Vec3 scale) { drawSphere(pos.toDirectXVector(), scale.toDirectXVector()); } void drawSphere(const XMVECTOR pos, const XMVECTOR scale) { // Setup position/normal effect (per object variables) XMMATRIX s = XMMatrixScaling(XMVectorGetX(scale), XMVectorGetY(scale),XMVectorGetZ(scale)); XMMATRIX t = XMMatrixTranslation(XMVectorGetX(pos), XMVectorGetY(pos), XMVectorGetZ(pos)); g_pEffectPositionNormal->SetWorld(s * t * g_camera.GetWorldMatrix()); // Draw // NOTE: The following generates one draw call per object, so performance will be bad for n>>1000 or so g_pSphere->Draw( g_pEffectPositionNormal, g_pInputLayoutPositionNormal); } void drawTeapot(Vec3 pos,Vec3 rot,Vec3 scale) { drawTeapot(pos.toDirectXVector(),rot.toDirectXVector(),scale.toDirectXVector()); } void drawTeapot(const XMVECTOR pos,const XMVECTOR rot,const XMVECTOR scale) { // Setup position/normal effect (per object variables) XMMATRIX s = XMMatrixScaling(XMVectorGetX(scale), XMVectorGetY(scale),XMVectorGetZ(scale)); XMMATRIX t = XMMatrixTranslation(XMVectorGetX(pos), XMVectorGetY(pos), XMVectorGetZ(pos)); XMMATRIX r = XMMatrixRotationRollPitchYaw(XMVectorGetX(rot), XMVectorGetX(rot), XMVectorGetX(rot)); g_pEffectPositionNormal->SetWorld(r * s * t * g_camera.GetWorldMatrix()); // Draw // NOTE: The following generates one draw call per object, so performance will be bad for n>>1000 or so g_pTeapot->Draw( g_pEffectPositionNormal, g_pInputLayoutPositionNormal); } void drawRigidBody(const XMMATRIX& m_objToWorld) { g_pEffectPositionNormal->SetWorld(m_objToWorld); g_pEffectPositionNormal->Apply(g_pd3dImmediateContext); g_pd3dImmediateContext->IASetInputLayout(g_pInputLayoutPositionNormal); // front g_pPrimitiveBatchPositionNormal->Begin(); g_pPrimitiveBatchPositionNormal->DrawQuad( VertexPositionNormal(XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT3(0,0,-1)), VertexPositionNormal(XMFLOAT3(-0.5f, 0.5f, -0.5f), XMFLOAT3(0,0,-1)), VertexPositionNormal(XMFLOAT3(0.5f, 0.5f, -0.5f), XMFLOAT3(0,0,-1)), VertexPositionNormal(XMFLOAT3(0.5f, -0.5f, -0.5f), XMFLOAT3(0,0,-1)) ); // back g_pPrimitiveBatchPositionNormal->DrawQuad( VertexPositionNormal(XMFLOAT3(0.5f, -0.5f, 0.5f), XMFLOAT3(0,0,1)), VertexPositionNormal(XMFLOAT3(0.5f, 0.5f, 0.5f), XMFLOAT3(0,0,1)), VertexPositionNormal(XMFLOAT3(-0.5f, 0.5f, 0.5f), XMFLOAT3(0,0,1)), VertexPositionNormal(XMFLOAT3(-0.5f, -0.5f, 0.5f), XMFLOAT3(0,0,1)) ); // left g_pPrimitiveBatchPositionNormal->DrawQuad( VertexPositionNormal(XMFLOAT3(-0.5f, -0.5f, 0.5f), XMFLOAT3(-1,0,0)), VertexPositionNormal(XMFLOAT3(-0.5f, 0.5f, 0.5f), XMFLOAT3(-1,0,0)), VertexPositionNormal(XMFLOAT3(-0.5f, 0.5f, -0.5f), XMFLOAT3(-1,0,0)), VertexPositionNormal(XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT3(-1,0,0)) ); // right g_pPrimitiveBatchPositionNormal->DrawQuad( VertexPositionNormal(XMFLOAT3(0.5f, -0.5f, -0.5f), XMFLOAT3(1,0,0)), VertexPositionNormal(XMFLOAT3(0.5f, 0.5f, -0.5f), XMFLOAT3(1,0,0)), VertexPositionNormal(XMFLOAT3(0.5f, 0.5f, 0.5f), XMFLOAT3(1,0,0)), VertexPositionNormal(XMFLOAT3(0.5f, -0.5f, 0.5f), XMFLOAT3(1,0,0)) ); // top g_pPrimitiveBatchPositionNormal->DrawQuad( VertexPositionNormal(XMFLOAT3(-0.5f, 0.5f, -0.5f), XMFLOAT3(0,1,0)), VertexPositionNormal(XMFLOAT3(-0.5f, 0.5f, 0.5f), XMFLOAT3(0,1,0)), VertexPositionNormal(XMFLOAT3(0.5f, 0.5f, 0.5f), XMFLOAT3(0,1,0)), VertexPositionNormal(XMFLOAT3(0.5f, 0.5f, -0.5f), XMFLOAT3(0,1,0)) ); // bottom g_pPrimitiveBatchPositionNormal->DrawQuad( VertexPositionNormal(XMFLOAT3(0.5f, -0.5f, -0.5f), XMFLOAT3(0,-1,0)), VertexPositionNormal(XMFLOAT3(0.5f, -0.5f, 0.5f), XMFLOAT3(0,-1,0)), VertexPositionNormal(XMFLOAT3(-0.5f, -0.5f, 0.5f), XMFLOAT3(0,-1,0)), VertexPositionNormal(XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT3(0,-1,0)) ); g_pPrimitiveBatchPositionNormal->End(); } void drawRigidBody(Mat4 m_objToWorld) { drawRigidBody(m_objToWorld.toDirectXMatrix()); } void DrawTriangleUsingShaders() { XMMATRIX world = g_camera.GetWorldMatrix(); XMMATRIX view = g_camera.GetViewMatrix(); XMMATRIX proj = g_camera.GetProjMatrix(); XMFLOAT4X4 mViewProj; XMStoreFloat4x4(&mViewProj, world * view * proj); g_pEffect->GetVariableByName("g_worldViewProj")->AsMatrix()->SetMatrix((float*)mViewProj.m); g_pEffect->GetTechniqueByIndex(0)->GetPassByIndex(0)->Apply(0, g_pd3dImmediateContext); g_pd3dImmediateContext->IASetVertexBuffers(0, 0, nullptr, nullptr, nullptr); g_pd3dImmediateContext->IASetIndexBuffer(nullptr, DXGI_FORMAT_R16_UINT, 0); g_pd3dImmediateContext->IASetInputLayout(nullptr); g_pd3dImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); g_pd3dImmediateContext->Draw(3, 0); } void beginLine() { g_pEffectPositionColor->SetWorld(g_camera.GetWorldMatrix()); g_pEffectPositionColor->Apply(g_pd3dImmediateContext); g_pd3dImmediateContext->IASetInputLayout(g_pInputLayoutPositionColor); // Draw g_pPrimitiveBatchPositionColor->Begin(); } void drawLine(Vec3 pos1,Vec3 color1, Vec3 pos2,Vec3 color2) { drawLine(pos1.toDirectXVector(),color1.toDirectXVector(),pos2.toDirectXVector(),color2.toDirectXVector()); } void drawLine(const XMVECTOR pos1,const XMVECTOR &color1, const XMVECTOR pos2,const XMVECTOR &color2) { g_pPrimitiveBatchPositionColor->DrawLine( VertexPositionColor(pos1, color1), VertexPositionColor(pos2, color2) ); } void endLine() { g_pPrimitiveBatchPositionColor->End(); } }; #endif