mirror of
https://github.com/overte-org/overte.git
synced 2025-08-07 13:30:33 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into temp1
This commit is contained in:
commit
f874a3ae82
12 changed files with 205 additions and 100 deletions
|
@ -18,3 +18,4 @@ Script.load("lobby.js");
|
||||||
Script.load("notifications.js");
|
Script.load("notifications.js");
|
||||||
Script.load("look.js");
|
Script.load("look.js");
|
||||||
Script.load("users.js");
|
Script.load("users.js");
|
||||||
|
Script.load("utilities/LODWarning.js");
|
||||||
|
|
16
examples/example/ui/LODManagerExample.js
Normal file
16
examples/example/ui/LODManagerExample.js
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
|
||||||
|
LODManager.LODIncreased.connect(function() {
|
||||||
|
print("LOD has been increased. You can now see "
|
||||||
|
+ LODManager.getLODFeedbackText()
|
||||||
|
+ ", fps:" + LODManager.getFPSAverage()
|
||||||
|
+ ", fast fps:" + LODManager.getFastFPSAverage()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
LODManager.LODDecreased.connect(function() {
|
||||||
|
print("LOD has been decreased. You can now see "
|
||||||
|
+ LODManager.getLODFeedbackText()
|
||||||
|
+ ", fps:" + LODManager.getFPSAverage()
|
||||||
|
+ ", fast fps:" + LODManager.getFastFPSAverage()
|
||||||
|
);
|
||||||
|
});
|
|
@ -13,4 +13,5 @@ Script.load("progress.js");
|
||||||
Script.load("lobby.js");
|
Script.load("lobby.js");
|
||||||
Script.load("notifications.js");
|
Script.load("notifications.js");
|
||||||
Script.load("controllers/oculus/goTo.js");
|
Script.load("controllers/oculus/goTo.js");
|
||||||
|
Script.load("utilities/LODWarning.js");
|
||||||
//Script.load("scripts.js"); // Not created yet
|
//Script.load("scripts.js"); // Not created yet
|
||||||
|
|
115
examples/utilities/LODWarning.js
Normal file
115
examples/utilities/LODWarning.js
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
// LODWarning.js
|
||||||
|
// examples
|
||||||
|
//
|
||||||
|
// Created by Brad Hefta-Gaub on 3/17/15.
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// This script will display a warning when the LOD is adjusted to do scene complexity.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
var DISPLAY_WARNING_FOR = 3; // in seconds
|
||||||
|
var DISTANCE_FROM_CAMERA = 2;
|
||||||
|
var SHOW_LOD_UP_MESSAGE = false; // By default we only display the LOD message when reducing LOD
|
||||||
|
|
||||||
|
|
||||||
|
var warningIsVisible = false; // initially the warning is hidden
|
||||||
|
var warningShownAt = 0;
|
||||||
|
var billboardPosition = Vec3.sum(Camera.getPosition(),
|
||||||
|
Vec3.multiply(DISTANCE_FROM_CAMERA, Quat.getFront(Camera.getOrientation())));
|
||||||
|
|
||||||
|
var warningOverlay = Overlays.addOverlay("text3d", {
|
||||||
|
position: billboardPosition,
|
||||||
|
dimensions: { x: 2, y: 1.25 },
|
||||||
|
width: 2,
|
||||||
|
height: 1.25,
|
||||||
|
backgroundColor: { red: 0, green: 0, blue: 0 },
|
||||||
|
color: { red: 255, green: 255, blue: 255},
|
||||||
|
topMargin: 0.1,
|
||||||
|
leftMargin: 0.1,
|
||||||
|
lineHeight: 0.07,
|
||||||
|
text: "",
|
||||||
|
alpha: 0.5,
|
||||||
|
backgroundAlpha: 0.7,
|
||||||
|
isFacingAvatar: true,
|
||||||
|
visible: warningIsVisible,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle moving the billboard to remain in front of the camera
|
||||||
|
var billboardNeedsMoving = false;
|
||||||
|
Script.update.connect(function() {
|
||||||
|
|
||||||
|
if (warningIsVisible) {
|
||||||
|
var bestBillboardPosition = Vec3.sum(Camera.getPosition(),
|
||||||
|
Vec3.multiply(DISTANCE_FROM_CAMERA, Quat.getFront(Camera.getOrientation())));
|
||||||
|
|
||||||
|
var MAX_DISTANCE = 0.5;
|
||||||
|
var CLOSE_ENOUGH = 0.01;
|
||||||
|
if (!billboardNeedsMoving && Vec3.distance(bestBillboardPosition, billboardPosition) > MAX_DISTANCE) {
|
||||||
|
billboardNeedsMoving = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (billboardNeedsMoving && Vec3.distance(bestBillboardPosition, billboardPosition) <= CLOSE_ENOUGH) {
|
||||||
|
billboardNeedsMoving = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (billboardNeedsMoving) {
|
||||||
|
// slurp the billboard to the best location
|
||||||
|
moveVector = Vec3.multiply(0.05, Vec3.subtract(bestBillboardPosition, billboardPosition));
|
||||||
|
billboardPosition = Vec3.sum(billboardPosition, moveVector);
|
||||||
|
Overlays.editOverlay(warningOverlay, { position: billboardPosition });
|
||||||
|
}
|
||||||
|
|
||||||
|
var now = new Date();
|
||||||
|
var sinceWarningShown = now - warningShownAt;
|
||||||
|
if (sinceWarningShown > 1000 * DISPLAY_WARNING_FOR) {
|
||||||
|
warningIsVisible = false;
|
||||||
|
Overlays.editOverlay(warningOverlay, { visible: warningIsVisible });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
LODManager.LODIncreased.connect(function() {
|
||||||
|
if (SHOW_LOD_UP_MESSAGE) {
|
||||||
|
// if the warning wasn't visible, then move it before showing it.
|
||||||
|
if (!warningIsVisible) {
|
||||||
|
billboardPosition = Vec3.sum(Camera.getPosition(),
|
||||||
|
Vec3.multiply(DISTANCE_FROM_CAMERA, Quat.getFront(Camera.getOrientation())));
|
||||||
|
Overlays.editOverlay(warningOverlay, { position: billboardPosition });
|
||||||
|
}
|
||||||
|
|
||||||
|
warningShownAt = new Date();
|
||||||
|
warningIsVisible = true;
|
||||||
|
warningText = "Level of detail has been increased. \n"
|
||||||
|
+ "You can now see: \n"
|
||||||
|
+ LODManager.getLODFeedbackText();
|
||||||
|
|
||||||
|
Overlays.editOverlay(warningOverlay, { visible: warningIsVisible, text: warningText });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
LODManager.LODDecreased.connect(function() {
|
||||||
|
// if the warning wasn't visible, then move it before showing it.
|
||||||
|
if (!warningIsVisible) {
|
||||||
|
billboardPosition = Vec3.sum(Camera.getPosition(),
|
||||||
|
Vec3.multiply(DISTANCE_FROM_CAMERA, Quat.getFront(Camera.getOrientation())));
|
||||||
|
Overlays.editOverlay(warningOverlay, { position: billboardPosition });
|
||||||
|
}
|
||||||
|
|
||||||
|
warningShownAt = new Date();
|
||||||
|
warningIsVisible = true;
|
||||||
|
warningText = "\n"
|
||||||
|
+ "Due to the complexity of the content, the \n"
|
||||||
|
+ "level of detail has been decreased. \n"
|
||||||
|
+ "You can now see: \n"
|
||||||
|
+ LODManager.getLODFeedbackText();
|
||||||
|
|
||||||
|
Overlays.editOverlay(warningOverlay, { visible: warningIsVisible, text: warningText });
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
Script.scriptEnding.connect(function() {
|
||||||
|
Overlays.deleteOverlay(warningOverlay);
|
||||||
|
});
|
|
@ -3565,6 +3565,8 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
|
||||||
|
|
||||||
scriptEngine->registerGlobalObject("UndoStack", &_undoStackScriptingInterface);
|
scriptEngine->registerGlobalObject("UndoStack", &_undoStackScriptingInterface);
|
||||||
|
|
||||||
|
scriptEngine->registerGlobalObject("LODManager", DependencyManager::get<LODManager>().data());
|
||||||
|
|
||||||
QScriptValue hmdInterface = scriptEngine->registerGlobalObject("HMD", &HMDScriptingInterface::getInstance());
|
QScriptValue hmdInterface = scriptEngine->registerGlobalObject("HMD", &HMDScriptingInterface::getInstance());
|
||||||
scriptEngine->registerFunction(hmdInterface, "getHUDLookAtPosition2D", HMDScriptingInterface::getHUDLookAtPosition2D, 0);
|
scriptEngine->registerFunction(hmdInterface, "getHUDLookAtPosition2D", HMDScriptingInterface::getHUDLookAtPosition2D, 0);
|
||||||
scriptEngine->registerFunction(hmdInterface, "getHUDLookAtPosition3D", HMDScriptingInterface::getHUDLookAtPosition3D, 0);
|
scriptEngine->registerFunction(hmdInterface, "getHUDLookAtPosition3D", HMDScriptingInterface::getHUDLookAtPosition3D, 0);
|
||||||
|
|
|
@ -76,6 +76,8 @@ void LODManager::autoAdjustLOD(float currentFPS) {
|
||||||
_lastAdjust = now;
|
_lastAdjust = now;
|
||||||
qDebug() << "adjusting LOD down... average fps for last approximately 5 seconds=" << _fpsAverage.getAverage()
|
qDebug() << "adjusting LOD down... average fps for last approximately 5 seconds=" << _fpsAverage.getAverage()
|
||||||
<< "_octreeSizeScale=" << _octreeSizeScale;
|
<< "_octreeSizeScale=" << _octreeSizeScale;
|
||||||
|
|
||||||
|
emit LODDecreased();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (elapsed > ADJUST_LOD_UP_DELAY && _fpsAverage.getAverage() > ADJUST_LOD_UP_FPS
|
if (elapsed > ADJUST_LOD_UP_DELAY && _fpsAverage.getAverage() > ADJUST_LOD_UP_FPS
|
||||||
|
@ -88,6 +90,8 @@ void LODManager::autoAdjustLOD(float currentFPS) {
|
||||||
_lastAdjust = now;
|
_lastAdjust = now;
|
||||||
qDebug() << "adjusting LOD up... average fps for last approximately 5 seconds=" << _fpsAverage.getAverage()
|
qDebug() << "adjusting LOD up... average fps for last approximately 5 seconds=" << _fpsAverage.getAverage()
|
||||||
<< "_octreeSizeScale=" << _octreeSizeScale;
|
<< "_octreeSizeScale=" << _octreeSizeScale;
|
||||||
|
|
||||||
|
emit LODIncreased();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
|
|
|
@ -21,13 +21,16 @@ const float ADJUST_LOD_DOWN_FPS = 40.0;
|
||||||
const float ADJUST_LOD_UP_FPS = 55.0;
|
const float ADJUST_LOD_UP_FPS = 55.0;
|
||||||
const float DEFAULT_ADJUST_AVATAR_LOD_DOWN_FPS = 30.0f;
|
const float DEFAULT_ADJUST_AVATAR_LOD_DOWN_FPS = 30.0f;
|
||||||
|
|
||||||
const quint64 ADJUST_LOD_DOWN_DELAY = 1000 * 1000 * 5;
|
const quint64 ADJUST_LOD_DOWN_DELAY = 1000 * 1000 * 0.5; // Consider adjusting LOD down after half a second
|
||||||
const quint64 ADJUST_LOD_UP_DELAY = ADJUST_LOD_DOWN_DELAY * 2;
|
const quint64 ADJUST_LOD_UP_DELAY = ADJUST_LOD_DOWN_DELAY * 2;
|
||||||
|
|
||||||
const float ADJUST_LOD_DOWN_BY = 0.9f;
|
const float ADJUST_LOD_DOWN_BY = 0.9f;
|
||||||
const float ADJUST_LOD_UP_BY = 1.1f;
|
const float ADJUST_LOD_UP_BY = 1.1f;
|
||||||
|
|
||||||
const float ADJUST_LOD_MIN_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE * 0.25f;
|
// This controls how low the auto-adjust LOD will go a value of 1 means it will adjust to a point where you must be 0.25
|
||||||
|
// meters away from an object of TREE_SCALE before you can see it (which is effectively completely blind). The default value
|
||||||
|
// DEFAULT_OCTREE_SIZE_SCALE means you can be 400 meters away from a 1 meter object in order to see it (which is ~20:20 vision).
|
||||||
|
const float ADJUST_LOD_MIN_SIZE_SCALE = 1.0f;
|
||||||
const float ADJUST_LOD_MAX_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE;
|
const float ADJUST_LOD_MAX_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE;
|
||||||
|
|
||||||
const float MINIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER = 0.1f;
|
const float MINIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER = 0.1f;
|
||||||
|
@ -38,7 +41,8 @@ const int ONE_SECOND_OF_FRAMES = 60;
|
||||||
const int FIVE_SECONDS_OF_FRAMES = 5 * ONE_SECOND_OF_FRAMES;
|
const int FIVE_SECONDS_OF_FRAMES = 5 * ONE_SECOND_OF_FRAMES;
|
||||||
|
|
||||||
|
|
||||||
class LODManager : public Dependency {
|
class LODManager : public QObject, public Dependency {
|
||||||
|
Q_OBJECT
|
||||||
SINGLETON_DEPENDENCY
|
SINGLETON_DEPENDENCY
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -52,21 +56,27 @@ public:
|
||||||
float getAvatarLODDistanceMultiplier() const { return _avatarLODDistanceMultiplier; }
|
float getAvatarLODDistanceMultiplier() const { return _avatarLODDistanceMultiplier; }
|
||||||
|
|
||||||
// User Tweakable LOD Items
|
// User Tweakable LOD Items
|
||||||
QString getLODFeedbackText();
|
Q_INVOKABLE QString getLODFeedbackText();
|
||||||
void setOctreeSizeScale(float sizeScale);
|
Q_INVOKABLE void setOctreeSizeScale(float sizeScale);
|
||||||
float getOctreeSizeScale() const { return _octreeSizeScale; }
|
Q_INVOKABLE float getOctreeSizeScale() const { return _octreeSizeScale; }
|
||||||
|
|
||||||
void setBoundaryLevelAdjust(int boundaryLevelAdjust);
|
Q_INVOKABLE void setBoundaryLevelAdjust(int boundaryLevelAdjust);
|
||||||
int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; }
|
Q_INVOKABLE int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; }
|
||||||
|
|
||||||
void autoAdjustLOD(float currentFPS);
|
void autoAdjustLOD(float currentFPS);
|
||||||
void resetLODAdjust();
|
Q_INVOKABLE void resetLODAdjust();
|
||||||
|
Q_INVOKABLE float getFPSAverage() const { return _fpsAverage.getAverage(); }
|
||||||
|
Q_INVOKABLE float getFastFPSAverage() const { return _fastFPSAverage.getAverage(); }
|
||||||
|
|
||||||
bool shouldRenderMesh(float largestDimension, float distanceToCamera);
|
bool shouldRenderMesh(float largestDimension, float distanceToCamera);
|
||||||
|
|
||||||
void loadSettings();
|
void loadSettings();
|
||||||
void saveSettings();
|
void saveSettings();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void LODIncreased();
|
||||||
|
void LODDecreased();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LODManager() {}
|
LODManager() {}
|
||||||
|
|
||||||
|
|
|
@ -303,7 +303,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
|
||||||
_points << mesh.vertices;
|
_points << mesh.vertices;
|
||||||
}
|
}
|
||||||
|
|
||||||
info.setParams(getShapeType(), 0.5f * getDimensions(), NULL, _collisionModelURL);
|
info.setParams(getShapeType(), 0.5f * getDimensions(), _collisionModelURL);
|
||||||
info.setConvexHull(_points);
|
info.setConvexHull(_points);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@ const int TREE_SCALE = 16384; // ~10 miles.. This is the number of meters of t
|
||||||
|
|
||||||
// This controls the LOD. Larger number will make smaller voxels visible at greater distance.
|
// This controls the LOD. Larger number will make smaller voxels visible at greater distance.
|
||||||
const float DEFAULT_OCTREE_SIZE_SCALE = TREE_SCALE * 400.0f;
|
const float DEFAULT_OCTREE_SIZE_SCALE = TREE_SCALE * 400.0f;
|
||||||
|
|
||||||
|
// This is used in the LOD Tools to translate between the size scale slider and the values used to set the OctreeSizeScale
|
||||||
const float MAX_LOD_SIZE_MULTIPLIER = 2000.0f;
|
const float MAX_LOD_SIZE_MULTIPLIER = 2000.0f;
|
||||||
|
|
||||||
const int NUMBER_OF_CHILDREN = 8;
|
const int NUMBER_OF_CHILDREN = 8;
|
||||||
|
|
|
@ -505,10 +505,8 @@ void PhysicsEngine::removeObjectFromBullet(ObjectMotionState* motionState) {
|
||||||
btRigidBody* body = motionState->getRigidBody();
|
btRigidBody* body = motionState->getRigidBody();
|
||||||
if (body) {
|
if (body) {
|
||||||
const btCollisionShape* shape = body->getCollisionShape();
|
const btCollisionShape* shape = body->getCollisionShape();
|
||||||
ShapeInfo shapeInfo;
|
|
||||||
ShapeInfoUtil::collectInfoFromShape(shape, shapeInfo);
|
|
||||||
_dynamicsWorld->removeRigidBody(body);
|
_dynamicsWorld->removeRigidBody(body);
|
||||||
_shapeManager.releaseShape(shapeInfo);
|
_shapeManager.releaseShape(shape);
|
||||||
// NOTE: setRigidBody() modifies body->m_userPointer so we should clear the MotionState's body BEFORE deleting it.
|
// NOTE: setRigidBody() modifies body->m_userPointer so we should clear the MotionState's body BEFORE deleting it.
|
||||||
motionState->setRigidBody(NULL);
|
motionState->setRigidBody(NULL);
|
||||||
delete body;
|
delete body;
|
||||||
|
|
|
@ -19,10 +19,9 @@ void ShapeInfo::clear() {
|
||||||
_type = SHAPE_TYPE_NONE;
|
_type = SHAPE_TYPE_NONE;
|
||||||
_halfExtents = glm::vec3(0.0f);
|
_halfExtents = glm::vec3(0.0f);
|
||||||
_doubleHashKey.clear();
|
_doubleHashKey.clear();
|
||||||
_externalData = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QVector<glm::vec3>* data, QString url) {
|
void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString url) {
|
||||||
_type = type;
|
_type = type;
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case SHAPE_TYPE_NONE:
|
case SHAPE_TYPE_NONE:
|
||||||
|
@ -45,7 +44,6 @@ void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QVector<
|
||||||
_halfExtents = halfExtents;
|
_halfExtents = halfExtents;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_externalData = data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShapeInfo::setBox(const glm::vec3& halfExtents) {
|
void ShapeInfo::setBox(const glm::vec3& halfExtents) {
|
||||||
|
@ -109,67 +107,20 @@ float ShapeInfo::computeVolume() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
const DoubleHashKey& ShapeInfo::getHash() const {
|
const DoubleHashKey& ShapeInfo::getHash() const {
|
||||||
// NOTE: we cache the hash so we only ever need to compute it once for any valid ShapeInfo instance.
|
// 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) {
|
if (_doubleHashKey.isNull() && _type != SHAPE_TYPE_NONE) {
|
||||||
// cast this to non-const pointer so we can do our dirty work
|
// The key is not yet cached therefore we must compute it! To this end we bypass the const-ness
|
||||||
|
// of this method by grabbing a non-const pointer to "this" and a non-const reference to _doubleHashKey.
|
||||||
ShapeInfo* thisPtr = const_cast<ShapeInfo*>(this);
|
ShapeInfo* thisPtr = const_cast<ShapeInfo*>(this);
|
||||||
|
DoubleHashKey& key = thisPtr->_doubleHashKey;
|
||||||
|
|
||||||
// compute hash1
|
// compute hash1
|
||||||
// TODO?: provide lookup table for hash/hash2 of _type rather than recompute?
|
// TODO?: provide lookup table for hash/hash2 of _type rather than recompute?
|
||||||
uint32_t primeIndex = 0;
|
uint32_t primeIndex = 0;
|
||||||
thisPtr->_doubleHashKey.computeHash((uint32_t)_type, primeIndex++);
|
key.computeHash((uint32_t)_type, primeIndex++);
|
||||||
|
|
||||||
const QVector<glm::vec3>* data = getData();
|
|
||||||
if (data) {
|
|
||||||
// if externalData exists we use it to continue the hash
|
|
||||||
|
|
||||||
// compute hash
|
|
||||||
uint32_t hash = _doubleHashKey.getHash();
|
|
||||||
|
|
||||||
glm::vec3 tmpData;
|
|
||||||
int numData = data->size();
|
|
||||||
for (int i = 0; i < numData; ++i) {
|
|
||||||
tmpData = (*data)[i];
|
|
||||||
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::hashFunction((uint32_t)(tmpData[j] * MILLIMETERS_PER_METER + copysignf(1.0f, tmpData[j]) * 0.49f), primeIndex++);
|
|
||||||
hash ^= floatHash;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
thisPtr->_doubleHashKey.setHash(hash);
|
|
||||||
|
|
||||||
// compute hash2
|
|
||||||
|
|
||||||
QString url = _url.toString();
|
|
||||||
|
|
||||||
if (url == "") {
|
|
||||||
hash = _doubleHashKey.getHash2();
|
|
||||||
for (int i = 0; i < numData; ++i) {
|
|
||||||
tmpData = (*data)[i];
|
|
||||||
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)(tmpData[j] * MILLIMETERS_PER_METER + copysignf(1.0f, tmpData[j]) * 0.49f));
|
|
||||||
hash += ~(floatHash << 17);
|
|
||||||
hash ^= (floatHash >> 11);
|
|
||||||
hash += (floatHash << 4);
|
|
||||||
hash ^= (floatHash >> 7);
|
|
||||||
hash += ~(floatHash << 10);
|
|
||||||
hash = (hash << 16) | (hash >> 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
QByteArray baUrl = url.toLocal8Bit();
|
|
||||||
const char *cUrl = baUrl.data();
|
|
||||||
hash = qChecksum(cUrl, baUrl.count());
|
|
||||||
}
|
|
||||||
thisPtr->_doubleHashKey.setHash2(hash);
|
|
||||||
} else {
|
|
||||||
// this shape info has no external data so type+extents should be enough to generate a unique hash
|
|
||||||
// compute hash1
|
// compute hash1
|
||||||
uint32_t hash = _doubleHashKey.getHash();
|
uint32_t hash = key.getHash();
|
||||||
for (int j = 0; j < 3; ++j) {
|
for (int j = 0; j < 3; ++j) {
|
||||||
// NOTE: 0.49f is used to bump the float up almost half a millimeter
|
// 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()
|
// so the cast to int produces a round() effect rather than a floor()
|
||||||
|
@ -177,10 +128,10 @@ const DoubleHashKey& ShapeInfo::getHash() const {
|
||||||
DoubleHashKey::hashFunction((uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f), primeIndex++);
|
DoubleHashKey::hashFunction((uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f), primeIndex++);
|
||||||
hash ^= floatHash;
|
hash ^= floatHash;
|
||||||
}
|
}
|
||||||
thisPtr->_doubleHashKey.setHash(hash);
|
key.setHash(hash);
|
||||||
|
|
||||||
// compute hash2
|
// compute hash2
|
||||||
hash = _doubleHashKey.getHash2();
|
hash = key.getHash2();
|
||||||
for (int j = 0; j < 3; ++j) {
|
for (int j = 0; j < 3; ++j) {
|
||||||
// NOTE: 0.49f is used to bump the float up almost half a millimeter
|
// 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()
|
// so the cast to int produces a round() effect rather than a floor()
|
||||||
|
@ -193,7 +144,16 @@ const DoubleHashKey& ShapeInfo::getHash() const {
|
||||||
hash += ~(floatHash << 10);
|
hash += ~(floatHash << 10);
|
||||||
hash = (hash << 16) | (hash >> 16);
|
hash = (hash << 16) | (hash >> 16);
|
||||||
}
|
}
|
||||||
thisPtr->_doubleHashKey.setHash2(hash);
|
key.setHash2(hash);
|
||||||
|
|
||||||
|
QString url = _url.toString();
|
||||||
|
if (!url.isEmpty()) {
|
||||||
|
// fold the urlHash into both parts
|
||||||
|
QByteArray baUrl = url.toLocal8Bit();
|
||||||
|
const char *cUrl = baUrl.data();
|
||||||
|
uint32_t urlHash = qChecksum(cUrl, baUrl.count());
|
||||||
|
key.setHash(key.getHash() ^ urlHash);
|
||||||
|
key.setHash2(key.getHash2() ^ urlHash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return _doubleHashKey;
|
return _doubleHashKey;
|
||||||
|
|
|
@ -40,7 +40,7 @@ class ShapeInfo {
|
||||||
public:
|
public:
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
void setParams(ShapeType type, const glm::vec3& halfExtents, QVector<glm::vec3>* data = NULL, QString url="");
|
void setParams(ShapeType type, const glm::vec3& halfExtents, QString url="");
|
||||||
void setBox(const glm::vec3& halfExtents);
|
void setBox(const glm::vec3& halfExtents);
|
||||||
void setSphere(float radius);
|
void setSphere(float radius);
|
||||||
void setEllipsoid(const glm::vec3& halfExtents);
|
void setEllipsoid(const glm::vec3& halfExtents);
|
||||||
|
@ -51,9 +51,6 @@ public:
|
||||||
|
|
||||||
const glm::vec3& getHalfExtents() const { return _halfExtents; }
|
const glm::vec3& getHalfExtents() const { return _halfExtents; }
|
||||||
|
|
||||||
void setData(const QVector<glm::vec3>* data) { _externalData = data; }
|
|
||||||
const QVector<glm::vec3>* getData() const { return _externalData; }
|
|
||||||
|
|
||||||
const QVector<glm::vec3>& getPoints() const { return _points; }
|
const QVector<glm::vec3>& getPoints() const { return _points; }
|
||||||
|
|
||||||
void clearPoints () { _points.clear(); }
|
void clearPoints () { _points.clear(); }
|
||||||
|
@ -67,7 +64,6 @@ protected:
|
||||||
ShapeType _type = SHAPE_TYPE_NONE;
|
ShapeType _type = SHAPE_TYPE_NONE;
|
||||||
glm::vec3 _halfExtents = glm::vec3(0.0f);
|
glm::vec3 _halfExtents = glm::vec3(0.0f);
|
||||||
DoubleHashKey _doubleHashKey;
|
DoubleHashKey _doubleHashKey;
|
||||||
const QVector<glm::vec3>* _externalData = NULL;
|
|
||||||
QVector<glm::vec3> _points; // points for convex collision hull
|
QVector<glm::vec3> _points; // points for convex collision hull
|
||||||
QUrl _url; // url for model of convex collision hull
|
QUrl _url; // url for model of convex collision hull
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue