Fixed capsule auxgeom draw for lights and other aux geom issues

Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com>
This commit is contained in:
antonmic
2021-11-17 22:55:29 -08:00
parent b44ce82435
commit 8587c8e033
7 changed files with 242 additions and 166 deletions
@@ -10,6 +10,7 @@
#include "AuxGeomDrawProcessorShared.h"
#include <AzCore/Debug/EventTrace.h>
#include <AzCore/std/algorithm.h>
#include <AzCore/std/containers/array.h>
#include <Atom/RHI/Factory.h>
@@ -69,11 +70,13 @@ namespace AZ
SetupInputStreamLayout(m_objectStreamLayout[DrawStyle_Solid], RHI::PrimitiveTopology::TriangleList, false);
SetupInputStreamLayout(m_objectStreamLayout[DrawStyle_Shaded], RHI::PrimitiveTopology::TriangleList, true);
CreateSphereBuffersAndViews();
CreateSphereBuffersAndViews(AuxGeomShapeType::ShapeType_Sphere);
CreateSphereBuffersAndViews(AuxGeomShapeType::ShapeType_Hemisphere);
CreateQuadBuffersAndViews();
CreateDiskBuffersAndViews();
CreateConeBuffersAndViews();
CreateCylinderBuffersAndViews();
CreateCylinderBuffersAndViews(AuxGeomShapeType::ShapeType_Cylinder);
CreateCylinderBuffersAndViews(AuxGeomShapeType::ShapeType_CylinderNoEnds);
CreateBoxBuffersAndViews();
// cache scene pointer for RHI::PipelineState creation.
@@ -293,8 +296,11 @@ namespace AZ
}
}
bool FixedShapeProcessor::CreateSphereBuffersAndViews()
bool FixedShapeProcessor::CreateSphereBuffersAndViews(AuxGeomShapeType sphereShapeType)
{
AZ_Assert(sphereShapeType == ShapeType_Sphere || sphereShapeType == ShapeType_Hemisphere,
"Trying to create sphere buffers and views with a non-sphere shape type!");
const uint32_t numSphereLods = 5;
struct LodInfo
{
@@ -311,13 +317,13 @@ namespace AZ
{ 9, 9, 0.0000f}
}};
auto& m_shape = m_shapes[ShapeType_Sphere];
auto& m_shape = m_shapes[sphereShapeType];
m_shape.m_numLods = numSphereLods;
for (uint32_t lodIndex = 0; lodIndex < numSphereLods; ++lodIndex)
{
MeshData meshData;
CreateSphereMeshData(meshData, lodInfo[lodIndex].numRings, lodInfo[lodIndex].numSections);
CreateSphereMeshData(meshData, lodInfo[lodIndex].numRings, lodInfo[lodIndex].numSections, sphereShapeType);
ObjectBuffers objectBuffers;
@@ -334,12 +340,25 @@ namespace AZ
return true;
}
void FixedShapeProcessor::CreateSphereMeshData(MeshData& meshData, uint32_t numRings, uint32_t numSections)
void FixedShapeProcessor::CreateSphereMeshData(MeshData& meshData, uint32_t numRings, uint32_t numSections, AuxGeomShapeType sphereShapeType)
{
const float radius = 1.0f;
// calculate "inner" vertices
float sectionAngle(DegToRad(360.0f / static_cast<float>(numSections)));
float ringSlice(DegToRad(180.0f / static_cast<float>(numRings)));
uint32_t numberOfPoles = 2;
if (sphereShapeType == ShapeType_Hemisphere)
{
numberOfPoles = 1;
numRings = (numRings + 1) / 2;
ringSlice = DegToRad(90.0f / static_cast<float>(numRings));
}
// calc required number of vertices/indices/triangles to build a sphere for the given parameters
uint32_t numVertices = (numRings - 1) * numSections + 2;
uint32_t numVertices = (numRings - 1) * numSections + numberOfPoles;
// setup buffers
auto& positions = meshData.m_positions;
@@ -354,30 +373,29 @@ namespace AZ
using NormalType = AuxGeomNormal;
// 1st pole vertex
positions.push_back(PosType(0.0f, 0.0f, radius));
normals.push_back(NormalType(0.0f, 0.0f, 1.0f));
positions.push_back(PosType(0.0f, radius, 0.0f));
normals.push_back(NormalType(0.0f, 1.0f, 0.0f));
// calculate "inner" vertices
float sectionAngle(DegToRad(360.0f / static_cast<float>(numSections)));
float ringSlice(DegToRad(180.0f / static_cast<float>(numRings)));
for (uint32_t ring = 1; ring < numRings; ++ring)
for (uint32_t ring = 1; ring < numRings - numberOfPoles + 2; ++ring)
{
float w(sinf(ring * ringSlice));
for (uint32_t section = 0; section < numSections; ++section)
{
float x = radius * cosf(section * sectionAngle) * w;
float y = radius * sinf(section * sectionAngle) * w;
float z = radius * cosf(ring * ringSlice);
float y = radius * cosf(ring * ringSlice);
float z = radius * sinf(section * sectionAngle) * w;
Vector3 radialVector(x, y, z);
positions.push_back(radialVector);
normals.push_back(radialVector.GetNormalized());
}
}
// 2nd vertex of pole (for end cap)
positions.push_back(PosType(0.0f, 0.0f, -radius));
normals.push_back(NormalType(0.0f, 0.0f, -1.0f));
if (sphereShapeType == ShapeType_Sphere)
{
// 2nd vertex of pole (for end cap)
positions.push_back(PosType(0.0f, -radius, 0.0f));
normals.push_back(NormalType(0.0f, -1.0f, 0.0f));
}
// point indices
{
@@ -393,7 +411,8 @@ namespace AZ
// line indices
{
const uint32_t numEdges = (numRings - 2) * numSections * 2 + 2 * numSections * 2;
// NumEdges = NumRingEdges + NumSectionEdges = (numRings * numSections) + (numRings * numSections)
const uint32_t numEdges = numRings * numSections * 2;
const uint32_t numLineIndices = numEdges * 2;
// build "inner" faces
@@ -401,10 +420,9 @@ namespace AZ
indices.clear();
indices.reserve(numLineIndices);
for (uint16_t ring = 0; ring < numRings - 2; ++ring)
for (uint16_t ring = 0; ring < numRings - numberOfPoles + 1; ++ring)
{
uint16_t firstVertOfThisRing = static_cast<uint16_t>(1 + ring * numSections);
uint16_t firstVertOfNextRing = static_cast<uint16_t>(1 + (ring + 1) * numSections);
for (uint16_t section = 0; section < numSections; ++section)
{
uint32_t nextSection = (section + 1) % numSections;
@@ -414,32 +432,33 @@ namespace AZ
indices.push_back(static_cast<uint16_t>(firstVertOfThisRing + nextSection));
// line around section
indices.push_back(firstVertOfThisRing + section);
indices.push_back(firstVertOfNextRing + section);
int currentVertexIndex = firstVertOfThisRing + section;
// max 0 will implicitly handle the top pole
int previousVertexIndex = AZStd::max(currentVertexIndex - (int)numSections, 0);
indices.push_back(static_cast<uint16_t>(currentVertexIndex));
indices.push_back(static_cast<uint16_t>(previousVertexIndex));
}
}
// build faces for end caps (to connect "inner" vertices with poles)
uint16_t firstPoleVert = 0;
uint16_t firstVertOfFirstRing = static_cast<uint16_t>(1 + (0) * numSections);
for (uint16_t section = 0; section < numSections; ++section)
if (sphereShapeType == ShapeType_Sphere)
{
indices.push_back(firstPoleVert);
indices.push_back(firstVertOfFirstRing + section);
}
uint16_t lastPoleVert = static_cast<uint16_t>((numRings - 1) * numSections + 1);
uint16_t firstVertOfLastRing = static_cast<uint16_t>(1 + (numRings - 2) * numSections);
for (uint16_t section = 0; section < numSections; ++section)
{
indices.push_back(firstVertOfLastRing + section);
indices.push_back(lastPoleVert);
// build faces for bottom pole (to connect "inner" vertices with poles)
uint16_t lastPoleVert = static_cast<uint16_t>((numRings - 1) * numSections + 1);
uint16_t firstVertOfLastRing = static_cast<uint16_t>(1 + (numRings - 2) * numSections);
for (uint16_t section = 0; section < numSections; ++section)
{
indices.push_back(firstVertOfLastRing + section);
indices.push_back(lastPoleVert);
}
}
}
// triangle indices
{
const uint32_t numTriangles = (numRings - 2) * numSections * 2 + 2 * numSections;
// NumTriangles = NumTrianglesAtPoles + NumQuads * 2
// = (numSections * 2) + ((numRings - 2) * numSections * 2)
// = (numSections * 2) * (numRings - 2 + 1)
const uint32_t numTriangles = (numRings - 1) * numSections * 2;
const uint32_t numTriangleIndices = numTriangles * 3;
// build "inner" faces
@@ -447,10 +466,10 @@ namespace AZ
indices.clear();
indices.reserve(numTriangleIndices);
for (uint32_t ring = 0; ring < numRings - 2; ++ring)
for (uint32_t ring = 0; ring < numRings - numberOfPoles; ++ring)
{
uint32_t firstVertOfThisRing = 1 + ring * numSections;
uint32_t firstVertOfNextRing = 1 + (ring + 1) * numSections;
uint32_t firstVertOfNextRing = firstVertOfThisRing + numSections;
for (uint32_t section = 0; section < numSections; ++section)
{
@@ -476,14 +495,17 @@ namespace AZ
indices.push_back(static_cast<uint16_t>(firstPoleVert));
}
uint32_t lastPoleVert = (numRings - 1) * numSections + 1;
uint32_t firstVertOfLastRing = 1 + (numRings - 2) * numSections;
for (uint32_t section = 0; section < numSections; ++section)
if (sphereShapeType == ShapeType_Sphere)
{
uint32_t nextSection = (section + 1) % numSections;
indices.push_back(static_cast<uint16_t>(firstVertOfLastRing + nextSection));
indices.push_back(static_cast<uint16_t>(firstVertOfLastRing + section));
indices.push_back(static_cast<uint16_t>(lastPoleVert));
uint32_t lastPoleVert = (numRings - 1) * numSections + 1;
uint32_t firstVertOfLastRing = 1 + (numRings - 2) * numSections;
for (uint32_t section = 0; section < numSections; ++section)
{
uint32_t nextSection = (section + 1) % numSections;
indices.push_back(static_cast<uint16_t>(firstVertOfLastRing + nextSection));
indices.push_back(static_cast<uint16_t>(firstVertOfLastRing + section));
indices.push_back(static_cast<uint16_t>(lastPoleVert));
}
}
}
}
@@ -827,8 +849,11 @@ namespace AZ
}
}
bool FixedShapeProcessor::CreateCylinderBuffersAndViews()
bool FixedShapeProcessor::CreateCylinderBuffersAndViews(AuxGeomShapeType cylinderShapeType)
{
AZ_Assert(cylinderShapeType == ShapeType_Cylinder || cylinderShapeType == ShapeType_CylinderNoEnds,
"Trying to create cylinder buffers and views with a non-cylinder shape type!");
const uint32_t numCylinderLods = 5;
struct LodInfo
{
@@ -836,21 +861,21 @@ namespace AZ
float screenPercentage;
};
const AZStd::array<LodInfo, numCylinderLods> lodInfo =
{{
{ {
{ 38, 0.1000f},
{ 22, 0.0100f},
{ 14, 0.0010f},
{ 10, 0.0001f},
{ 8, 0.0000f}
}};
} };
auto& m_shape = m_shapes[ShapeType_Cylinder];
auto& m_shape = m_shapes[cylinderShapeType];
m_shape.m_numLods = numCylinderLods;
for (uint32_t lodIndex = 0; lodIndex < numCylinderLods; ++lodIndex)
{
MeshData meshData;
CreateCylinderMeshData(meshData, lodInfo[lodIndex].numSections);
CreateCylinderMeshData(meshData, lodInfo[lodIndex].numSections, cylinderShapeType);
ObjectBuffers objectBuffers;
@@ -867,13 +892,25 @@ namespace AZ
return true;
}
void FixedShapeProcessor::CreateCylinderMeshData(MeshData& meshData, uint32_t numSections)
void FixedShapeProcessor::CreateCylinderMeshData(MeshData& meshData, uint32_t numSections, AuxGeomShapeType cylinderShapeType)
{
const float radius = 1.0f;
const float height = 1.0f;
//uint16_t indexOfBottomCenter = 0;
//uint16_t indexOfBottomStart = 1;
//uint16_t indexOfTopCenter = numSections + 1;
//uint16_t indexOfTopStart = numSections + 2;
uint16_t indexOfSidesStart = static_cast<uint16_t>(2 * numSections + 2);
if (cylinderShapeType == ShapeType_CylinderNoEnds)
{
// We won't draw disks at the ends of the cylinder, so no need to offset side indices
indexOfSidesStart = 0;
}
// calc required number of vertices to build a cylinder for the given parameters
uint32_t numVertices = 4 * numSections + 2;
uint32_t numVertices = indexOfSidesStart + 2 * numSections;
// setup buffers
auto& positions = meshData.m_positions;
@@ -888,8 +925,11 @@ namespace AZ
float topHeight = height * 0.5f;
// Create caps
CreateDiskMeshData(meshData, numSections, Facing::Down, bottomHeight);
CreateDiskMeshData(meshData, numSections, Facing::Up, topHeight);
if (cylinderShapeType == ShapeType_Cylinder)
{
CreateDiskMeshData(meshData, numSections, Facing::Down, bottomHeight);
CreateDiskMeshData(meshData, numSections, Facing::Up, topHeight);
}
// create vertices for side (so normal points out correctly)
float sectionAngle(DegToRad(360.0f / (float)numSections));
@@ -906,12 +946,6 @@ namespace AZ
normals.push_back(normal);
}
//uint16_t indexOfBottomCenter = 0;
//uint16_t indexOfBottomStart = 1;
//uint16_t indexOfTopCenter = numSections + 1;
//uint16_t indexOfTopStart = numSections + 2;
uint16_t indexOfSidesStart = static_cast<uint16_t>(2 * numSections + 2);
// build point indices
{
auto& indices = meshData.m_pointIndices;
@@ -930,6 +964,24 @@ namespace AZ
indices.push_back(indexOfSidesStart + 2 * section);
indices.push_back(indexOfSidesStart + 2 * section + 1);
}
// If we're not drawing the disks at the ends of the cylinder, we still want to
// draw a ring around the end to join the tips of lines we created just above
if (cylinderShapeType == ShapeType_CylinderNoEnds)
{
for (uint16_t section = 0; section < numSections; ++section)
{
uint16_t nextSection = (section + 1) % numSections;
// line around the bottom cap
indices.push_back(section * 2);
indices.push_back(nextSection * 2);
// line around the top cap
indices.push_back(section * 2 + 1);
indices.push_back(nextSection * 2 + 1);
}
}
}
// indices for triangles