mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 14:58:03 +02:00
[WL21389] WL21389 PR2: Representation of collision shapes need updating (details below).
This commit adds support for the polyhedrons and polygons sans Torus and Quad which aren't currently supported within GeometryCache. * Moves GeometryCache::_shapes from public to private scope * Nothing aside from the class should be directly altering this, only querying * Updated instances of direct referencing which looks to have been limited to prior testing of instancing and shapes. * Adds an accessor function for ShapeData to GeometryCache * Consolidates point list generation to helper function * GeometryCache::computeSimpleHullPointListForShape * Moves GeometryCache::Shape to entity::Shape mapping to GeometryCache from RenderableShapeEntityItem * Adds conversion accessor to GeometryCache, GeometryCache::Shape getShapeForEntityShape * Sets ShapeEntityItem::ShapeInfoCalculator callback committed earlier. * This helps circumvent the issue with library inclusion. entity-render knows about entity; however, entity doesn't know about entity-renderer; however, GeometryCache data is needed within entity::ShapeEntityItem to compose the ShapeInfo point list data. * This callback is set up within Application::init of the Interface as it knows about both halves of the equation, and the callback needs to be setup prior to any entities collision data getting generated. * Removes _type reset within ShapeInfo::setPointCollection * This should avoid any issues due to subversively setting the type or incorrectly setting the type as a tangential operation. * Audited instances of ShapeInfo::setPointCollection and all seemed to be calling the function immediately after having set the type via ShapeInfo::setParams * Adds new ShapeType: SHAPE_TYPE_CIRCLE * This type is reserved for the circle which is now treated as a special type of Cylinder_Y with regard to collision as opposed to a simple hull. * Fixes the issue where jumping on a circle, at times, would result in the avatar sliding off towards an edge as if atop a squished cone. * Also updates ShapeInfo::getType() to return ShapeType as opposed to int * Auditing calls showed that majority of places were comparing against ShapeType * ShapeType::_type is a ShapeType so returning the type explicitly is more consistent. * ShapeInfo file houses ShapeType enum so any file aware of ShapeInfo is aware of ShapeType enumeration. * entity::Quad defaults to SHAPE_TYPE_ELLIPSOID * Like entity::Shape::Torus, entity::Shape::Quad is currently unsupported within GeometryCache::buildShapes. * Also it appears that a Quad shape can't be created within world via the creation menu. * There's no explicit option at present to create one. * Trying subvert the Cube/Box creation option to generate one results in an enforced stubby box as opposed to a quad. * Given the aforementioned points, entity::Shape::Quad will default to SHAPE_TYPE_ELLIPSOID as opposed to SHAPE_TYPE_BOX. * Added Todo regarding the shape being unsupported along with a notation to create a special ShapeType, SHAPE_TYPE_QUAD, for it should it be added in the future. * Adds some comments and has some minor clean up. Reviewed-by: Leander Hasty <leander@1stplayable.com> Changes Committed: modified: interface/src/Application.cpp modified: interface/src/Util.cpp modified: interface/src/Util.h modified: libraries/entities-renderer/src/RenderableShapeEntityItem.cpp modified: libraries/entities/src/ShapeEntityItem.cpp modified: libraries/entities/src/ShapeEntityItem.h modified: libraries/physics/src/ShapeFactory.cpp modified: libraries/render-utils/src/GeometryCache.cpp modified: libraries/render-utils/src/GeometryCache.h modified: libraries/shared/src/ShapeInfo.cpp modified: libraries/shared/src/ShapeInfo.h modified: tests/gpu-test/src/TestInstancedShapes.cpp
This commit is contained in:
parent
9981a44b71
commit
5b50b362f1
12 changed files with 221 additions and 97 deletions
|
@ -120,6 +120,7 @@
|
||||||
#include <SceneScriptingInterface.h>
|
#include <SceneScriptingInterface.h>
|
||||||
#include <ScriptEngines.h>
|
#include <ScriptEngines.h>
|
||||||
#include <ScriptCache.h>
|
#include <ScriptCache.h>
|
||||||
|
#include <ShapeEntityItem.h>
|
||||||
#include <SoundCache.h>
|
#include <SoundCache.h>
|
||||||
#include <ui/TabletScriptingInterface.h>
|
#include <ui/TabletScriptingInterface.h>
|
||||||
#include <ui/ToolbarScriptingInterface.h>
|
#include <ui/ToolbarScriptingInterface.h>
|
||||||
|
@ -4228,6 +4229,10 @@ void Application::init() {
|
||||||
// fire off an immediate domain-server check in now that settings are loaded
|
// fire off an immediate domain-server check in now that settings are loaded
|
||||||
DependencyManager::get<NodeList>()->sendDomainServerCheckIn();
|
DependencyManager::get<NodeList>()->sendDomainServerCheckIn();
|
||||||
|
|
||||||
|
// This allows collision to be set up properly for shape entities supported by GeometryCache.
|
||||||
|
// This is before entity setup to ensure that it's ready for whenever instance collision is initialized.
|
||||||
|
ShapeEntityItem::setShapeInfoCalulator(ShapeEntityItem::ShapeInfoCalculator(&shapeInfoCalculator));
|
||||||
|
|
||||||
getEntities()->init();
|
getEntities()->init();
|
||||||
getEntities()->setEntityLoadingPriorityFunction([this](const EntityItem& item) {
|
getEntities()->setEntityLoadingPriorityFunction([this](const EntityItem& item) {
|
||||||
auto dims = item.getDimensions();
|
auto dims = item.getDimensions();
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
#include <GeometryCache.h>
|
#include <GeometryCache.h>
|
||||||
#include <OctreeConstants.h>
|
#include <OctreeConstants.h>
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
#include <ShapeEntityItem.h>
|
||||||
|
#include <ShapeInfo.h>
|
||||||
|
|
||||||
#include "InterfaceLogging.h"
|
#include "InterfaceLogging.h"
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
|
@ -393,4 +395,13 @@ void runUnitTests() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void shapeInfoCalculator(const ShapeEntityItem * const shapeEntity, ShapeInfo &shapeInfo) {
|
||||||
|
ShapeInfo::PointCollection pointCollection;
|
||||||
|
ShapeInfo::PointList points;
|
||||||
|
|
||||||
|
GeometryCache::computeSimpleHullPointListForShape(shapeEntity, points);
|
||||||
|
pointCollection.push_back(points);
|
||||||
|
shapeInfo.setPointCollection(pointCollection);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,9 @@
|
||||||
#include <gpu/Batch.h>
|
#include <gpu/Batch.h>
|
||||||
#include <render/Forward.h>
|
#include <render/Forward.h>
|
||||||
|
|
||||||
|
class ShapeEntityItem;
|
||||||
|
class ShapeInfo;
|
||||||
|
|
||||||
void renderWorldBox(RenderArgs* args, gpu::Batch& batch);
|
void renderWorldBox(RenderArgs* args, gpu::Batch& batch);
|
||||||
|
|
||||||
void runTimingTests();
|
void runTimingTests();
|
||||||
|
@ -28,4 +31,6 @@ bool rayIntersectsSphere(const glm::vec3& rayStarting, const glm::vec3& rayNorma
|
||||||
|
|
||||||
bool pointInSphere(glm::vec3& point, glm::vec3& sphereCenter, double sphereRadius);
|
bool pointInSphere(glm::vec3& point, glm::vec3& sphereCenter, double sphereRadius);
|
||||||
|
|
||||||
|
void shapeInfoCalculator(const ShapeEntityItem * const shapeEntity, ShapeInfo &shapeInfo);
|
||||||
|
|
||||||
#endif // hifi_Util_h
|
#endif // hifi_Util_h
|
||||||
|
|
|
@ -30,23 +30,6 @@ using namespace render::entities;
|
||||||
// is a half unit sphere. However, the geometry cache renders a UNIT sphere, so we need to scale down.
|
// is a half unit sphere. However, the geometry cache renders a UNIT sphere, so we need to scale down.
|
||||||
static const float SPHERE_ENTITY_SCALE = 0.5f;
|
static const float SPHERE_ENTITY_SCALE = 0.5f;
|
||||||
|
|
||||||
static std::array<GeometryCache::Shape, entity::NUM_SHAPES> MAPPING { {
|
|
||||||
GeometryCache::Triangle,
|
|
||||||
GeometryCache::Quad,
|
|
||||||
GeometryCache::Hexagon,
|
|
||||||
GeometryCache::Octagon,
|
|
||||||
GeometryCache::Circle,
|
|
||||||
GeometryCache::Cube,
|
|
||||||
GeometryCache::Sphere,
|
|
||||||
GeometryCache::Tetrahedron,
|
|
||||||
GeometryCache::Octahedron,
|
|
||||||
GeometryCache::Dodecahedron,
|
|
||||||
GeometryCache::Icosahedron,
|
|
||||||
GeometryCache::Torus,
|
|
||||||
GeometryCache::Cone,
|
|
||||||
GeometryCache::Cylinder,
|
|
||||||
} };
|
|
||||||
|
|
||||||
|
|
||||||
ShapeEntityRenderer::ShapeEntityRenderer(const EntityItemPointer& entity) : Parent(entity) {
|
ShapeEntityRenderer::ShapeEntityRenderer(const EntityItemPointer& entity) : Parent(entity) {
|
||||||
_procedural._vertexSource = simple_vert;
|
_procedural._vertexSource = simple_vert;
|
||||||
|
@ -137,11 +120,12 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
||||||
|
|
||||||
gpu::Batch& batch = *args->_batch;
|
gpu::Batch& batch = *args->_batch;
|
||||||
|
|
||||||
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
GeometryCache::Shape geometryShape;
|
GeometryCache::Shape geometryShape;
|
||||||
bool proceduralRender = false;
|
bool proceduralRender = false;
|
||||||
glm::vec4 outColor;
|
glm::vec4 outColor;
|
||||||
withReadLock([&] {
|
withReadLock([&] {
|
||||||
geometryShape = MAPPING[_shape];
|
geometryShape = geometryCache->getShapeForEntityShape(_shape);
|
||||||
batch.setModelTransform(_renderTransform); // use a transform with scale, rotation, registration point and translation
|
batch.setModelTransform(_renderTransform); // use a transform with scale, rotation, registration point and translation
|
||||||
outColor = _color;
|
outColor = _color;
|
||||||
if (_procedural.isReady()) {
|
if (_procedural.isReady()) {
|
||||||
|
@ -155,14 +139,13 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
||||||
if (proceduralRender) {
|
if (proceduralRender) {
|
||||||
batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a);
|
batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a);
|
||||||
if (render::ShapeKey(args->_globalShapeKey).isWireframe()) {
|
if (render::ShapeKey(args->_globalShapeKey).isWireframe()) {
|
||||||
DependencyManager::get<GeometryCache>()->renderWireShape(batch, geometryShape);
|
geometryCache->renderWireShape(batch, geometryShape);
|
||||||
} else {
|
} else {
|
||||||
DependencyManager::get<GeometryCache>()->renderShape(batch, geometryShape);
|
geometryCache->renderShape(batch, geometryShape);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// FIXME, support instanced multi-shape rendering using multidraw indirect
|
// FIXME, support instanced multi-shape rendering using multidraw indirect
|
||||||
outColor.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
|
outColor.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
|
||||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
|
||||||
auto pipeline = outColor.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline();
|
auto pipeline = outColor.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline();
|
||||||
if (render::ShapeKey(args->_globalShapeKey).isWireframe()) {
|
if (render::ShapeKey(args->_globalShapeKey).isWireframe()) {
|
||||||
geometryCache->renderWireShapeInstance(args, batch, geometryShape, outColor, pipeline);
|
geometryCache->renderWireShapeInstance(args, batch, geometryShape, outColor, pipeline);
|
||||||
|
@ -171,6 +154,6 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const auto triCount = DependencyManager::get<GeometryCache>()->getShapeTriangleCount(geometryShape);
|
static const auto triCount = geometryCache->getShapeTriangleCount(geometryShape);
|
||||||
args->_details._trianglesRendered += (int)triCount;
|
args->_details._trianglesRendered += (int)triCount;
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,79 +241,95 @@ void ShapeEntityItem::computeShapeInfo(ShapeInfo& info) {
|
||||||
|
|
||||||
const glm::vec3 entityDimensions = getDimensions();
|
const glm::vec3 entityDimensions = getDimensions();
|
||||||
|
|
||||||
switch (_shape) {
|
switch (_shape){
|
||||||
case entity::Shape::Quad:
|
case entity::Shape::Quad: {
|
||||||
case entity::Shape::Cube:
|
// Not in GeometryCache::buildShapes, unsupported.
|
||||||
{
|
_collisionShapeType = SHAPE_TYPE_ELLIPSOID;
|
||||||
_collisionShapeType = SHAPE_TYPE_BOX;
|
//TODO WL21389: Add a SHAPE_TYPE_QUAD ShapeType and treat
|
||||||
|
// as a special box (later if desired support)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case entity::Shape::Cube: {
|
||||||
|
_collisionShapeType = SHAPE_TYPE_BOX;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case entity::Shape::Sphere: {
|
||||||
|
|
||||||
|
float diameter = entityDimensions.x;
|
||||||
|
const float MIN_DIAMETER = 0.001f;
|
||||||
|
const float MIN_RELATIVE_SPHERICAL_ERROR = 0.001f;
|
||||||
|
if (diameter > MIN_DIAMETER
|
||||||
|
&& fabsf(diameter - entityDimensions.y) / diameter < MIN_RELATIVE_SPHERICAL_ERROR
|
||||||
|
&& fabsf(diameter - entityDimensions.z) / diameter < MIN_RELATIVE_SPHERICAL_ERROR) {
|
||||||
|
|
||||||
|
_collisionShapeType = SHAPE_TYPE_SPHERE;
|
||||||
|
} else {
|
||||||
|
_collisionShapeType = SHAPE_TYPE_ELLIPSOID;
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case entity::Shape::Sphere:
|
break;
|
||||||
{
|
case entity::Shape::Circle: {
|
||||||
|
_collisionShapeType = SHAPE_TYPE_CIRCLE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case entity::Shape::Cylinder: {
|
||||||
|
_collisionShapeType = SHAPE_TYPE_CYLINDER_Y;
|
||||||
|
// TODO WL21389: determine if rotation is axis-aligned
|
||||||
|
//const Transform::Quat & rot = _transform.getRotation();
|
||||||
|
|
||||||
float diameter = entityDimensions.x;
|
// TODO WL21389: some way to tell apart SHAPE_TYPE_CYLINDER_Y, _X, _Z based on rotation and
|
||||||
const float MIN_DIAMETER = 0.001f;
|
// hull ( or dimensions, need circular cross section)
|
||||||
const float MIN_RELATIVE_SPHERICAL_ERROR = 0.001f;
|
// Should allow for minor variance along axes?
|
||||||
if (diameter > MIN_DIAMETER
|
|
||||||
&& fabsf(diameter - entityDimensions.y) / diameter < MIN_RELATIVE_SPHERICAL_ERROR
|
|
||||||
&& fabsf(diameter - entityDimensions.z) / diameter < MIN_RELATIVE_SPHERICAL_ERROR) {
|
|
||||||
|
|
||||||
_collisionShapeType = SHAPE_TYPE_SPHERE;
|
}
|
||||||
} else {
|
break;
|
||||||
_collisionShapeType = SHAPE_TYPE_ELLIPSOID;
|
// gons, ones, & angles built via GeometryCache::extrudePolygon
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case entity::Shape::Cylinder:
|
|
||||||
{
|
|
||||||
_collisionShapeType = SHAPE_TYPE_CYLINDER_Y;
|
|
||||||
// TODO WL21389: determine if rotation is axis-aligned
|
|
||||||
//const Transform::Quat & rot = _transform.getRotation();
|
|
||||||
|
|
||||||
// TODO WL21389: some way to tell apart SHAPE_TYPE_CYLINDER_Y, _X, _Z based on rotation and
|
|
||||||
// hull ( or dimensions, need circular cross section)
|
|
||||||
// Should allow for minor variance along axes?
|
|
||||||
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case entity::Shape::Triangle:
|
case entity::Shape::Triangle:
|
||||||
case entity::Shape::Hexagon:
|
case entity::Shape::Hexagon:
|
||||||
case entity::Shape::Octagon:
|
case entity::Shape::Octagon:
|
||||||
case entity::Shape::Circle:
|
case entity::Shape::Cone: {
|
||||||
|
if (shapeCalculator) {
|
||||||
|
shapeCalculator(this, info);
|
||||||
|
// shapeCalculator only supports convex shapes (e.g. SHAPE_TYPE_HULL)
|
||||||
|
// TODO: figure out how to support concave shapes
|
||||||
|
_collisionShapeType = SHAPE_TYPE_SIMPLE_HULL;
|
||||||
|
} else {
|
||||||
|
_collisionShapeType = SHAPE_TYPE_ELLIPSOID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
// hedrons built via GeometryCache::setUpFlatShapes
|
||||||
case entity::Shape::Tetrahedron:
|
case entity::Shape::Tetrahedron:
|
||||||
case entity::Shape::Octahedron:
|
case entity::Shape::Octahedron:
|
||||||
case entity::Shape::Dodecahedron:
|
case entity::Shape::Dodecahedron:
|
||||||
case entity::Shape::Icosahedron:
|
case entity::Shape::Icosahedron: {
|
||||||
case entity::Shape::Cone:
|
if ( shapeCalculator ) {
|
||||||
{
|
shapeCalculator(this, info);
|
||||||
if (shapeCalculator) {
|
// shapeCalculator only supports convex shapes (e.g. SHAPE_TYPE_HULL)
|
||||||
shapeCalculator(info, _shape, getDimensions());
|
// TODO: figure out how to support concave shapes
|
||||||
// shapeCalculator only supports convex shapes (e.g. SHAPE_TYPE_HULL)
|
_collisionShapeType = SHAPE_TYPE_SIMPLE_HULL;
|
||||||
// TODO: figure out how to support concave shapes
|
} else {
|
||||||
_collisionShapeType = SHAPE_TYPE_HULL;
|
|
||||||
} else {
|
|
||||||
_collisionShapeType = SHAPE_TYPE_ELLIPSOID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case entity::Shape::Torus:
|
|
||||||
{
|
|
||||||
// Not in GeometryCache::buildShapes, unsupported.
|
|
||||||
_collisionShapeType = SHAPE_TYPE_ELLIPSOID;
|
|
||||||
//TODO WL21389: SHAPE_TYPE_SIMPLE_HULL and pointCollection (later if desired support)
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
_collisionShapeType = SHAPE_TYPE_ELLIPSOID;
|
_collisionShapeType = SHAPE_TYPE_ELLIPSOID;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case entity::Shape::Torus: {
|
||||||
|
// Not in GeometryCache::buildShapes, unsupported.
|
||||||
|
_collisionShapeType = SHAPE_TYPE_ELLIPSOID;
|
||||||
|
//TODO WL21389: SHAPE_TYPE_SIMPLE_HULL and pointCollection (later if desired support)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: {
|
||||||
|
_collisionShapeType = SHAPE_TYPE_ELLIPSOID;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityItem::computeShapeInfo(info);
|
EntityItem::computeShapeInfo(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This value specifes how the shape should be treated by physics calculations.
|
// This value specifies how the shape should be treated by physics calculations.
|
||||||
ShapeType ShapeEntityItem::getShapeType() const {
|
ShapeType ShapeEntityItem::getShapeType() const {
|
||||||
return _collisionShapeType;
|
return _collisionShapeType;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ public:
|
||||||
static EntityItemPointer sphereFactory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
static EntityItemPointer sphereFactory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||||
static EntityItemPointer boxFactory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
static EntityItemPointer boxFactory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||||
|
|
||||||
using ShapeInfoCalculator = std::function<void(ShapeInfo& info, entity::Shape shape, glm::vec3 dimensions)>;
|
using ShapeInfoCalculator = std::function<void( const ShapeEntityItem * const shapeEntity, ShapeInfo& info)>;
|
||||||
static void setShapeInfoCalulator(ShapeInfoCalculator callback);
|
static void setShapeInfoCalulator(ShapeInfoCalculator callback);
|
||||||
|
|
||||||
ShapeEntityItem(const EntityItemID& entityItemID);
|
ShapeEntityItem(const EntityItemID& entityItemID);
|
||||||
|
|
|
@ -314,6 +314,7 @@ const btCollisionShape* ShapeFactory::createShapeFromInfo(const ShapeInfo& info)
|
||||||
shape = new btCylinderShapeZ(btHalfExtents);
|
shape = new btCylinderShapeZ(btHalfExtents);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case SHAPE_TYPE_CIRCLE:
|
||||||
case SHAPE_TYPE_CYLINDER_Y: {
|
case SHAPE_TYPE_CYLINDER_Y: {
|
||||||
const glm::vec3 halfExtents = info.getHalfExtents();
|
const glm::vec3 halfExtents = info.getHalfExtents();
|
||||||
const btVector3 btHalfExtents(halfExtents.x, halfExtents.y, halfExtents.z);
|
const btVector3 btHalfExtents(halfExtents.x, halfExtents.y, halfExtents.z);
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include <FSTReader.h>
|
#include <FSTReader.h>
|
||||||
#include <NumericalConstants.h>
|
#include <NumericalConstants.h>
|
||||||
|
#include <ShapeEntityItem.h>
|
||||||
|
|
||||||
#include "TextureCache.h"
|
#include "TextureCache.h"
|
||||||
#include "RenderUtilsLogging.h"
|
#include "RenderUtilsLogging.h"
|
||||||
|
@ -52,6 +53,24 @@
|
||||||
|
|
||||||
//#define WANT_DEBUG
|
//#define WANT_DEBUG
|
||||||
|
|
||||||
|
static std::array<GeometryCache::Shape, entity::NUM_SHAPES> MAPPING{ {
|
||||||
|
GeometryCache::Triangle,
|
||||||
|
GeometryCache::Quad,
|
||||||
|
GeometryCache::Hexagon,
|
||||||
|
GeometryCache::Octagon,
|
||||||
|
GeometryCache::Circle,
|
||||||
|
GeometryCache::Cube,
|
||||||
|
GeometryCache::Sphere,
|
||||||
|
GeometryCache::Tetrahedron,
|
||||||
|
GeometryCache::Octahedron,
|
||||||
|
GeometryCache::Dodecahedron,
|
||||||
|
GeometryCache::Icosahedron,
|
||||||
|
GeometryCache::Torus,
|
||||||
|
GeometryCache::Cone,
|
||||||
|
GeometryCache::Cylinder,
|
||||||
|
} };
|
||||||
|
|
||||||
|
|
||||||
const int GeometryCache::UNKNOWN_ID = -1;
|
const int GeometryCache::UNKNOWN_ID = -1;
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,6 +88,52 @@ static gpu::Stream::FormatPointer INSTANCED_SOLID_FADE_STREAM_FORMAT;
|
||||||
static const uint SHAPE_VERTEX_STRIDE = sizeof(glm::vec3) * 2; // vertices and normals
|
static const uint SHAPE_VERTEX_STRIDE = sizeof(glm::vec3) * 2; // vertices and normals
|
||||||
static const uint SHAPE_NORMALS_OFFSET = sizeof(glm::vec3);
|
static const uint SHAPE_NORMALS_OFFSET = sizeof(glm::vec3);
|
||||||
|
|
||||||
|
void GeometryCache::computeSimpleHullPointListForShape(const ShapeEntityItem * const shapePtr, QVector<glm::vec3> &outPointList){
|
||||||
|
|
||||||
|
if (shapePtr == nullptr){
|
||||||
|
//--EARLY EXIT--
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
|
const GeometryCache::ShapeData * shapeData = geometryCache->getShapeData(MAPPING[shapePtr->getShape()]);
|
||||||
|
if (!shapeData){
|
||||||
|
//--EARLY EXIT--( data isn't ready for some reason... )
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const gpu::BufferView & shapeVerts = shapeData->_positionView;
|
||||||
|
const gpu::BufferView & shapeNorms = shapeData->_normalView;
|
||||||
|
assert(shapeVerts._size == shapeNorms._size);
|
||||||
|
|
||||||
|
const gpu::BufferView::Size numItems = shapeVerts.getNumElements();
|
||||||
|
const glm::vec3 halfExtents = shapePtr->getDimensions() * 0.5f;
|
||||||
|
#if DEBUG_SIMPLE_HULL_POINT_GENERATION
|
||||||
|
shapePtr->debugDump();
|
||||||
|
qCDebug(entities) << "------------------ Begin Vert Info( ComputeShapeInfo )[FlatShapes] -----------------------------";
|
||||||
|
qCDebug(entities) << " name:" << shapePtr->getName() << ": has " << numItems << " vert info pairs.";
|
||||||
|
#endif
|
||||||
|
outPointList.reserve(numItems);
|
||||||
|
for (gpu::BufferView::Index i = 0; i < (gpu::BufferView::Index)numItems; ++i) {
|
||||||
|
const geometry::Vec &curNorm = shapeNorms.get<geometry::Vec>(i);
|
||||||
|
#if DEBUG_SIMPLE_HULL_POINT_GENERATION
|
||||||
|
const geometry::Vec &curVert = shapeVerts.get<geometry::Vec>(i);
|
||||||
|
qCDebug(entities) << " --------------------";
|
||||||
|
qCDebug(entities) << " Vert( " << i << " ): " << debugTreeVector(curVert);
|
||||||
|
qCDebug(entities) << " Norm( " << i << " ): " << debugTreeVector(curNorm);
|
||||||
|
#endif
|
||||||
|
outPointList.push_back(curNorm * halfExtents);
|
||||||
|
|
||||||
|
#if DEBUG_SIMPLE_HULL_POINT_GENERATION
|
||||||
|
qCDebug(entities) << " Point( " << i << " ): " << debugTreeVector((curNorm * halfExtents));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DEBUG_SIMPLE_HULL_POINT_GENERATION
|
||||||
|
qCDebug(entities) << "-------------------- End Vert Info( ComputeShapeInfo ) -----------------------------";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
template <size_t SIDES>
|
template <size_t SIDES>
|
||||||
std::vector<vec3> polygon() {
|
std::vector<vec3> polygon() {
|
||||||
std::vector<vec3> result;
|
std::vector<vec3> result;
|
||||||
|
@ -447,6 +512,22 @@ void GeometryCache::buildShapes() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const GeometryCache::ShapeData * GeometryCache::getShapeData(const Shape shape) const {
|
||||||
|
if (((int)shape < 0) || ((int)shape >= _shapes.size())){
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &_shapes[shape];
|
||||||
|
}
|
||||||
|
|
||||||
|
GeometryCache::Shape GeometryCache::getShapeForEntityShape(int entityShape) {
|
||||||
|
if ((entityShape < 0) || (entityShape >= MAPPING.size())){
|
||||||
|
return NUM_SHAPES;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MAPPING[entityShape];
|
||||||
|
}
|
||||||
|
|
||||||
gpu::Stream::FormatPointer& getSolidStreamFormat() {
|
gpu::Stream::FormatPointer& getSolidStreamFormat() {
|
||||||
if (!SOLID_STREAM_FORMAT) {
|
if (!SOLID_STREAM_FORMAT) {
|
||||||
SOLID_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone
|
SOLID_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include <model/Asset.h>
|
#include <model/Asset.h>
|
||||||
|
|
||||||
class SimpleProgramKey;
|
class SimpleProgramKey;
|
||||||
|
class ShapeEntityItem;
|
||||||
|
|
||||||
typedef QPair<glm::vec2, float> Vec2FloatPair;
|
typedef QPair<glm::vec2, float> Vec2FloatPair;
|
||||||
typedef QPair<Vec2FloatPair, Vec2FloatPair> Vec2FloatPairPair;
|
typedef QPair<Vec2FloatPair, Vec2FloatPair> Vec2FloatPairPair;
|
||||||
|
@ -147,6 +148,15 @@ public:
|
||||||
NUM_SHAPES,
|
NUM_SHAPES,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// @param entityShapeEnum: The entity::Shape enumeration for the shape
|
||||||
|
/// whose GeometryCache::Shape is desired.
|
||||||
|
/// @return GeometryCache::NUM_SHAPES in the event of an error; otherwise,
|
||||||
|
/// the GeometryCache::Shape enum which aligns with the
|
||||||
|
/// specified entityShapeEnum
|
||||||
|
static GeometryCache::Shape getShapeForEntityShape(int entityShapeEnum);
|
||||||
|
|
||||||
|
static void computeSimpleHullPointListForShape(const ShapeEntityItem * const shapePtr, QVector<glm::vec3> &outPointList);
|
||||||
|
|
||||||
static uint8_t CUSTOM_PIPELINE_NUMBER;
|
static uint8_t CUSTOM_PIPELINE_NUMBER;
|
||||||
static render::ShapePipelinePointer shapePipelineFactory(const render::ShapePlumber& plumber, const render::ShapeKey& key);
|
static render::ShapePipelinePointer shapePipelineFactory(const render::ShapePlumber& plumber, const render::ShapeKey& key);
|
||||||
static void registerShapePipeline() {
|
static void registerShapePipeline() {
|
||||||
|
@ -355,15 +365,21 @@ public:
|
||||||
|
|
||||||
using VShape = std::array<ShapeData, NUM_SHAPES>;
|
using VShape = std::array<ShapeData, NUM_SHAPES>;
|
||||||
|
|
||||||
VShape _shapes;
|
/// returns ShapeData associated with the specified shape,
|
||||||
|
/// otherwise nullptr in the event of an error.
|
||||||
|
const ShapeData * getShapeData(Shape shape) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
GeometryCache();
|
GeometryCache();
|
||||||
virtual ~GeometryCache();
|
virtual ~GeometryCache();
|
||||||
void buildShapes();
|
void buildShapes();
|
||||||
|
|
||||||
typedef QPair<int, int> IntPair;
|
typedef QPair<int, int> IntPair;
|
||||||
typedef QPair<unsigned int, unsigned int> VerticesIndices;
|
typedef QPair<unsigned int, unsigned int> VerticesIndices;
|
||||||
|
|
||||||
|
|
||||||
|
VShape _shapes;
|
||||||
|
|
||||||
gpu::PipelinePointer _standardDrawPipeline;
|
gpu::PipelinePointer _standardDrawPipeline;
|
||||||
gpu::PipelinePointer _standardDrawPipelineNoBlend;
|
gpu::PipelinePointer _standardDrawPipelineNoBlend;
|
||||||
|
|
|
@ -45,6 +45,10 @@ void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString
|
||||||
_halfExtents = glm::vec3(radius);
|
_halfExtents = glm::vec3(radius);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case SHAPE_TYPE_CIRCLE: {
|
||||||
|
_halfExtents = glm::vec3(_halfExtents.x, MIN_HALF_EXTENT, _halfExtents.z);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case SHAPE_TYPE_COMPOUND:
|
case SHAPE_TYPE_COMPOUND:
|
||||||
case SHAPE_TYPE_STATIC_MESH:
|
case SHAPE_TYPE_STATIC_MESH:
|
||||||
_url = QUrl(url);
|
_url = QUrl(url);
|
||||||
|
@ -75,9 +79,7 @@ void ShapeInfo::setSphere(float radius) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShapeInfo::setPointCollection(const ShapeInfo::PointCollection& pointCollection) {
|
void ShapeInfo::setPointCollection(const ShapeInfo::PointCollection& pointCollection) {
|
||||||
//TODO WL21389: May need to skip resetting type here.
|
|
||||||
_pointCollection = pointCollection;
|
_pointCollection = pointCollection;
|
||||||
_type = (_pointCollection.size() > 0) ? SHAPE_TYPE_COMPOUND : SHAPE_TYPE_NONE;
|
|
||||||
_doubleHashKey.clear();
|
_doubleHashKey.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +126,7 @@ int ShapeInfo::getLargestSubshapePointCount() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
float ShapeInfo::computeVolume() const {
|
float ShapeInfo::computeVolume() const {
|
||||||
//TODO WL21389: Add support for other ShapeTypes( CYLINDER_X, CYLINDER_Y, etc).
|
//TODO WL21389: Add support for other ShapeTypes( CYLINDER_X, CYLINDER_Z, etc).
|
||||||
const float DEFAULT_VOLUME = 1.0f;
|
const float DEFAULT_VOLUME = 1.0f;
|
||||||
float volume = DEFAULT_VOLUME;
|
float volume = DEFAULT_VOLUME;
|
||||||
switch(_type) {
|
switch(_type) {
|
||||||
|
|
|
@ -46,7 +46,8 @@ enum ShapeType {
|
||||||
SHAPE_TYPE_SIMPLE_HULL,
|
SHAPE_TYPE_SIMPLE_HULL,
|
||||||
SHAPE_TYPE_SIMPLE_COMPOUND,
|
SHAPE_TYPE_SIMPLE_COMPOUND,
|
||||||
SHAPE_TYPE_STATIC_MESH,
|
SHAPE_TYPE_STATIC_MESH,
|
||||||
SHAPE_TYPE_ELLIPSOID
|
SHAPE_TYPE_ELLIPSOID,
|
||||||
|
SHAPE_TYPE_CIRCLE
|
||||||
};
|
};
|
||||||
|
|
||||||
class ShapeInfo {
|
class ShapeInfo {
|
||||||
|
@ -66,7 +67,7 @@ public:
|
||||||
void setCapsuleY(float radius, float halfHeight);
|
void setCapsuleY(float radius, float halfHeight);
|
||||||
void setOffset(const glm::vec3& offset);
|
void setOffset(const glm::vec3& offset);
|
||||||
|
|
||||||
int getType() const { return _type; }
|
ShapeType getType() const { return _type; }
|
||||||
|
|
||||||
const glm::vec3& getHalfExtents() const { return _halfExtents; }
|
const glm::vec3& getHalfExtents() const { return _halfExtents; }
|
||||||
const glm::vec3& getOffset() const { return _offset; }
|
const glm::vec3& getOffset() const { return _offset; }
|
||||||
|
|
|
@ -10,18 +10,18 @@
|
||||||
|
|
||||||
gpu::Stream::FormatPointer& getInstancedSolidStreamFormat();
|
gpu::Stream::FormatPointer& getInstancedSolidStreamFormat();
|
||||||
|
|
||||||
static const size_t TYPE_COUNT = 4;
|
static GeometryCache::Shape SHAPE[] = {
|
||||||
static const size_t ITEM_COUNT = 50;
|
|
||||||
static const float SHAPE_INTERVAL = (PI * 2.0f) / ITEM_COUNT;
|
|
||||||
static const float ITEM_INTERVAL = SHAPE_INTERVAL / TYPE_COUNT;
|
|
||||||
|
|
||||||
static GeometryCache::Shape SHAPE[TYPE_COUNT] = {
|
|
||||||
GeometryCache::Icosahedron,
|
GeometryCache::Icosahedron,
|
||||||
GeometryCache::Cube,
|
GeometryCache::Cube,
|
||||||
GeometryCache::Sphere,
|
GeometryCache::Sphere,
|
||||||
GeometryCache::Tetrahedron,
|
GeometryCache::Tetrahedron,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const size_t TYPE_COUNT = (sizeof(SHAPE) / sizeof((SHAPE)[0]));
|
||||||
|
static const size_t ITEM_COUNT = 50;
|
||||||
|
static const float SHAPE_INTERVAL = (PI * 2.0f) / ITEM_COUNT;
|
||||||
|
static const float ITEM_INTERVAL = SHAPE_INTERVAL / TYPE_COUNT;
|
||||||
|
|
||||||
const gpu::Element POSITION_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ };
|
const gpu::Element POSITION_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ };
|
||||||
const gpu::Element NORMAL_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ };
|
const gpu::Element NORMAL_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ };
|
||||||
const gpu::Element COLOR_ELEMENT { gpu::VEC4, gpu::NUINT8, gpu::RGBA };
|
const gpu::Element COLOR_ELEMENT { gpu::VEC4, gpu::NUINT8, gpu::RGBA };
|
||||||
|
@ -34,8 +34,6 @@ TestInstancedShapes::TestInstancedShapes() {
|
||||||
static const float ITEM_RADIUS = 20;
|
static const float ITEM_RADIUS = 20;
|
||||||
static const vec3 ITEM_TRANSLATION { 0, 0, -ITEM_RADIUS };
|
static const vec3 ITEM_TRANSLATION { 0, 0, -ITEM_RADIUS };
|
||||||
for (size_t i = 0; i < TYPE_COUNT; ++i) {
|
for (size_t i = 0; i < TYPE_COUNT; ++i) {
|
||||||
GeometryCache::Shape shape = SHAPE[i];
|
|
||||||
GeometryCache::ShapeData shapeData = geometryCache->_shapes[shape];
|
|
||||||
//indirectCommand._count
|
//indirectCommand._count
|
||||||
float startingInterval = ITEM_INTERVAL * i;
|
float startingInterval = ITEM_INTERVAL * i;
|
||||||
std::vector<mat4> typeTransforms;
|
std::vector<mat4> typeTransforms;
|
||||||
|
@ -62,7 +60,12 @@ void TestInstancedShapes::renderTest(size_t testId, RenderArgs* args) {
|
||||||
batch.setInputFormat(getInstancedSolidStreamFormat());
|
batch.setInputFormat(getInstancedSolidStreamFormat());
|
||||||
for (size_t i = 0; i < TYPE_COUNT; ++i) {
|
for (size_t i = 0; i < TYPE_COUNT; ++i) {
|
||||||
GeometryCache::Shape shape = SHAPE[i];
|
GeometryCache::Shape shape = SHAPE[i];
|
||||||
GeometryCache::ShapeData shapeData = geometryCache->_shapes[shape];
|
const GeometryCache::ShapeData *shapeData = geometryCache->getShapeData( shape );
|
||||||
|
if (!shapeData) {
|
||||||
|
|
||||||
|
//--EARLY ITERATION EXIT--( didn't have shape data yet )
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
std::string namedCall = __FUNCTION__ + std::to_string(i);
|
std::string namedCall = __FUNCTION__ + std::to_string(i);
|
||||||
|
|
||||||
|
@ -71,13 +74,13 @@ void TestInstancedShapes::renderTest(size_t testId, RenderArgs* args) {
|
||||||
batch.setModelTransform(transforms[i][j]);
|
batch.setModelTransform(transforms[i][j]);
|
||||||
batch.setupNamedCalls(namedCall, [=](gpu::Batch& batch, gpu::Batch::NamedBatchData&) {
|
batch.setupNamedCalls(namedCall, [=](gpu::Batch& batch, gpu::Batch::NamedBatchData&) {
|
||||||
batch.setInputBuffer(gpu::Stream::COLOR, gpu::BufferView(colorBuffer, i * ITEM_COUNT * 4, colorBuffer->getSize(), COLOR_ELEMENT));
|
batch.setInputBuffer(gpu::Stream::COLOR, gpu::BufferView(colorBuffer, i * ITEM_COUNT * 4, colorBuffer->getSize(), COLOR_ELEMENT));
|
||||||
shapeData.drawInstances(batch, ITEM_COUNT);
|
shapeData->drawInstances(batch, ITEM_COUNT);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//for (size_t j = 0; j < ITEM_COUNT; ++j) {
|
//for (size_t j = 0; j < ITEM_COUNT; ++j) {
|
||||||
// batch.setModelTransform(transforms[j + i * ITEM_COUNT]);
|
// batch.setModelTransform(transforms[j + i * ITEM_COUNT]);
|
||||||
// shapeData.draw(batch);
|
// shapeData->draw(batch);
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue