432 lines
12 KiB
C++
432 lines
12 KiB
C++
#include "stdafx.h"
|
|
#include "IResourceFactory.h"
|
|
#include "GeometryBuffer.h"
|
|
|
|
|
|
GeometryBuffer::GeometryBuffer(IEngine& argEngine)
|
|
: m_Engine(argEngine)
|
|
, m_VertexBuffer(NULL)
|
|
, m_IndexBuffer(NULL)
|
|
, m_InputElementDesc(NULL)
|
|
, m_VertexCount(0)
|
|
, m_VertexElementSize(0)
|
|
, m_IndexCount(0)
|
|
, m_VertexOffset(0)
|
|
, m_VertexDataMapped(false)
|
|
, m_IndexDataMapped(false)
|
|
, m_RawVertexData_(NULL)
|
|
, m_RawIndexData(NULL)
|
|
, m_PrimitiveTopology(PrimitiveTopology::TriangleList)
|
|
, m_IndexOffset(0)
|
|
, m_UsableIndexCount(0)
|
|
{
|
|
m_Commands.push_back(new Command(this, CommandFlags::None, SetIndexBufferCommandType, 1));
|
|
m_Commands.push_back(new Command(this, CommandFlags::None, SetVertexBufferCommandType, 0));
|
|
m_Commands.push_back(new Command(this, CommandFlags::EndChain | CommandFlags::Unique, DrawGeometryCommandType, 6));
|
|
}
|
|
|
|
|
|
GeometryBuffer::~GeometryBuffer()
|
|
{
|
|
this->Uninitialize();
|
|
m_Engine.get_ResourceFactory().DeleteGeometryBuffer(*const_cast<GeometryBuffer*>(this), true);
|
|
}
|
|
|
|
|
|
void GeometryBuffer::Uninitialize()
|
|
{
|
|
if (m_Engine.get_EngineStates().LastIndexBufferProvider == this)
|
|
m_Engine.get_EngineStates().LastIndexBufferProvider = NULL;
|
|
if (m_Engine.get_EngineStates().LastVertexBufferProvider == this)
|
|
m_Engine.get_EngineStates().LastVertexBufferProvider = NULL;
|
|
|
|
this->DeleteVertexData();
|
|
this->DeleteIndexData();
|
|
}
|
|
|
|
|
|
void GeometryBuffer::SetVertexData(uint32 argVertexCount, uint32 argVertexElementSize, void* a_VertexData_, const std::vector<VertexElement>& argVertexElements, bool argNeedsDynamicAccess)
|
|
{
|
|
this->DeleteVertexData();
|
|
|
|
D3D10_BUFFER_DESC desc;
|
|
desc.Usage = argNeedsDynamicAccess ? D3D10_USAGE_DYNAMIC : D3D10_USAGE_DEFAULT;
|
|
desc.ByteWidth = argVertexElementSize * argVertexCount;
|
|
desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
|
|
desc.CPUAccessFlags = argNeedsDynamicAccess ? D3D10_CPU_ACCESS_WRITE : 0;
|
|
desc.MiscFlags = 0;
|
|
|
|
D3D10_SUBRESOURCE_DATA initData;
|
|
initData.pSysMem = a_VertexData_;
|
|
if (S_OK != m_Engine.get_DX10Device().CreateBuffer(&desc, &initData, &m_VertexBuffer))
|
|
{
|
|
throw L"GeometryBuffer: Unable to create vertex buffer.";
|
|
}
|
|
|
|
m_VertexCount = argVertexCount;
|
|
m_VertexElementSize = argVertexElementSize;
|
|
m_VertexElements = argVertexElements;
|
|
|
|
m_RawVertexData_ = new char[argVertexElementSize * argVertexCount];
|
|
::memcpy(m_RawVertexData_, a_VertexData_, argVertexElementSize * argVertexCount);
|
|
|
|
if (m_InputElementDesc == NULL)
|
|
{
|
|
if (!m_VertexElements.empty())
|
|
{
|
|
m_InputElementDesc = new D3D10_INPUT_ELEMENT_DESC[m_VertexElements.size()];
|
|
|
|
for (uint32 i = 0; i < m_VertexElements.size(); ++i)
|
|
{
|
|
D3D10_INPUT_ELEMENT_DESC desc;
|
|
VertexElement& element = m_VertexElements[i];
|
|
|
|
desc.AlignedByteOffset = D3D10_APPEND_ALIGNED_ELEMENT;
|
|
desc.Format = (DXGI_FORMAT)element.m_ElementFormat;
|
|
desc.InputSlot = 0; // should this be a parameter too?
|
|
desc.InputSlotClass = D3D10_INPUT_PER_VERTEX_DATA;
|
|
desc.InstanceDataStepRate = 0;
|
|
desc.SemanticIndex = element.m_NameIndex;
|
|
desc.SemanticName = element.m_SemanticName.c_str();
|
|
m_InputElementDesc[i] = desc;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void GeometryBuffer::DeleteVertexData()
|
|
{
|
|
if (m_VertexBuffer != NULL)
|
|
m_Engine.get_DX10Device().ClearState();
|
|
|
|
m_VertexElements.clear();
|
|
|
|
if (m_VertexBuffer != NULL)
|
|
m_VertexBuffer->Release();
|
|
m_VertexBuffer = NULL;
|
|
|
|
m_VertexCount = 0;
|
|
m_VertexElementSize = 0;
|
|
m_VertexDataMapped = false;
|
|
|
|
if (m_RawVertexData_ != NULL)
|
|
delete [] m_RawVertexData_;
|
|
m_RawVertexData_ = NULL;
|
|
|
|
if (m_InputElementDesc != NULL)
|
|
delete [] m_InputElementDesc;
|
|
m_InputElementDesc = NULL;
|
|
}
|
|
|
|
|
|
void GeometryBuffer::SetIndexData(uint32 argIndexCount, uint32* aui_IndexData_, bool argNeedsDynamicAccess)
|
|
{
|
|
this->DeleteIndexData();
|
|
|
|
D3D10_BUFFER_DESC desc;
|
|
desc.Usage = D3D10_USAGE_DEFAULT;
|
|
desc.ByteWidth = sizeof(uint32) * argIndexCount;
|
|
desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
|
|
desc.CPUAccessFlags = argNeedsDynamicAccess ? D3D10_CPU_ACCESS_WRITE : 0;
|
|
desc.MiscFlags = 0;
|
|
|
|
D3D10_SUBRESOURCE_DATA initData;
|
|
initData.pSysMem = aui_IndexData_;
|
|
initData.SysMemPitch = 0;
|
|
initData.SysMemSlicePitch = 0;
|
|
if (S_OK != m_Engine.get_DX10Device().CreateBuffer(&desc, &initData, &m_IndexBuffer))
|
|
{
|
|
throw L"GeometryBuffer: Unable to create index buffer.";
|
|
}
|
|
|
|
m_IndexCount = argIndexCount;
|
|
m_UsableIndexCount = argIndexCount;
|
|
m_IndexOffset = 0;
|
|
|
|
m_RawIndexData = new uint32[m_IndexCount];
|
|
::memcpy(m_RawIndexData, aui_IndexData_, sizeof(uint32) * m_IndexCount);
|
|
}
|
|
|
|
|
|
void GeometryBuffer::DeleteIndexData()
|
|
{
|
|
if (m_IndexBuffer != NULL)
|
|
m_Engine.get_DX10Device().ClearState();
|
|
|
|
if (m_IndexBuffer != NULL)
|
|
m_IndexBuffer->Release();
|
|
m_IndexBuffer = NULL;
|
|
|
|
if (m_RawIndexData != NULL)
|
|
delete [] m_RawIndexData;
|
|
m_RawIndexData = NULL;
|
|
|
|
m_IndexCount = 0;
|
|
|
|
while (!m_VertexLayoutsPerShaderAndPass.empty())
|
|
{
|
|
while (!m_VertexLayoutsPerShaderAndPass.begin()->second.empty())
|
|
{
|
|
m_VertexLayoutsPerShaderAndPass.begin()->second.back()->Release();
|
|
m_VertexLayoutsPerShaderAndPass.begin()->second.pop_back();
|
|
}
|
|
m_VertexLayoutsPerShaderAndPass.erase(m_VertexLayoutsPerShaderAndPass.begin());
|
|
}
|
|
}
|
|
|
|
|
|
void* GeometryBuffer::MapVertexBuffer(DataAccessMode::Enumeration argAccessMode)
|
|
{
|
|
if (m_VertexBuffer == NULL)
|
|
{
|
|
throw L"GeometryBuffer: Access forbidden until resource has been initialized.";
|
|
}
|
|
|
|
if (m_VertexDataMapped)
|
|
{
|
|
throw L"GeometryBuffer: Only one access to the vertex buffer at one time possible.";
|
|
}
|
|
|
|
void* dataPointer = NULL;
|
|
if (S_OK != m_VertexBuffer->Map((D3D10_MAP)argAccessMode, 0, &dataPointer))
|
|
{
|
|
throw L"GeometryBuffer: Access to the vertex buffer was not successfull.";
|
|
}
|
|
|
|
m_VertexDataMapped = true;
|
|
|
|
return dataPointer;
|
|
}
|
|
|
|
|
|
void GeometryBuffer::UnmapVertexBuffer()
|
|
{
|
|
if (m_VertexBuffer == NULL)
|
|
{
|
|
throw L"GeometryBuffer: Access forbidden until resource has been initialized.";
|
|
}
|
|
|
|
if (!m_VertexDataMapped)
|
|
{
|
|
throw L"GeometryBuffer: No access was done ending the access to the vertex buffer is not possible.";
|
|
}
|
|
|
|
m_VertexBuffer->Unmap();
|
|
|
|
m_VertexDataMapped = false;
|
|
}
|
|
|
|
|
|
uint32* GeometryBuffer::MapIndexBuffer(DataAccessMode::Enumeration argAccessMode)
|
|
{
|
|
if (m_IndexBuffer == NULL)
|
|
{
|
|
throw L"GeometryBuffer: Access forbidden until resource has been initialized.";
|
|
}
|
|
|
|
if (m_IndexDataMapped)
|
|
{
|
|
throw L"GeometryBuffer: Only one access to the index buffer at one time possible.";
|
|
}
|
|
|
|
void* dataPointer = NULL;
|
|
if (S_OK != m_IndexBuffer->Map((D3D10_MAP)argAccessMode, 0, &dataPointer))
|
|
{
|
|
throw L"GeometryBuffer: Access to the index buffer was not successfull.";
|
|
}
|
|
|
|
m_IndexDataMapped = true;
|
|
|
|
return (uint32*)dataPointer;
|
|
}
|
|
|
|
|
|
void GeometryBuffer::UnmapIndexBuffer()
|
|
{
|
|
if (m_IndexBuffer == NULL)
|
|
{
|
|
throw L"GeometryBuffer: Access forbidden until resource has been initialized.";
|
|
}
|
|
|
|
if (!m_IndexDataMapped)
|
|
{
|
|
throw L"GeometryBuffer: No access was done ending the access to the index buffer is not possible.";
|
|
}
|
|
|
|
m_IndexBuffer->Unmap();
|
|
|
|
m_IndexDataMapped = false;
|
|
}
|
|
|
|
|
|
void GeometryBuffer::ConvertToAdjacency()
|
|
{
|
|
switch (m_PrimitiveTopology)
|
|
{
|
|
case PrimitiveTopology::LineList:
|
|
case PrimitiveTopology::LineStrip:
|
|
case PrimitiveTopology::TriangleList:
|
|
case PrimitiveTopology::TriangleStrip:
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
D3D10_INPUT_ELEMENT_DESC inputLayout[2] =
|
|
{
|
|
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
|
|
{ "END", 0, DXGI_FORMAT_R8_UINT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
|
|
};
|
|
|
|
inputLayout[1].AlignedByteOffset = m_VertexElementSize - 1;
|
|
|
|
// create the mesh
|
|
uint32 numVertices = m_VertexCount;
|
|
uint32 numIndices = m_IndexCount;
|
|
uint32 Options = D3DX10_MESH_32_BIT;
|
|
ID3DX10Mesh* mesh = NULL;
|
|
|
|
if (S_OK != D3DX10CreateMesh(&m_Engine.get_DX10Device(),
|
|
inputLayout,
|
|
2,
|
|
inputLayout[0].SemanticName,
|
|
numVertices,
|
|
numIndices / 3,
|
|
Options,
|
|
&mesh ) )
|
|
{
|
|
throw L"GeometryBuffer: Unable to create temp. mesh for adjacency data generation.";
|
|
}
|
|
|
|
//set the VB
|
|
mesh->SetVertexData(0, (void*)m_RawVertexData_);
|
|
|
|
//set the IB
|
|
mesh->SetIndexData((void*)m_RawIndexData, numIndices);
|
|
|
|
//generate adjacency
|
|
const float epsilon = 0.0f;
|
|
mesh->GenerateAdjacencyAndPointReps(epsilon);
|
|
|
|
//generate adjacency indices
|
|
mesh->GenerateGSAdjacency();
|
|
|
|
//get the adjacency data out of the mesh
|
|
ID3DX10MeshBuffer* indexBufferMesh = NULL;
|
|
unsigned char* adjIndices = NULL;
|
|
SIZE_T Size = 0;
|
|
|
|
if(S_OK != mesh->GetIndexBuffer(&indexBufferMesh))
|
|
{
|
|
throw L"GeometryBuffer: Unable to retrive indexdata for adjacency data generation.";
|
|
}
|
|
|
|
if(S_OK != indexBufferMesh->Map((void**)&adjIndices, &Size))
|
|
{
|
|
throw L"GeometryBuffer: Unable to map indexdata for adjacency data generation.";
|
|
}
|
|
|
|
this->SetIndexData((uint32)Size/sizeof(uint32), (uint32*)adjIndices, false);
|
|
|
|
//cleanup
|
|
indexBufferMesh->Unmap();
|
|
indexBufferMesh->Release();
|
|
mesh->Release();
|
|
|
|
switch (m_PrimitiveTopology)
|
|
{
|
|
case PrimitiveTopology::LineList:
|
|
this->set_PrimitiveTopology(PrimitiveTopology::LineListAdjacency);
|
|
break;
|
|
case PrimitiveTopology::LineStrip:
|
|
this->set_PrimitiveTopology(PrimitiveTopology::LineStripAdjacency);
|
|
break;
|
|
case PrimitiveTopology::TriangleList:
|
|
this->set_PrimitiveTopology(PrimitiveTopology::TriangleListAdjacency);
|
|
break;
|
|
case PrimitiveTopology::TriangleStrip:
|
|
this->set_PrimitiveTopology(PrimitiveTopology::TriangleStripAdjacency);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
CommandExecuteResult::Enumeration GeometryBuffer::ExecuteCommand(unsigned char argCommandType, ICommandBuffer& argCurrentBuffer, uint32 argCurrentPositon)
|
|
{
|
|
ID3D10Device& device = m_Engine.get_DX10Device();
|
|
|
|
if (argCommandType == GeometryBuffer::SetIndexBufferCommandType)
|
|
{
|
|
if (m_Engine.get_EngineStates().LastIndexBufferProvider != this)
|
|
{
|
|
device.IASetIndexBuffer(m_IndexBuffer, DXGI_FORMAT_R32_UINT, m_IndexOffset);
|
|
m_Engine.get_EngineStates().LastIndexBufferProvider = this;
|
|
}
|
|
}
|
|
else if (argCommandType == GeometryBuffer::SetVertexBufferCommandType)
|
|
{
|
|
if (m_Engine.get_EngineStates().LastVertexBufferProvider != this)
|
|
{
|
|
device.IASetVertexBuffers(0, 1, &m_VertexBuffer, &m_VertexElementSize, &m_VertexOffset);
|
|
device.IASetPrimitiveTopology((D3D10_PRIMITIVE_TOPOLOGY)m_PrimitiveTopology);
|
|
|
|
m_Engine.get_EngineStates().LastVertexBufferProvider = this;
|
|
}
|
|
}
|
|
else if (argCommandType == GeometryBuffer::DrawGeometryCommandType)
|
|
{
|
|
if (m_Engine.get_EngineStates().LastShader == NULL)
|
|
std::wcout << std::red << "GeometryBuffer could not render without a valid shader." << std::white << std::endl;
|
|
else if (m_Engine.get_EngineStates().LastVertexBufferProvider == NULL)
|
|
std::wcout << std::red << "GeometryBuffer could not render without a valid vertex buffer." << std::white << std::endl;
|
|
else
|
|
this->Render(*m_Engine.get_EngineStates().LastShader);
|
|
}
|
|
return CommandExecuteResult::None;
|
|
}
|
|
|
|
|
|
void GeometryBuffer::Render(IShader& argShader)
|
|
{
|
|
if (m_VertexElements.empty())
|
|
return;
|
|
|
|
uint32 currentPass = argShader.get_CurrentRenderPass();
|
|
ID3D10EffectPass* currentEffectPass = argShader.get_DX10Technique()->GetPassByIndex(currentPass);
|
|
|
|
ID3D10InputLayout* vertexLayout = NULL;
|
|
tk_VertexLayoutsPerShaderAndPass::iterator found = m_VertexLayoutsPerShaderAndPass.find(&argShader);
|
|
if (found != m_VertexLayoutsPerShaderAndPass.end() && found->second.size() > currentPass)
|
|
{
|
|
vertexLayout = found->second[currentPass];
|
|
}
|
|
else
|
|
{
|
|
D3D10_PASS_DESC passDesc;
|
|
currentEffectPass->GetDesc(&passDesc);
|
|
if (S_OK == m_Engine.get_DX10Device().CreateInputLayout(m_InputElementDesc, m_VertexElements.size(), passDesc.pIAInputSignature,
|
|
passDesc.IAInputSignatureSize, &vertexLayout ))
|
|
{
|
|
if (found == m_VertexLayoutsPerShaderAndPass.end())
|
|
{
|
|
std::vector<ID3D10InputLayout*> val;
|
|
val.push_back(vertexLayout);
|
|
m_VertexLayoutsPerShaderAndPass[&argShader] = val;
|
|
}
|
|
else
|
|
found->second.push_back(vertexLayout);
|
|
}
|
|
}
|
|
|
|
if (vertexLayout != NULL)
|
|
{
|
|
currentEffectPass->Apply(0);
|
|
m_Engine.get_DX10Device().IASetInputLayout(vertexLayout);
|
|
if (m_IndexBuffer == NULL)
|
|
m_Engine.get_DX10Device().Draw(m_VertexCount, 0);
|
|
else
|
|
m_Engine.get_DX10Device().DrawIndexed(m_UsableIndexCount, m_IndexOffset, 0);
|
|
}
|
|
}
|