|
|
|
|
@ -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)
|
|
|
|
|
{
|
|
|
|
|
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)
|
|
|
|
|
if (sphereShapeType == ShapeType_Sphere)
|
|
|
|
|
{
|
|
|
|
|
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
|
|
|
|
|
|