mirror of
https://github.com/Armored-Dragon/overte.git
synced 2025-03-11 16:13:16 +01:00
Merge branch 'master' of git://github.com/highfidelity/hifi into shadow
This commit is contained in:
commit
186b531be6
19 changed files with 444 additions and 161 deletions
|
@ -120,6 +120,7 @@
|
|||
#include <SceneScriptingInterface.h>
|
||||
#include <ScriptEngines.h>
|
||||
#include <ScriptCache.h>
|
||||
#include <ShapeEntityItem.h>
|
||||
#include <SoundCache.h>
|
||||
#include <ui/TabletScriptingInterface.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
|
||||
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()->setEntityLoadingPriorityFunction([this](const EntityItem& item) {
|
||||
auto dims = item.getDimensions();
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include <GeometryCache.h>
|
||||
#include <OctreeConstants.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <ShapeEntityItem.h>
|
||||
#include <ShapeInfo.h>
|
||||
|
||||
#include "InterfaceLogging.h"
|
||||
#include "world.h"
|
||||
|
@ -393,4 +395,20 @@ void runUnitTests() {
|
|||
}
|
||||
}
|
||||
|
||||
void shapeInfoCalculator(const ShapeEntityItem * const shapeEntity, ShapeInfo &shapeInfo) {
|
||||
|
||||
if (shapeEntity == nullptr) {
|
||||
|
||||
//--EARLY EXIT--
|
||||
return;
|
||||
}
|
||||
|
||||
ShapeInfo::PointCollection pointCollection;
|
||||
ShapeInfo::PointList points;
|
||||
pointCollection.push_back(points);
|
||||
|
||||
GeometryCache::computeSimpleHullPointListForShape((int)shapeEntity->getShape(), shapeEntity->getDimensions(), pointCollection.back());
|
||||
shapeInfo.setPointCollection(pointCollection);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
#include <gpu/Batch.h>
|
||||
#include <render/Forward.h>
|
||||
|
||||
class ShapeEntityItem;
|
||||
class ShapeInfo;
|
||||
|
||||
void renderWorldBox(RenderArgs* args, gpu::Batch& batch);
|
||||
|
||||
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);
|
||||
|
||||
void shapeInfoCalculator(const ShapeEntityItem * const shapeEntity, ShapeInfo &shapeInfo);
|
||||
|
||||
#endif // hifi_Util_h
|
||||
|
|
|
@ -72,7 +72,7 @@ void JSBaker::bake() {
|
|||
bool JSBaker::bakeJS(const QByteArray& inputFile, QByteArray& outputFile) {
|
||||
// Read from inputFile and write to outputFile per character
|
||||
QTextStream in(inputFile, QIODevice::ReadOnly);
|
||||
QTextStream out(outputFile, QIODevice::WriteOnly);
|
||||
QTextStream out(&outputFile, QIODevice::WriteOnly);
|
||||
|
||||
// Algorithm requires the knowledge of previous and next character for each character read
|
||||
QChar currentCharacter;
|
||||
|
|
|
@ -234,7 +234,8 @@ void CompositorHelper::handleLeaveEvent() {
|
|||
|
||||
bool CompositorHelper::handleRealMouseMoveEvent(bool sendFakeEvent) {
|
||||
// If the mouse move came from a capture mouse related move, we completely ignore it.
|
||||
if (_ignoreMouseMove) {
|
||||
// Note: if not going to synthesize event - do not touch _ignoreMouseMove flag
|
||||
if (_ignoreMouseMove && sendFakeEvent) {
|
||||
_ignoreMouseMove = false;
|
||||
return true; // swallow the event
|
||||
}
|
||||
|
@ -246,7 +247,12 @@ bool CompositorHelper::handleRealMouseMoveEvent(bool sendFakeEvent) {
|
|||
auto changeInRealMouse = newPosition - _lastKnownRealMouse;
|
||||
auto newReticlePosition = _reticlePositionInHMD + toGlm(changeInRealMouse);
|
||||
setReticlePosition(newReticlePosition, sendFakeEvent);
|
||||
_ignoreMouseMove = true;
|
||||
|
||||
// Note: if not going to synthesize event - do not touch _ignoreMouseMove flag
|
||||
if (sendFakeEvent) {
|
||||
_ignoreMouseMove = true;
|
||||
}
|
||||
|
||||
QCursor::setPos(QPoint(_lastKnownRealMouse.x(), _lastKnownRealMouse.y())); // move cursor back to where it was
|
||||
return true; // swallow the event
|
||||
} else {
|
||||
|
|
|
@ -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.
|
||||
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) {
|
||||
_procedural._vertexSource = simple_vert;
|
||||
|
@ -137,11 +120,12 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
|||
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
GeometryCache::Shape geometryShape;
|
||||
bool proceduralRender = false;
|
||||
glm::vec4 outColor;
|
||||
withReadLock([&] {
|
||||
geometryShape = MAPPING[_shape];
|
||||
geometryShape = geometryCache->getShapeForEntityShape(_shape);
|
||||
batch.setModelTransform(_renderTransform); // use a transform with scale, rotation, registration point and translation
|
||||
outColor = _color;
|
||||
if (_procedural.isReady()) {
|
||||
|
@ -155,14 +139,13 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
|||
if (proceduralRender) {
|
||||
batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a);
|
||||
if (render::ShapeKey(args->_globalShapeKey).isWireframe()) {
|
||||
DependencyManager::get<GeometryCache>()->renderWireShape(batch, geometryShape);
|
||||
geometryCache->renderWireShape(batch, geometryShape);
|
||||
} else {
|
||||
DependencyManager::get<GeometryCache>()->renderShape(batch, geometryShape);
|
||||
geometryCache->renderShape(batch, geometryShape);
|
||||
}
|
||||
} else {
|
||||
// FIXME, support instanced multi-shape rendering using multidraw indirect
|
||||
outColor.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
auto pipeline = outColor.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline();
|
||||
if (render::ShapeKey(args->_globalShapeKey).isWireframe()) {
|
||||
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);
|
||||
const auto triCount = geometryCache->getShapeTriangleCount(geometryShape);
|
||||
args->_details._trianglesRendered += (int)triCount;
|
||||
}
|
||||
|
|
|
@ -84,28 +84,11 @@ void EntityItemProperties::setLastEdited(quint64 usecTime) {
|
|||
_lastEdited = usecTime > _created ? usecTime : _created;
|
||||
}
|
||||
|
||||
const char* shapeTypeNames[] = {
|
||||
"none",
|
||||
"box",
|
||||
"sphere",
|
||||
"capsule-x",
|
||||
"capsule-y",
|
||||
"capsule-z",
|
||||
"cylinder-x",
|
||||
"cylinder-y",
|
||||
"cylinder-z",
|
||||
"hull",
|
||||
"plane",
|
||||
"compound",
|
||||
"simple-hull",
|
||||
"simple-compound",
|
||||
"static-mesh"
|
||||
};
|
||||
|
||||
QHash<QString, ShapeType> stringToShapeTypeLookup;
|
||||
|
||||
void addShapeType(ShapeType type) {
|
||||
stringToShapeTypeLookup[shapeTypeNames[type]] = type;
|
||||
stringToShapeTypeLookup[ShapeInfo::getNameForShapeType(type)] = type;
|
||||
}
|
||||
|
||||
void buildStringToShapeTypeLookup() {
|
||||
|
@ -180,9 +163,7 @@ void EntityItemProperties::setCollisionMaskFromString(const QString& maskString)
|
|||
}
|
||||
|
||||
QString EntityItemProperties::getShapeTypeAsString() const {
|
||||
if (_shapeType < sizeof(shapeTypeNames) / sizeof(char *))
|
||||
return QString(shapeTypeNames[_shapeType]);
|
||||
return QString(shapeTypeNames[SHAPE_TYPE_NONE]);
|
||||
return ShapeInfo::getNameForShapeType(_shapeType);
|
||||
}
|
||||
|
||||
void EntityItemProperties::setShapeTypeFromString(const QString& shapeName) {
|
||||
|
|
|
@ -51,6 +51,14 @@ namespace entity {
|
|||
}
|
||||
}
|
||||
|
||||
// shapeCalculator is a hook for external code that knows how to configure a ShapeInfo
|
||||
// for given entity::Shape and dimensions
|
||||
ShapeEntityItem::ShapeInfoCalculator shapeCalculator = nullptr;
|
||||
|
||||
void ShapeEntityItem::setShapeInfoCalulator(ShapeEntityItem::ShapeInfoCalculator callback) {
|
||||
shapeCalculator = callback;
|
||||
}
|
||||
|
||||
ShapeEntityItem::Pointer ShapeEntityItem::baseFactory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
Pointer entity(new ShapeEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
|
@ -87,6 +95,7 @@ EntityItemProperties ShapeEntityItem::getProperties(EntityPropertyFlags desiredP
|
|||
}
|
||||
|
||||
void ShapeEntityItem::setShape(const entity::Shape& shape) {
|
||||
const entity::Shape prevShape = _shape;
|
||||
_shape = shape;
|
||||
switch (_shape) {
|
||||
case entity::Shape::Cube:
|
||||
|
@ -99,6 +108,11 @@ void ShapeEntityItem::setShape(const entity::Shape& shape) {
|
|||
_type = EntityTypes::Shape;
|
||||
break;
|
||||
}
|
||||
|
||||
if (_shape != prevShape) {
|
||||
// Internally grabs writeLock
|
||||
markDirtyFlags(Simulation::DIRTY_SHAPE);
|
||||
}
|
||||
}
|
||||
|
||||
bool ShapeEntityItem::setProperties(const EntityItemProperties& properties) {
|
||||
|
@ -219,6 +233,7 @@ void ShapeEntityItem::debugDump() const {
|
|||
qCDebug(entities) << "SHAPE EntityItem id:" << getEntityItemID() << "---------------------------------------------";
|
||||
qCDebug(entities) << " name:" << _name;
|
||||
qCDebug(entities) << " shape:" << stringFromShape(_shape) << " (EnumId: " << _shape << " )";
|
||||
qCDebug(entities) << " collisionShapeType:" << ShapeInfo::getNameForShapeType(getShapeType());
|
||||
qCDebug(entities) << " color:" << _color[0] << "," << _color[1] << "," << _color[2];
|
||||
qCDebug(entities) << " position:" << debugTreeVector(getPosition());
|
||||
qCDebug(entities) << " dimensions:" << debugTreeVector(getDimensions());
|
||||
|
@ -233,73 +248,101 @@ void ShapeEntityItem::computeShapeInfo(ShapeInfo& info) {
|
|||
|
||||
const glm::vec3 entityDimensions = getDimensions();
|
||||
|
||||
switch (_shape) {
|
||||
case entity::Shape::Quad:
|
||||
case entity::Shape::Cube:
|
||||
{
|
||||
_collisionShapeType = SHAPE_TYPE_BOX;
|
||||
switch (_shape){
|
||||
case entity::Shape::Quad: {
|
||||
// Not in GeometryCache::buildShapes, unsupported.
|
||||
_collisionShapeType = SHAPE_TYPE_ELLIPSOID;
|
||||
//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;
|
||||
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) {
|
||||
// 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?
|
||||
|
||||
_collisionShapeType = SHAPE_TYPE_SPHERE;
|
||||
} else {
|
||||
_collisionShapeType = SHAPE_TYPE_ELLIPSOID;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case entity::Shape::Cone: {
|
||||
if (shapeCalculator) {
|
||||
shapeCalculator(this, info);
|
||||
// shapeCalculator only supports convex shapes (e.g. SHAPE_TYPE_HULL)
|
||||
_collisionShapeType = SHAPE_TYPE_SIMPLE_HULL;
|
||||
} else {
|
||||
_collisionShapeType = SHAPE_TYPE_ELLIPSOID;
|
||||
}
|
||||
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;
|
||||
}
|
||||
break;
|
||||
// gons, ones, & angles built via GeometryCache::extrudePolygon
|
||||
case entity::Shape::Triangle:
|
||||
case entity::Shape::Hexagon:
|
||||
case entity::Shape::Octagon:
|
||||
case entity::Shape::Circle:
|
||||
case entity::Shape::Octagon: {
|
||||
if (shapeCalculator) {
|
||||
shapeCalculator(this, info);
|
||||
// shapeCalculator only supports convex shapes (e.g. SHAPE_TYPE_HULL)
|
||||
_collisionShapeType = SHAPE_TYPE_SIMPLE_HULL;
|
||||
} else {
|
||||
_collisionShapeType = SHAPE_TYPE_ELLIPSOID;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// hedrons built via GeometryCache::setUpFlatShapes
|
||||
case entity::Shape::Tetrahedron:
|
||||
case entity::Shape::Octahedron:
|
||||
case entity::Shape::Dodecahedron:
|
||||
case entity::Shape::Icosahedron:
|
||||
case entity::Shape::Cone:
|
||||
{
|
||||
//TODO WL21389: SHAPE_TYPE_SIMPLE_HULL and pointCollection (later)
|
||||
case entity::Shape::Icosahedron: {
|
||||
if ( shapeCalculator ) {
|
||||
shapeCalculator(this, info);
|
||||
// shapeCalculator only supports convex shapes (e.g. SHAPE_TYPE_HULL)
|
||||
_collisionShapeType = SHAPE_TYPE_SIMPLE_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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return _collisionShapeType;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@ namespace entity {
|
|||
::QString stringFromShape(Shape shape);
|
||||
}
|
||||
|
||||
|
||||
class ShapeEntityItem : public EntityItem {
|
||||
using Pointer = std::shared_ptr<ShapeEntityItem>;
|
||||
static Pointer baseFactory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
@ -43,6 +42,9 @@ public:
|
|||
static EntityItemPointer sphereFactory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
static EntityItemPointer boxFactory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
using ShapeInfoCalculator = std::function<void( const ShapeEntityItem * const shapeEntity, ShapeInfo& info)>;
|
||||
static void setShapeInfoCalulator(ShapeInfoCalculator callback);
|
||||
|
||||
ShapeEntityItem(const EntityItemID& entityItemID);
|
||||
|
||||
void pureVirtualFunctionPlaceHolder() override { };
|
||||
|
|
|
@ -66,7 +66,7 @@ class PhysicsEngine;
|
|||
|
||||
class ObjectMotionState : public btMotionState {
|
||||
public:
|
||||
// These poroperties of the PhysicsEngine are "global" within the context of all ObjectMotionStates
|
||||
// These properties of the PhysicsEngine are "global" within the context of all ObjectMotionStates
|
||||
// (assuming just one PhysicsEngine). They are cached as statics for fast calculations in the
|
||||
// ObjectMotionState context.
|
||||
static void setWorldOffset(const glm::vec3& offset);
|
||||
|
|
|
@ -314,6 +314,7 @@ const btCollisionShape* ShapeFactory::createShapeFromInfo(const ShapeInfo& info)
|
|||
shape = new btCylinderShapeZ(btHalfExtents);
|
||||
}
|
||||
break;
|
||||
case SHAPE_TYPE_CIRCLE:
|
||||
case SHAPE_TYPE_CYLINDER_Y: {
|
||||
const glm::vec3 halfExtents = info.getHalfExtents();
|
||||
const btVector3 btHalfExtents(halfExtents.x, halfExtents.y, halfExtents.z);
|
||||
|
|
|
@ -52,6 +52,46 @@
|
|||
|
||||
//#define WANT_DEBUG
|
||||
|
||||
// @note: Originally size entity::NUM_SHAPES
|
||||
// As of Commit b93e91b9, render-utils no longer retains knowledge of
|
||||
// entity lib, and thus doesn't know about entity::NUM_SHAPES. Should
|
||||
// the enumerations be altered, this will need to be updated.
|
||||
// @see ShapeEntityItem.h
|
||||
static std::array<GeometryCache::Shape, (GeometryCache::NUM_SHAPES - 1)> 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,
|
||||
} };
|
||||
|
||||
static const std::array<const char * const, GeometryCache::NUM_SHAPES> GEOCACHE_SHAPE_STRINGS{ {
|
||||
"Line",
|
||||
"Triangle",
|
||||
"Quad",
|
||||
"Hexagon",
|
||||
"Octagon",
|
||||
"Circle",
|
||||
"Cube",
|
||||
"Sphere",
|
||||
"Tetrahedron",
|
||||
"Octahedron",
|
||||
"Dodecahedron",
|
||||
"Icosahedron",
|
||||
"Torus",
|
||||
"Cone",
|
||||
"Cylinder"
|
||||
} };
|
||||
|
||||
const int GeometryCache::UNKNOWN_ID = -1;
|
||||
|
||||
|
||||
|
@ -69,6 +109,51 @@ 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_NORMALS_OFFSET = sizeof(glm::vec3);
|
||||
|
||||
void GeometryCache::computeSimpleHullPointListForShape(const int entityShape, const glm::vec3 &entityExtents, QVector<glm::vec3> &outPointList) {
|
||||
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
const GeometryCache::Shape geometryShape = GeometryCache::getShapeForEntityShape( entityShape );
|
||||
const GeometryCache::ShapeData * shapeData = geometryCache->getShapeData( geometryShape );
|
||||
if (!shapeData){
|
||||
//--EARLY EXIT--( data isn't ready for some reason... )
|
||||
return;
|
||||
}
|
||||
|
||||
const gpu::BufferView & shapeVerts = shapeData->_positionView;
|
||||
const gpu::BufferView::Size numItems = shapeVerts.getNumElements();
|
||||
|
||||
outPointList.reserve((int)numItems);
|
||||
QVector<glm::vec3> uniqueVerts;
|
||||
uniqueVerts.reserve((int)numItems);
|
||||
|
||||
const float MAX_INCLUSIVE_FILTER_DISTANCE_SQUARED = 1.0e-6f; //< 1mm^2
|
||||
for (gpu::BufferView::Index i = 0; i < (gpu::BufferView::Index)numItems; ++i) {
|
||||
const int numUniquePoints = (int)uniqueVerts.size();
|
||||
const geometry::Vec &curVert = shapeVerts.get<geometry::Vec>(i);
|
||||
bool isUniquePoint = true;
|
||||
|
||||
for (int uniqueIndex = 0; uniqueIndex < numUniquePoints; ++uniqueIndex) {
|
||||
const geometry::Vec knownVert = uniqueVerts[uniqueIndex];
|
||||
const float distToKnownPoint = glm::length2(knownVert - curVert);
|
||||
|
||||
if (distToKnownPoint <= MAX_INCLUSIVE_FILTER_DISTANCE_SQUARED) {
|
||||
isUniquePoint = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isUniquePoint) {
|
||||
|
||||
//--EARLY ITERATION EXIT--
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
uniqueVerts.push_back(curVert);
|
||||
outPointList.push_back(curVert * entityExtents);
|
||||
}
|
||||
}
|
||||
|
||||
template <size_t SIDES>
|
||||
std::vector<vec3> polygon() {
|
||||
std::vector<vec3> result;
|
||||
|
@ -85,7 +170,7 @@ void GeometryCache::ShapeData::setupVertices(gpu::BufferPointer& vertexBuffer, c
|
|||
gpu::Buffer::Size offset = vertexBuffer->getSize();
|
||||
vertexBuffer->append(vertices);
|
||||
|
||||
gpu::Buffer::Size viewSize = vertices.size() * 2 * sizeof(glm::vec3);
|
||||
gpu::Buffer::Size viewSize = vertices.size() * sizeof(glm::vec3);
|
||||
|
||||
_positionView = gpu::BufferView(vertexBuffer, offset,
|
||||
viewSize, SHAPE_VERTEX_STRIDE, POSITION_ELEMENT);
|
||||
|
@ -441,12 +526,46 @@ void GeometryCache::buildShapes() {
|
|||
extrudePolygon<64>(_shapes[Cone], _shapeVertices, _shapeIndices, true);
|
||||
//Circle
|
||||
drawCircle(_shapes[Circle], _shapeVertices, _shapeIndices);
|
||||
// Not implememented yet:
|
||||
// Not implemented yet:
|
||||
//Quad,
|
||||
//Torus,
|
||||
|
||||
}
|
||||
|
||||
const GeometryCache::ShapeData * GeometryCache::getShapeData(const Shape shape) const {
|
||||
if (((int)shape < 0) || ((int)shape >= (int)_shapes.size())) {
|
||||
qCWarning(renderutils) << "GeometryCache::getShapeData - Invalid shape " << shape << " specified. Returning default fallback.";
|
||||
|
||||
//--EARLY EXIT--( No valid shape data for shape )
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &_shapes[shape];
|
||||
}
|
||||
|
||||
GeometryCache::Shape GeometryCache::getShapeForEntityShape(int entityShape) {
|
||||
if ((entityShape < 0) || (entityShape >= (int)MAPPING.size())) {
|
||||
qCWarning(renderutils) << "GeometryCache::getShapeForEntityShape - Invalid shape " << entityShape << " specified. Returning default fallback.";
|
||||
|
||||
//--EARLY EXIT--( fall back to default assumption )
|
||||
return GeometryCache::Sphere;
|
||||
}
|
||||
|
||||
return MAPPING[entityShape];
|
||||
}
|
||||
|
||||
QString GeometryCache::stringFromShape(GeometryCache::Shape geoShape)
|
||||
{
|
||||
if (((int)geoShape < 0) || ((int)geoShape >= (int)GeometryCache::NUM_SHAPES)) {
|
||||
qCWarning(renderutils) << "GeometryCache::stringFromShape - Invalid shape " << geoShape << " specified.";
|
||||
|
||||
//--EARLY EXIT--
|
||||
return "INVALID_GEOCACHE_SHAPE";
|
||||
}
|
||||
|
||||
return GEOCACHE_SHAPE_STRINGS[geoShape];
|
||||
}
|
||||
|
||||
gpu::Stream::FormatPointer& getSolidStreamFormat() {
|
||||
if (!SOLID_STREAM_FORMAT) {
|
||||
SOLID_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone
|
||||
|
|
|
@ -147,6 +147,16 @@ public:
|
|||
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 QString stringFromShape(GeometryCache::Shape geoShape);
|
||||
|
||||
static void computeSimpleHullPointListForShape(int entityShape, const glm::vec3 &entityExtents, QVector<glm::vec3> &outPointList);
|
||||
|
||||
static uint8_t CUSTOM_PIPELINE_NUMBER;
|
||||
static render::ShapePipelinePointer shapePipelineFactory(const render::ShapePlumber& plumber, const render::ShapeKey& key);
|
||||
static void registerShapePipeline() {
|
||||
|
@ -355,15 +365,21 @@ public:
|
|||
|
||||
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:
|
||||
|
||||
GeometryCache();
|
||||
virtual ~GeometryCache();
|
||||
void buildShapes();
|
||||
|
||||
typedef QPair<int, int> IntPair;
|
||||
typedef QPair<unsigned int, unsigned int> VerticesIndices;
|
||||
|
||||
|
||||
VShape _shapes;
|
||||
|
||||
gpu::PipelinePointer _standardDrawPipeline;
|
||||
gpu::PipelinePointer _standardDrawPipelineNoBlend;
|
||||
|
|
|
@ -15,9 +15,38 @@
|
|||
|
||||
#include "NumericalConstants.h" // for MILLIMETERS_PER_METER
|
||||
|
||||
// Originally within EntityItemProperties.cpp
|
||||
const char* shapeTypeNames[] = {
|
||||
"none",
|
||||
"box",
|
||||
"sphere",
|
||||
"capsule-x",
|
||||
"capsule-y",
|
||||
"capsule-z",
|
||||
"cylinder-x",
|
||||
"cylinder-y",
|
||||
"cylinder-z",
|
||||
"hull",
|
||||
"plane",
|
||||
"compound",
|
||||
"simple-hull",
|
||||
"simple-compound",
|
||||
"static-mesh"
|
||||
};
|
||||
|
||||
static const size_t SHAPETYPE_NAME_COUNT = (sizeof(shapeTypeNames) / sizeof((shapeTypeNames)[0]));
|
||||
|
||||
// Bullet doesn't support arbitrarily small shapes
|
||||
const float MIN_HALF_EXTENT = 0.005f; // 0.5 cm
|
||||
|
||||
QString ShapeInfo::getNameForShapeType(ShapeType type) {
|
||||
if (((int)type <= 0) || ((int)type >= (int)SHAPETYPE_NAME_COUNT)) {
|
||||
type = (ShapeType)0;
|
||||
}
|
||||
|
||||
return shapeTypeNames[(int)type];
|
||||
}
|
||||
|
||||
void ShapeInfo::clear() {
|
||||
_url.clear();
|
||||
_pointCollection.clear();
|
||||
|
@ -29,7 +58,6 @@ void ShapeInfo::clear() {
|
|||
}
|
||||
|
||||
void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString url) {
|
||||
//TODO WL21389: Does this need additional cases and handling added?
|
||||
_url = "";
|
||||
_type = type;
|
||||
setHalfExtents(halfExtents);
|
||||
|
@ -38,6 +66,7 @@ void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString
|
|||
_halfExtents = glm::vec3(0.0f);
|
||||
break;
|
||||
case SHAPE_TYPE_BOX:
|
||||
case SHAPE_TYPE_HULL:
|
||||
break;
|
||||
case SHAPE_TYPE_SPHERE: {
|
||||
float radius = glm::length(halfExtents) / SQUARE_ROOT_OF_3;
|
||||
|
@ -45,6 +74,10 @@ void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString
|
|||
_halfExtents = glm::vec3(radius);
|
||||
}
|
||||
break;
|
||||
case SHAPE_TYPE_CIRCLE: {
|
||||
_halfExtents = glm::vec3(_halfExtents.x, MIN_HALF_EXTENT, _halfExtents.z);
|
||||
}
|
||||
break;
|
||||
case SHAPE_TYPE_COMPOUND:
|
||||
case SHAPE_TYPE_SIMPLE_HULL:
|
||||
case SHAPE_TYPE_SIMPLE_COMPOUND:
|
||||
|
@ -58,9 +91,6 @@ void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString
|
|||
}
|
||||
|
||||
void ShapeInfo::setBox(const glm::vec3& halfExtents) {
|
||||
//TODO WL21389: Should this pointlist clearance added in case
|
||||
// this is a re-purposed instance?
|
||||
// See https://github.com/highfidelity/hifi/pull/11024#discussion_r128885491
|
||||
_url = "";
|
||||
_type = SHAPE_TYPE_BOX;
|
||||
setHalfExtents(halfExtents);
|
||||
|
@ -68,7 +98,6 @@ void ShapeInfo::setBox(const glm::vec3& halfExtents) {
|
|||
}
|
||||
|
||||
void ShapeInfo::setSphere(float radius) {
|
||||
//TODO WL21389: See comment in setBox regarding clearance
|
||||
_url = "";
|
||||
_type = SHAPE_TYPE_SPHERE;
|
||||
radius = glm::max(radius, MIN_HALF_EXTENT);
|
||||
|
@ -77,14 +106,11 @@ void ShapeInfo::setSphere(float radius) {
|
|||
}
|
||||
|
||||
void ShapeInfo::setPointCollection(const ShapeInfo::PointCollection& pointCollection) {
|
||||
//TODO WL21389: May need to skip resetting type here.
|
||||
_pointCollection = pointCollection;
|
||||
_type = (_pointCollection.size() > 0) ? SHAPE_TYPE_COMPOUND : SHAPE_TYPE_NONE;
|
||||
_doubleHashKey.clear();
|
||||
}
|
||||
|
||||
void ShapeInfo::setCapsuleY(float radius, float halfHeight) {
|
||||
//TODO WL21389: See comment in setBox regarding clearance
|
||||
_url = "";
|
||||
_type = SHAPE_TYPE_CAPSULE_Y;
|
||||
radius = glm::max(radius, MIN_HALF_EXTENT);
|
||||
|
@ -125,8 +151,15 @@ int ShapeInfo::getLargestSubshapePointCount() const {
|
|||
return numPoints;
|
||||
}
|
||||
|
||||
float computeCylinderVolume(const float radius, const float height) {
|
||||
return PI * radius * radius * 2.0f * height;
|
||||
}
|
||||
|
||||
float computeCapsuleVolume(const float radius, const float cylinderHeight) {
|
||||
return PI * radius * radius * (cylinderHeight + 4.0f * radius / 3.0f);
|
||||
}
|
||||
|
||||
float ShapeInfo::computeVolume() const {
|
||||
//TODO WL21389: Add support for other ShapeTypes( CYLINDER_X, CYLINDER_Y, etc).
|
||||
const float DEFAULT_VOLUME = 1.0f;
|
||||
float volume = DEFAULT_VOLUME;
|
||||
switch(_type) {
|
||||
|
@ -139,17 +172,37 @@ float ShapeInfo::computeVolume() const {
|
|||
volume = 4.0f * PI * _halfExtents.x * _halfExtents.y * _halfExtents.z / 3.0f;
|
||||
break;
|
||||
}
|
||||
case SHAPE_TYPE_CYLINDER_X: {
|
||||
volume = computeCylinderVolume(_halfExtents.y, _halfExtents.x);
|
||||
break;
|
||||
}
|
||||
case SHAPE_TYPE_CYLINDER_Y: {
|
||||
float radius = _halfExtents.x;
|
||||
volume = PI * radius * radius * 2.0f * _halfExtents.y;
|
||||
volume = computeCylinderVolume(_halfExtents.x, _halfExtents.y);
|
||||
break;
|
||||
}
|
||||
case SHAPE_TYPE_CYLINDER_Z: {
|
||||
volume = computeCylinderVolume(_halfExtents.x, _halfExtents.z);
|
||||
break;
|
||||
}
|
||||
case SHAPE_TYPE_CAPSULE_X: {
|
||||
// Need to offset halfExtents.x by y to account for the system treating
|
||||
// the x extent of the capsule as the cylindrical height + spherical radius.
|
||||
const float cylinderHeight = 2.0f * (_halfExtents.x - _halfExtents.y);
|
||||
volume = computeCapsuleVolume(_halfExtents.y, cylinderHeight);
|
||||
break;
|
||||
}
|
||||
case SHAPE_TYPE_CAPSULE_Y: {
|
||||
float radius = _halfExtents.x;
|
||||
// Need to offset halfExtents.y by x to account for the system treating
|
||||
// the y extent of the capsule as the cylindrical height + spherical radius.
|
||||
float cylinderHeight = 2.0f * (_halfExtents.y - _halfExtents.x);
|
||||
volume = PI * radius * radius * (cylinderHeight + 4.0f * radius / 3.0f);
|
||||
const float cylinderHeight = 2.0f * (_halfExtents.y - _halfExtents.x);
|
||||
volume = computeCapsuleVolume(_halfExtents.x, cylinderHeight);
|
||||
break;
|
||||
}
|
||||
case SHAPE_TYPE_CAPSULE_Z: {
|
||||
// Need to offset halfExtents.z by x to account for the system treating
|
||||
// the z extent of the capsule as the cylindrical height + spherical radius.
|
||||
const float cylinderHeight = 2.0f * (_halfExtents.z - _halfExtents.x);
|
||||
volume = computeCapsuleVolume(_halfExtents.x, cylinderHeight);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -160,7 +213,6 @@ float ShapeInfo::computeVolume() const {
|
|||
}
|
||||
|
||||
bool ShapeInfo::contains(const glm::vec3& point) const {
|
||||
//TODO WL21389: Add support for other ShapeTypes like Ellipsoid/Compound.
|
||||
switch(_type) {
|
||||
case SHAPE_TYPE_SPHERE:
|
||||
return glm::length(point) <= _halfExtents.x;
|
||||
|
@ -205,7 +257,6 @@ bool ShapeInfo::contains(const glm::vec3& point) const {
|
|||
}
|
||||
|
||||
const DoubleHashKey& ShapeInfo::getHash() const {
|
||||
//TODO WL21389: Need to include the pointlist for SIMPLE_HULL in hash
|
||||
// NOTE: we cache the key so we only ever need to compute it once for any valid ShapeInfo instance.
|
||||
if (_doubleHashKey.isNull() && _type != SHAPE_TYPE_NONE) {
|
||||
bool useOffset = glm::length2(_offset) > MIN_SHAPE_OFFSET * MIN_SHAPE_OFFSET;
|
||||
|
@ -216,41 +267,82 @@ const DoubleHashKey& ShapeInfo::getHash() const {
|
|||
uint32_t primeIndex = 0;
|
||||
_doubleHashKey.computeHash((uint32_t)_type, primeIndex++);
|
||||
|
||||
// compute hash1
|
||||
uint32_t hash = _doubleHashKey.getHash();
|
||||
for (int j = 0; j < 3; ++j) {
|
||||
// NOTE: 0.49f is used to bump the float up almost half a millimeter
|
||||
// so the cast to int produces a round() effect rather than a floor()
|
||||
hash ^= DoubleHashKey::hashFunction(
|
||||
if (_type != SHAPE_TYPE_SIMPLE_HULL) {
|
||||
// compute hash1
|
||||
uint32_t hash = _doubleHashKey.getHash();
|
||||
for (int j = 0; j < 3; ++j) {
|
||||
// NOTE: 0.49f is used to bump the float up almost half a millimeter
|
||||
// so the cast to int produces a round() effect rather than a floor()
|
||||
hash ^= DoubleHashKey::hashFunction(
|
||||
(uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f),
|
||||
primeIndex++);
|
||||
if (useOffset) {
|
||||
hash ^= DoubleHashKey::hashFunction(
|
||||
if (useOffset) {
|
||||
hash ^= DoubleHashKey::hashFunction(
|
||||
(uint32_t)(_offset[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _offset[j]) * 0.49f),
|
||||
primeIndex++);
|
||||
}
|
||||
}
|
||||
}
|
||||
_doubleHashKey.setHash(hash);
|
||||
_doubleHashKey.setHash(hash);
|
||||
|
||||
// compute hash2
|
||||
hash = _doubleHashKey.getHash2();
|
||||
for (int j = 0; j < 3; ++j) {
|
||||
// NOTE: 0.49f is used to bump the float up almost half a millimeter
|
||||
// so the cast to int produces a round() effect rather than a floor()
|
||||
uint32_t floatHash = DoubleHashKey::hashFunction2(
|
||||
// compute hash2
|
||||
hash = _doubleHashKey.getHash2();
|
||||
for (int j = 0; j < 3; ++j) {
|
||||
// NOTE: 0.49f is used to bump the float up almost half a millimeter
|
||||
// so the cast to int produces a round() effect rather than a floor()
|
||||
uint32_t floatHash = DoubleHashKey::hashFunction2(
|
||||
(uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f));
|
||||
if (useOffset) {
|
||||
floatHash ^= DoubleHashKey::hashFunction2(
|
||||
if (useOffset) {
|
||||
floatHash ^= DoubleHashKey::hashFunction2(
|
||||
(uint32_t)(_offset[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _offset[j]) * 0.49f));
|
||||
}
|
||||
hash += ~(floatHash << 17);
|
||||
hash ^= (floatHash >> 11);
|
||||
hash += (floatHash << 4);
|
||||
hash ^= (floatHash >> 7);
|
||||
hash += ~(floatHash << 10);
|
||||
hash = (hash << 16) | (hash >> 16);
|
||||
}
|
||||
hash += ~(floatHash << 17);
|
||||
hash ^= (floatHash >> 11);
|
||||
hash += (floatHash << 4);
|
||||
hash ^= (floatHash >> 7);
|
||||
hash += ~(floatHash << 10);
|
||||
hash = (hash << 16) | (hash >> 16);
|
||||
_doubleHashKey.setHash2(hash);
|
||||
} else {
|
||||
|
||||
assert(_pointCollection.size() == (size_t)1);
|
||||
const PointList & points = _pointCollection.back();
|
||||
const int numPoints = (int)points.size();
|
||||
uint32_t hash = _doubleHashKey.getHash();
|
||||
uint32_t hash2 = _doubleHashKey.getHash2();
|
||||
|
||||
for (int pointIndex = 0; pointIndex < numPoints; ++pointIndex) {
|
||||
// compute hash1 & 2
|
||||
const glm::vec3 &curPoint = points[pointIndex];
|
||||
for (int vecCompIndex = 0; vecCompIndex < 3; ++vecCompIndex) {
|
||||
|
||||
// NOTE: 0.49f is used to bump the float up almost half a millimeter
|
||||
// so the cast to int produces a round() effect rather than a floor()
|
||||
uint32_t valueToHash = (uint32_t)(curPoint[vecCompIndex] * MILLIMETERS_PER_METER + copysignf(1.0f, curPoint[vecCompIndex]) * 0.49f);
|
||||
|
||||
hash ^= DoubleHashKey::hashFunction(valueToHash, primeIndex++);
|
||||
uint32_t floatHash = DoubleHashKey::hashFunction2(valueToHash);
|
||||
|
||||
if (useOffset) {
|
||||
|
||||
const uint32_t offsetValToHash = (uint32_t)(_offset[vecCompIndex] * MILLIMETERS_PER_METER + copysignf(1.0f, _offset[vecCompIndex])* 0.49f);
|
||||
|
||||
hash ^= DoubleHashKey::hashFunction(offsetValToHash, primeIndex++);
|
||||
floatHash ^= DoubleHashKey::hashFunction2(offsetValToHash);
|
||||
}
|
||||
|
||||
hash2 += ~(floatHash << 17);
|
||||
hash2 ^= (floatHash >> 11);
|
||||
hash2 += (floatHash << 4);
|
||||
hash2 ^= (floatHash >> 7);
|
||||
hash2 += ~(floatHash << 10);
|
||||
hash2 = (hash2 << 16) | (hash2 >> 16);
|
||||
}
|
||||
}
|
||||
|
||||
_doubleHashKey.setHash(hash);
|
||||
_doubleHashKey.setHash2(hash2);
|
||||
}
|
||||
_doubleHashKey.setHash2(hash);
|
||||
|
||||
QString url = _url.toString();
|
||||
if (!url.isEmpty()) {
|
||||
|
@ -268,7 +360,7 @@ const DoubleHashKey& ShapeInfo::getHash() const {
|
|||
numHulls = 1;
|
||||
}
|
||||
if (numHulls > 0) {
|
||||
hash = DoubleHashKey::hashFunction(numHulls, primeIndex++);
|
||||
uint32_t hash = DoubleHashKey::hashFunction(numHulls, primeIndex++);
|
||||
_doubleHashKey.setHash(_doubleHashKey.getHash() ^ hash);
|
||||
hash = DoubleHashKey::hashFunction2(numHulls);
|
||||
_doubleHashKey.setHash2(_doubleHashKey.getHash2() ^ hash);
|
||||
|
|
|
@ -46,7 +46,8 @@ enum ShapeType {
|
|||
SHAPE_TYPE_SIMPLE_HULL,
|
||||
SHAPE_TYPE_SIMPLE_COMPOUND,
|
||||
SHAPE_TYPE_STATIC_MESH,
|
||||
SHAPE_TYPE_ELLIPSOID
|
||||
SHAPE_TYPE_ELLIPSOID,
|
||||
SHAPE_TYPE_CIRCLE
|
||||
};
|
||||
|
||||
class ShapeInfo {
|
||||
|
@ -57,6 +58,8 @@ public:
|
|||
using PointCollection = QVector<PointList>;
|
||||
using TriangleIndices = QVector<int32_t>;
|
||||
|
||||
static QString getNameForShapeType(ShapeType type);
|
||||
|
||||
void clear();
|
||||
|
||||
void setParams(ShapeType type, const glm::vec3& halfExtents, QString url="");
|
||||
|
@ -66,7 +69,7 @@ public:
|
|||
void setCapsuleY(float radius, float halfHeight);
|
||||
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& getOffset() const { return _offset; }
|
||||
|
|
|
@ -104,8 +104,9 @@ bool TriangleSet::TriangleOctreeCell::findRayIntersectionInternal(const glm::vec
|
|||
if (_bounds.findRayIntersection(origin, direction, boxDistance, face, surfaceNormal)) {
|
||||
|
||||
// if our bounding box intersects at a distance greater than the current known
|
||||
// best distance, than we can safely not check any of our triangles
|
||||
if (boxDistance > bestDistance) {
|
||||
// best distance, and our origin isn't inside the boounds, then we can safely
|
||||
// not check any of our triangles
|
||||
if (boxDistance > bestDistance && !_bounds.contains(origin)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -119,6 +119,7 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
this.actionID = null; // action this script created...
|
||||
this.entityWithContextOverlay = false;
|
||||
this.contextOverlayTimer = false;
|
||||
this.previousCollisionStatus = false;
|
||||
this.reticleMinX = MARGIN;
|
||||
this.reticleMaxX;
|
||||
this.reticleMinY = MARGIN;
|
||||
|
@ -342,7 +343,9 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
if (this.madeDynamic) {
|
||||
var props = {};
|
||||
props.dynamic = false;
|
||||
props.collisionless = this.previousCollisionStatus;
|
||||
props.localVelocity = {x: 0, y: 0, z: 0};
|
||||
props.localRotation = {x: 0, y: 0, z: 0};
|
||||
Entities.editEntity(this.grabbedThingID, props);
|
||||
this.madeDynamic = false;
|
||||
}
|
||||
|
@ -507,10 +510,12 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
if (entityIsGrabbable(targetProps)) {
|
||||
if (!entityIsDistanceGrabbable(targetProps)) {
|
||||
targetProps.dynamic = true;
|
||||
this.previousCollisionStatus = targetProps.collisionless;
|
||||
targetProps.collisionless = true;
|
||||
Entities.editEntity(entityID, targetProps);
|
||||
this.madeDynamic = true;
|
||||
}
|
||||
|
||||
|
||||
if (!this.distanceRotating) {
|
||||
this.grabbedThingID = entityID;
|
||||
this.grabbedDistance = rayPickInfo.distance;
|
||||
|
|
|
@ -1373,7 +1373,7 @@ function loaded() {
|
|||
elShape.addEventListener('change', createEmitTextPropertyUpdateFunction('shape'));
|
||||
|
||||
elWebSourceURL.addEventListener('change', createEmitTextPropertyUpdateFunction('sourceUrl'));
|
||||
elWebDPI.addEventListener('change', createEmitNumberPropertyUpdateFunction('dpi'));
|
||||
elWebDPI.addEventListener('change', createEmitNumberPropertyUpdateFunction('dpi', 0));
|
||||
|
||||
elModelURL.addEventListener('change', createEmitTextPropertyUpdateFunction('modelURL'));
|
||||
elShapeType.addEventListener('change', createEmitTextPropertyUpdateFunction('shapeType'));
|
||||
|
|
|
@ -10,18 +10,18 @@
|
|||
|
||||
gpu::Stream::FormatPointer& getInstancedSolidStreamFormat();
|
||||
|
||||
static const size_t TYPE_COUNT = 4;
|
||||
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] = {
|
||||
static GeometryCache::Shape SHAPE[] = {
|
||||
GeometryCache::Icosahedron,
|
||||
GeometryCache::Cube,
|
||||
GeometryCache::Sphere,
|
||||
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 NORMAL_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ };
|
||||
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 vec3 ITEM_TRANSLATION { 0, 0, -ITEM_RADIUS };
|
||||
for (size_t i = 0; i < TYPE_COUNT; ++i) {
|
||||
GeometryCache::Shape shape = SHAPE[i];
|
||||
GeometryCache::ShapeData shapeData = geometryCache->_shapes[shape];
|
||||
//indirectCommand._count
|
||||
float startingInterval = ITEM_INTERVAL * i;
|
||||
std::vector<mat4> typeTransforms;
|
||||
|
@ -62,7 +60,12 @@ void TestInstancedShapes::renderTest(size_t testId, RenderArgs* args) {
|
|||
batch.setInputFormat(getInstancedSolidStreamFormat());
|
||||
for (size_t i = 0; i < TYPE_COUNT; ++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);
|
||||
|
||||
|
@ -71,13 +74,13 @@ void TestInstancedShapes::renderTest(size_t testId, RenderArgs* args) {
|
|||
batch.setModelTransform(transforms[i][j]);
|
||||
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));
|
||||
shapeData.drawInstances(batch, ITEM_COUNT);
|
||||
shapeData->drawInstances(batch, ITEM_COUNT);
|
||||
});
|
||||
}
|
||||
|
||||
//for (size_t j = 0; j < ITEM_COUNT; ++j) {
|
||||
// batch.setModelTransform(transforms[j + i * ITEM_COUNT]);
|
||||
// shapeData.draw(batch);
|
||||
// shapeData->draw(batch);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue