mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 12:28:02 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi
This commit is contained in:
commit
cea9d969e3
8 changed files with 178 additions and 41 deletions
3
interface/resources/images/NoPictureProvided.svg
Normal file
3
interface/resources/images/NoPictureProvided.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="618 289 264 186" width="22pc" height="186pt"><metadata xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:date>2015-06-22 17:35Z</dc:date><!-- Produced by OmniGraffle Professional 5.4.4 --></metadata><defs><font-face font-family="Helvetica" font-size="19" units-per-em="1000" underline-position="-75.683594" underline-thickness="49.316406" slope="0" x-height="522.94922" cap-height="717.28516" ascent="770.01953" descent="-229.98047" font-weight="500"><font-face-src><font-face-name name="Helvetica"/></font-face-src></font-face></defs><g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1"><title>Canvas 1</title><g><title>No info</title><path d="M 620 291 L 879.5 291 L 879.5 473 L 620 473 Z" stroke="#999" stroke-linecap="butt" stroke-linejoin="miter" stroke-width="1" stroke-dasharray="4,4"/><text transform="translate(625 370.5)" fill="#ccc"><tspan font-family="Helvetica" font-size="19" font-weight="500" fill="#ccc" x="40.265863" y="19" textLength="174.24707">No Picture Provided </tspan></text></g></g></svg>
|
After Width: | Height: | Size: 1.2 KiB |
3
interface/resources/images/header_sep.svg
Normal file
3
interface/resources/images/header_sep.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="624 233 250 8" width="250pt" height="8pt"><metadata xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:date>2015-06-22 17:35Z</dc:date><!-- Produced by OmniGraffle Professional 5.4.4 --></metadata><defs></defs><g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1"><title>Canvas 1</title><g><title>No info</title><line x1="627" y1="236.4375" x2="871" y2="236.4375" stroke="white" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/></g></g></svg>
|
After Width: | Height: | Size: 715 B |
3
interface/resources/images/tooltip_container.svg
Normal file
3
interface/resources/images/tooltip_container.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="594 183 323 423" width="323pt" height="423pt"><metadata xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:date>2015-06-22 17:35Z</dc:date><!-- Produced by OmniGraffle Professional 5.4.4 --></metadata><defs></defs><g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1"><title>Canvas 1</title><g><title>Info</title><path d="M 603 183 L 908 183 C 912.97056 183 917 187.02944 917 192 L 917 597 C 917 601.97056 912.97056 606 908 606 L 603 606 C 598.02944 606 594 601.97056 594 597 L 594 192 C 594 187.02944 598.02944 183 603 183 Z" fill="#333" fill-opacity=".67"/></g></g></svg>
|
After Width: | Height: | Size: 830 B |
|
@ -1,31 +1,76 @@
|
||||||
import Hifi 1.0 as Hifi
|
import Hifi 1.0 as Hifi
|
||||||
import QtQuick 2.3 as Original
|
import QtQuick 2.4
|
||||||
|
import QtQuick.Layouts 1.1
|
||||||
import "controls"
|
import "controls"
|
||||||
import "styles"
|
import "styles"
|
||||||
|
|
||||||
Hifi.Tooltip {
|
Hifi.Tooltip {
|
||||||
id: root
|
id: root
|
||||||
HifiConstants { id: hifi }
|
HifiConstants { id: hifi }
|
||||||
// FIXME adjust position based on the edges of the screen
|
x: lastMousePosition.x + offsetX
|
||||||
x: (lastMousePosition.x > surfaceSize.width/2) ? lastMousePosition.x - 140 : lastMousePosition.x + 20
|
y: lastMousePosition.y + offsetY
|
||||||
//y: lastMousePosition.y + 5
|
property int offsetX: 0
|
||||||
y: (lastMousePosition.y > surfaceSize.height/2) ? lastMousePosition.y - 70 : lastMousePosition.y + 5
|
property int offsetY: 0
|
||||||
implicitWidth: border.implicitWidth
|
width: border.width
|
||||||
implicitHeight: border.implicitHeight
|
height: border.height
|
||||||
|
|
||||||
Border {
|
Component.onCompleted: {
|
||||||
|
offsetX = (lastMousePosition.x > surfaceSize.width/2) ? -root.width : 0
|
||||||
|
offsetY = (lastMousePosition.y > surfaceSize.height/2) ? -root.height : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
id: border
|
id: border
|
||||||
anchors.fill: parent
|
color: "#7f000000"
|
||||||
implicitWidth: text.implicitWidth
|
width: 322
|
||||||
implicitHeight: Math.max(text.implicitHeight, 64)
|
height: col.height + hifi.layout.spacing * 2
|
||||||
|
|
||||||
Text {
|
Column {
|
||||||
id: text
|
id: col
|
||||||
anchors.fill: parent
|
x: hifi.layout.spacing
|
||||||
anchors.margins: 16
|
y: hifi.layout.spacing
|
||||||
font.pixelSize: hifi.fonts.pixelSize / 2
|
anchors.left: parent.left
|
||||||
text: root.text
|
anchors.leftMargin: hifi.layout.spacing
|
||||||
wrapMode: Original.Text.WordWrap
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: hifi.layout.spacing
|
||||||
|
spacing: 5
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: textPlace
|
||||||
|
color: "white"
|
||||||
|
font.underline: true
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
font.pixelSize: hifi.fonts.pixelSize / 2
|
||||||
|
text: root.text
|
||||||
|
wrapMode: Text.WrapAnywhere
|
||||||
|
|
||||||
|
/* Uncomment for debugging to see the extent of the
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
color: "#7fff00ff"
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: tooltipPic
|
||||||
|
source: "../images/NoPictureProvided.svg"
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
verticalAlignment: Image.AlignVCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: textDescription
|
||||||
|
color: "white"
|
||||||
|
width: border.implicitWidth
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
font.pixelSize: hifi.fonts.pixelSize / 2
|
||||||
|
text: root.text
|
||||||
|
wrapMode: Text.WrapAnywhere
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2496,24 +2496,45 @@ void Application::update(float deltaTime) {
|
||||||
|
|
||||||
_entitySimulation.lock();
|
_entitySimulation.lock();
|
||||||
_physicsEngine.deleteObjects(_entitySimulation.getObjectsToDelete());
|
_physicsEngine.deleteObjects(_entitySimulation.getObjectsToDelete());
|
||||||
|
_entitySimulation.unlock();
|
||||||
|
|
||||||
|
_entities.getTree()->lockForWrite();
|
||||||
|
_entitySimulation.lock();
|
||||||
_physicsEngine.addObjects(_entitySimulation.getObjectsToAdd());
|
_physicsEngine.addObjects(_entitySimulation.getObjectsToAdd());
|
||||||
|
_entitySimulation.unlock();
|
||||||
|
_entities.getTree()->unlock();
|
||||||
|
|
||||||
|
_entities.getTree()->lockForWrite();
|
||||||
|
_entitySimulation.lock();
|
||||||
_physicsEngine.changeObjects(_entitySimulation.getObjectsToChange());
|
_physicsEngine.changeObjects(_entitySimulation.getObjectsToChange());
|
||||||
|
_entitySimulation.unlock();
|
||||||
|
_entities.getTree()->unlock();
|
||||||
|
|
||||||
|
_entitySimulation.lock();
|
||||||
_entitySimulation.applyActionChanges();
|
_entitySimulation.applyActionChanges();
|
||||||
_entitySimulation.unlock();
|
_entitySimulation.unlock();
|
||||||
|
|
||||||
|
|
||||||
AvatarManager* avatarManager = DependencyManager::get<AvatarManager>().data();
|
AvatarManager* avatarManager = DependencyManager::get<AvatarManager>().data();
|
||||||
_physicsEngine.deleteObjects(avatarManager->getObjectsToDelete());
|
_physicsEngine.deleteObjects(avatarManager->getObjectsToDelete());
|
||||||
_physicsEngine.addObjects(avatarManager->getObjectsToAdd());
|
_physicsEngine.addObjects(avatarManager->getObjectsToAdd());
|
||||||
_physicsEngine.changeObjects(avatarManager->getObjectsToChange());
|
_physicsEngine.changeObjects(avatarManager->getObjectsToChange());
|
||||||
|
|
||||||
|
_entities.getTree()->lockForWrite();
|
||||||
_physicsEngine.stepSimulation();
|
_physicsEngine.stepSimulation();
|
||||||
|
_entities.getTree()->unlock();
|
||||||
|
|
||||||
if (_physicsEngine.hasOutgoingChanges()) {
|
if (_physicsEngine.hasOutgoingChanges()) {
|
||||||
|
_entities.getTree()->lockForWrite();
|
||||||
_entitySimulation.lock();
|
_entitySimulation.lock();
|
||||||
_entitySimulation.handleOutgoingChanges(_physicsEngine.getOutgoingChanges(), _physicsEngine.getSessionID());
|
_entitySimulation.handleOutgoingChanges(_physicsEngine.getOutgoingChanges(), _physicsEngine.getSessionID());
|
||||||
_entitySimulation.unlock();
|
_entitySimulation.unlock();
|
||||||
|
_entities.getTree()->unlock();
|
||||||
|
|
||||||
|
_entities.getTree()->lockForWrite();
|
||||||
avatarManager->handleOutgoingChanges(_physicsEngine.getOutgoingChanges());
|
avatarManager->handleOutgoingChanges(_physicsEngine.getOutgoingChanges());
|
||||||
|
_entities.getTree()->unlock();
|
||||||
|
|
||||||
auto collisionEvents = _physicsEngine.getCollisionEvents();
|
auto collisionEvents = _physicsEngine.getCollisionEvents();
|
||||||
avatarManager->handleCollisionEvents(collisionEvents);
|
avatarManager->handleCollisionEvents(collisionEvents);
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#include "RenderableLineEntityItem.h"
|
#include "RenderableLineEntityItem.h"
|
||||||
#include "RenderablePolyVoxEntityItem.h"
|
#include "RenderablePolyVoxEntityItem.h"
|
||||||
#include "EntitiesRendererLogging.h"
|
#include "EntitiesRendererLogging.h"
|
||||||
|
#include "AddressManager.h"
|
||||||
|
|
||||||
EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState,
|
EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState,
|
||||||
AbstractScriptingServicesInterface* scriptingServices) :
|
AbstractScriptingServicesInterface* scriptingServices) :
|
||||||
|
@ -836,6 +837,14 @@ void EntityTreeRenderer::mousePressEvent(QMouseEvent* event, unsigned int device
|
||||||
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking);
|
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking);
|
||||||
if (rayPickResult.intersects) {
|
if (rayPickResult.intersects) {
|
||||||
//qCDebug(entitiesrenderer) << "mousePressEvent over entity:" << rayPickResult.entityID;
|
//qCDebug(entitiesrenderer) << "mousePressEvent over entity:" << rayPickResult.entityID;
|
||||||
|
|
||||||
|
QString urlString = rayPickResult.properties.getHref();
|
||||||
|
QUrl url = QUrl(urlString, QUrl::StrictMode);
|
||||||
|
if (url.isValid() && !url.isEmpty()){
|
||||||
|
DependencyManager::get<AddressManager>()->handleLookupString(urlString);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
emit mousePressOnEntity(rayPickResult, event, deviceID);
|
emit mousePressOnEntity(rayPickResult, event, deviceID);
|
||||||
|
|
||||||
QScriptValueList entityScriptArgs = createMouseEventArgs(rayPickResult.entityID, event, deviceID);
|
QScriptValueList entityScriptArgs = createMouseEventArgs(rayPickResult.entityID, event, deviceID);
|
||||||
|
|
|
@ -19,10 +19,42 @@
|
||||||
#include "PhysicsHelpers.h"
|
#include "PhysicsHelpers.h"
|
||||||
#include "PhysicsLogging.h"
|
#include "PhysicsLogging.h"
|
||||||
|
|
||||||
|
#ifdef WANT_DEBUG_ENTITY_TREE_LOCKS
|
||||||
|
#include "EntityTree.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
static const float ACCELERATION_EQUIVALENT_EPSILON_RATIO = 0.1f;
|
static const float ACCELERATION_EQUIVALENT_EPSILON_RATIO = 0.1f;
|
||||||
static const quint8 STEPS_TO_DECIDE_BALLISTIC = 4;
|
static const quint8 STEPS_TO_DECIDE_BALLISTIC = 4;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef WANT_DEBUG_ENTITY_TREE_LOCKS
|
||||||
|
bool EntityMotionState::entityTreeIsLocked() const {
|
||||||
|
EntityTreeElement* element = _entity ? _entity->getElement() : nullptr;
|
||||||
|
EntityTree* tree = element ? element->getTree() : nullptr;
|
||||||
|
if (tree) {
|
||||||
|
bool readSuccess = tree->tryLockForRead();
|
||||||
|
if (readSuccess) {
|
||||||
|
tree->unlock();
|
||||||
|
}
|
||||||
|
bool writeSuccess = tree->tryLockForWrite();
|
||||||
|
if (writeSuccess) {
|
||||||
|
tree->unlock();
|
||||||
|
}
|
||||||
|
if (readSuccess && writeSuccess) {
|
||||||
|
return false; // if we can take either kind of lock, there was no tree lock.
|
||||||
|
}
|
||||||
|
return true; // either read or write failed, so there is some lock in place.
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
bool entityTreeIsLocked() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
EntityMotionState::EntityMotionState(btCollisionShape* shape, EntityItemPointer entity) :
|
EntityMotionState::EntityMotionState(btCollisionShape* shape, EntityItemPointer entity) :
|
||||||
ObjectMotionState(shape),
|
ObjectMotionState(shape),
|
||||||
_entity(entity),
|
_entity(entity),
|
||||||
|
@ -42,6 +74,7 @@ EntityMotionState::EntityMotionState(btCollisionShape* shape, EntityItemPointer
|
||||||
{
|
{
|
||||||
_type = MOTIONSTATE_TYPE_ENTITY;
|
_type = MOTIONSTATE_TYPE_ENTITY;
|
||||||
assert(_entity != nullptr);
|
assert(_entity != nullptr);
|
||||||
|
assert(entityTreeIsLocked());
|
||||||
setMass(_entity->computeMass());
|
setMass(_entity->computeMass());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +84,7 @@ EntityMotionState::~EntityMotionState() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityMotionState::updateServerPhysicsVariables() {
|
void EntityMotionState::updateServerPhysicsVariables() {
|
||||||
|
assert(entityTreeIsLocked());
|
||||||
_serverPosition = _entity->getPosition();
|
_serverPosition = _entity->getPosition();
|
||||||
_serverRotation = _entity->getRotation();
|
_serverRotation = _entity->getRotation();
|
||||||
_serverVelocity = _entity->getVelocity();
|
_serverVelocity = _entity->getVelocity();
|
||||||
|
@ -60,6 +94,7 @@ void EntityMotionState::updateServerPhysicsVariables() {
|
||||||
|
|
||||||
// virtual
|
// virtual
|
||||||
void EntityMotionState::handleEasyChanges(uint32_t flags) {
|
void EntityMotionState::handleEasyChanges(uint32_t flags) {
|
||||||
|
assert(entityTreeIsLocked());
|
||||||
updateServerPhysicsVariables();
|
updateServerPhysicsVariables();
|
||||||
ObjectMotionState::handleEasyChanges(flags);
|
ObjectMotionState::handleEasyChanges(flags);
|
||||||
if (flags & EntityItem::DIRTY_SIMULATOR_ID) {
|
if (flags & EntityItem::DIRTY_SIMULATOR_ID) {
|
||||||
|
@ -101,6 +136,7 @@ MotionType EntityMotionState::computeObjectMotionType() const {
|
||||||
if (!_entity) {
|
if (!_entity) {
|
||||||
return MOTION_TYPE_STATIC;
|
return MOTION_TYPE_STATIC;
|
||||||
}
|
}
|
||||||
|
assert(entityTreeIsLocked());
|
||||||
if (_entity->getCollisionsWillMove()) {
|
if (_entity->getCollisionsWillMove()) {
|
||||||
return MOTION_TYPE_DYNAMIC;
|
return MOTION_TYPE_DYNAMIC;
|
||||||
}
|
}
|
||||||
|
@ -108,6 +144,7 @@ MotionType EntityMotionState::computeObjectMotionType() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityMotionState::isMoving() const {
|
bool EntityMotionState::isMoving() const {
|
||||||
|
assert(entityTreeIsLocked());
|
||||||
return _entity && _entity->isMoving();
|
return _entity && _entity->isMoving();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,6 +157,7 @@ void EntityMotionState::getWorldTransform(btTransform& worldTrans) const {
|
||||||
if (!_entity) {
|
if (!_entity) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
assert(entityTreeIsLocked());
|
||||||
if (_motionType == MOTION_TYPE_KINEMATIC) {
|
if (_motionType == MOTION_TYPE_KINEMATIC) {
|
||||||
// This is physical kinematic motion which steps strictly by the subframe count
|
// This is physical kinematic motion which steps strictly by the subframe count
|
||||||
// of the physics simulation.
|
// of the physics simulation.
|
||||||
|
@ -140,6 +178,7 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) {
|
||||||
if (!_entity) {
|
if (!_entity) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
assert(entityTreeIsLocked());
|
||||||
measureBodyAcceleration();
|
measureBodyAcceleration();
|
||||||
_entity->setPosition(bulletToGLM(worldTrans.getOrigin()) + ObjectMotionState::getWorldOffset());
|
_entity->setPosition(bulletToGLM(worldTrans.getOrigin()) + ObjectMotionState::getWorldOffset());
|
||||||
_entity->setRotation(bulletToGLM(worldTrans.getRotation()));
|
_entity->setRotation(bulletToGLM(worldTrans.getRotation()));
|
||||||
|
@ -164,9 +203,12 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) {
|
||||||
#ifdef WANT_DEBUG
|
#ifdef WANT_DEBUG
|
||||||
quint64 now = usecTimestampNow();
|
quint64 now = usecTimestampNow();
|
||||||
qCDebug(physics) << "EntityMotionState::setWorldTransform()... changed entity:" << _entity->getEntityItemID();
|
qCDebug(physics) << "EntityMotionState::setWorldTransform()... changed entity:" << _entity->getEntityItemID();
|
||||||
qCDebug(physics) << " last edited:" << _entity->getLastEdited() << formatUsecTime(now - _entity->getLastEdited()) << "ago";
|
qCDebug(physics) << " last edited:" << _entity->getLastEdited()
|
||||||
qCDebug(physics) << " last simulated:" << _entity->getLastSimulated() << formatUsecTime(now - _entity->getLastSimulated()) << "ago";
|
<< formatUsecTime(now - _entity->getLastEdited()) << "ago";
|
||||||
qCDebug(physics) << " last updated:" << _entity->getLastUpdated() << formatUsecTime(now - _entity->getLastUpdated()) << "ago";
|
qCDebug(physics) << " last simulated:" << _entity->getLastSimulated()
|
||||||
|
<< formatUsecTime(now - _entity->getLastSimulated()) << "ago";
|
||||||
|
qCDebug(physics) << " last updated:" << _entity->getLastUpdated()
|
||||||
|
<< formatUsecTime(now - _entity->getLastUpdated()) << "ago";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,16 +216,18 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) {
|
||||||
btCollisionShape* EntityMotionState::computeNewShape() {
|
btCollisionShape* EntityMotionState::computeNewShape() {
|
||||||
if (_entity) {
|
if (_entity) {
|
||||||
ShapeInfo shapeInfo;
|
ShapeInfo shapeInfo;
|
||||||
|
assert(entityTreeIsLocked());
|
||||||
_entity->computeShapeInfo(shapeInfo);
|
_entity->computeShapeInfo(shapeInfo);
|
||||||
return getShapeManager()->getShape(shapeInfo);
|
return getShapeManager()->getShape(shapeInfo);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityMotionState::isCandidateForOwnership(const QUuid& sessionID) const {
|
bool EntityMotionState::isCandidateForOwnership(const QUuid& sessionID) const {
|
||||||
if (!_body || !_entity) {
|
if (!_body || !_entity) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
assert(entityTreeIsLocked());
|
||||||
return _candidateForOwnership || sessionID == _entity->getSimulatorID();
|
return _candidateForOwnership || sessionID == _entity->getSimulatorID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,7 +244,7 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
||||||
_sentActive = false;
|
_sentActive = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WANT_DEBUG
|
#ifdef WANT_DEBUG
|
||||||
glm::vec3 wasPosition = _serverPosition;
|
glm::vec3 wasPosition = _serverPosition;
|
||||||
glm::quat wasRotation = _serverRotation;
|
glm::quat wasRotation = _serverRotation;
|
||||||
|
@ -213,7 +257,7 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
||||||
const float INACTIVE_UPDATE_PERIOD = 0.5f;
|
const float INACTIVE_UPDATE_PERIOD = 0.5f;
|
||||||
if (!_sentActive) {
|
if (!_sentActive) {
|
||||||
// we resend the inactive update every INACTIVE_UPDATE_PERIOD
|
// we resend the inactive update every INACTIVE_UPDATE_PERIOD
|
||||||
// until it is removed from the outgoing updates
|
// until it is removed from the outgoing updates
|
||||||
// (which happens when we don't own the simulation and it isn't touching our simulation)
|
// (which happens when we don't own the simulation and it isn't touching our simulation)
|
||||||
return (dt > INACTIVE_UPDATE_PERIOD);
|
return (dt > INACTIVE_UPDATE_PERIOD);
|
||||||
}
|
}
|
||||||
|
@ -231,10 +275,10 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
||||||
_serverPosition += dt * _serverVelocity;
|
_serverPosition += dt * _serverVelocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Else we measure the error between current and extrapolated transform (according to expected behavior
|
// Else we measure the error between current and extrapolated transform (according to expected behavior
|
||||||
// of remote EntitySimulation) and return true if the error is significant.
|
// of remote EntitySimulation) and return true if the error is significant.
|
||||||
|
|
||||||
// NOTE: math is done in the simulation-frame, which is NOT necessarily the same as the world-frame
|
// NOTE: math is done in the simulation-frame, which is NOT necessarily the same as the world-frame
|
||||||
// due to _worldOffset.
|
// due to _worldOffset.
|
||||||
// TODO: compensate for _worldOffset offset here
|
// TODO: compensate for _worldOffset offset here
|
||||||
|
|
||||||
|
@ -242,7 +286,7 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
||||||
|
|
||||||
btTransform worldTrans = _body->getWorldTransform();
|
btTransform worldTrans = _body->getWorldTransform();
|
||||||
glm::vec3 position = bulletToGLM(worldTrans.getOrigin());
|
glm::vec3 position = bulletToGLM(worldTrans.getOrigin());
|
||||||
|
|
||||||
float dx2 = glm::distance2(position, _serverPosition);
|
float dx2 = glm::distance2(position, _serverPosition);
|
||||||
|
|
||||||
const float MAX_POSITION_ERROR_SQUARED = 0.000004f; // Sqrt() - corresponds to 2 millimeters
|
const float MAX_POSITION_ERROR_SQUARED = 0.000004f; // Sqrt() - corresponds to 2 millimeters
|
||||||
|
@ -258,13 +302,13 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (glm::length2(_serverAngularVelocity) > 0.0f) {
|
if (glm::length2(_serverAngularVelocity) > 0.0f) {
|
||||||
// compute rotation error
|
// compute rotation error
|
||||||
float attenuation = powf(1.0f - _body->getAngularDamping(), dt);
|
float attenuation = powf(1.0f - _body->getAngularDamping(), dt);
|
||||||
_serverAngularVelocity *= attenuation;
|
_serverAngularVelocity *= attenuation;
|
||||||
|
|
||||||
// Bullet caps the effective rotation velocity inside its rotation integration step, therefore
|
// Bullet caps the effective rotation velocity inside its rotation integration step, therefore
|
||||||
// we must integrate with the same algorithm and timestep in order achieve similar results.
|
// we must integrate with the same algorithm and timestep in order achieve similar results.
|
||||||
for (int i = 0; i < numSteps; ++i) {
|
for (int i = 0; i < numSteps; ++i) {
|
||||||
_serverRotation = glm::normalize(computeBulletRotationStep(_serverAngularVelocity, PHYSICS_ENGINE_FIXED_SUBSTEP) * _serverRotation);
|
_serverRotation = glm::normalize(computeBulletRotationStep(_serverAngularVelocity, PHYSICS_ENGINE_FIXED_SUBSTEP) * _serverRotation);
|
||||||
|
@ -276,7 +320,7 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
||||||
#ifdef WANT_DEBUG
|
#ifdef WANT_DEBUG
|
||||||
if ((fabsf(glm::dot(actualRotation, _serverRotation)) < MIN_ROTATION_DOT)) {
|
if ((fabsf(glm::dot(actualRotation, _serverRotation)) < MIN_ROTATION_DOT)) {
|
||||||
qCDebug(physics) << ".... ((fabsf(glm::dot(actualRotation, _serverRotation)) < MIN_ROTATION_DOT)) ....";
|
qCDebug(physics) << ".... ((fabsf(glm::dot(actualRotation, _serverRotation)) < MIN_ROTATION_DOT)) ....";
|
||||||
|
|
||||||
qCDebug(physics) << "wasAngularVelocity:" << wasAngularVelocity;
|
qCDebug(physics) << "wasAngularVelocity:" << wasAngularVelocity;
|
||||||
qCDebug(physics) << "_serverAngularVelocity:" << _serverAngularVelocity;
|
qCDebug(physics) << "_serverAngularVelocity:" << _serverAngularVelocity;
|
||||||
|
|
||||||
|
@ -293,10 +337,11 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep, const QUuid& sessionID) {
|
bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep, const QUuid& sessionID) {
|
||||||
// NOTE: we expect _entity and _body to be valid in this context, since shouldSendUpdate() is only called
|
// NOTE: we expect _entity and _body to be valid in this context, since shouldSendUpdate() is only called
|
||||||
// after doesNotNeedToSendUpdate() returns false and that call should return 'true' if _entity or _body are NULL.
|
// after doesNotNeedToSendUpdate() returns false and that call should return 'true' if _entity or _body are NULL.
|
||||||
assert(_entity);
|
assert(_entity);
|
||||||
assert(_body);
|
assert(_body);
|
||||||
|
assert(entityTreeIsLocked());
|
||||||
|
|
||||||
if (!remoteSimulationOutOfSync(simulationStep)) {
|
if (!remoteSimulationOutOfSync(simulationStep)) {
|
||||||
_candidateForOwnership = false;
|
_candidateForOwnership = false;
|
||||||
|
@ -326,6 +371,7 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep, const QUuid& s
|
||||||
|
|
||||||
void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, const QUuid& sessionID, uint32_t step) {
|
void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, const QUuid& sessionID, uint32_t step) {
|
||||||
assert(_entity);
|
assert(_entity);
|
||||||
|
assert(entityTreeIsLocked());
|
||||||
|
|
||||||
bool active = _body->isActive();
|
bool active = _body->isActive();
|
||||||
if (!active) {
|
if (!active) {
|
||||||
|
@ -435,17 +481,18 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, const Q
|
||||||
_lastStep = step;
|
_lastStep = step;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t EntityMotionState::getAndClearIncomingDirtyFlags() {
|
uint32_t EntityMotionState::getAndClearIncomingDirtyFlags() {
|
||||||
|
assert(entityTreeIsLocked());
|
||||||
uint32_t dirtyFlags = 0;
|
uint32_t dirtyFlags = 0;
|
||||||
if (_body && _entity) {
|
if (_body && _entity) {
|
||||||
dirtyFlags = _entity->getDirtyFlags();
|
dirtyFlags = _entity->getDirtyFlags();
|
||||||
_entity->clearDirtyFlags();
|
_entity->clearDirtyFlags();
|
||||||
// we add DIRTY_MOTION_TYPE if the body's motion type disagrees with entity velocity settings
|
// we add DIRTY_MOTION_TYPE if the body's motion type disagrees with entity velocity settings
|
||||||
int bodyFlags = _body->getCollisionFlags();
|
int bodyFlags = _body->getCollisionFlags();
|
||||||
bool isMoving = _entity->isMoving();
|
bool isMoving = _entity->isMoving();
|
||||||
if (((bodyFlags & btCollisionObject::CF_STATIC_OBJECT) && isMoving) ||
|
if (((bodyFlags & btCollisionObject::CF_STATIC_OBJECT) && isMoving) ||
|
||||||
(bodyFlags & btCollisionObject::CF_KINEMATIC_OBJECT && !isMoving)) {
|
(bodyFlags & btCollisionObject::CF_KINEMATIC_OBJECT && !isMoving)) {
|
||||||
dirtyFlags |= EntityItem::DIRTY_MOTION_TYPE;
|
dirtyFlags |= EntityItem::DIRTY_MOTION_TYPE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return dirtyFlags;
|
return dirtyFlags;
|
||||||
|
@ -455,6 +502,7 @@ uint32_t EntityMotionState::getAndClearIncomingDirtyFlags() {
|
||||||
// virtual
|
// virtual
|
||||||
QUuid EntityMotionState::getSimulatorID() const {
|
QUuid EntityMotionState::getSimulatorID() const {
|
||||||
if (_entity) {
|
if (_entity) {
|
||||||
|
assert(entityTreeIsLocked());
|
||||||
return _entity->getSimulatorID();
|
return _entity->getSimulatorID();
|
||||||
}
|
}
|
||||||
return QUuid();
|
return QUuid();
|
||||||
|
@ -469,12 +517,12 @@ void EntityMotionState::bump() {
|
||||||
void EntityMotionState::resetMeasuredBodyAcceleration() {
|
void EntityMotionState::resetMeasuredBodyAcceleration() {
|
||||||
_lastMeasureStep = ObjectMotionState::getWorldSimulationStep();
|
_lastMeasureStep = ObjectMotionState::getWorldSimulationStep();
|
||||||
if (_body) {
|
if (_body) {
|
||||||
_lastVelocity = bulletToGLM(_body->getLinearVelocity());
|
_lastVelocity = bulletToGLM(_body->getLinearVelocity());
|
||||||
} else {
|
} else {
|
||||||
_lastVelocity = glm::vec3(0.0f);
|
_lastVelocity = glm::vec3(0.0f);
|
||||||
}
|
}
|
||||||
_measuredAcceleration = glm::vec3(0.0f);
|
_measuredAcceleration = glm::vec3(0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityMotionState::measureBodyAcceleration() {
|
void EntityMotionState::measureBodyAcceleration() {
|
||||||
// try to manually measure the true acceleration of the object
|
// try to manually measure the true acceleration of the object
|
||||||
|
@ -504,7 +552,7 @@ glm::vec3 EntityMotionState::getObjectLinearVelocityChange() const {
|
||||||
return _measuredAcceleration * _measuredDeltaTime;
|
return _measuredAcceleration * _measuredDeltaTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
// virtual
|
// virtual
|
||||||
void EntityMotionState::setMotionType(MotionType motionType) {
|
void EntityMotionState::setMotionType(MotionType motionType) {
|
||||||
ObjectMotionState::setMotionType(motionType);
|
ObjectMotionState::setMotionType(motionType);
|
||||||
resetMeasuredBodyAcceleration();
|
resetMeasuredBodyAcceleration();
|
||||||
|
@ -514,12 +562,13 @@ void EntityMotionState::setMotionType(MotionType motionType) {
|
||||||
// virtual
|
// virtual
|
||||||
QString EntityMotionState::getName() {
|
QString EntityMotionState::getName() {
|
||||||
if (_entity) {
|
if (_entity) {
|
||||||
|
assert(entityTreeIsLocked());
|
||||||
return _entity->getName();
|
return _entity->getName();
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// virtual
|
// virtual
|
||||||
int16_t EntityMotionState::computeCollisionGroup() {
|
int16_t EntityMotionState::computeCollisionGroup() {
|
||||||
switch (computeObjectMotionType()){
|
switch (computeObjectMotionType()){
|
||||||
case MOTION_TYPE_STATIC:
|
case MOTION_TYPE_STATIC:
|
||||||
|
|
|
@ -83,6 +83,10 @@ public:
|
||||||
friend class PhysicalEntitySimulation;
|
friend class PhysicalEntitySimulation;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
#ifdef WANT_DEBUG_ENTITY_TREE_LOCKS
|
||||||
|
bool entityTreeIsLocked() const;
|
||||||
|
#endif
|
||||||
|
|
||||||
virtual btCollisionShape* computeNewShape();
|
virtual btCollisionShape* computeNewShape();
|
||||||
virtual void clearObjectBackPointer();
|
virtual void clearObjectBackPointer();
|
||||||
virtual void setMotionType(MotionType motionType);
|
virtual void setMotionType(MotionType motionType);
|
||||||
|
|
Loading…
Reference in a new issue