mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
commit
d9a1563396
94 changed files with 1476 additions and 1050 deletions
|
@ -157,7 +157,7 @@ void AvatarMixer::broadcastAvatarData() {
|
|||
++_sumListeners;
|
||||
|
||||
AvatarData& avatar = nodeData->getAvatar();
|
||||
glm::vec3 myPosition = avatar.getPosition();
|
||||
glm::vec3 myPosition = avatar.getClientGlobalPosition();
|
||||
|
||||
// reset the internal state for correct random number distribution
|
||||
distribution.reset();
|
||||
|
@ -290,7 +290,7 @@ void AvatarMixer::broadcastAvatarData() {
|
|||
|
||||
// The full rate distance is the distance at which EVERY update will be sent for this avatar
|
||||
// at twice the full rate distance, there will be a 50% chance of sending this avatar's update
|
||||
glm::vec3 otherPosition = otherAvatar.getPosition();
|
||||
glm::vec3 otherPosition = otherAvatar.getClientGlobalPosition();
|
||||
float distanceToAvatar = glm::length(myPosition - otherPosition);
|
||||
|
||||
// potentially update the max full rate distance for this frame
|
||||
|
|
19
assignment-client/src/entities/AssignmentParentFinder.cpp
Normal file
19
assignment-client/src/entities/AssignmentParentFinder.cpp
Normal file
|
@ -0,0 +1,19 @@
|
|||
//
|
||||
// AssignmentParentFinder.cpp
|
||||
// assignment-client/src/entities
|
||||
//
|
||||
// Created by Seth Alves on 2015-10-22
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "AssignmentParentFinder.h"
|
||||
|
||||
SpatiallyNestableWeakPointer AssignmentParentFinder::find(QUuid parentID) const {
|
||||
SpatiallyNestableWeakPointer parent;
|
||||
// search entities
|
||||
parent = _tree->findEntityByEntityItemID(parentID);
|
||||
return parent;
|
||||
}
|
34
assignment-client/src/entities/AssignmentParentFinder.h
Normal file
34
assignment-client/src/entities/AssignmentParentFinder.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
//
|
||||
// AssignmentParentFinder.h
|
||||
// interface/src/entities
|
||||
//
|
||||
// Created by Seth Alves on 2015-10-21
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_AssignmentParentFinder_h
|
||||
#define hifi_AssignmentParentFinder_h
|
||||
|
||||
#include <memory>
|
||||
#include <QUuid>
|
||||
|
||||
#include <EntityTree.h>
|
||||
#include <SpatialParentFinder.h>
|
||||
|
||||
// This interface is used to turn a QUuid into a pointer to a "parent" -- something that children can
|
||||
// be spatially relative to. At this point, this means either an EntityItem or an Avatar.
|
||||
|
||||
class AssignmentParentFinder : public SpatialParentFinder {
|
||||
public:
|
||||
AssignmentParentFinder(EntityTreePointer tree) : _tree(tree) { }
|
||||
virtual ~AssignmentParentFinder() { }
|
||||
virtual SpatiallyNestableWeakPointer find(QUuid parentID) const;
|
||||
|
||||
protected:
|
||||
EntityTreePointer _tree;
|
||||
};
|
||||
|
||||
#endif // hifi_AssignmentParentFinder_h
|
|
@ -16,6 +16,7 @@
|
|||
#include "EntityServer.h"
|
||||
#include "EntityServerConsts.h"
|
||||
#include "EntityNodeData.h"
|
||||
#include "AssignmentParentFinder.h"
|
||||
|
||||
const char* MODEL_SERVER_NAME = "Entity";
|
||||
const char* MODEL_SERVER_LOGGING_TARGET_NAME = "entity-server";
|
||||
|
@ -60,6 +61,10 @@ OctreePointer EntityServer::createTree() {
|
|||
tree->setSimulation(simpleSimulation);
|
||||
_entitySimulation = simpleSimulation;
|
||||
}
|
||||
|
||||
DependencyManager::registerInheritance<SpatialParentFinder, AssignmentParentFinder>();
|
||||
DependencyManager::set<AssignmentParentFinder>(tree);
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
|
|
|
@ -223,7 +223,9 @@
|
|||
var elDimensionsZ = document.getElementById("property-dim-z");
|
||||
var elResetToNaturalDimensions = document.getElementById("reset-to-natural-dimensions");
|
||||
var elRescaleDimensionsPct = document.getElementById("dimension-rescale-pct");
|
||||
var elRescaleDimensionsButton = document.getElementById("dimension-rescale-button");
|
||||
var elRescaleDimensionsButton = document.getElementById("dimension-rescale-button");
|
||||
|
||||
var elParentID = document.getElementById("property-parent-id");
|
||||
|
||||
var elRegistrationX = document.getElementById("property-reg-x");
|
||||
var elRegistrationY = document.getElementById("property-reg-y");
|
||||
|
@ -453,6 +455,8 @@
|
|||
elDimensionsY.value = properties.dimensions.y.toFixed(2);
|
||||
elDimensionsZ.value = properties.dimensions.z.toFixed(2);
|
||||
|
||||
elParentID.value = properties.parentID;
|
||||
|
||||
elRegistrationX.value = properties.registrationPoint.x.toFixed(2);
|
||||
elRegistrationY.value = properties.registrationPoint.y.toFixed(2);
|
||||
elRegistrationZ.value = properties.registrationPoint.z.toFixed(2);
|
||||
|
@ -666,6 +670,8 @@
|
|||
elDimensionsY.addEventListener('change', dimensionsChangeFunction);
|
||||
elDimensionsZ.addEventListener('change', dimensionsChangeFunction);
|
||||
|
||||
elParentID.addEventListener('change', createEmitTextPropertyUpdateFunction('parentID'));
|
||||
|
||||
var registrationChangeFunction = createEmitVec3PropertyUpdateFunction(
|
||||
'registrationPoint', elRegistrationX, elRegistrationY, elRegistrationZ);
|
||||
elRegistrationX.addEventListener('change', registrationChangeFunction);
|
||||
|
@ -1055,6 +1061,13 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="property">
|
||||
<span class="label" style="float: left; margin-right: 6px">ParentID</span>
|
||||
<div class="value" style="overflow: hidden;">
|
||||
<input type="text" id="property-parent-id">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="property">
|
||||
<div class="label">Registration</div>
|
||||
<div class="value">
|
||||
|
|
|
@ -147,6 +147,8 @@
|
|||
#include "ui/Stats.h"
|
||||
#include "ui/UpdateDialog.h"
|
||||
#include "Util.h"
|
||||
#include "InterfaceParentFinder.h"
|
||||
|
||||
|
||||
|
||||
// ON WIndows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU
|
||||
|
@ -295,6 +297,7 @@ bool setupEssentials(int& argc, char** argv) {
|
|||
DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
|
||||
DependencyManager::registerInheritance<AvatarHashMap, AvatarManager>();
|
||||
DependencyManager::registerInheritance<EntityActionFactoryInterface, InterfaceActionFactory>();
|
||||
DependencyManager::registerInheritance<SpatialParentFinder, InterfaceParentFinder>();
|
||||
|
||||
Setting::init();
|
||||
|
||||
|
@ -343,6 +346,7 @@ bool setupEssentials(int& argc, char** argv) {
|
|||
DependencyManager::set<MessagesClient>();
|
||||
DependencyManager::set<UserInputMapper>();
|
||||
DependencyManager::set<controller::ScriptingInterface, ControllerScriptingInterface>();
|
||||
DependencyManager::set<InterfaceParentFinder>();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1241,7 +1245,7 @@ void Application::paintGL() {
|
|||
* glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)) * hmdRotation);
|
||||
glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix());
|
||||
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
||||
+ glm::vec3(0, _raiseMirror * myAvatar->getScale(), 0)
|
||||
+ glm::vec3(0, _raiseMirror * myAvatar->getAvatarScale(), 0)
|
||||
+ (myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) *
|
||||
glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror
|
||||
+ (myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f))) * hmdOffset);
|
||||
|
@ -1249,7 +1253,7 @@ void Application::paintGL() {
|
|||
_myCamera.setRotation(myAvatar->getWorldAlignedOrientation()
|
||||
* glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
|
||||
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
||||
+ glm::vec3(0, _raiseMirror * myAvatar->getScale(), 0)
|
||||
+ glm::vec3(0, _raiseMirror * myAvatar->getAvatarScale(), 0)
|
||||
+ (myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) *
|
||||
glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
|
||||
}
|
||||
|
@ -3310,7 +3314,7 @@ MyAvatar* Application::getMyAvatar() const {
|
|||
return DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
}
|
||||
|
||||
const glm::vec3& Application::getAvatarPosition() const {
|
||||
glm::vec3 Application::getAvatarPosition() const {
|
||||
return getMyAvatar()->getPosition();
|
||||
}
|
||||
|
||||
|
|
|
@ -185,7 +185,7 @@ public:
|
|||
virtual float getSizeScale() const;
|
||||
virtual int getBoundaryLevelAdjust() const;
|
||||
virtual PickRay computePickRay(float x, float y) const;
|
||||
virtual const glm::vec3& getAvatarPosition() const;
|
||||
virtual glm::vec3 getAvatarPosition() const;
|
||||
virtual void overrideEnvironmentData(const EnvironmentData& newData) { _environment.override(newData); }
|
||||
virtual void endOverrideEnvironmentData() { _environment.endOverride(); }
|
||||
virtual qreal getDevicePixelRatio();
|
||||
|
|
37
interface/src/InterfaceParentFinder.cpp
Normal file
37
interface/src/InterfaceParentFinder.cpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// InterfaceParentFinder.cpp
|
||||
// interface/src/
|
||||
//
|
||||
// Created by Seth Alves on 2015-10-21
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <Application.h>
|
||||
#include <EntityTree.h>
|
||||
#include <EntityTreeRenderer.h>
|
||||
#include <avatar/AvatarManager.h>
|
||||
|
||||
#include "InterfaceParentFinder.h"
|
||||
|
||||
SpatiallyNestableWeakPointer InterfaceParentFinder::find(QUuid parentID) const {
|
||||
SpatiallyNestableWeakPointer parent;
|
||||
|
||||
if (parentID.isNull()) {
|
||||
return parent;
|
||||
}
|
||||
|
||||
// search entities
|
||||
EntityTreeRenderer* treeRenderer = qApp->getEntities();
|
||||
EntityTreePointer tree = treeRenderer->getTree();
|
||||
parent = tree->findEntityByEntityItemID(parentID);
|
||||
if (!parent.expired()) {
|
||||
return parent;
|
||||
}
|
||||
|
||||
// search avatars
|
||||
QSharedPointer<AvatarManager> avatarManager = DependencyManager::get<AvatarManager>();
|
||||
return avatarManager->getAvatarBySessionID(parentID);
|
||||
}
|
27
interface/src/InterfaceParentFinder.h
Normal file
27
interface/src/InterfaceParentFinder.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
//
|
||||
// InterfaceParentFinder.h
|
||||
// interface/src/
|
||||
//
|
||||
// Created by Seth Alves on 2015-10-21
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_InterfaceParentFinder_h
|
||||
#define hifi_InterfaceParentFinder_h
|
||||
|
||||
#include <memory>
|
||||
#include <QUuid>
|
||||
|
||||
#include <SpatialParentFinder.h>
|
||||
|
||||
class InterfaceParentFinder : public SpatialParentFinder {
|
||||
public:
|
||||
InterfaceParentFinder() { }
|
||||
virtual ~InterfaceParentFinder() { }
|
||||
virtual SpatiallyNestableWeakPointer find(QUuid parentID) const;
|
||||
};
|
||||
|
||||
#endif // hifi_InterfaceParentFinder_h
|
|
@ -38,7 +38,6 @@
|
|||
#include "Hand.h"
|
||||
#include "Head.h"
|
||||
#include "Menu.h"
|
||||
#include "ModelReferential.h"
|
||||
#include "Physics.h"
|
||||
#include "Util.h"
|
||||
#include "world.h"
|
||||
|
@ -91,7 +90,6 @@ Avatar::Avatar(RigPointer rig) :
|
|||
_angularAcceleration(0.0f),
|
||||
_lastOrientation(),
|
||||
_leanScale(0.5f),
|
||||
_scale(1.0f),
|
||||
_worldUpDirection(DEFAULT_UP_DIRECTION),
|
||||
_moving(false),
|
||||
_initialized(false),
|
||||
|
@ -101,6 +99,7 @@ Avatar::Avatar(RigPointer rig) :
|
|||
// we may have been created in the network thread, but we live in the main thread
|
||||
moveToThread(qApp->thread());
|
||||
|
||||
setAvatarScale(1.0f);
|
||||
// give the pointer to our head to inherited _headData variable from AvatarData
|
||||
_headData = static_cast<HeadData*>(new Head(this));
|
||||
_handData = static_cast<HandData*>(new Hand(this));
|
||||
|
@ -125,12 +124,12 @@ void Avatar::init() {
|
|||
glm::vec3 Avatar::getChestPosition() const {
|
||||
// for now, let's just assume that the "chest" is halfway between the root and the neck
|
||||
glm::vec3 neckPosition;
|
||||
return _skeletonModel.getNeckPosition(neckPosition) ? (_position + neckPosition) * 0.5f : _position;
|
||||
return _skeletonModel.getNeckPosition(neckPosition) ? (getPosition() + neckPosition) * 0.5f : getPosition();
|
||||
}
|
||||
|
||||
glm::vec3 Avatar::getNeckPosition() const {
|
||||
glm::vec3 neckPosition;
|
||||
return _skeletonModel.getNeckPosition(neckPosition) ? neckPosition : _position;
|
||||
return _skeletonModel.getNeckPosition(neckPosition) ? neckPosition : getPosition();
|
||||
}
|
||||
|
||||
|
||||
|
@ -144,38 +143,14 @@ AABox Avatar::getBounds() const {
|
|||
|
||||
float Avatar::getLODDistance() const {
|
||||
return DependencyManager::get<LODManager>()->getAvatarLODDistanceMultiplier() *
|
||||
glm::distance(qApp->getCamera()->getPosition(), _position) / _scale;
|
||||
glm::distance(qApp->getCamera()->getPosition(), getPosition()) / getAvatarScale();
|
||||
}
|
||||
|
||||
void Avatar::simulate(float deltaTime) {
|
||||
PerformanceTimer perfTimer("simulate");
|
||||
|
||||
// update the avatar's position according to its referential
|
||||
if (_referential) {
|
||||
if (_referential->hasExtraData()) {
|
||||
EntityTreePointer tree = qApp->getEntities()->getTree();
|
||||
switch (_referential->type()) {
|
||||
case Referential::MODEL:
|
||||
_referential = new ModelReferential(_referential,
|
||||
tree,
|
||||
this);
|
||||
break;
|
||||
case Referential::JOINT:
|
||||
_referential = new JointReferential(_referential,
|
||||
tree,
|
||||
this);
|
||||
break;
|
||||
default:
|
||||
qCDebug(interfaceapp) << "[WARNING] Avatar::simulate(): Unknown referential type.";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_referential->update();
|
||||
}
|
||||
|
||||
if (_scale != _targetScale) {
|
||||
setScale(_targetScale);
|
||||
if (getAvatarScale() != _targetScale) {
|
||||
setAvatarScale(_targetScale);
|
||||
}
|
||||
|
||||
// update the billboard render flag
|
||||
|
@ -193,7 +168,7 @@ void Avatar::simulate(float deltaTime) {
|
|||
const bool isControllerLogging = DependencyManager::get<AvatarManager>()->getRenderDistanceControllerIsLogging();
|
||||
float renderDistance = DependencyManager::get<AvatarManager>()->getRenderDistance();
|
||||
const float SKIP_HYSTERESIS_PROPORTION = isControllerLogging ? 0.0f : BILLBOARD_HYSTERESIS_PROPORTION;
|
||||
float distance = glm::distance(qApp->getCamera()->getPosition(), _position);
|
||||
float distance = glm::distance(qApp->getCamera()->getPosition(), getPosition());
|
||||
if (_shouldSkipRender) {
|
||||
if (distance < renderDistance * (1.0f - SKIP_HYSTERESIS_PROPORTION)) {
|
||||
_shouldSkipRender = false;
|
||||
|
@ -212,7 +187,7 @@ void Avatar::simulate(float deltaTime) {
|
|||
|
||||
// simple frustum check
|
||||
float boundingRadius = getBillboardSize();
|
||||
bool inViewFrustum = qApp->getViewFrustum()->sphereInFrustum(_position, boundingRadius) !=
|
||||
bool inViewFrustum = qApp->getViewFrustum()->sphereInFrustum(getPosition(), boundingRadius) !=
|
||||
ViewFrustum::OUTSIDE;
|
||||
|
||||
{
|
||||
|
@ -231,11 +206,11 @@ void Avatar::simulate(float deltaTime) {
|
|||
}
|
||||
{
|
||||
PerformanceTimer perfTimer("head");
|
||||
glm::vec3 headPosition = _position;
|
||||
glm::vec3 headPosition = getPosition();
|
||||
_skeletonModel.getHeadPosition(headPosition);
|
||||
Head* head = getHead();
|
||||
head->setPosition(headPosition);
|
||||
head->setScale(_scale);
|
||||
head->setScale(getAvatarScale());
|
||||
head->simulate(deltaTime, false, _shouldRenderBillboard);
|
||||
}
|
||||
}
|
||||
|
@ -268,7 +243,7 @@ bool Avatar::isLookingAtMe(AvatarSharedPointer avatar) {
|
|||
glm::vec3 theirLookAt = dynamic_pointer_cast<Avatar>(avatar)->getHead()->getLookAtPosition();
|
||||
glm::vec3 myEyePosition = getHead()->getEyePosition();
|
||||
|
||||
return glm::distance(theirLookAt, myEyePosition) <= (HEAD_SPHERE_RADIUS * getScale());
|
||||
return glm::distance(theirLookAt, myEyePosition) <= (HEAD_SPHERE_RADIUS * getAvatarScale());
|
||||
}
|
||||
|
||||
void Avatar::slamPosition(const glm::vec3& newPosition) {
|
||||
|
@ -279,7 +254,7 @@ void Avatar::slamPosition(const glm::vec3& newPosition) {
|
|||
}
|
||||
|
||||
void Avatar::applyPositionDelta(const glm::vec3& delta) {
|
||||
_position += delta;
|
||||
setPosition(getPosition() + delta);
|
||||
_positionDeltaAccumulator += delta;
|
||||
}
|
||||
|
||||
|
@ -345,15 +320,10 @@ void Avatar::removeFromScene(AvatarSharedPointer self, std::shared_ptr<render::S
|
|||
}
|
||||
|
||||
void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
||||
startRender();
|
||||
if (_referential) {
|
||||
_referential->update();
|
||||
}
|
||||
|
||||
auto& batch = *renderArgs->_batch;
|
||||
PROFILE_RANGE_BATCH(batch, __FUNCTION__);
|
||||
|
||||
if (glm::distance(DependencyManager::get<AvatarManager>()->getMyAvatar()->getPosition(), _position) < 10.0f) {
|
||||
if (glm::distance(DependencyManager::get<AvatarManager>()->getMyAvatar()->getPosition(), getPosition()) < 10.0f) {
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
auto deferredLighting = DependencyManager::get<DeferredLightingEffect>();
|
||||
|
||||
|
@ -453,7 +423,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
|||
const float BASE_LIGHT_DISTANCE = 2.0f;
|
||||
const float LIGHT_EXPONENT = 1.0f;
|
||||
const float LIGHT_CUTOFF = glm::radians(80.0f);
|
||||
float distance = BASE_LIGHT_DISTANCE * _scale;
|
||||
float distance = BASE_LIGHT_DISTANCE * getAvatarScale();
|
||||
glm::vec3 position = glm::mix(_skeletonModel.getTranslation(), getHead()->getFaceModel().getTranslation(), 0.9f);
|
||||
glm::quat orientation = getOrientation();
|
||||
foreach (const AvatarManager::LocalLight& light, DependencyManager::get<AvatarManager>()->getLocalLights()) {
|
||||
|
@ -484,7 +454,8 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
|||
static const float INDICATOR_OFFSET = 0.22f;
|
||||
static const float INDICATOR_RADIUS = 0.03f;
|
||||
static const glm::vec4 LOOK_AT_INDICATOR_COLOR = { 0.8f, 0.0f, 0.0f, 0.75f };
|
||||
glm::vec3 position = glm::vec3(_position.x, getDisplayNamePosition().y + INDICATOR_OFFSET, _position.z);
|
||||
glm::vec3 avatarPosition = getPosition();
|
||||
glm::vec3 position = glm::vec3(avatarPosition.x, getDisplayNamePosition().y + INDICATOR_OFFSET, avatarPosition.z);
|
||||
PROFILE_RANGE_BATCH(batch, __FUNCTION__":renderFocusIndicator");
|
||||
Transform transform;
|
||||
transform.setTranslation(position);
|
||||
|
@ -518,7 +489,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
|||
}
|
||||
|
||||
DependencyManager::get<DeferredLightingEffect>()->renderSolidSphereInstance(batch,
|
||||
Transform(transform).postScale(eyeDiameter * _scale / 2.0f + RADIUS_INCREMENT),
|
||||
Transform(transform).postScale(eyeDiameter * getAvatarScale() / 2.0f + RADIUS_INCREMENT),
|
||||
glm::vec4(LOOKING_AT_ME_COLOR, alpha));
|
||||
|
||||
position = getHead()->getRightEyePosition();
|
||||
|
@ -528,7 +499,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
|||
eyeDiameter = DEFAULT_EYE_DIAMETER;
|
||||
}
|
||||
DependencyManager::get<DeferredLightingEffect>()->renderSolidSphereInstance(batch,
|
||||
Transform(transform).postScale(eyeDiameter * _scale / 2.0f + RADIUS_INCREMENT),
|
||||
Transform(transform).postScale(eyeDiameter * getAvatarScale() / 2.0f + RADIUS_INCREMENT),
|
||||
glm::vec4(LOOKING_AT_ME_COLOR, alpha));
|
||||
|
||||
}
|
||||
|
@ -559,7 +530,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
|||
|
||||
|
||||
Transform transform;
|
||||
transform.setTranslation(_position);
|
||||
transform.setTranslation(getPosition());
|
||||
transform.setScale(height);
|
||||
transform.postScale(sphereRadius);
|
||||
DependencyManager::get<DeferredLightingEffect>()->renderSolidSphereInstance(batch,
|
||||
|
@ -662,9 +633,9 @@ void Avatar::simulateAttachments(float deltaTime) {
|
|||
glm::quat jointRotation;
|
||||
if (_skeletonModel.getJointPositionInWorldFrame(jointIndex, jointPosition) &&
|
||||
_skeletonModel.getJointRotationInWorldFrame(jointIndex, jointRotation)) {
|
||||
model->setTranslation(jointPosition + jointRotation * attachment.translation * _scale);
|
||||
model->setTranslation(jointPosition + jointRotation * attachment.translation * getAvatarScale());
|
||||
model->setRotation(jointRotation * attachment.rotation);
|
||||
model->setScaleToFit(true, _scale * attachment.scale, true); // hack to force rescale
|
||||
model->setScaleToFit(true, getAvatarScale() * attachment.scale, true); // hack to force rescale
|
||||
model->setSnapModelToCenter(false); // hack to force resnap
|
||||
model->setSnapModelToCenter(true);
|
||||
model->simulate(deltaTime);
|
||||
|
@ -694,14 +665,14 @@ void Avatar::renderBillboard(RenderArgs* renderArgs) {
|
|||
}
|
||||
// rotate about vertical to face the camera
|
||||
glm::quat rotation = getOrientation();
|
||||
glm::vec3 cameraVector = glm::inverse(rotation) * (qApp->getCamera()->getPosition() - _position);
|
||||
glm::vec3 cameraVector = glm::inverse(rotation) * (qApp->getCamera()->getPosition() - getPosition());
|
||||
rotation = rotation * glm::angleAxis(atan2f(-cameraVector.x, -cameraVector.z), glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
|
||||
// compute the size from the billboard camera parameters and scale
|
||||
float size = getBillboardSize();
|
||||
|
||||
Transform transform;
|
||||
transform.setTranslation(_position);
|
||||
transform.setTranslation(getPosition());
|
||||
transform.setRotation(rotation);
|
||||
transform.setScale(size);
|
||||
|
||||
|
@ -719,7 +690,7 @@ void Avatar::renderBillboard(RenderArgs* renderArgs) {
|
|||
}
|
||||
|
||||
float Avatar::getBillboardSize() const {
|
||||
return _scale * BILLBOARD_DISTANCE * glm::tan(glm::radians(BILLBOARD_FIELD_OF_VIEW / 2.0f));
|
||||
return getAvatarScale() * BILLBOARD_DISTANCE * glm::tan(glm::radians(BILLBOARD_FIELD_OF_VIEW / 2.0f));
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -754,9 +725,9 @@ glm::vec3 Avatar::getDisplayNamePosition() const {
|
|||
const float HEAD_PROPORTION = 0.75f;
|
||||
float billboardSize = getBillboardSize();
|
||||
|
||||
DEBUG_VALUE("_position =", _position);
|
||||
DEBUG_VALUE("_position =", getPosition());
|
||||
DEBUG_VALUE("billboardSize =", billboardSize);
|
||||
namePosition = _position + bodyUpDirection * (billboardSize * HEAD_PROPORTION);
|
||||
namePosition = getPosition() + bodyUpDirection * (billboardSize * HEAD_PROPORTION);
|
||||
}
|
||||
|
||||
if (glm::any(glm::isnan(namePosition)) || glm::any(glm::isinf(namePosition))) {
|
||||
|
@ -868,7 +839,7 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum, co
|
|||
}
|
||||
|
||||
void Avatar::setSkeletonOffset(const glm::vec3& offset) {
|
||||
const float MAX_OFFSET_LENGTH = _scale * 0.5f;
|
||||
const float MAX_OFFSET_LENGTH = getAvatarScale() * 0.5f;
|
||||
float offsetLength = glm::length(offset);
|
||||
if (offsetLength > MAX_OFFSET_LENGTH) {
|
||||
_skeletonOffset = (MAX_OFFSET_LENGTH / offsetLength) * offset;
|
||||
|
@ -881,7 +852,7 @@ glm::vec3 Avatar::getSkeletonPosition() const {
|
|||
// The avatar is rotated PI about the yAxis, so we have to correct for it
|
||||
// to get the skeleton offset contribution in the world-frame.
|
||||
const glm::quat FLIP = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
return _position + getOrientation() * FLIP * _skeletonOffset;
|
||||
return getPosition() + getOrientation() * FLIP * _skeletonOffset;
|
||||
}
|
||||
|
||||
QVector<glm::quat> Avatar::getJointRotations() const {
|
||||
|
@ -960,7 +931,7 @@ glm::vec3 Avatar::getJointPosition(const QString& name) const {
|
|||
|
||||
void Avatar::scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const {
|
||||
//Scale a world space vector as if it was relative to the position
|
||||
positionToScale = _position + _scale * (positionToScale - _position);
|
||||
positionToScale = getPosition() + getAvatarScale() * (positionToScale - getPosition());
|
||||
}
|
||||
|
||||
void Avatar::setFaceModelURL(const QUrl& faceModelURL) {
|
||||
|
@ -1000,7 +971,7 @@ void Avatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
|||
for (int i = 0; i < attachmentData.size(); i++) {
|
||||
_attachmentModels[i]->setURL(attachmentData.at(i).modelURL);
|
||||
_attachmentModels[i]->setSnapModelToCenter(true);
|
||||
_attachmentModels[i]->setScaleToFit(true, _scale * _attachmentData.at(i).scale);
|
||||
_attachmentModels[i]->setScaleToFit(true, getAvatarScale() * _attachmentData.at(i).scale);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1019,12 +990,12 @@ int Avatar::parseDataFromBuffer(const QByteArray& buffer) {
|
|||
}
|
||||
|
||||
// change in position implies movement
|
||||
glm::vec3 oldPosition = _position;
|
||||
glm::vec3 oldPosition = getPosition();
|
||||
|
||||
int bytesRead = AvatarData::parseDataFromBuffer(buffer);
|
||||
|
||||
const float MOVE_DISTANCE_THRESHOLD = 0.001f;
|
||||
_moving = glm::distance(oldPosition, _position) > MOVE_DISTANCE_THRESHOLD;
|
||||
_moving = glm::distance(oldPosition, getPosition()) > MOVE_DISTANCE_THRESHOLD;
|
||||
if (_moving && _motionState) {
|
||||
_motionState->addDirtyFlags(Simulation::DIRTY_POSITION);
|
||||
}
|
||||
|
@ -1088,12 +1059,12 @@ void Avatar::renderJointConnectingCone(gpu::Batch& batch, glm::vec3 position1, g
|
|||
}
|
||||
}
|
||||
|
||||
void Avatar::setScale(float scale) {
|
||||
_scale = scale;
|
||||
|
||||
if (_targetScale * (1.0f - RESCALING_TOLERANCE) < _scale &&
|
||||
_scale < _targetScale * (1.0f + RESCALING_TOLERANCE)) {
|
||||
_scale = _targetScale;
|
||||
void Avatar::setAvatarScale(float scale) {
|
||||
if (_targetScale * (1.0f - RESCALING_TOLERANCE) < scale &&
|
||||
scale < _targetScale * (1.0f + RESCALING_TOLERANCE)) {
|
||||
setScale(glm::vec3(_targetScale));
|
||||
} else {
|
||||
setScale(glm::vec3(scale));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1108,7 +1079,7 @@ float Avatar::getHeadHeight() const {
|
|||
|
||||
// HACK: We have a really odd case when fading out for some models where this value explodes
|
||||
float result = extents.maximum.y - extents.minimum.y;
|
||||
if (result >= 0.0f && result < 100.0f * _scale ) {
|
||||
if (result >= 0.0f && result < 100.0f * getAvatarScale() ) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -1116,7 +1087,7 @@ float Avatar::getHeadHeight() const {
|
|||
extents = _skeletonModel.getMeshExtents();
|
||||
glm::vec3 neckPosition;
|
||||
if (!extents.isEmpty() && extents.isValid() && _skeletonModel.getNeckPosition(neckPosition)) {
|
||||
return extents.maximum.y / 2.0f - neckPosition.y + _position.y;
|
||||
return extents.maximum.y / 2.0f - neckPosition.y + getPosition().y;
|
||||
}
|
||||
|
||||
const float DEFAULT_HEAD_HEIGHT = 0.25f;
|
||||
|
@ -1189,3 +1160,13 @@ glm::quat Avatar::getRightPalmRotation() {
|
|||
getSkeletonModel().getJointRotationInWorldFrame(getSkeletonModel().getRightHandJointIndex(), rightRotation);
|
||||
return rightRotation;
|
||||
}
|
||||
|
||||
void Avatar::setPosition(const glm::vec3 position) {
|
||||
AvatarData::setPosition(position);
|
||||
updateAttitude();
|
||||
}
|
||||
|
||||
void Avatar::setOrientation(const glm::quat orientation) {
|
||||
AvatarData::setOrientation(orientation);
|
||||
updateAttitude();
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ public:
|
|||
const SkeletonModel& getSkeletonModel() const { return _skeletonModel; }
|
||||
const QVector<Model*>& getAttachmentModels() const { return _attachmentModels; }
|
||||
glm::vec3 getChestPosition() const;
|
||||
float getScale() const { return _scale; }
|
||||
float getAvatarScale() const { return getScale().y; }
|
||||
const Head* getHead() const { return static_cast<const Head*>(_headData); }
|
||||
Head* getHead() { return static_cast<Head*>(_headData); }
|
||||
Hand* getHand() { return static_cast<Hand*>(_handData); }
|
||||
|
@ -155,6 +155,9 @@ public:
|
|||
void setMotionState(AvatarMotionState* motionState) { _motionState = motionState; }
|
||||
AvatarMotionState* getMotionState() { return _motionState; }
|
||||
|
||||
virtual void setPosition(glm::vec3 position);
|
||||
virtual void setOrientation(glm::quat orientation);
|
||||
|
||||
public slots:
|
||||
|
||||
// FIXME - these should be migrated to use Pose data instead
|
||||
|
@ -186,7 +189,6 @@ protected:
|
|||
glm::quat _lastOrientation;
|
||||
|
||||
float _leanScale;
|
||||
float _scale;
|
||||
glm::vec3 _worldUpDirection;
|
||||
float _stringLength;
|
||||
bool _moving; ///< set when position is changing
|
||||
|
@ -198,7 +200,7 @@ protected:
|
|||
glm::vec3 getBodyUpDirection() const { return getOrientation() * IDENTITY_UP; }
|
||||
glm::vec3 getBodyFrontDirection() const { return getOrientation() * IDENTITY_FRONT; }
|
||||
glm::quat computeRotationFromBodyToWorldUp(float proportion = 1.0f) const;
|
||||
void setScale(float scale);
|
||||
void setAvatarScale(float scale);
|
||||
void measureMotionDerivatives(float deltaTime);
|
||||
|
||||
float getSkeletonHeight() const;
|
||||
|
|
|
@ -198,7 +198,7 @@ void AvatarManager::simulateAvatarFades(float deltaTime) {
|
|||
while (fadingIterator != _avatarFades.end()) {
|
||||
auto avatar = std::static_pointer_cast<Avatar>(*fadingIterator);
|
||||
avatar->startUpdate();
|
||||
avatar->setTargetScale(avatar->getScale() * SHRINK_RATE, true);
|
||||
avatar->setTargetScale(avatar->getAvatarScale() * SHRINK_RATE);
|
||||
if (avatar->getTargetScale() <= MIN_FADE_SCALE) {
|
||||
avatar->removeFromScene(*fadingIterator, scene, pendingChanges);
|
||||
fadingIterator = _avatarFades.erase(fadingIterator);
|
||||
|
|
|
@ -37,7 +37,7 @@ void Hand::simulate(float deltaTime, bool isMine) {
|
|||
void Hand::renderHandTargets(RenderArgs* renderArgs, bool isMine) {
|
||||
float avatarScale = 1.0f;
|
||||
if (_owningAvatar) {
|
||||
avatarScale = _owningAvatar->getScale();
|
||||
avatarScale = _owningAvatar->getAvatarScale();
|
||||
}
|
||||
|
||||
const float alpha = 1.0f;
|
||||
|
|
|
@ -1,192 +0,0 @@
|
|||
//
|
||||
// ModelReferential.cpp
|
||||
//
|
||||
//
|
||||
// Created by Clement on 7/30/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <AvatarData.h>
|
||||
#include <EntityTree.h>
|
||||
#include <Model.h>
|
||||
|
||||
#include "InterfaceLogging.h"
|
||||
#include "ModelReferential.h"
|
||||
|
||||
ModelReferential::ModelReferential(Referential* referential, EntityTreePointer tree, AvatarData* avatar) :
|
||||
Referential(MODEL, avatar),
|
||||
_tree(tree)
|
||||
{
|
||||
_translation = referential->getTranslation();
|
||||
_rotation = referential->getRotation();
|
||||
unpackExtraData(reinterpret_cast<unsigned char*>(referential->getExtraData().data()),
|
||||
referential->getExtraData().size());
|
||||
|
||||
if (!isValid()) {
|
||||
qCDebug(interfaceapp) << "ModelReferential::copyConstructor(): Not Valid";
|
||||
return;
|
||||
}
|
||||
|
||||
EntityItemPointer item = _tree->findEntityByID(_entityID);
|
||||
if (item != NULL) {
|
||||
_lastRefDimension = item->getDimensions();
|
||||
_refRotation = item->getRotation();
|
||||
_refPosition = item->getPosition();
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
ModelReferential::ModelReferential(const QUuid& entityID, EntityTreePointer tree, AvatarData* avatar) :
|
||||
Referential(MODEL, avatar),
|
||||
_entityID(entityID),
|
||||
_tree(tree)
|
||||
{
|
||||
EntityItemPointer item = _tree->findEntityByID(_entityID);
|
||||
if (!isValid() || item == NULL) {
|
||||
qCDebug(interfaceapp) << "ModelReferential::constructor(): Not Valid";
|
||||
_isValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
_lastRefDimension = item->getDimensions();
|
||||
_refRotation = item->getRotation();
|
||||
_refPosition = item->getPosition();
|
||||
|
||||
glm::quat refInvRot = glm::inverse(_refRotation);
|
||||
_rotation = refInvRot * _avatar->getOrientation();
|
||||
_translation = refInvRot * (avatar->getPosition() - _refPosition);
|
||||
}
|
||||
|
||||
void ModelReferential::update() {
|
||||
EntityItemPointer item = _tree->findEntityByID(_entityID);
|
||||
if (!isValid() || item == NULL || _avatar == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool somethingChanged = false;
|
||||
if (item->getDimensions() != _lastRefDimension) {
|
||||
glm::vec3 oldDimension = _lastRefDimension;
|
||||
_lastRefDimension = item->getDimensions();
|
||||
_translation *= _lastRefDimension / oldDimension;
|
||||
somethingChanged = true;
|
||||
}
|
||||
if (item->getRotation() != _refRotation) {
|
||||
_refRotation = item->getRotation();
|
||||
_avatar->setOrientation(_refRotation * _rotation, true);
|
||||
somethingChanged = true;
|
||||
}
|
||||
if (item->getPosition() != _refPosition || somethingChanged) {
|
||||
_refPosition = item->getPosition();
|
||||
_avatar->setPosition(_refPosition + _refRotation * _translation, true);
|
||||
}
|
||||
}
|
||||
|
||||
int ModelReferential::packExtraData(unsigned char* destinationBuffer) const {
|
||||
QByteArray encodedEntityID = _entityID.toRfc4122();
|
||||
memcpy(destinationBuffer, encodedEntityID.constData(), encodedEntityID.size());
|
||||
return encodedEntityID.size();
|
||||
}
|
||||
|
||||
int ModelReferential::unpackExtraData(const unsigned char *sourceBuffer, int size) {
|
||||
QByteArray encodedEntityID((const char*)sourceBuffer, NUM_BYTES_RFC4122_UUID);
|
||||
_entityID = QUuid::fromRfc4122(encodedEntityID);
|
||||
return NUM_BYTES_RFC4122_UUID;
|
||||
}
|
||||
|
||||
JointReferential::JointReferential(Referential* referential, EntityTreePointer tree, AvatarData* avatar) :
|
||||
ModelReferential(referential, tree, avatar)
|
||||
{
|
||||
_type = JOINT;
|
||||
if (!isValid()) {
|
||||
qCDebug(interfaceapp) << "JointReferential::copyConstructor(): Not Valid";
|
||||
return;
|
||||
}
|
||||
|
||||
EntityItemPointer item = _tree->findEntityByID(_entityID);
|
||||
const Model* model = getModel(item);
|
||||
if (isValid() && model != NULL && _jointIndex < (uint32_t)(model->getJointStateCount())) {
|
||||
_lastRefDimension = item->getDimensions();
|
||||
model->getJointRotationInWorldFrame(_jointIndex, _refRotation);
|
||||
model->getJointPositionInWorldFrame(_jointIndex, _refPosition);
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
JointReferential::JointReferential(uint32_t jointIndex, const QUuid& entityID, EntityTreePointer tree, AvatarData* avatar) :
|
||||
ModelReferential(entityID, tree, avatar),
|
||||
_jointIndex(jointIndex)
|
||||
{
|
||||
_type = JOINT;
|
||||
EntityItemPointer item = _tree->findEntityByID(_entityID);
|
||||
const Model* model = getModel(item);
|
||||
if (!isValid() || model == NULL || _jointIndex >= (uint32_t)(model->getJointStateCount())) {
|
||||
qCDebug(interfaceapp) << "JointReferential::constructor(): Not Valid";
|
||||
_isValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
_lastRefDimension = item->getDimensions();
|
||||
model->getJointRotationInWorldFrame(_jointIndex, _refRotation);
|
||||
model->getJointPositionInWorldFrame(_jointIndex, _refPosition);
|
||||
|
||||
glm::quat refInvRot = glm::inverse(_refRotation);
|
||||
_rotation = refInvRot * _avatar->getOrientation();
|
||||
// BUG! _refPosition is in domain units, but avatar is in meters
|
||||
_translation = refInvRot * (avatar->getPosition() - _refPosition);
|
||||
}
|
||||
|
||||
void JointReferential::update() {
|
||||
EntityItemPointer item = _tree->findEntityByID(_entityID);
|
||||
const Model* model = getModel(item);
|
||||
if (!isValid() || model == NULL || _jointIndex >= (uint32_t)(model->getJointStateCount())) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool somethingChanged = false;
|
||||
if (item->getDimensions() != _lastRefDimension) {
|
||||
glm::vec3 oldDimension = _lastRefDimension;
|
||||
_lastRefDimension = item->getDimensions();
|
||||
_translation *= _lastRefDimension / oldDimension;
|
||||
somethingChanged = true;
|
||||
}
|
||||
if (item->getRotation() != _refRotation) {
|
||||
model->getJointRotationInWorldFrame(_jointIndex, _refRotation);
|
||||
_avatar->setOrientation(_refRotation * _rotation, true);
|
||||
somethingChanged = true;
|
||||
}
|
||||
if (item->getPosition() != _refPosition || somethingChanged) {
|
||||
model->getJointPositionInWorldFrame(_jointIndex, _refPosition);
|
||||
_avatar->setPosition(_refPosition + _refRotation * _translation, true);
|
||||
}
|
||||
}
|
||||
|
||||
const Model* JointReferential::getModel(EntityItemPointer item) {
|
||||
EntityItemFBXService* fbxService = _tree->getFBXService();
|
||||
if (item != NULL && fbxService != NULL) {
|
||||
return fbxService->getModelForEntityItem(item);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int JointReferential::packExtraData(unsigned char* destinationBuffer) const {
|
||||
unsigned char* startPosition = destinationBuffer;
|
||||
destinationBuffer += ModelReferential::packExtraData(destinationBuffer);
|
||||
|
||||
memcpy(destinationBuffer, &_jointIndex, sizeof(_jointIndex));
|
||||
destinationBuffer += sizeof(_jointIndex);
|
||||
|
||||
return destinationBuffer - startPosition;
|
||||
}
|
||||
|
||||
int JointReferential::unpackExtraData(const unsigned char *sourceBuffer, int size) {
|
||||
const unsigned char* startPosition = sourceBuffer;
|
||||
sourceBuffer += ModelReferential::unpackExtraData(sourceBuffer, size);
|
||||
|
||||
memcpy(&_jointIndex, sourceBuffer, sizeof(_jointIndex));
|
||||
sourceBuffer += sizeof(_jointIndex);
|
||||
|
||||
return sourceBuffer - startPosition;
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
//
|
||||
// ModelReferential.h
|
||||
//
|
||||
//
|
||||
// Created by Clement on 7/30/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_ModelReferential_h
|
||||
#define hifi_ModelReferential_h
|
||||
|
||||
#include <Referential.h>
|
||||
|
||||
class EntityTree;
|
||||
class Model;
|
||||
|
||||
class ModelReferential : public Referential {
|
||||
public:
|
||||
ModelReferential(Referential* ref, EntityTreePointer tree, AvatarData* avatar);
|
||||
ModelReferential(const QUuid& entityID, EntityTreePointer tree, AvatarData* avatar);
|
||||
virtual void update();
|
||||
|
||||
protected:
|
||||
virtual int packExtraData(unsigned char* destinationBuffer) const;
|
||||
virtual int unpackExtraData(const unsigned char* sourceBuffer, int size);
|
||||
|
||||
QUuid _entityID;
|
||||
EntityTreePointer _tree;
|
||||
};
|
||||
|
||||
class JointReferential : public ModelReferential {
|
||||
public:
|
||||
JointReferential(Referential* ref, EntityTreePointer tree, AvatarData* avatar);
|
||||
JointReferential(uint32_t jointIndex, const QUuid& entityID, EntityTreePointer tree, AvatarData* avatar);
|
||||
virtual void update();
|
||||
|
||||
protected:
|
||||
const Model* getModel(EntityItemPointer item);
|
||||
virtual int packExtraData(unsigned char* destinationBuffer) const;
|
||||
virtual int unpackExtraData(const unsigned char* sourceBuffer, int size);
|
||||
|
||||
uint32_t _jointIndex;
|
||||
};
|
||||
|
||||
#endif // hifi_ModelReferential_h
|
|
@ -45,7 +45,6 @@
|
|||
#include "AvatarManager.h"
|
||||
#include "Environment.h"
|
||||
#include "Menu.h"
|
||||
#include "ModelReferential.h"
|
||||
#include "MyAvatar.h"
|
||||
#include "Physics.h"
|
||||
#include "Util.h"
|
||||
|
@ -204,13 +203,14 @@ MyAvatar::~MyAvatar() {
|
|||
|
||||
QByteArray MyAvatar::toByteArray(bool cullSmallChanges, bool sendAll) {
|
||||
CameraMode mode = qApp->getCamera()->getMode();
|
||||
_globalPosition = getPosition();
|
||||
if (mode == CAMERA_MODE_THIRD_PERSON || mode == CAMERA_MODE_INDEPENDENT) {
|
||||
// fake the avatar position that is sent up to the AvatarMixer
|
||||
glm::vec3 oldPosition = _position;
|
||||
_position = getSkeletonPosition();
|
||||
glm::vec3 oldPosition = getPosition();
|
||||
setPosition(getSkeletonPosition());
|
||||
QByteArray array = AvatarData::toByteArray(cullSmallChanges, sendAll);
|
||||
// copy the correct position back
|
||||
_position = oldPosition;
|
||||
setPosition(oldPosition);
|
||||
return array;
|
||||
}
|
||||
return AvatarData::toByteArray(cullSmallChanges, sendAll);
|
||||
|
@ -269,10 +269,6 @@ void MyAvatar::update(float deltaTime) {
|
|||
updateSensorToWorldMatrix();
|
||||
}
|
||||
|
||||
if (_referential) {
|
||||
_referential->update();
|
||||
}
|
||||
|
||||
Head* head = getHead();
|
||||
head->relaxLean(deltaTime);
|
||||
updateFromTrackers(deltaTime);
|
||||
|
@ -291,9 +287,9 @@ extern void avatarStateFromFrame(const QByteArray& frameData, AvatarData* _avata
|
|||
void MyAvatar::simulate(float deltaTime) {
|
||||
PerformanceTimer perfTimer("simulate");
|
||||
|
||||
if (_scale != _targetScale) {
|
||||
float scale = (1.0f - SMOOTHING_RATIO) * _scale + SMOOTHING_RATIO * _targetScale;
|
||||
setScale(scale);
|
||||
if (getAvatarScale() != _targetScale) {
|
||||
float scale = (1.0f - SMOOTHING_RATIO) * getAvatarScale() + SMOOTHING_RATIO * _targetScale;
|
||||
setAvatarScale(scale);
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -343,10 +339,10 @@ void MyAvatar::simulate(float deltaTime) {
|
|||
Head* head = getHead();
|
||||
glm::vec3 headPosition;
|
||||
if (!_skeletonModel.getHeadPosition(headPosition)) {
|
||||
headPosition = _position;
|
||||
headPosition = getPosition();
|
||||
}
|
||||
head->setPosition(headPosition);
|
||||
head->setScale(_scale);
|
||||
head->setScale(getAvatarScale());
|
||||
head->simulate(deltaTime, true);
|
||||
}
|
||||
|
||||
|
@ -568,32 +564,6 @@ void MyAvatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
|||
Avatar::render(renderArgs, cameraPosition);
|
||||
}
|
||||
|
||||
void MyAvatar::clearReferential() {
|
||||
changeReferential(NULL);
|
||||
}
|
||||
|
||||
bool MyAvatar::setModelReferential(const QUuid& id) {
|
||||
EntityTreePointer tree = qApp->getEntities()->getTree();
|
||||
changeReferential(new ModelReferential(id, tree, this));
|
||||
if (_referential->isValid()) {
|
||||
return true;
|
||||
} else {
|
||||
changeReferential(NULL);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool MyAvatar::setJointReferential(const QUuid& id, int jointIndex) {
|
||||
EntityTreePointer tree = qApp->getEntities()->getTree();
|
||||
changeReferential(new JointReferential(jointIndex, id, tree, this));
|
||||
if (!_referential->isValid()) {
|
||||
return true;
|
||||
} else {
|
||||
changeReferential(NULL);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void MyAvatar::overrideAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "overrideAnimation", Q_ARG(const QString&, url), Q_ARG(float, fps),
|
||||
|
@ -732,7 +702,7 @@ void MyAvatar::loadData() {
|
|||
|
||||
_leanScale = loadSetting(settings, "leanScale", 0.05f);
|
||||
_targetScale = loadSetting(settings, "scale", 1.0f);
|
||||
setScale(_scale);
|
||||
setAvatarScale(getAvatarScale());
|
||||
|
||||
_animGraphUrl = settings.value("animGraphURL", "").toString();
|
||||
_fullAvatarURLFromPreferences = settings.value("fullAvatarURL", AvatarData::defaultFullAvatarModelUrl()).toUrl();
|
||||
|
@ -859,7 +829,8 @@ void MyAvatar::updateLookAtTargetAvatar() {
|
|||
bool isCurrentTarget = avatar->getIsLookAtTarget();
|
||||
float distanceTo = glm::length(avatar->getHead()->getEyePosition() - cameraPosition);
|
||||
avatar->setIsLookAtTarget(false);
|
||||
if (!avatar->isMyAvatar() && avatar->isInitialized() && (distanceTo < GREATEST_LOOKING_AT_DISTANCE * getScale())) {
|
||||
if (!avatar->isMyAvatar() && avatar->isInitialized() &&
|
||||
(distanceTo < GREATEST_LOOKING_AT_DISTANCE * getAvatarScale())) {
|
||||
float angleTo = glm::angle(lookForward, glm::normalize(avatar->getHead()->getEyePosition() - cameraPosition));
|
||||
if (angleTo < (smallestAngleTo * (isCurrentTarget ? KEEP_LOOKING_AT_CURRENT_ANGLE_FACTOR : 1.0f))) {
|
||||
_lookAtTargetAvatar = avatarPointer;
|
||||
|
@ -1071,7 +1042,7 @@ glm::vec3 MyAvatar::getSkeletonPosition() const {
|
|||
// The avatar is rotated PI about the yAxis, so we have to correct for it
|
||||
// to get the skeleton offset contribution in the world-frame.
|
||||
const glm::quat FLIP = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
return _position + getOrientation() * FLIP * _skeletonOffset;
|
||||
return getPosition() + getOrientation() * FLIP * _skeletonOffset;
|
||||
}
|
||||
return Avatar::getPosition();
|
||||
}
|
||||
|
@ -1361,7 +1332,7 @@ const float RENDER_HEAD_CUTOFF_DISTANCE = 0.50f;
|
|||
bool MyAvatar::cameraInsideHead() const {
|
||||
const Head* head = getHead();
|
||||
const glm::vec3 cameraPosition = qApp->getCamera()->getPosition();
|
||||
return glm::length(cameraPosition - head->getEyePosition()) < (RENDER_HEAD_CUTOFF_DISTANCE * _scale);
|
||||
return glm::length(cameraPosition - head->getEyePosition()) < (RENDER_HEAD_CUTOFF_DISTANCE * getAvatarScale());
|
||||
}
|
||||
|
||||
bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const {
|
||||
|
@ -1491,11 +1462,11 @@ glm::vec3 MyAvatar::applyKeyboardMotor(float deltaTime, const glm::vec3& localVe
|
|||
if (isHovering) {
|
||||
// we're flying --> complex acceleration curve with high max speed
|
||||
float motorSpeed = glm::length(_keyboardMotorVelocity);
|
||||
float finalMaxMotorSpeed = _scale * MAX_KEYBOARD_MOTOR_SPEED;
|
||||
float finalMaxMotorSpeed = getAvatarScale() * MAX_KEYBOARD_MOTOR_SPEED;
|
||||
float speedGrowthTimescale = 2.0f;
|
||||
float speedIncreaseFactor = 1.8f;
|
||||
motorSpeed *= 1.0f + glm::clamp(deltaTime / speedGrowthTimescale , 0.0f, 1.0f) * speedIncreaseFactor;
|
||||
const float maxBoostSpeed = _scale * MAX_BOOST_SPEED;
|
||||
const float maxBoostSpeed = getAvatarScale() * MAX_BOOST_SPEED;
|
||||
if (motorSpeed < maxBoostSpeed) {
|
||||
// an active keyboard motor should never be slower than this
|
||||
float boostCoefficient = (maxBoostSpeed - motorSpeed) / maxBoostSpeed;
|
||||
|
|
|
@ -247,10 +247,6 @@ public slots:
|
|||
|
||||
Q_INVOKABLE void updateMotionBehaviorFromMenu();
|
||||
|
||||
void clearReferential();
|
||||
bool setModelReferential(const QUuid& id);
|
||||
bool setJointReferential(const QUuid& id, int jointIndex);
|
||||
|
||||
virtual void rebuildSkeletonBody() override;
|
||||
|
||||
const QString& getAnimGraphUrl() const { return _animGraphUrl; }
|
||||
|
|
|
@ -416,7 +416,7 @@ bool ApplicationCompositor::calculateRayUICollisionPoint(const glm::vec3& positi
|
|||
glm::vec3 relativeDirection = glm::normalize(inverseOrientation * direction);
|
||||
|
||||
float t;
|
||||
if (raySphereIntersect(relativeDirection, relativePosition, _oculusUIRadius * myAvatar->getScale(), &t)){
|
||||
if (raySphereIntersect(relativeDirection, relativePosition, _oculusUIRadius * myAvatar->getAvatarScale(), &t)){
|
||||
result = position + direction * t;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -189,7 +189,7 @@ void PreferencesDialog::loadPreferences() {
|
|||
|
||||
ui.leanScaleSpin->setValue(myAvatar->getLeanScale());
|
||||
|
||||
ui.avatarScaleSpin->setValue(myAvatar->getScale());
|
||||
ui.avatarScaleSpin->setValue(myAvatar->getAvatarScale());
|
||||
ui.avatarAnimationEdit->setText(myAvatar->getAnimGraphUrl());
|
||||
|
||||
ui.maxOctreePPSSpin->setValue(qApp->getMaxOctreePacketsPerSecond());
|
||||
|
|
|
@ -68,7 +68,7 @@ namespace render {
|
|||
glm::vec3 myAvatarPosition = avatar->getPosition();
|
||||
float angle = glm::degrees(glm::angle(myAvatarRotation));
|
||||
glm::vec3 axis = glm::axis(myAvatarRotation);
|
||||
float myAvatarScale = avatar->getScale();
|
||||
float myAvatarScale = avatar->getAvatarScale();
|
||||
Transform transform = Transform();
|
||||
transform.setTranslation(myAvatarPosition);
|
||||
transform.setRotation(glm::angleAxis(angle, axis));
|
||||
|
|
|
@ -47,13 +47,8 @@ const QString AvatarData::FRAME_NAME = "com.highfidelity.recording.AvatarData";
|
|||
static std::once_flag frameTypeRegistration;
|
||||
|
||||
AvatarData::AvatarData() :
|
||||
_sessionUUID(),
|
||||
_position(0.0f),
|
||||
SpatiallyNestable(NestableTypes::Avatar, QUuid()),
|
||||
_handPosition(0.0f),
|
||||
_referential(NULL),
|
||||
_bodyYaw(-90.0f),
|
||||
_bodyPitch(0.0f),
|
||||
_bodyRoll(0.0f),
|
||||
_targetScale(1.0f),
|
||||
_handState(0),
|
||||
_keyState(NO_KEY_DOWN),
|
||||
|
@ -72,12 +67,14 @@ AvatarData::AvatarData() :
|
|||
_targetVelocity(0.0f),
|
||||
_localAABox(DEFAULT_LOCAL_AABOX_CORNER, DEFAULT_LOCAL_AABOX_SCALE)
|
||||
{
|
||||
setBodyPitch(0.0f);
|
||||
setBodyYaw(-90.0f);
|
||||
setBodyRoll(0.0f);
|
||||
}
|
||||
|
||||
AvatarData::~AvatarData() {
|
||||
delete _headData;
|
||||
delete _handData;
|
||||
delete _referential;
|
||||
}
|
||||
|
||||
// We cannot have a file-level variable (const or otherwise) in the header if it uses PathUtils, because that references Application, which will not yet initialized.
|
||||
|
@ -90,49 +87,18 @@ const QUrl& AvatarData::defaultFullAvatarModelUrl() {
|
|||
return _defaultFullAvatarModelUrl;
|
||||
}
|
||||
|
||||
const glm::vec3& AvatarData::getPosition() const {
|
||||
if (_referential) {
|
||||
_referential->update();
|
||||
}
|
||||
return _position;
|
||||
}
|
||||
|
||||
void AvatarData::setPosition(const glm::vec3 position, bool overideReferential) {
|
||||
if (!_referential || overideReferential) {
|
||||
_position = position;
|
||||
}
|
||||
}
|
||||
|
||||
glm::quat AvatarData::getOrientation() const {
|
||||
if (_referential) {
|
||||
_referential->update();
|
||||
}
|
||||
|
||||
return glm::quat(glm::radians(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll)));
|
||||
}
|
||||
|
||||
void AvatarData::setOrientation(const glm::quat& orientation, bool overideReferential) {
|
||||
if (!_referential || overideReferential) {
|
||||
glm::vec3 eulerAngles = glm::degrees(safeEulerAngles(orientation));
|
||||
_bodyPitch = eulerAngles.x;
|
||||
_bodyYaw = eulerAngles.y;
|
||||
_bodyRoll = eulerAngles.z;
|
||||
}
|
||||
}
|
||||
|
||||
// There are a number of possible strategies for this set of tools through endRender, below.
|
||||
void AvatarData::nextAttitude(glm::vec3 position, glm::quat orientation) {
|
||||
avatarLock.lock();
|
||||
setPosition(position, true);
|
||||
setOrientation(orientation, true);
|
||||
Transform trans;
|
||||
trans.setTranslation(position);
|
||||
trans.setRotation(orientation);
|
||||
SpatiallyNestable::setTransform(trans);
|
||||
avatarLock.unlock();
|
||||
updateAttitude();
|
||||
}
|
||||
void AvatarData::startCapture() {
|
||||
avatarLock.lock();
|
||||
assert(_nextAllowed);
|
||||
_nextAllowed = false;
|
||||
_nextPosition = getPosition();
|
||||
_nextOrientation = getOrientation();
|
||||
}
|
||||
void AvatarData::endCapture() {
|
||||
avatarLock.unlock();
|
||||
|
@ -145,57 +111,42 @@ void AvatarData::endUpdate() {
|
|||
}
|
||||
void AvatarData::startRenderRun() {
|
||||
// I'd like to get rid of this and just (un)lock at (end-)startRender.
|
||||
// But somehow that causes judder in rotations.
|
||||
// But somehow that causes judder in rotations.
|
||||
avatarLock.lock();
|
||||
}
|
||||
void AvatarData::endRenderRun() {
|
||||
avatarLock.unlock();
|
||||
}
|
||||
void AvatarData::startRender() {
|
||||
glm::vec3 pos = getPosition();
|
||||
glm::quat rot = getOrientation();
|
||||
setPosition(_nextPosition, true);
|
||||
setOrientation(_nextOrientation, true);
|
||||
updateAttitude();
|
||||
_nextPosition = pos;
|
||||
_nextOrientation = rot;
|
||||
}
|
||||
void AvatarData::endRender() {
|
||||
setPosition(_nextPosition, true);
|
||||
setOrientation(_nextOrientation, true);
|
||||
updateAttitude();
|
||||
_nextAllowed = true;
|
||||
}
|
||||
|
||||
float AvatarData::getTargetScale() const {
|
||||
if (_referential) {
|
||||
_referential->update();
|
||||
}
|
||||
|
||||
return _targetScale;
|
||||
}
|
||||
|
||||
void AvatarData::setTargetScale(float targetScale, bool overideReferential) {
|
||||
if (!_referential || overideReferential) {
|
||||
_targetScale = std::max(MIN_AVATAR_SCALE, std::min(MAX_AVATAR_SCALE, targetScale));
|
||||
}
|
||||
void AvatarData::setTargetScale(float targetScale) {
|
||||
_targetScale = std::max(MIN_AVATAR_SCALE, std::min(MAX_AVATAR_SCALE, targetScale));
|
||||
}
|
||||
|
||||
void AvatarData::setClampedTargetScale(float targetScale, bool overideReferential) {
|
||||
void AvatarData::setClampedTargetScale(float targetScale) {
|
||||
|
||||
targetScale = glm::clamp(targetScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE);
|
||||
|
||||
setTargetScale(targetScale, overideReferential);
|
||||
setTargetScale(targetScale);
|
||||
qCDebug(avatars) << "Changed scale to " << _targetScale;
|
||||
}
|
||||
|
||||
glm::vec3 AvatarData::getHandPosition() const {
|
||||
return getOrientation() * _handPosition + _position;
|
||||
return getOrientation() * _handPosition + getPosition();
|
||||
}
|
||||
|
||||
void AvatarData::setHandPosition(const glm::vec3& handPosition) {
|
||||
// store relative to position/orientation
|
||||
_handPosition = glm::inverse(getOrientation()) * (handPosition - _position);
|
||||
_handPosition = glm::inverse(getOrientation()) * (handPosition - getPosition());
|
||||
}
|
||||
|
||||
QByteArray AvatarData::toByteArray(bool cullSmallChanges, bool sendAll) {
|
||||
|
@ -216,13 +167,18 @@ QByteArray AvatarData::toByteArray(bool cullSmallChanges, bool sendAll) {
|
|||
unsigned char* destinationBuffer = reinterpret_cast<unsigned char*>(avatarDataByteArray.data());
|
||||
unsigned char* startPosition = destinationBuffer;
|
||||
|
||||
memcpy(destinationBuffer, &_position, sizeof(_position));
|
||||
destinationBuffer += sizeof(_position);
|
||||
const glm::vec3& position = getLocalPosition();
|
||||
memcpy(destinationBuffer, &position, sizeof(position));
|
||||
destinationBuffer += sizeof(position);
|
||||
|
||||
// Body rotation (NOTE: This needs to become a quaternion to save two bytes)
|
||||
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _bodyYaw);
|
||||
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _bodyPitch);
|
||||
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _bodyRoll);
|
||||
memcpy(destinationBuffer, &_globalPosition, sizeof(_globalPosition));
|
||||
destinationBuffer += sizeof(_globalPosition);
|
||||
|
||||
// Body rotation
|
||||
glm::vec3 bodyEulerAngles = glm::degrees(safeEulerAngles(getLocalOrientation()));
|
||||
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, bodyEulerAngles.y);
|
||||
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, bodyEulerAngles.x);
|
||||
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, bodyEulerAngles.z);
|
||||
|
||||
// Body scale
|
||||
destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _targetScale);
|
||||
|
@ -255,14 +211,18 @@ QByteArray AvatarData::toByteArray(bool cullSmallChanges, bool sendAll) {
|
|||
setAtBit(bitItems, IS_EYE_TRACKER_CONNECTED);
|
||||
}
|
||||
// referential state
|
||||
if (_referential != NULL && _referential->isValid()) {
|
||||
SpatiallyNestablePointer parent = getParentPointer();
|
||||
if (parent) {
|
||||
setAtBit(bitItems, HAS_REFERENTIAL);
|
||||
}
|
||||
*destinationBuffer++ = bitItems;
|
||||
|
||||
// Add referential
|
||||
if (_referential != NULL && _referential->isValid()) {
|
||||
destinationBuffer += _referential->packReferential(destinationBuffer);
|
||||
if (parent) {
|
||||
QByteArray referentialAsBytes = parent->getID().toRfc4122();
|
||||
memcpy(destinationBuffer, referentialAsBytes.data(), referentialAsBytes.size());
|
||||
destinationBuffer += referentialAsBytes.size();
|
||||
memcpy(destinationBuffer, &_parentJointIndex, sizeof(_parentJointIndex));
|
||||
destinationBuffer += sizeof(_parentJointIndex);
|
||||
}
|
||||
|
||||
// If it is connected, pack up the data
|
||||
|
@ -496,13 +456,16 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
|
|||
memcpy(&position, sourceBuffer, sizeof(position));
|
||||
sourceBuffer += sizeof(position);
|
||||
|
||||
memcpy(&_globalPosition, sourceBuffer, sizeof(_globalPosition));
|
||||
sourceBuffer += sizeof(_globalPosition);
|
||||
|
||||
if (glm::isnan(position.x) || glm::isnan(position.y) || glm::isnan(position.z)) {
|
||||
if (shouldLogError(now)) {
|
||||
qCDebug(avatars) << "Discard nan AvatarData::position; displayName = '" << _displayName << "'";
|
||||
}
|
||||
return maxAvailableSize;
|
||||
}
|
||||
setPosition(position);
|
||||
setLocalPosition(position);
|
||||
|
||||
// rotation (NOTE: This needs to become a quaternion to save two bytes)
|
||||
float yaw, pitch, roll;
|
||||
|
@ -515,11 +478,18 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
|
|||
}
|
||||
return maxAvailableSize;
|
||||
}
|
||||
if (_bodyYaw != yaw || _bodyPitch != pitch || _bodyRoll != roll) {
|
||||
|
||||
// TODO is this safe? will the floats not exactly match?
|
||||
// Andrew says:
|
||||
// Yes, there is a possibility that the transmitted will not quite match the extracted despite being originally
|
||||
// extracted from the exact same quaternion. I followed the code through and it appears the risk is that the
|
||||
// avatar's SkeletonModel might fall into the CPU expensive part of Model::updateClusterMatrices() when otherwise it
|
||||
// would not have required it. However, we know we can update many simultaneously animating avatars, and most
|
||||
// avatars will be moving constantly anyway, so I don't think we need to worry.
|
||||
if (getBodyYaw() != yaw || getBodyPitch() != pitch || getBodyRoll() != roll) {
|
||||
_hasNewJointRotations = true;
|
||||
_bodyYaw = yaw;
|
||||
_bodyPitch = pitch;
|
||||
_bodyRoll = roll;
|
||||
glm::vec3 eulerAngles(pitch, yaw, roll);
|
||||
setLocalOrientation(glm::quat(glm::radians(eulerAngles)));
|
||||
}
|
||||
|
||||
// scale
|
||||
|
@ -581,21 +551,17 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
|
|||
_headData->_isEyeTrackerConnected = oneAtBit(bitItems, IS_EYE_TRACKER_CONNECTED);
|
||||
bool hasReferential = oneAtBit(bitItems, HAS_REFERENTIAL);
|
||||
|
||||
// Referential
|
||||
if (hasReferential) {
|
||||
Referential* ref = new Referential(sourceBuffer, this);
|
||||
if (_referential == NULL ||
|
||||
ref->version() != _referential->version()) {
|
||||
changeReferential(ref);
|
||||
} else {
|
||||
delete ref;
|
||||
}
|
||||
_referential->update();
|
||||
} else if (_referential != NULL) {
|
||||
changeReferential(NULL);
|
||||
const int sizeOfPackedUuid = 16;
|
||||
QByteArray referentialAsBytes((const char*)sourceBuffer, sizeOfPackedUuid);
|
||||
_parentID = QUuid::fromRfc4122(referentialAsBytes);
|
||||
sourceBuffer += sizeOfPackedUuid;
|
||||
memcpy(&_parentJointIndex, sourceBuffer, sizeof(_parentJointIndex));
|
||||
sourceBuffer += sizeof(_parentJointIndex);
|
||||
} else {
|
||||
_parentID = QUuid();
|
||||
}
|
||||
|
||||
|
||||
if (_headData->_isFaceTrackerConnected) {
|
||||
float leftEyeBlink, rightEyeBlink, averageLoudness, browAudioLift;
|
||||
minPossibleSize += sizeof(leftEyeBlink) + sizeof(rightEyeBlink) + sizeof(averageLoudness) + sizeof(browAudioLift);
|
||||
|
@ -788,19 +754,10 @@ int AvatarData::getReceiveRate() const {
|
|||
return lrint(1.0f / _averageBytesReceived.getEventDeltaAverage());
|
||||
}
|
||||
|
||||
bool AvatarData::hasReferential() {
|
||||
return _referential != NULL;
|
||||
}
|
||||
|
||||
std::shared_ptr<Transform> AvatarData::getRecordingBasis() const {
|
||||
return _recordingBasis;
|
||||
}
|
||||
|
||||
void AvatarData::changeReferential(Referential* ref) {
|
||||
delete _referential;
|
||||
_referential = ref;
|
||||
}
|
||||
|
||||
void AvatarData::setRawJointData(QVector<JointData> data) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setRawJointData", Q_ARG(QVector<JointData>, data));
|
||||
|
@ -1437,14 +1394,6 @@ void AvatarData::clearRecordingBasis() {
|
|||
_recordingBasis.reset();
|
||||
}
|
||||
|
||||
Transform AvatarData::getTransform() const {
|
||||
Transform result;
|
||||
result.setRotation(getOrientation());
|
||||
result.setTranslation(getPosition());
|
||||
result.setScale(getTargetScale());
|
||||
return result;
|
||||
}
|
||||
|
||||
static const QString JSON_AVATAR_BASIS = QStringLiteral("basisTransform");
|
||||
static const QString JSON_AVATAR_RELATIVE = QStringLiteral("relativeTransform");
|
||||
static const QString JSON_AVATAR_JOINT_ARRAY = QStringLiteral("jointArray");
|
||||
|
@ -1495,15 +1444,17 @@ QJsonObject AvatarData::toJson() const {
|
|||
}
|
||||
|
||||
auto recordingBasis = getRecordingBasis();
|
||||
Transform avatarTransform = getTransform();
|
||||
avatarTransform.setScale(getTargetScale());
|
||||
if (recordingBasis) {
|
||||
root[JSON_AVATAR_BASIS] = Transform::toJson(*recordingBasis);
|
||||
// Find the relative transform
|
||||
auto relativeTransform = recordingBasis->relativeTransform(getTransform());
|
||||
auto relativeTransform = recordingBasis->relativeTransform(avatarTransform);
|
||||
if (!relativeTransform.isIdentity()) {
|
||||
root[JSON_AVATAR_RELATIVE] = Transform::toJson(relativeTransform);
|
||||
}
|
||||
} else {
|
||||
root[JSON_AVATAR_RELATIVE] = Transform::toJson(getTransform());
|
||||
root[JSON_AVATAR_RELATIVE] = Transform::toJson(avatarTransform);
|
||||
}
|
||||
|
||||
auto scale = getTargetScale();
|
||||
|
@ -1641,3 +1592,44 @@ void AvatarData::fromFrame(const QByteArray& frameData, AvatarData& result) {
|
|||
#endif
|
||||
result.fromJson(doc.object());
|
||||
}
|
||||
|
||||
float AvatarData::getBodyYaw() const {
|
||||
glm::vec3 eulerAngles = glm::degrees(safeEulerAngles(getOrientation()));
|
||||
return eulerAngles.y;
|
||||
}
|
||||
|
||||
void AvatarData::setBodyYaw(float bodyYaw) {
|
||||
glm::vec3 eulerAngles = glm::degrees(safeEulerAngles(getOrientation()));
|
||||
eulerAngles.y = bodyYaw;
|
||||
setOrientation(glm::quat(glm::radians(eulerAngles)));
|
||||
}
|
||||
|
||||
float AvatarData::getBodyPitch() const {
|
||||
glm::vec3 eulerAngles = glm::degrees(safeEulerAngles(getOrientation()));
|
||||
return eulerAngles.x;
|
||||
}
|
||||
|
||||
void AvatarData::setBodyPitch(float bodyPitch) {
|
||||
glm::vec3 eulerAngles = glm::degrees(safeEulerAngles(getOrientation()));
|
||||
eulerAngles.x = bodyPitch;
|
||||
setOrientation(glm::quat(glm::radians(eulerAngles)));
|
||||
}
|
||||
|
||||
float AvatarData::getBodyRoll() const {
|
||||
glm::vec3 eulerAngles = glm::degrees(safeEulerAngles(getOrientation()));
|
||||
return eulerAngles.z;
|
||||
}
|
||||
|
||||
void AvatarData::setBodyRoll(float bodyRoll) {
|
||||
glm::vec3 eulerAngles = glm::degrees(safeEulerAngles(getOrientation()));
|
||||
eulerAngles.z = bodyRoll;
|
||||
setOrientation(glm::quat(glm::radians(eulerAngles)));
|
||||
}
|
||||
|
||||
void AvatarData::setPosition(const glm::vec3 position) {
|
||||
SpatiallyNestable::setPosition(position);
|
||||
}
|
||||
|
||||
void AvatarData::setOrientation(const glm::quat orientation) {
|
||||
SpatiallyNestable::setOrientation(orientation);
|
||||
}
|
||||
|
|
|
@ -51,12 +51,12 @@ typedef unsigned long long quint64;
|
|||
#include <Node.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <SimpleMovingAverage.h>
|
||||
#include <SpatiallyNestable.h>
|
||||
|
||||
#include "AABox.h"
|
||||
#include "HandData.h"
|
||||
#include "HeadData.h"
|
||||
#include "PathUtils.h"
|
||||
#include "Referential.h"
|
||||
|
||||
using AvatarSharedPointer = std::shared_ptr<AvatarData>;
|
||||
using AvatarWeakPointer = std::weak_ptr<AvatarData>;
|
||||
|
@ -135,7 +135,7 @@ class AttachmentData;
|
|||
class Transform;
|
||||
using TransformPointer = std::shared_ptr<Transform>;
|
||||
|
||||
class AvatarData : public QObject {
|
||||
class AvatarData : public QObject, public SpatiallyNestable {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(glm::vec3 position READ getPosition WRITE setPosition)
|
||||
|
@ -177,10 +177,7 @@ public:
|
|||
|
||||
virtual bool isMyAvatar() const { return false; }
|
||||
|
||||
const QUuid& getSessionUUID() const { return _sessionUUID; }
|
||||
|
||||
const glm::vec3& getPosition() const;
|
||||
virtual void setPosition(const glm::vec3 position, bool overideReferential = false);
|
||||
const QUuid& getSessionUUID() const { return getID(); }
|
||||
|
||||
glm::vec3 getHandPosition() const;
|
||||
void setHandPosition(const glm::vec3& handPosition);
|
||||
|
@ -196,16 +193,16 @@ public:
|
|||
/// \return number of bytes parsed
|
||||
virtual int parseDataFromBuffer(const QByteArray& buffer);
|
||||
|
||||
// Body Rotation (degrees)
|
||||
float getBodyYaw() const { return _bodyYaw; }
|
||||
void setBodyYaw(float bodyYaw) { _bodyYaw = bodyYaw; }
|
||||
float getBodyPitch() const { return _bodyPitch; }
|
||||
void setBodyPitch(float bodyPitch) { _bodyPitch = bodyPitch; }
|
||||
float getBodyRoll() const { return _bodyRoll; }
|
||||
void setBodyRoll(float bodyRoll) { _bodyRoll = bodyRoll; }
|
||||
// Body Rotation (degrees)
|
||||
float getBodyYaw() const;
|
||||
void setBodyYaw(float bodyYaw);
|
||||
float getBodyPitch() const;
|
||||
void setBodyPitch(float bodyPitch);
|
||||
float getBodyRoll() const;
|
||||
void setBodyRoll(float bodyRoll);
|
||||
|
||||
glm::quat getOrientation() const;
|
||||
virtual void setOrientation(const glm::quat& orientation, bool overideReferential = false);
|
||||
virtual void setPosition(glm::vec3 position);
|
||||
virtual void setOrientation(glm::quat orientation);
|
||||
|
||||
void nextAttitude(glm::vec3 position, glm::quat orientation); // Can be safely called at any time.
|
||||
void startCapture(); // start/end of the period in which the latest values are about to be captured for camera, etc.
|
||||
|
@ -239,8 +236,8 @@ public:
|
|||
|
||||
// Scale
|
||||
float getTargetScale() const;
|
||||
void setTargetScale(float targetScale, bool overideReferential = false);
|
||||
void setClampedTargetScale(float targetScale, bool overideReferential = false);
|
||||
void setTargetScale(float targetScale);
|
||||
void setClampedTargetScale(float targetScale);
|
||||
|
||||
// Hand State
|
||||
Q_INVOKABLE void setHandState(char s) { _handState = s; }
|
||||
|
@ -326,7 +323,6 @@ public:
|
|||
void setOwningAvatarMixer(const QWeakPointer<Node>& owningAvatarMixer) { _owningAvatarMixer = owningAvatarMixer; }
|
||||
|
||||
const AABox& getLocalAABox() const { return _localAABox; }
|
||||
const Referential* getReferential() const { return _referential; }
|
||||
|
||||
int getUsecsSinceLastUpdate() const { return _averageBytesReceived.getUsecsSinceLastEvent(); }
|
||||
int getAverageBytesReceivedPerSecond() const;
|
||||
|
@ -338,13 +334,14 @@ public:
|
|||
|
||||
bool shouldDie() const { return _owningAvatarMixer.isNull() || getUsecsSinceLastUpdate() > AVATAR_SILENCE_THRESHOLD_USECS; }
|
||||
|
||||
Transform getTransform() const;
|
||||
void clearRecordingBasis();
|
||||
TransformPointer getRecordingBasis() const;
|
||||
void setRecordingBasis(TransformPointer recordingBasis = TransformPointer());
|
||||
QJsonObject toJson() const;
|
||||
void fromJson(const QJsonObject& json);
|
||||
|
||||
glm::vec3 getClientGlobalPosition() { return _globalPosition; }
|
||||
|
||||
public slots:
|
||||
void sendAvatarDataPacket();
|
||||
void sendIdentityPacket();
|
||||
|
@ -352,24 +349,10 @@ public slots:
|
|||
|
||||
void setBillboardFromNetworkReply();
|
||||
void setJointMappingsFromNetworkReply();
|
||||
void setSessionUUID(const QUuid& sessionUUID) { _sessionUUID = sessionUUID; }
|
||||
bool hasReferential();
|
||||
void setSessionUUID(const QUuid& sessionUUID) { setID(sessionUUID); }
|
||||
|
||||
protected:
|
||||
QUuid _sessionUUID;
|
||||
glm::vec3 _position = START_LOCATION;
|
||||
glm::vec3 _handPosition;
|
||||
|
||||
Referential* _referential;
|
||||
|
||||
// Body rotation
|
||||
float _bodyYaw; // degrees
|
||||
float _bodyPitch; // degrees
|
||||
float _bodyRoll; // degrees
|
||||
|
||||
glm::vec3 _nextPosition {};
|
||||
glm::quat _nextOrientation {};
|
||||
bool _nextAllowed {true};
|
||||
|
||||
// Body scale
|
||||
float _targetScale;
|
||||
|
@ -411,7 +394,6 @@ protected:
|
|||
|
||||
/// Loads the joint indices, names from the FST file (if any)
|
||||
virtual void updateJointMappings();
|
||||
void changeReferential(Referential* ref);
|
||||
|
||||
glm::vec3 _velocity;
|
||||
glm::vec3 _targetVelocity;
|
||||
|
@ -426,6 +408,11 @@ protected:
|
|||
// During playback, it holds the origin from which to play the relative positions in the clip
|
||||
TransformPointer _recordingBasis;
|
||||
|
||||
// _globalPosition is sent along with localPosition + parent because the avatar-mixer doesn't know
|
||||
// where Entities are located. This is currently only used by the mixer to decide how often to send
|
||||
// updates about one avatar to another.
|
||||
glm::vec3 _globalPosition;
|
||||
|
||||
private:
|
||||
friend void avatarStateFromFrame(const QByteArray& frameData, AvatarData* _avatar);
|
||||
static QUrl _defaultFullAvatarModelUrl;
|
||||
|
|
|
@ -65,7 +65,10 @@ AvatarSharedPointer AvatarHashMap::newOrExistingAvatar(const QUuid& sessionUUID,
|
|||
|
||||
AvatarSharedPointer AvatarHashMap::findAvatar(const QUuid& sessionUUID) {
|
||||
QReadLocker locker(&_hashLock);
|
||||
return _avatarHash.value(sessionUUID);
|
||||
if (_avatarHash.contains(sessionUUID)) {
|
||||
return _avatarHash.value(sessionUUID);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void AvatarHashMap::processAvatarDataPacket(QSharedPointer<NLPacket> packet, SharedNodePointer sendingNode) {
|
||||
|
|
|
@ -1,109 +0,0 @@
|
|||
//
|
||||
// Referential.cpp
|
||||
//
|
||||
//
|
||||
// Created by Clement on 7/30/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <GLMHelpers.h>
|
||||
|
||||
#include "AvatarData.h"
|
||||
#include "AvatarLogging.h"
|
||||
#include "Referential.h"
|
||||
|
||||
Referential::Referential(Type type, AvatarData* avatar) :
|
||||
_type(type),
|
||||
_version(0),
|
||||
_isValid(true),
|
||||
_avatar(avatar)
|
||||
{
|
||||
if (_avatar == NULL) {
|
||||
_isValid = false;
|
||||
return;
|
||||
}
|
||||
if (_avatar->hasReferential()) {
|
||||
_version = _avatar->getReferential()->version() + 1;
|
||||
}
|
||||
}
|
||||
|
||||
Referential::Referential(const unsigned char*& sourceBuffer, AvatarData* avatar) :
|
||||
_isValid(false),
|
||||
_avatar(avatar)
|
||||
{
|
||||
// Since we can't return how many byte have been read
|
||||
// We take a reference to the pointer as argument and increment the pointer ouself.
|
||||
sourceBuffer += unpackReferential(sourceBuffer);
|
||||
// The actual unpacking to the right referential type happens in Avatar::simulate()
|
||||
// If subclassed, make sure to add a case there to unpack the new referential type correctly
|
||||
}
|
||||
|
||||
Referential::~Referential() {
|
||||
}
|
||||
|
||||
int Referential::packReferential(unsigned char* destinationBuffer) const {
|
||||
const unsigned char* startPosition = destinationBuffer;
|
||||
destinationBuffer += pack(destinationBuffer);
|
||||
|
||||
unsigned char* sizePosition = destinationBuffer++; // Save a spot for the extra data size
|
||||
char size = packExtraData(destinationBuffer);
|
||||
*sizePosition = size; // write extra data size in saved spot here
|
||||
destinationBuffer += size;
|
||||
return destinationBuffer - startPosition;
|
||||
}
|
||||
|
||||
int Referential::unpackReferential(const unsigned char* sourceBuffer) {
|
||||
const unsigned char* startPosition = sourceBuffer;
|
||||
sourceBuffer += unpack(sourceBuffer);
|
||||
char expectedSize = *sourceBuffer++;
|
||||
char bytesRead = unpackExtraData(sourceBuffer, expectedSize);
|
||||
_isValid = (bytesRead == expectedSize);
|
||||
if (!_isValid) {
|
||||
// Will occur if the new instance unpacking is of the wrong type
|
||||
qCDebug(avatars) << "[ERROR] Referential extra data overflow";
|
||||
}
|
||||
sourceBuffer += expectedSize;
|
||||
return sourceBuffer - startPosition;
|
||||
}
|
||||
|
||||
int Referential::pack(unsigned char* destinationBuffer) const {
|
||||
unsigned char* startPosition = destinationBuffer;
|
||||
*destinationBuffer++ = (unsigned char)_type;
|
||||
memcpy(destinationBuffer, &_version, sizeof(_version));
|
||||
destinationBuffer += sizeof(_version);
|
||||
|
||||
destinationBuffer += packFloatVec3ToSignedTwoByteFixed(destinationBuffer, _translation, 0);
|
||||
destinationBuffer += packOrientationQuatToBytes(destinationBuffer, _rotation);
|
||||
return destinationBuffer - startPosition;
|
||||
}
|
||||
|
||||
int Referential::unpack(const unsigned char* sourceBuffer) {
|
||||
const unsigned char* startPosition = sourceBuffer;
|
||||
_type = (Type)*sourceBuffer++;
|
||||
if (_type < 0 || _type >= NUM_TYPES) {
|
||||
_type = UNKNOWN;
|
||||
}
|
||||
memcpy(&_version, sourceBuffer, sizeof(_version));
|
||||
sourceBuffer += sizeof(_version);
|
||||
|
||||
sourceBuffer += unpackFloatVec3FromSignedTwoByteFixed(sourceBuffer, _translation, 0);
|
||||
sourceBuffer += unpackOrientationQuatFromBytes(sourceBuffer, _rotation);
|
||||
return sourceBuffer - startPosition;
|
||||
}
|
||||
|
||||
int Referential::packExtraData(unsigned char *destinationBuffer) const {
|
||||
// Since we can't interpret that data, just store it in a buffer for later use.
|
||||
memcpy(destinationBuffer, _extraDataBuffer.data(), _extraDataBuffer.size());
|
||||
return _extraDataBuffer.size();
|
||||
}
|
||||
|
||||
|
||||
int Referential::unpackExtraData(const unsigned char* sourceBuffer, int size) {
|
||||
_extraDataBuffer.clear();
|
||||
_extraDataBuffer.append(reinterpret_cast<const char*>(sourceBuffer), size);
|
||||
return size;
|
||||
}
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
//
|
||||
// Referential.h
|
||||
//
|
||||
//
|
||||
// Created by Clement on 7/30/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_Referential_h
|
||||
#define hifi_Referential_h
|
||||
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
#include <glm/vec3.hpp>
|
||||
|
||||
class AvatarData;
|
||||
|
||||
/// Stores and enforce the relative position of an avatar to a given referential (ie. model, joint, ...)
|
||||
class Referential {
|
||||
public:
|
||||
enum Type {
|
||||
UNKNOWN,
|
||||
MODEL,
|
||||
JOINT,
|
||||
AVATAR,
|
||||
|
||||
NUM_TYPES
|
||||
};
|
||||
|
||||
Referential(const unsigned char*& sourceBuffer, AvatarData* avatar);
|
||||
virtual ~Referential();
|
||||
|
||||
Type type() const { return _type; }
|
||||
quint8 version() const { return _version; }
|
||||
bool isValid() const { return _isValid; }
|
||||
bool hasExtraData() const { return !_extraDataBuffer.isEmpty(); }
|
||||
|
||||
glm::vec3 getTranslation() const { return _translation; }
|
||||
glm::quat getRotation() const { return _rotation; }
|
||||
QByteArray getExtraData() const { return _extraDataBuffer; }
|
||||
|
||||
virtual void update() {}
|
||||
int packReferential(unsigned char* destinationBuffer) const;
|
||||
int unpackReferential(const unsigned char* sourceBuffer);
|
||||
|
||||
protected:
|
||||
Referential(Type type, AvatarData* avatar);
|
||||
|
||||
// packs the base class data
|
||||
int pack(unsigned char* destinationBuffer) const;
|
||||
int unpack(const unsigned char* sourceBuffer);
|
||||
// virtual functions that pack fthe extra data of subclasses (needs to be reimplemented in subclass)
|
||||
virtual int packExtraData(unsigned char* destinationBuffer) const;
|
||||
virtual int unpackExtraData(const unsigned char* sourceBuffer, int size);
|
||||
|
||||
Type _type;
|
||||
quint8 _version;
|
||||
bool _isValid;
|
||||
AvatarData* _avatar;
|
||||
QByteArray _extraDataBuffer;
|
||||
|
||||
glm::vec3 _refPosition; // position of object in world-frame
|
||||
glm::quat _refRotation; // rotation of object in world-frame
|
||||
glm::vec3 _lastRefDimension; // dimension of object when _translation was last computed
|
||||
|
||||
glm::vec3 _translation; // offset of avatar in object local-frame
|
||||
glm::quat _rotation; // rotation of avatar in object local-frame
|
||||
};
|
||||
|
||||
|
||||
#endif // hifi_Referential_h
|
|
@ -24,7 +24,9 @@
|
|||
#include "../render-utils/simple_frag.h"
|
||||
|
||||
EntityItemPointer RenderableBoxEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
return std::make_shared<RenderableBoxEntityItem>(entityID, properties);
|
||||
EntityItemPointer entity{ new RenderableBoxEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
void RenderableBoxEntityItem::setUserData(const QString& value) {
|
||||
|
|
|
@ -20,10 +20,7 @@
|
|||
class RenderableBoxEntityItem : public BoxEntityItem {
|
||||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
RenderableBoxEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
BoxEntityItem(entityItemID, properties)
|
||||
{ }
|
||||
RenderableBoxEntityItem(const EntityItemID& entityItemID) : BoxEntityItem(entityItemID) { }
|
||||
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual void setUserData(const QString& value);
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
#include "RenderableLightEntityItem.h"
|
||||
|
||||
EntityItemPointer RenderableLightEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
return std::make_shared<RenderableLightEntityItem>(entityID, properties);
|
||||
EntityItemPointer entity{ new RenderableLightEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
void RenderableLightEntityItem::render(RenderArgs* args) {
|
||||
|
|
|
@ -18,10 +18,7 @@
|
|||
class RenderableLightEntityItem : public LightEntityItem {
|
||||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
RenderableLightEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
LightEntityItem(entityItemID, properties)
|
||||
{ }
|
||||
RenderableLightEntityItem(const EntityItemID& entityItemID) : LightEntityItem(entityItemID) { }
|
||||
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual bool supportsDetailedRayIntersection() const { return true; }
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
#include "RenderableLineEntityItem.h"
|
||||
|
||||
EntityItemPointer RenderableLineEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
return std::make_shared<RenderableLineEntityItem>(entityID, properties);
|
||||
EntityItemPointer entity{ new RenderableLineEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
void RenderableLineEntityItem::updateGeometry() {
|
||||
|
|
|
@ -19,9 +19,8 @@
|
|||
class RenderableLineEntityItem : public LineEntityItem {
|
||||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
RenderableLineEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
LineEntityItem(entityItemID, properties),
|
||||
RenderableLineEntityItem(const EntityItemID& entityItemID) :
|
||||
LineEntityItem(entityItemID),
|
||||
_lineVerticesID(GeometryCache::UNKNOWN_ID)
|
||||
{ }
|
||||
|
||||
|
|
|
@ -26,13 +26,14 @@
|
|||
#include "RenderableEntityItem.h"
|
||||
|
||||
EntityItemPointer RenderableModelEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
return std::make_shared<RenderableModelEntityItem>(entityID, properties);
|
||||
EntityItemPointer entity{ new RenderableModelEntityItem(entityID, properties.getDimensionsInitialized()) };
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
RenderableModelEntityItem::RenderableModelEntityItem(const EntityItemID& entityItemID,
|
||||
const EntityItemProperties& properties) :
|
||||
ModelEntityItem(entityItemID, properties),
|
||||
_dimensionsInitialized(properties.getDimensionsInitialized())
|
||||
{
|
||||
|
||||
RenderableModelEntityItem::RenderableModelEntityItem(const EntityItemID& entityItemID, bool dimensionsInitialized) :
|
||||
ModelEntityItem(entityItemID),
|
||||
_dimensionsInitialized(dimensionsInitialized) {
|
||||
}
|
||||
|
||||
RenderableModelEntityItem::~RenderableModelEntityItem() {
|
||||
|
@ -43,7 +44,7 @@ RenderableModelEntityItem::~RenderableModelEntityItem() {
|
|||
}
|
||||
}
|
||||
|
||||
void RenderableModelEntityItem::setDimensions(const glm::vec3& value) {
|
||||
void RenderableModelEntityItem::setDimensions(const glm::vec3 value) {
|
||||
_dimensionsInitialized = true;
|
||||
ModelEntityItem::setDimensions(value);
|
||||
}
|
||||
|
@ -192,7 +193,7 @@ bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_p
|
|||
|
||||
if (_model) {
|
||||
render::Item::Status::Getters statusGetters;
|
||||
makeEntityItemStatusGetters(shared_from_this(), statusGetters);
|
||||
makeEntityItemStatusGetters(getThisPointer(), statusGetters);
|
||||
|
||||
// note: we don't care if the model fails to add items, we always added our meta item and therefore we return
|
||||
// true so that the system knows our meta item is in the scene!
|
||||
|
@ -238,7 +239,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
|
|||
_model->removeFromScene(scene, pendingChanges);
|
||||
|
||||
render::Item::Status::Getters statusGetters;
|
||||
makeEntityItemStatusGetters(shared_from_this(), statusGetters);
|
||||
makeEntityItemStatusGetters(getThisPointer(), statusGetters);
|
||||
_model->addToScene(scene, pendingChanges, statusGetters, _showCollisionHull);
|
||||
|
||||
scene->enqueuePendingChanges(pendingChanges);
|
||||
|
@ -563,3 +564,23 @@ bool RenderableModelEntityItem::contains(const glm::vec3& point) const {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
glm::quat RenderableModelEntityItem::getJointRotation(int index) const {
|
||||
if (_model) {
|
||||
glm::quat result;
|
||||
if (_model->getJointRotation(index, result)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return glm::quat();
|
||||
}
|
||||
|
||||
glm::vec3 RenderableModelEntityItem::getJointTranslation(int index) const {
|
||||
if (_model) {
|
||||
glm::vec3 result;
|
||||
if (_model->getJointTranslation(index, result)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
|
|
|
@ -24,11 +24,11 @@ class RenderableModelEntityItem : public ModelEntityItem {
|
|||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
RenderableModelEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
|
||||
RenderableModelEntityItem(const EntityItemID& entityItemID, bool dimensionsInitialized);
|
||||
|
||||
virtual ~RenderableModelEntityItem();
|
||||
|
||||
virtual void setDimensions(const glm::vec3& value) override;
|
||||
virtual void setDimensions(const glm::vec3 value) override;
|
||||
|
||||
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override;
|
||||
virtual bool setProperties(const EntityItemProperties& properties) override;
|
||||
|
@ -67,6 +67,10 @@ public:
|
|||
|
||||
virtual bool contains(const glm::vec3& point) const override;
|
||||
|
||||
// these are in the frame of this object
|
||||
virtual glm::quat getJointRotation(int index) const;
|
||||
virtual glm::vec3 getJointTranslation(int index) const;
|
||||
|
||||
private:
|
||||
void remapTextures();
|
||||
|
||||
|
|
|
@ -117,13 +117,15 @@ namespace render {
|
|||
|
||||
|
||||
|
||||
EntityItemPointer RenderableParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
return std::make_shared<RenderableParticleEffectEntityItem>(entityID, properties);
|
||||
EntityItemPointer RenderableParticleEffectEntityItem::factory(const EntityItemID& entityID,
|
||||
const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity{ new RenderableParticleEffectEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
RenderableParticleEffectEntityItem::RenderableParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
ParticleEffectEntityItem(entityItemID, properties) {
|
||||
|
||||
RenderableParticleEffectEntityItem::RenderableParticleEffectEntityItem(const EntityItemID& entityItemID) :
|
||||
ParticleEffectEntityItem(entityItemID) {
|
||||
// lazy creation of particle system pipeline
|
||||
if (!_untexturedPipeline && !_texturedPipeline) {
|
||||
createPipelines();
|
||||
|
@ -134,13 +136,14 @@ bool RenderableParticleEffectEntityItem::addToScene(EntityItemPointer self,
|
|||
render::ScenePointer scene,
|
||||
render::PendingChanges& pendingChanges) {
|
||||
|
||||
auto particlePayload = std::shared_ptr<ParticlePayload>(new ParticlePayload(shared_from_this()));
|
||||
auto particlePayload =
|
||||
std::shared_ptr<ParticlePayload>(new ParticlePayload(getThisPointer()));
|
||||
particlePayload->setPipeline(_untexturedPipeline);
|
||||
_renderItemId = scene->allocateID();
|
||||
auto renderData = ParticlePayload::Pointer(particlePayload);
|
||||
auto renderPayload = render::PayloadPointer(new ParticlePayload::Payload(renderData));
|
||||
render::Item::Status::Getters statusGetters;
|
||||
makeEntityItemStatusGetters(shared_from_this(), statusGetters);
|
||||
makeEntityItemStatusGetters(getThisPointer(), statusGetters);
|
||||
renderPayload->addStatusGetters(statusGetters);
|
||||
pendingChanges.resetItem(_renderItemId, renderPayload);
|
||||
_scene = scene;
|
||||
|
|
|
@ -19,7 +19,7 @@ class RenderableParticleEffectEntityItem : public ParticleEffectEntityItem {
|
|||
friend class ParticlePayload;
|
||||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
RenderableParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
|
||||
RenderableParticleEffectEntityItem(const EntityItemID& entityItemID);
|
||||
|
||||
virtual void update(const quint64& now) override;
|
||||
|
||||
|
|
|
@ -23,16 +23,16 @@
|
|||
#include "paintStroke_frag.h"
|
||||
|
||||
|
||||
|
||||
EntityItemPointer RenderablePolyLineEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
return EntityItemPointer(new RenderablePolyLineEntityItem(entityID, properties));
|
||||
EntityItemPointer entity{ new RenderablePolyLineEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
RenderablePolyLineEntityItem::RenderablePolyLineEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
PolyLineEntityItem(entityItemID, properties) {
|
||||
RenderablePolyLineEntityItem::RenderablePolyLineEntityItem(const EntityItemID& entityItemID) :
|
||||
PolyLineEntityItem(entityItemID) {
|
||||
_numVertices = 0;
|
||||
_vertices = QVector<glm::vec3>(0.0f);
|
||||
|
||||
}
|
||||
|
||||
gpu::PipelinePointer RenderablePolyLineEntityItem::_pipeline;
|
||||
|
|
|
@ -26,7 +26,7 @@ class RenderablePolyLineEntityItem : public PolyLineEntityItem {
|
|||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
static void createPipeline();
|
||||
RenderablePolyLineEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
|
||||
RenderablePolyLineEntityItem(const EntityItemID& entityItemID);
|
||||
|
||||
virtual void render(RenderArgs* args);
|
||||
|
||||
|
|
|
@ -50,12 +50,13 @@ gpu::PipelinePointer RenderablePolyVoxEntityItem::_pipeline = nullptr;
|
|||
const float MARCHING_CUBE_COLLISION_HULL_OFFSET = 0.5;
|
||||
|
||||
EntityItemPointer RenderablePolyVoxEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
return std::make_shared<RenderablePolyVoxEntityItem>(entityID, properties);
|
||||
EntityItemPointer entity{ new RenderablePolyVoxEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
RenderablePolyVoxEntityItem::RenderablePolyVoxEntityItem(const EntityItemID& entityItemID,
|
||||
const EntityItemProperties& properties) :
|
||||
PolyVoxEntityItem(entityItemID, properties),
|
||||
RenderablePolyVoxEntityItem::RenderablePolyVoxEntityItem(const EntityItemID& entityItemID) :
|
||||
PolyVoxEntityItem(entityItemID),
|
||||
_mesh(new model::Mesh()),
|
||||
_meshDirty(true),
|
||||
_xTexture(nullptr),
|
||||
|
@ -546,12 +547,12 @@ bool RenderablePolyVoxEntityItem::addToScene(EntityItemPointer self,
|
|||
render::PendingChanges& pendingChanges) {
|
||||
_myItem = scene->allocateID();
|
||||
|
||||
auto renderItem = std::make_shared<PolyVoxPayload>(shared_from_this());
|
||||
auto renderItem = std::make_shared<PolyVoxPayload>(getThisPointer());
|
||||
auto renderData = PolyVoxPayload::Pointer(renderItem);
|
||||
auto renderPayload = std::make_shared<PolyVoxPayload::Payload>(renderData);
|
||||
|
||||
render::Item::Status::Getters statusGetters;
|
||||
makeEntityItemStatusGetters(shared_from_this(), statusGetters);
|
||||
makeEntityItemStatusGetters(getThisPointer(), statusGetters);
|
||||
renderPayload->addStatusGetters(statusGetters);
|
||||
|
||||
pendingChanges.resetItem(_myItem, renderPayload);
|
||||
|
|
|
@ -44,8 +44,7 @@ namespace render {
|
|||
class RenderablePolyVoxEntityItem : public PolyVoxEntityItem {
|
||||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
RenderablePolyVoxEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
|
||||
RenderablePolyVoxEntityItem(const EntityItemID& entityItemID);
|
||||
|
||||
virtual ~RenderablePolyVoxEntityItem();
|
||||
|
||||
|
|
|
@ -29,7 +29,9 @@ static const float SPHERE_ENTITY_SCALE = 0.5f;
|
|||
|
||||
|
||||
EntityItemPointer RenderableSphereEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
return std::make_shared<RenderableSphereEntityItem>(entityID, properties);
|
||||
EntityItemPointer entity{ new RenderableSphereEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
void RenderableSphereEntityItem::setUserData(const QString& value) {
|
||||
|
|
|
@ -20,10 +20,7 @@
|
|||
class RenderableSphereEntityItem : public SphereEntityItem {
|
||||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
RenderableSphereEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
SphereEntityItem(entityItemID, properties)
|
||||
{ }
|
||||
RenderableSphereEntityItem(const EntityItemID& entityItemID) : SphereEntityItem(entityItemID) { }
|
||||
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual void setUserData(const QString& value);
|
||||
|
|
|
@ -22,7 +22,9 @@
|
|||
#include "GLMHelpers.h"
|
||||
|
||||
EntityItemPointer RenderableTextEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
return std::make_shared<RenderableTextEntityItem>(entityID, properties);
|
||||
EntityItemPointer entity{ new RenderableTextEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
void RenderableTextEntityItem::render(RenderArgs* args) {
|
||||
|
|
|
@ -22,10 +22,7 @@ const int FIXED_FONT_POINT_SIZE = 40;
|
|||
class RenderableTextEntityItem : public TextEntityItem {
|
||||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
RenderableTextEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
TextEntityItem(entityItemID, properties)
|
||||
{ }
|
||||
RenderableTextEntityItem(const EntityItemID& entityItemID) : TextEntityItem(entityItemID) { }
|
||||
~RenderableTextEntityItem() { delete _textRenderer; }
|
||||
|
||||
virtual void render(RenderArgs* args);
|
||||
|
|
|
@ -31,11 +31,13 @@ const float DPI = 30.47f;
|
|||
const float METERS_TO_INCHES = 39.3701f;
|
||||
|
||||
EntityItemPointer RenderableWebEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
return std::make_shared<RenderableWebEntityItem>(entityID, properties);
|
||||
EntityItemPointer entity{ new RenderableWebEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
RenderableWebEntityItem::RenderableWebEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
WebEntityItem(entityItemID, properties) {
|
||||
RenderableWebEntityItem::RenderableWebEntityItem(const EntityItemID& entityItemID) :
|
||||
WebEntityItem(entityItemID) {
|
||||
qDebug() << "Created web entity " << getID();
|
||||
}
|
||||
|
||||
|
|
|
@ -22,8 +22,7 @@ class QObject;
|
|||
class RenderableWebEntityItem : public WebEntityItem {
|
||||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
RenderableWebEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
|
||||
RenderableWebEntityItem(const EntityItemID& entityItemID);
|
||||
~RenderableWebEntityItem();
|
||||
|
||||
virtual void render(RenderArgs* args);
|
||||
|
|
|
@ -26,7 +26,9 @@
|
|||
static const float SPHERE_ENTITY_SCALE = 0.5f;
|
||||
|
||||
EntityItemPointer RenderableZoneEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
return std::make_shared<RenderableZoneEntityItem>(entityID, properties);
|
||||
EntityItemPointer entity{ new RenderableZoneEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
template<typename Lambda>
|
||||
|
@ -115,7 +117,7 @@ void RenderableZoneEntityItem::render(RenderArgs* args) {
|
|||
render::PendingChanges pendingChanges;
|
||||
_model->removeFromScene(scene, pendingChanges);
|
||||
render::Item::Status::Getters statusGetters;
|
||||
makeEntityItemStatusGetters(shared_from_this(), statusGetters);
|
||||
makeEntityItemStatusGetters(getThisPointer(), statusGetters);
|
||||
_model->addToScene(scene, pendingChanges, false);
|
||||
|
||||
scene->enqueuePendingChanges(pendingChanges);
|
||||
|
@ -209,7 +211,7 @@ bool RenderableZoneEntityItem::addToScene(EntityItemPointer self, std::shared_pt
|
|||
auto renderPayload = std::make_shared<RenderableZoneEntityItemMeta::Payload>(renderData);
|
||||
|
||||
render::Item::Status::Getters statusGetters;
|
||||
makeEntityItemStatusGetters(shared_from_this(), statusGetters);
|
||||
makeEntityItemStatusGetters(getThisPointer(), statusGetters);
|
||||
renderPayload->addStatusGetters(statusGetters);
|
||||
|
||||
pendingChanges.resetItem(_myMetaItem, renderPayload);
|
||||
|
|
|
@ -21,10 +21,10 @@ class RenderableZoneEntityItem : public ZoneEntityItem {
|
|||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
RenderableZoneEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
ZoneEntityItem(entityItemID, properties),
|
||||
_model(NULL),
|
||||
_needsInitialSimulation(true)
|
||||
RenderableZoneEntityItem(const EntityItemID& entityItemID) :
|
||||
ZoneEntityItem(entityItemID),
|
||||
_model(NULL),
|
||||
_needsInitialSimulation(true)
|
||||
{ }
|
||||
|
||||
virtual bool setProperties(const EntityItemProperties& properties);
|
||||
|
|
83
libraries/entities/src/BoundingBoxRelatedProperties.cpp
Normal file
83
libraries/entities/src/BoundingBoxRelatedProperties.cpp
Normal file
|
@ -0,0 +1,83 @@
|
|||
//
|
||||
// BoundingBoxRelatedProperties.cpp
|
||||
// libraries/entities/src
|
||||
//
|
||||
// Created by Seth Alves on 2015-9-24
|
||||
// Copyright 2013 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "EntityItemProperties.h"
|
||||
#include "BoundingBoxRelatedProperties.h"
|
||||
#include "EntityTree.h"
|
||||
|
||||
BoundingBoxRelatedProperties::BoundingBoxRelatedProperties(EntityItemPointer entity) :
|
||||
position(entity->getPosition()),
|
||||
rotation(entity->getRotation()),
|
||||
registrationPoint(entity->getRegistrationPoint()),
|
||||
dimensions(entity->getDimensions()),
|
||||
parentID(entity->getParentID()) {
|
||||
}
|
||||
|
||||
BoundingBoxRelatedProperties::BoundingBoxRelatedProperties(EntityItemPointer entity,
|
||||
const EntityItemProperties& propertiesWithUpdates) :
|
||||
BoundingBoxRelatedProperties(entity) {
|
||||
|
||||
if (propertiesWithUpdates.parentIDChanged()) {
|
||||
parentID = propertiesWithUpdates.getParentID();
|
||||
}
|
||||
|
||||
bool parentFound = false;
|
||||
if (parentID != UNKNOWN_ENTITY_ID) {
|
||||
EntityTreePointer tree = entity->getTree();
|
||||
EntityItemPointer parentZone = tree->findEntityByID(parentID);
|
||||
if (parentZone) {
|
||||
parentFound = true;
|
||||
glm::vec3 localPosition = propertiesWithUpdates.containsPositionChange() ?
|
||||
propertiesWithUpdates.getPosition() :
|
||||
entity->getLocalPosition();
|
||||
|
||||
glm::quat localRotation = propertiesWithUpdates.rotationChanged() ?
|
||||
propertiesWithUpdates.getRotation() :
|
||||
entity->getLocalOrientation();
|
||||
|
||||
const Transform parentTransform = parentZone->getTransformToCenter();
|
||||
Transform parentDescaled(parentTransform.getRotation(), glm::vec3(1.0f), parentTransform.getTranslation());
|
||||
|
||||
Transform localTransform(localRotation, glm::vec3(1.0f), localPosition);
|
||||
Transform result;
|
||||
Transform::mult(result, parentDescaled, localTransform);
|
||||
position = result.getTranslation();
|
||||
rotation = result.getRotation();
|
||||
}
|
||||
}
|
||||
|
||||
if (!parentFound) {
|
||||
if (propertiesWithUpdates.containsPositionChange()) {
|
||||
position = propertiesWithUpdates.getPosition();
|
||||
}
|
||||
if (propertiesWithUpdates.rotationChanged()) {
|
||||
rotation = propertiesWithUpdates.getRotation();
|
||||
}
|
||||
}
|
||||
|
||||
if (propertiesWithUpdates.registrationPointChanged()) {
|
||||
registrationPoint = propertiesWithUpdates.getRegistrationPoint();
|
||||
}
|
||||
|
||||
if (propertiesWithUpdates.dimensionsChanged()) {
|
||||
dimensions = propertiesWithUpdates.getDimensions();
|
||||
}
|
||||
}
|
||||
|
||||
AACube BoundingBoxRelatedProperties::getMaximumAACube() const {
|
||||
// see EntityItem::getMaximumAACube for comments which explain the following.
|
||||
glm::vec3 scaledRegistrationPoint = (dimensions * registrationPoint);
|
||||
glm::vec3 registrationRemainder = (dimensions * (glm::vec3(1.0f, 1.0f, 1.0f) - registrationPoint));
|
||||
glm::vec3 furthestExtentFromRegistration = glm::max(scaledRegistrationPoint, registrationRemainder);
|
||||
float radius = glm::length(furthestExtentFromRegistration);
|
||||
glm::vec3 minimumCorner = position - glm::vec3(radius, radius, radius);
|
||||
return AACube(minimumCorner, radius * 2.0f);
|
||||
}
|
30
libraries/entities/src/BoundingBoxRelatedProperties.h
Normal file
30
libraries/entities/src/BoundingBoxRelatedProperties.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// BoundingBoxRelatedProperties.h
|
||||
// libraries/entities/src
|
||||
//
|
||||
// Created by Seth Alves on 2015-9-24
|
||||
// Copyright 2013 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "EntityItem.h"
|
||||
|
||||
#ifndef hifi_BoundingBoxRelatedProperties_h
|
||||
#define hifi_BoundingBoxRelatedProperties_h
|
||||
|
||||
class BoundingBoxRelatedProperties {
|
||||
public:
|
||||
BoundingBoxRelatedProperties(EntityItemPointer entity);
|
||||
BoundingBoxRelatedProperties(EntityItemPointer entity, const EntityItemProperties& propertiesWithUpdates);
|
||||
AACube getMaximumAACube() const;
|
||||
|
||||
glm::vec3 position;
|
||||
glm::quat rotation;
|
||||
glm::vec3 registrationPoint;
|
||||
glm::vec3 dimensions;
|
||||
EntityItemID parentID;
|
||||
};
|
||||
|
||||
#endif // hifi_BoundingBoxRelatedProperties_h
|
|
@ -21,15 +21,13 @@
|
|||
#include "EntityTreeElement.h"
|
||||
|
||||
EntityItemPointer BoxEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer result { new BoxEntityItem(entityID, properties) };
|
||||
return result;
|
||||
EntityItemPointer entity { new BoxEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
BoxEntityItem::BoxEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
EntityItem(entityItemID)
|
||||
{
|
||||
BoxEntityItem::BoxEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID) {
|
||||
_type = EntityTypes::Box;
|
||||
setProperties(properties);
|
||||
}
|
||||
|
||||
EntityItemProperties BoxEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
|
||||
|
|
|
@ -18,7 +18,7 @@ class BoxEntityItem : public EntityItem {
|
|||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
BoxEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
|
||||
BoxEntityItem(const EntityItemID& entityItemID);
|
||||
|
||||
ALLOW_INSTANTIATION // This class can be instantiated
|
||||
|
||||
|
|
|
@ -36,8 +36,8 @@ int EntityItem::_maxActionsDataSize = 800;
|
|||
quint64 EntityItem::_rememberDeletedActionTime = 20 * USECS_PER_SECOND;
|
||||
|
||||
EntityItem::EntityItem(const EntityItemID& entityItemID) :
|
||||
SpatiallyNestable(NestableTypes::Entity, entityItemID),
|
||||
_type(EntityTypes::Unknown),
|
||||
_id(entityItemID),
|
||||
_lastSimulated(0),
|
||||
_lastUpdated(0),
|
||||
_lastEdited(0),
|
||||
|
@ -45,7 +45,6 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) :
|
|||
_lastEditedFromRemoteInRemoteTime(0),
|
||||
_created(UNKNOWN_CREATED_TIME),
|
||||
_changedOnServer(0),
|
||||
_transform(),
|
||||
_glowLevel(ENTITY_ITEM_DEFAULT_GLOW_LEVEL),
|
||||
_localRenderAlpha(ENTITY_ITEM_DEFAULT_LOCAL_RENDER_ALPHA),
|
||||
_density(ENTITY_ITEM_DEFAULT_DENSITY),
|
||||
|
@ -79,9 +78,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) :
|
|||
_simulated(false)
|
||||
{
|
||||
// explicitly set transform parts to set dirty flags used by batch rendering
|
||||
_transform.setTranslation(ENTITY_ITEM_DEFAULT_POSITION);
|
||||
_transform.setRotation(ENTITY_ITEM_DEFAULT_ROTATION);
|
||||
_transform.setScale(ENTITY_ITEM_DEFAULT_DIMENSIONS);
|
||||
setScale(ENTITY_ITEM_DEFAULT_DIMENSIONS);
|
||||
quint64 now = usecTimestampNow();
|
||||
_lastSimulated = now;
|
||||
_lastUpdated = now;
|
||||
|
@ -134,6 +131,8 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param
|
|||
requestedProperties += PROP_HREF;
|
||||
requestedProperties += PROP_DESCRIPTION;
|
||||
requestedProperties += PROP_ACTION_DATA;
|
||||
requestedProperties += PROP_PARENT_ID;
|
||||
requestedProperties += PROP_PARENT_JOINT_INDEX;
|
||||
|
||||
return requestedProperties;
|
||||
}
|
||||
|
@ -240,8 +239,8 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
|||
// PROP_CUSTOM_PROPERTIES_INCLUDED,
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_SIMULATION_OWNER, _simulationOwner.toByteArray());
|
||||
APPEND_ENTITY_PROPERTY(PROP_POSITION, getPosition());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ROTATION, getRotation());
|
||||
APPEND_ENTITY_PROPERTY(PROP_POSITION, getLocalPosition());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ROTATION, getLocalOrientation());
|
||||
APPEND_ENTITY_PROPERTY(PROP_VELOCITY, getVelocity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, getAngularVelocity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ACCELERATION, getAcceleration());
|
||||
|
@ -268,7 +267,8 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
|||
APPEND_ENTITY_PROPERTY(PROP_HREF, getHref());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DESCRIPTION, getDescription());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ACTION_DATA, getActionData());
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_PARENT_ID, getParentID());
|
||||
APPEND_ENTITY_PROPERTY(PROP_PARENT_JOINT_INDEX, getParentJointIndex());
|
||||
|
||||
appendSubclassData(packetData, params, entityTreeElementExtraEncodeData,
|
||||
requestedProperties,
|
||||
|
@ -722,6 +722,9 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
READ_ENTITY_PROPERTY(PROP_DESCRIPTION, QString, setDescription);
|
||||
READ_ENTITY_PROPERTY(PROP_ACTION_DATA, QByteArray, setActionData);
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_PARENT_ID, QUuid, setParentID);
|
||||
READ_ENTITY_PROPERTY(PROP_PARENT_JOINT_INDEX, quint16, setParentJointIndex);
|
||||
|
||||
bytesRead += readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
|
||||
propertyFlags, overwriteLocalData, somethingChanged);
|
||||
|
||||
|
@ -1044,9 +1047,9 @@ EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProper
|
|||
properties._type = getType();
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(simulationOwner, getSimulationOwner);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(position, getPosition);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(position, getLocalPosition);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(dimensions, getDimensions); // NOTE: radius is obsolete
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(rotation, getRotation);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(rotation, getLocalOrientation);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(density, getDensity);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(velocity, getVelocity);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(gravity, getGravity);
|
||||
|
@ -1074,6 +1077,8 @@ EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProper
|
|||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(href, getHref);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(description, getDescription);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(actionData, getActionData);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(parentID, getParentID);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(parentJointIndex, getParentJointIndex);
|
||||
|
||||
properties._defaultSettings = false;
|
||||
|
||||
|
@ -1082,9 +1087,9 @@ EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProper
|
|||
|
||||
void EntityItem::getAllTerseUpdateProperties(EntityItemProperties& properties) const {
|
||||
// a TerseUpdate includes the transform and its derivatives
|
||||
properties._position = getPosition();
|
||||
properties._position = getLocalPosition();
|
||||
properties._velocity = _velocity;
|
||||
properties._rotation = getRotation();
|
||||
properties._rotation = getLocalOrientation();
|
||||
properties._angularVelocity = _angularVelocity;
|
||||
properties._acceleration = _acceleration;
|
||||
|
||||
|
@ -1136,6 +1141,8 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(href, setHref);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(description, setDescription);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(actionData, setActionData);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(parentID, setParentID);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(parentJointIndex, setParentJointIndex);
|
||||
|
||||
if (somethingChanged) {
|
||||
uint64_t now = usecTimestampNow();
|
||||
|
@ -1185,11 +1192,11 @@ const Transform EntityItem::getTransformToCenter() const {
|
|||
return result;
|
||||
}
|
||||
|
||||
void EntityItem::setDimensions(const glm::vec3& value) {
|
||||
void EntityItem::setDimensions(const glm::vec3 value) {
|
||||
if (value.x <= 0.0f || value.y <= 0.0f || value.z <= 0.0f) {
|
||||
return;
|
||||
}
|
||||
_transform.setScale(value);
|
||||
setScale(value);
|
||||
requiresRecalcBoxes();
|
||||
}
|
||||
|
||||
|
@ -1315,9 +1322,8 @@ void EntityItem::updatePosition(const glm::vec3& value) {
|
|||
if (shouldSuppressLocationEdits()) {
|
||||
return;
|
||||
}
|
||||
if (getPosition() != value) {
|
||||
setPosition(value);
|
||||
_dirtyFlags |= Simulation::DIRTY_POSITION;
|
||||
if (getLocalPosition() != value) {
|
||||
setLocalPosition(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1332,9 +1338,16 @@ void EntityItem::updateRotation(const glm::quat& rotation) {
|
|||
if (shouldSuppressLocationEdits()) {
|
||||
return;
|
||||
}
|
||||
if (getRotation() != rotation) {
|
||||
setRotation(rotation);
|
||||
if (getLocalOrientation() != rotation) {
|
||||
setLocalOrientation(rotation);
|
||||
_dirtyFlags |= Simulation::DIRTY_ROTATION;
|
||||
forEachDescendant([&](SpatiallyNestablePointer object) {
|
||||
if (object->getNestableType() == NestableTypes::Entity) {
|
||||
EntityItemPointer entity = std::static_pointer_cast<EntityItem>(object);
|
||||
entity->_dirtyFlags |= Simulation::DIRTY_ROTATION;
|
||||
entity->_dirtyFlags |= Simulation::DIRTY_POSITION;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1523,7 +1536,6 @@ bool EntityItem::addAction(EntitySimulation* simulation, EntityActionPointer act
|
|||
}
|
||||
|
||||
bool EntityItem::addActionInternal(EntitySimulation* simulation, EntityActionPointer action) {
|
||||
assertLocked();
|
||||
assert(action);
|
||||
assert(simulation);
|
||||
auto actionOwnerEntity = action->getOwnerEntity().lock();
|
||||
|
@ -1579,7 +1591,6 @@ bool EntityItem::removeAction(EntitySimulation* simulation, const QUuid& actionI
|
|||
}
|
||||
|
||||
bool EntityItem::removeActionInternal(const QUuid& actionID, EntitySimulation* simulation) {
|
||||
assertWriteLocked();
|
||||
_previouslyDeletedActions.insert(actionID, usecTimestampNow());
|
||||
if (_objectActions.contains(actionID)) {
|
||||
if (!simulation) {
|
||||
|
@ -1625,7 +1636,6 @@ bool EntityItem::clearActions(EntitySimulation* simulation) {
|
|||
|
||||
|
||||
void EntityItem::deserializeActions() {
|
||||
assertUnlocked();
|
||||
withWriteLock([&] {
|
||||
deserializeActionsInternal();
|
||||
});
|
||||
|
@ -1633,8 +1643,6 @@ void EntityItem::deserializeActions() {
|
|||
|
||||
|
||||
void EntityItem::deserializeActionsInternal() {
|
||||
assertWriteLocked();
|
||||
|
||||
quint64 now = usecTimestampNow();
|
||||
|
||||
if (!_element) {
|
||||
|
@ -1676,7 +1684,7 @@ void EntityItem::deserializeActionsInternal() {
|
|||
action->locallyAddedButNotYetReceived = false;
|
||||
} else {
|
||||
auto actionFactory = DependencyManager::get<EntityActionFactoryInterface>();
|
||||
EntityItemPointer entity = shared_from_this();
|
||||
EntityItemPointer entity = getThisPointer();
|
||||
EntityActionPointer action = actionFactory->factoryBA(entity, serializedAction);
|
||||
if (action) {
|
||||
entity->addActionInternal(simulation, action);
|
||||
|
@ -1717,7 +1725,6 @@ void EntityItem::deserializeActionsInternal() {
|
|||
}
|
||||
|
||||
void EntityItem::checkWaitingToRemove(EntitySimulation* simulation) {
|
||||
assertLocked();
|
||||
foreach(QUuid actionID, _actionsToRemove) {
|
||||
removeActionInternal(actionID, simulation);
|
||||
}
|
||||
|
@ -1725,14 +1732,12 @@ void EntityItem::checkWaitingToRemove(EntitySimulation* simulation) {
|
|||
}
|
||||
|
||||
void EntityItem::setActionData(QByteArray actionData) {
|
||||
assertUnlocked();
|
||||
withWriteLock([&] {
|
||||
setActionDataInternal(actionData);
|
||||
});
|
||||
}
|
||||
|
||||
void EntityItem::setActionDataInternal(QByteArray actionData) {
|
||||
assertWriteLocked();
|
||||
if (_allActionsDataCache != actionData) {
|
||||
_allActionsDataCache = actionData;
|
||||
deserializeActionsInternal();
|
||||
|
@ -1741,8 +1746,6 @@ void EntityItem::setActionDataInternal(QByteArray actionData) {
|
|||
}
|
||||
|
||||
void EntityItem::serializeActions(bool& success, QByteArray& result) const {
|
||||
assertLocked();
|
||||
|
||||
if (_objectActions.size() == 0) {
|
||||
success = true;
|
||||
result.clear();
|
||||
|
@ -1785,7 +1788,6 @@ const QByteArray EntityItem::getActionDataInternal() const {
|
|||
|
||||
const QByteArray EntityItem::getActionData() const {
|
||||
QByteArray result;
|
||||
assertUnlocked();
|
||||
|
||||
if (_actionDataDirty) {
|
||||
withWriteLock([&] {
|
||||
|
@ -1839,3 +1841,8 @@ QList<EntityActionPointer> EntityItem::getActionsOfType(EntityActionType typeToG
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
void EntityItem::locationChanged() {
|
||||
requiresRecalcBoxes();
|
||||
SpatiallyNestable::locationChanged(); // tell all the children, also
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <OctreePacketData.h>
|
||||
#include <ShapeInfo.h>
|
||||
#include <Transform.h>
|
||||
#include <SpatiallyNestable.h>
|
||||
|
||||
#include "EntityItemID.h"
|
||||
#include "EntityItemPropertiesDefaults.h"
|
||||
|
@ -55,31 +56,10 @@ namespace render {
|
|||
#define debugTimeOnly(T) qPrintable(QString("%1").arg(T, 16, 10))
|
||||
#define debugTreeVector(V) V << "[" << V << " in meters ]"
|
||||
|
||||
//#if DEBUG
|
||||
// #define assertLocked() assert(isLocked())
|
||||
//#else
|
||||
// #define assertLocked()
|
||||
//#endif
|
||||
//
|
||||
//#if DEBUG
|
||||
// #define assertWriteLocked() assert(isWriteLocked())
|
||||
//#else
|
||||
// #define assertWriteLocked()
|
||||
//#endif
|
||||
//
|
||||
//#if DEBUG
|
||||
// #define assertUnlocked() assert(isUnlocked())
|
||||
//#else
|
||||
// #define assertUnlocked()
|
||||
//#endif
|
||||
#define assertLocked()
|
||||
#define assertUnlocked()
|
||||
#define assertWriteLocked()
|
||||
|
||||
/// EntityItem class this is the base class for all entity types. It handles the basic properties and functionality available
|
||||
/// to all other entity types. In particular: postion, size, rotation, age, lifetime, velocity, gravity. You can not instantiate
|
||||
/// one directly, instead you must only construct one of it's derived classes with additional features.
|
||||
class EntityItem : public std::enable_shared_from_this<EntityItem>, public ReadWriteLockable {
|
||||
class EntityItem : public SpatiallyNestable, public ReadWriteLockable {
|
||||
// These two classes manage lists of EntityItem pointers and must be able to cleanup pointers when an EntityItem is deleted.
|
||||
// To make the cleanup robust each EntityItem has backpointers to its manager classes (which are only ever set/cleared by
|
||||
// the managers themselves, hence they are fiends) whose NULL status can be used to determine which managers still need to
|
||||
|
@ -93,9 +73,8 @@ public:
|
|||
EntityItem(const EntityItemID& entityItemID);
|
||||
virtual ~EntityItem();
|
||||
|
||||
// ID and EntityItemID related methods
|
||||
const QUuid& getID() const { return _id; }
|
||||
void setID(const QUuid& id) { _id = id; }
|
||||
inline EntityItemPointer getThisPointer() { return std::static_pointer_cast<EntityItem>(shared_from_this()); }
|
||||
|
||||
EntityItemID getEntityItemID() const { return EntityItemID(_id); }
|
||||
|
||||
// methods for getting/setting all properties of an entity
|
||||
|
@ -188,16 +167,6 @@ public:
|
|||
const Transform getTransformToCenter() const;
|
||||
void setTranformToCenter(const Transform& transform);
|
||||
|
||||
inline const Transform& getTransform() const { return _transform; }
|
||||
inline void setTransform(const Transform& transform) { _transform = transform; requiresRecalcBoxes(); }
|
||||
|
||||
/// Position in meters (-TREE_SCALE - TREE_SCALE)
|
||||
inline const glm::vec3& getPosition() const { return _transform.getTranslation(); }
|
||||
inline void setPosition(const glm::vec3& value) { _transform.setTranslation(value); requiresRecalcBoxes(); }
|
||||
|
||||
inline const glm::quat& getRotation() const { return _transform.getRotation(); }
|
||||
inline void setRotation(const glm::quat& rotation) { _transform.setRotation(rotation); requiresRecalcBoxes(); }
|
||||
|
||||
inline void requiresRecalcBoxes() { _recalcAABox = true; _recalcMinAACube = true; _recalcMaxAACube = true; }
|
||||
|
||||
// Hyperlink related getters and setters
|
||||
|
@ -208,8 +177,8 @@ public:
|
|||
void setDescription(QString value) { _description = value; }
|
||||
|
||||
/// Dimensions in meters (0.0 - TREE_SCALE)
|
||||
inline const glm::vec3& getDimensions() const { return _transform.getScale(); }
|
||||
virtual void setDimensions(const glm::vec3& value);
|
||||
inline const glm::vec3 getDimensions() const { return getScale(); }
|
||||
virtual void setDimensions(const glm::vec3 value);
|
||||
|
||||
float getGlowLevel() const { return _glowLevel; }
|
||||
void setGlowLevel(float glowLevel) { _glowLevel = glowLevel; }
|
||||
|
@ -337,6 +306,10 @@ public:
|
|||
/// return preferred shape type (actual physical shape may differ)
|
||||
virtual ShapeType getShapeType() const { return SHAPE_TYPE_NONE; }
|
||||
|
||||
// these are only needed because the names don't match
|
||||
virtual const glm::quat getRotation() const { return getOrientation(); }
|
||||
virtual void setRotation(glm::quat orientation) { setOrientation(orientation); }
|
||||
|
||||
// updateFoo() methods to be used when changes need to be accumulated in the _dirtyFlags
|
||||
void updatePosition(const glm::vec3& value);
|
||||
void updateDimensions(const glm::vec3& value);
|
||||
|
@ -405,13 +378,17 @@ public:
|
|||
|
||||
QList<EntityActionPointer> getActionsOfType(EntityActionType typeToGet);
|
||||
|
||||
// these are in the frame of this object
|
||||
virtual glm::quat getJointRotation(int index) const { return glm::quat(); }
|
||||
virtual glm::vec3 getJointTranslation(int index) const { return glm::vec3(0.0f); }
|
||||
|
||||
protected:
|
||||
|
||||
const QByteArray getActionDataInternal() const;
|
||||
void setActionDataInternal(QByteArray actionData);
|
||||
|
||||
virtual void locationChanged();
|
||||
EntityTypes::EntityType _type;
|
||||
QUuid _id;
|
||||
quint64 _lastSimulated; // last time this entity called simulate(), this includes velocity, angular velocity,
|
||||
// and physics changes
|
||||
quint64 _lastUpdated; // last time this entity called update(), this includes animations and non-physics changes
|
||||
|
@ -423,7 +400,6 @@ protected:
|
|||
quint64 _created;
|
||||
quint64 _changedOnServer;
|
||||
|
||||
Transform _transform;
|
||||
mutable AABox _cachedAABox;
|
||||
mutable AACube _maxAACube;
|
||||
mutable AACube _minAACube;
|
||||
|
|
|
@ -260,6 +260,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
CHECK_PROPERTY_CHANGE(PROP_X_P_NEIGHBOR_ID, xPNeighborID);
|
||||
CHECK_PROPERTY_CHANGE(PROP_Y_P_NEIGHBOR_ID, yPNeighborID);
|
||||
CHECK_PROPERTY_CHANGE(PROP_Z_P_NEIGHBOR_ID, zPNeighborID);
|
||||
CHECK_PROPERTY_CHANGE(PROP_PARENT_ID, parentID);
|
||||
CHECK_PROPERTY_CHANGE(PROP_PARENT_JOINT_INDEX, parentJointIndex);
|
||||
|
||||
changedProperties += _animation.getChangedProperties();
|
||||
changedProperties += _keyLight.getChangedProperties();
|
||||
|
@ -353,7 +355,8 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_START, alphaStart);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_FINISH, alphaFinish);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ADDITIVE_BLENDING, additiveBlending);
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_POSITION, localPosition);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_ROTATION, localRotation);
|
||||
}
|
||||
|
||||
// Models only
|
||||
|
@ -468,6 +471,12 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(originalTextures, textureNamesList); // gettable, but not settable
|
||||
}
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_PARENT_ID, parentID);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_PARENT_JOINT_INDEX, parentJointIndex);
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_POSITION, localPosition);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_ROTATION, localRotation);
|
||||
|
||||
// FIXME - I don't think these properties are supported any more
|
||||
//COPY_PROPERTY_TO_QSCRIPTVALUE(glowLevel);
|
||||
//COPY_PROPERTY_TO_QSCRIPTVALUE(localRenderAlpha);
|
||||
|
@ -590,6 +599,12 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
|
|||
COPY_PROPERTY_FROM_QSCRIPTVALUE(yPNeighborID, EntityItemID, setYPNeighborID);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(zPNeighborID, EntityItemID, setZPNeighborID);
|
||||
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(parentID, QUuid, setParentID);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(parentJointIndex, quint16, setParentJointIndex);
|
||||
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(localPosition, glmVec3, setLocalPosition);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(localRotation, glmQuat, setLocalRotation);
|
||||
|
||||
_lastEdited = usecTimestampNow();
|
||||
}
|
||||
|
||||
|
@ -906,7 +921,8 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
|
|||
APPEND_ENTITY_PROPERTY(PROP_USER_DATA, properties.getUserData());
|
||||
APPEND_ENTITY_PROPERTY(PROP_HREF, properties.getHref());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DESCRIPTION, properties.getDescription());
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_PARENT_ID, properties.getParentID());
|
||||
APPEND_ENTITY_PROPERTY(PROP_PARENT_JOINT_INDEX, properties.getParentJointIndex());
|
||||
|
||||
if (properties.getType() == EntityTypes::Web) {
|
||||
APPEND_ENTITY_PROPERTY(PROP_SOURCE_URL, properties.getSourceUrl());
|
||||
|
@ -1191,7 +1207,8 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_USER_DATA, QString, setUserData);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_HREF, QString, setHref);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DESCRIPTION, QString, setDescription);
|
||||
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARENT_ID, QUuid, setParentID);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARENT_JOINT_INDEX, quint16, setParentJointIndex);
|
||||
|
||||
if (properties.getType() == EntityTypes::Web) {
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SOURCE_URL, QString, setSourceUrl);
|
||||
|
@ -1441,6 +1458,9 @@ void EntityItemProperties::markAllChanged() {
|
|||
_xPNeighborIDChanged = true;
|
||||
_yPNeighborIDChanged = true;
|
||||
_zPNeighborIDChanged = true;
|
||||
|
||||
_parentIDChanged = true;
|
||||
_parentJointIndexChanged = true;
|
||||
}
|
||||
|
||||
/// The maximum bounding cube for the entity, independent of it's rotation.
|
||||
|
@ -1478,7 +1498,7 @@ AABox EntityItemProperties::getAABox() const {
|
|||
glm::vec3 unrotatedMinRelativeToEntity = - (_dimensions * _registrationPoint);
|
||||
glm::vec3 unrotatedMaxRelativeToEntity = _dimensions * registrationRemainder;
|
||||
Extents unrotatedExtentsRelativeToRegistrationPoint = { unrotatedMinRelativeToEntity, unrotatedMaxRelativeToEntity };
|
||||
Extents rotatedExtentsRelativeToRegistrationPoint = unrotatedExtentsRelativeToRegistrationPoint.getRotated(getRotation());
|
||||
Extents rotatedExtentsRelativeToRegistrationPoint = unrotatedExtentsRelativeToRegistrationPoint.getRotated(_rotation);
|
||||
|
||||
// shift the extents to be relative to the position/registration point
|
||||
rotatedExtentsRelativeToRegistrationPoint.shiftBy(_position);
|
||||
|
@ -1769,3 +1789,7 @@ QList<QString> EntityItemProperties::listChangedProperties() {
|
|||
|
||||
return out;
|
||||
}
|
||||
|
||||
bool EntityItemProperties::parentDependentPropertyChanged() {
|
||||
return localPositionChanged() || positionChanged() || localRotationChanged() || rotationChanged();
|
||||
}
|
||||
|
|
|
@ -83,6 +83,8 @@ public:
|
|||
{ return (float)(usecTimestampNow() - getLastEdited()) / (float)USECS_PER_SECOND; }
|
||||
EntityPropertyFlags getChangedProperties() const;
|
||||
|
||||
bool parentDependentPropertyChanged(); // was there a changed in a property that requires parent info to interpret?
|
||||
|
||||
AACube getMaximumAACube() const;
|
||||
AABox getAABox() const;
|
||||
|
||||
|
@ -189,6 +191,12 @@ public:
|
|||
DEFINE_PROPERTY_REF(PROP_X_P_NEIGHBOR_ID, XPNeighborID, xPNeighborID, EntityItemID, UNKNOWN_ENTITY_ID);
|
||||
DEFINE_PROPERTY_REF(PROP_Y_P_NEIGHBOR_ID, YPNeighborID, yPNeighborID, EntityItemID, UNKNOWN_ENTITY_ID);
|
||||
DEFINE_PROPERTY_REF(PROP_Z_P_NEIGHBOR_ID, ZPNeighborID, zPNeighborID, EntityItemID, UNKNOWN_ENTITY_ID);
|
||||
DEFINE_PROPERTY_REF(PROP_PARENT_ID, ParentID, parentID, QUuid, UNKNOWN_ENTITY_ID);
|
||||
DEFINE_PROPERTY_REF(PROP_PARENT_JOINT_INDEX, ParentJointIndex, parentJointIndex, quint16, 0);
|
||||
|
||||
// these are used when bouncing location data into and out of scripts
|
||||
DEFINE_PROPERTY_REF(PROP_LOCAL_POSITION, LocalPosition, localPosition, glmVec3, ENTITY_ITEM_ZERO_VEC3);
|
||||
DEFINE_PROPERTY_REF(PROP_LOCAL_ROTATION, LocalRotation, localRotation, glmQuat, ENTITY_ITEM_DEFAULT_ROTATION);
|
||||
|
||||
static QString getBackgroundModeString(BackgroundMode mode);
|
||||
|
||||
|
@ -387,6 +395,9 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) {
|
|||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, YPNeighborID, yPNeighborID, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, ZPNeighborID, zPNeighborID, "");
|
||||
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, ParentID, parentID, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, ParentJointIndex, parentJointIndex, "");
|
||||
|
||||
properties.getAnimation().debugDump();
|
||||
properties.getAtmosphere().debugDump();
|
||||
properties.getSkybox().debugDump();
|
||||
|
|
|
@ -104,6 +104,7 @@
|
|||
inline QScriptValue convertScriptValue(QScriptEngine* e, const glm::vec3& v) { return vec3toScriptValue(e, v); }
|
||||
inline QScriptValue convertScriptValue(QScriptEngine* e, float v) { return QScriptValue(v); }
|
||||
inline QScriptValue convertScriptValue(QScriptEngine* e, int v) { return QScriptValue(v); }
|
||||
inline QScriptValue convertScriptValue(QScriptEngine* e, quint16 v) { return QScriptValue(v); }
|
||||
inline QScriptValue convertScriptValue(QScriptEngine* e, quint32 v) { return QScriptValue(v); }
|
||||
inline QScriptValue convertScriptValue(QScriptEngine* e, quint64 v) { return QScriptValue((qsreal)v); }
|
||||
inline QScriptValue convertScriptValue(QScriptEngine* e, const QString& v) { return QScriptValue(v); }
|
||||
|
@ -179,6 +180,7 @@ inline quint32 quint32_convertFromScriptValue(const QScriptValue& v, bool& isVal
|
|||
// Use QString::toUInt() so that isValid is set to false if the number is outside the quint32 range.
|
||||
return v.toString().toUInt(&isValid);
|
||||
}
|
||||
inline quint16 quint16_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toInt(&isValid); }
|
||||
inline uint16_t uint16_t_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toInt(&isValid); }
|
||||
inline int int_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toInt(&isValid); }
|
||||
inline bool bool_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; return v.toVariant().toBool(); }
|
||||
|
|
|
@ -151,6 +151,12 @@ enum EntityPropertyList {
|
|||
|
||||
PROP_ADDITIVE_BLENDING,
|
||||
|
||||
PROP_PARENT_ID,
|
||||
PROP_PARENT_JOINT_INDEX,
|
||||
|
||||
PROP_LOCAL_POSITION, // only used to convert values to and from scripts
|
||||
PROP_LOCAL_ROTATION, // only used to convert values to and from scripts
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ATTENTION: add new properties to end of list just ABOVE this line
|
||||
PROP_AFTER_LAST_ITEM,
|
||||
|
|
|
@ -64,8 +64,56 @@ void EntityScriptingInterface::setEntityTree(EntityTreePointer elementTree) {
|
|||
}
|
||||
}
|
||||
|
||||
EntityItemProperties convertLocationToScriptSemantics(EntityItemProperties entitySideProperties) {
|
||||
// In EntityTree code, properties.position and properties.rotation are relative to the parent. In javascript,
|
||||
// they are in world-space. The local versions are put into localPosition and localRotation and position and
|
||||
// rotation are converted from local to world space.
|
||||
EntityItemProperties scriptSideProperties = entitySideProperties;
|
||||
scriptSideProperties.setLocalPosition(entitySideProperties.getPosition());
|
||||
scriptSideProperties.setLocalRotation(entitySideProperties.getRotation());
|
||||
|
||||
glm::vec3 worldPosition = SpatiallyNestable::localToWorld(entitySideProperties.getPosition(),
|
||||
entitySideProperties.getParentID(),
|
||||
entitySideProperties.getParentJointIndex());
|
||||
glm::quat worldRotation = SpatiallyNestable::localToWorld(entitySideProperties.getRotation(),
|
||||
entitySideProperties.getParentID(),
|
||||
entitySideProperties.getParentJointIndex());
|
||||
scriptSideProperties.setPosition(worldPosition);
|
||||
scriptSideProperties.setRotation(worldRotation);
|
||||
|
||||
return scriptSideProperties;
|
||||
}
|
||||
|
||||
|
||||
EntityItemProperties convertLocationFromScriptSemantics(EntityItemProperties scriptSideProperties) {
|
||||
// convert position and rotation properties from world-space to local, unless localPosition and localRotation
|
||||
// are set. If they are set, they overwrite position and rotation.
|
||||
EntityItemProperties entitySideProperties = scriptSideProperties;
|
||||
|
||||
if (scriptSideProperties.localPositionChanged()) {
|
||||
entitySideProperties.setPosition(scriptSideProperties.getLocalPosition());
|
||||
} else if (scriptSideProperties.positionChanged()) {
|
||||
glm::vec3 localPosition = SpatiallyNestable::worldToLocal(entitySideProperties.getPosition(),
|
||||
entitySideProperties.getParentID(),
|
||||
entitySideProperties.getParentJointIndex());
|
||||
entitySideProperties.setPosition(localPosition);
|
||||
}
|
||||
|
||||
if (scriptSideProperties.localRotationChanged()) {
|
||||
entitySideProperties.setRotation(scriptSideProperties.getLocalRotation());
|
||||
} else if (scriptSideProperties.rotationChanged()) {
|
||||
glm::quat localRotation = SpatiallyNestable::worldToLocal(entitySideProperties.getRotation(),
|
||||
entitySideProperties.getParentID(),
|
||||
entitySideProperties.getParentJointIndex());
|
||||
entitySideProperties.setRotation(localRotation);
|
||||
}
|
||||
|
||||
return entitySideProperties;
|
||||
}
|
||||
|
||||
|
||||
QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties) {
|
||||
EntityItemProperties propertiesWithSimID = properties;
|
||||
EntityItemProperties propertiesWithSimID = convertLocationFromScriptSemantics(properties);
|
||||
propertiesWithSimID.setDimensionsInitialized(properties.dimensionsChanged());
|
||||
|
||||
EntityItemID id = EntityItemID(QUuid::createUuid());
|
||||
|
@ -111,6 +159,15 @@ EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identit
|
|||
_entityTree->withReadLock([&] {
|
||||
EntityItemPointer entity = _entityTree->findEntityByEntityItemID(EntityItemID(identity));
|
||||
if (entity) {
|
||||
if (desiredProperties.getHasProperty(PROP_POSITION) ||
|
||||
desiredProperties.getHasProperty(PROP_ROTATION) ||
|
||||
desiredProperties.getHasProperty(PROP_LOCAL_POSITION) ||
|
||||
desiredProperties.getHasProperty(PROP_LOCAL_ROTATION)) {
|
||||
// if we are explicitly getting position or rotation, we need parent information to make sense of them.
|
||||
desiredProperties.setHasProperty(PROP_PARENT_ID);
|
||||
desiredProperties.setHasProperty(PROP_PARENT_JOINT_INDEX);
|
||||
}
|
||||
|
||||
results = entity->getProperties(desiredProperties);
|
||||
|
||||
// TODO: improve sitting points and naturalDimensions in the future,
|
||||
|
@ -130,10 +187,11 @@ EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identit
|
|||
});
|
||||
}
|
||||
|
||||
return results;
|
||||
return convertLocationToScriptSemantics(results);
|
||||
}
|
||||
|
||||
QUuid EntityScriptingInterface::editEntity(QUuid id, EntityItemProperties properties) {
|
||||
QUuid EntityScriptingInterface::editEntity(QUuid id, EntityItemProperties scriptSideProperties) {
|
||||
EntityItemProperties properties = scriptSideProperties;
|
||||
EntityItemID entityID(id);
|
||||
// If we have a local entity tree set, then also update it.
|
||||
if (!_entityTree) {
|
||||
|
@ -143,10 +201,23 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, EntityItemProperties proper
|
|||
|
||||
bool updatedEntity = false;
|
||||
_entityTree->withWriteLock([&] {
|
||||
if (scriptSideProperties.parentDependentPropertyChanged()) {
|
||||
// if the script sets a location property but didn't include parent information, grab the needed
|
||||
// properties from the entity.
|
||||
if (!scriptSideProperties.parentIDChanged() || !scriptSideProperties.parentJointIndexChanged()) {
|
||||
EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID);
|
||||
if (entity && !scriptSideProperties.parentIDChanged()) {
|
||||
properties.setParentID(entity->getParentID());
|
||||
}
|
||||
if (entity && !scriptSideProperties.parentJointIndexChanged()) {
|
||||
properties.setParentJointIndex(entity->getParentJointIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
properties = convertLocationFromScriptSemantics(properties);
|
||||
updatedEntity = _entityTree->updateEntity(entityID, properties);
|
||||
});
|
||||
|
||||
|
||||
if (!updatedEntity) {
|
||||
return QUuid();
|
||||
}
|
||||
|
|
|
@ -140,8 +140,11 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
|
|||
if (!wantsLocked) {
|
||||
EntityItemProperties tempProperties;
|
||||
tempProperties.setLocked(wantsLocked);
|
||||
UpdateEntityOperator theOperator(getThisPointer(), containingElement, entity, tempProperties);
|
||||
|
||||
BoundingBoxRelatedProperties newBBRelProperties(entity, tempProperties);
|
||||
UpdateEntityOperator theOperator(getThisPointer(), containingElement, entity, newBBRelProperties);
|
||||
recurseTreeWithOperator(&theOperator);
|
||||
entity->setProperties(tempProperties);
|
||||
_isDirty = true;
|
||||
}
|
||||
}
|
||||
|
@ -206,8 +209,34 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
|
|||
quint64 entityScriptTimestampBefore = entity->getScriptTimestamp();
|
||||
QString collisionSoundURLBefore = entity->getCollisionSoundURL();
|
||||
uint32_t preFlags = entity->getDirtyFlags();
|
||||
UpdateEntityOperator theOperator(getThisPointer(), containingElement, entity, properties);
|
||||
|
||||
BoundingBoxRelatedProperties newBBRelProperties(entity, properties);
|
||||
UpdateEntityOperator theOperator(getThisPointer(), containingElement, entity, newBBRelProperties);
|
||||
recurseTreeWithOperator(&theOperator);
|
||||
entity->setProperties(properties);
|
||||
|
||||
// if the entity has children, run UpdateEntityOperator on them. If the children have children, recurse
|
||||
QQueue<SpatiallyNestablePointer> toProcess;
|
||||
foreach (SpatiallyNestablePointer child, entity->getChildren()) {
|
||||
if (child && child->getNestableType() == NestableTypes::Entity) {
|
||||
toProcess.enqueue(child);
|
||||
}
|
||||
}
|
||||
|
||||
while (!toProcess.empty()) {
|
||||
EntityItemPointer childEntity = std::static_pointer_cast<EntityItem>(toProcess.dequeue());
|
||||
BoundingBoxRelatedProperties newChildBBRelProperties(childEntity);
|
||||
UpdateEntityOperator theChildOperator(getThisPointer(),
|
||||
childEntity->getElement(),
|
||||
childEntity, newChildBBRelProperties);
|
||||
recurseTreeWithOperator(&theChildOperator);
|
||||
foreach (SpatiallyNestablePointer childChild, childEntity->getChildren()) {
|
||||
if (childChild && childChild->getNestableType() == NestableTypes::Entity) {
|
||||
toProcess.enqueue(childChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_isDirty = true;
|
||||
|
||||
uint32_t newFlags = entity->getDirtyFlags() & ~preFlags;
|
||||
|
|
|
@ -24,26 +24,23 @@
|
|||
bool LightEntityItem::_lightsArePickable = false;
|
||||
|
||||
EntityItemPointer LightEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer result { new LightEntityItem(entityID, properties) };
|
||||
return result;
|
||||
EntityItemPointer entity { new LightEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
// our non-pure virtual subclass for now...
|
||||
LightEntityItem::LightEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
EntityItem(entityItemID)
|
||||
{
|
||||
LightEntityItem::LightEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID) {
|
||||
_type = EntityTypes::Light;
|
||||
|
||||
|
||||
// default property values
|
||||
_color[RED_INDEX] = _color[GREEN_INDEX] = _color[BLUE_INDEX] = 0;
|
||||
_intensity = 1.0f;
|
||||
_exponent = 0.0f;
|
||||
_cutoff = PI;
|
||||
|
||||
setProperties(properties);
|
||||
}
|
||||
|
||||
void LightEntityItem::setDimensions(const glm::vec3& value) {
|
||||
void LightEntityItem::setDimensions(const glm::vec3 value) {
|
||||
if (_isSpotlight) {
|
||||
// If we are a spotlight, treat the z value as our radius or length, and
|
||||
// recalculate the x/y dimensions to properly encapsulate the spotlight.
|
||||
|
|
|
@ -18,12 +18,12 @@ class LightEntityItem : public EntityItem {
|
|||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
LightEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
|
||||
LightEntityItem(const EntityItemID& entityItemID);
|
||||
|
||||
ALLOW_INSTANTIATION // This class can be instantiated
|
||||
|
||||
/// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately
|
||||
virtual void setDimensions(const glm::vec3& value);
|
||||
virtual void setDimensions(const glm::vec3 value);
|
||||
|
||||
// methods for getting/setting all properties of an entity
|
||||
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const;
|
||||
|
|
|
@ -26,20 +26,18 @@ const int LineEntityItem::MAX_POINTS_PER_LINE = 70;
|
|||
|
||||
|
||||
EntityItemPointer LineEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer result { new LineEntityItem(entityID, properties) };
|
||||
return result;
|
||||
EntityItemPointer entity { new LineEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
LineEntityItem::LineEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
EntityItem(entityItemID) ,
|
||||
LineEntityItem::LineEntityItem(const EntityItemID& entityItemID) :
|
||||
EntityItem(entityItemID),
|
||||
_lineWidth(DEFAULT_LINE_WIDTH),
|
||||
_pointsChanged(true),
|
||||
_points(QVector<glm::vec3>(0))
|
||||
{
|
||||
_type = EntityTypes::Line;
|
||||
setProperties(properties);
|
||||
|
||||
|
||||
}
|
||||
|
||||
EntityItemProperties LineEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
|
||||
|
|
|
@ -18,7 +18,7 @@ class LineEntityItem : public EntityItem {
|
|||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
LineEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
|
||||
LineEntityItem(const EntityItemID& entityItemID);
|
||||
|
||||
ALLOW_INSTANTIATION // This class can be instantiated
|
||||
|
||||
|
|
|
@ -25,17 +25,17 @@ const QString ModelEntityItem::DEFAULT_MODEL_URL = QString("");
|
|||
const QString ModelEntityItem::DEFAULT_COMPOUND_SHAPE_URL = QString("");
|
||||
|
||||
EntityItemPointer ModelEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
return std::make_shared<ModelEntityItem>(entityID, properties);
|
||||
EntityItemPointer entity { new ModelEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
ModelEntityItem::ModelEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
EntityItem(entityItemID)
|
||||
ModelEntityItem::ModelEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID)
|
||||
{
|
||||
_animationProperties.associateWithAnimationLoop(&_animationLoop);
|
||||
_animationLoop.setResetOnRunning(false);
|
||||
|
||||
_type = EntityTypes::Model;
|
||||
setProperties(properties);
|
||||
_jointMappingCompleted = false;
|
||||
_lastKnownCurrentFrame = -1;
|
||||
_color[0] = _color[1] = _color[2] = 0;
|
||||
|
|
|
@ -21,7 +21,7 @@ class ModelEntityItem : public EntityItem {
|
|||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
ModelEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
|
||||
ModelEntityItem(const EntityItemID& entityItemID);
|
||||
|
||||
ALLOW_INSTANTIATION // This class can be instantiated
|
||||
|
||||
|
|
|
@ -98,11 +98,13 @@ const bool ParticleEffectEntityItem::DEFAULT_ADDITIVE_BLENDING = false;
|
|||
|
||||
|
||||
EntityItemPointer ParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
return std::make_shared<ParticleEffectEntityItem>(entityID, properties);
|
||||
EntityItemPointer entity { new ParticleEffectEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
// our non-pure virtual subclass for now...
|
||||
ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityItemID) :
|
||||
EntityItem(entityItemID),
|
||||
_lastSimulated(usecTimestampNow()),
|
||||
_particleLifetimes(DEFAULT_MAX_PARTICLES, 0.0f),
|
||||
|
@ -128,7 +130,6 @@ ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityIte
|
|||
|
||||
_type = EntityTypes::ParticleEffect;
|
||||
setColor(DEFAULT_COLOR);
|
||||
setProperties(properties);
|
||||
}
|
||||
|
||||
ParticleEffectEntityItem::~ParticleEffectEntityItem() {
|
||||
|
|
|
@ -20,7 +20,7 @@ public:
|
|||
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
ParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
|
||||
ParticleEffectEntityItem(const EntityItemID& entityItemID);
|
||||
virtual ~ParticleEffectEntityItem();
|
||||
|
||||
ALLOW_INSTANTIATION // This class can be instantiated
|
||||
|
|
|
@ -26,11 +26,12 @@ const int PolyLineEntityItem::MAX_POINTS_PER_LINE = 70;
|
|||
|
||||
|
||||
EntityItemPointer PolyLineEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer result{ new PolyLineEntityItem(entityID, properties) };
|
||||
return result;
|
||||
EntityItemPointer entity{ new PolyLineEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
PolyLineEntityItem::PolyLineEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
PolyLineEntityItem::PolyLineEntityItem(const EntityItemID& entityItemID) :
|
||||
EntityItem(entityItemID),
|
||||
_lineWidth(DEFAULT_LINE_WIDTH),
|
||||
_pointsChanged(true),
|
||||
|
@ -42,8 +43,6 @@ _strokeWidths(QVector<float>(0.0f)),
|
|||
_textures("")
|
||||
{
|
||||
_type = EntityTypes::PolyLine;
|
||||
_created = properties.getCreated();
|
||||
setProperties(properties);
|
||||
}
|
||||
|
||||
EntityItemProperties PolyLineEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
|
||||
|
|
|
@ -18,7 +18,7 @@ class PolyLineEntityItem : public EntityItem {
|
|||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
PolyLineEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
|
||||
PolyLineEntityItem(const EntityItemID& entityItemID);
|
||||
|
||||
ALLOW_INSTANTIATION // This class can be instantiated
|
||||
|
||||
|
|
|
@ -32,7 +32,9 @@ const QString PolyVoxEntityItem::DEFAULT_Y_TEXTURE_URL = QString("");
|
|||
const QString PolyVoxEntityItem::DEFAULT_Z_TEXTURE_URL = QString("");
|
||||
|
||||
EntityItemPointer PolyVoxEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
return std::make_shared<PolyVoxEntityItem>(entityID, properties);
|
||||
EntityItemPointer entity { new PolyVoxEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
QByteArray PolyVoxEntityItem::makeEmptyVoxelData(quint16 voxelXSize, quint16 voxelYSize, quint16 voxelZSize) {
|
||||
|
@ -49,7 +51,7 @@ QByteArray PolyVoxEntityItem::makeEmptyVoxelData(quint16 voxelXSize, quint16 vox
|
|||
return newVoxelData;
|
||||
}
|
||||
|
||||
PolyVoxEntityItem::PolyVoxEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
PolyVoxEntityItem::PolyVoxEntityItem(const EntityItemID& entityItemID) :
|
||||
EntityItem(entityItemID),
|
||||
_voxelVolumeSize(PolyVoxEntityItem::DEFAULT_VOXEL_VOLUME_SIZE),
|
||||
_voxelData(PolyVoxEntityItem::DEFAULT_VOXEL_DATA),
|
||||
|
@ -59,7 +61,6 @@ PolyVoxEntityItem::PolyVoxEntityItem(const EntityItemID& entityItemID, const Ent
|
|||
_yTextureURL(PolyVoxEntityItem::DEFAULT_Y_TEXTURE_URL),
|
||||
_zTextureURL(PolyVoxEntityItem::DEFAULT_Z_TEXTURE_URL) {
|
||||
_type = EntityTypes::PolyVox;
|
||||
setProperties(properties);
|
||||
}
|
||||
|
||||
void PolyVoxEntityItem::setVoxelVolumeSize(glm::vec3 voxelVolumeSize) {
|
||||
|
|
|
@ -18,7 +18,7 @@ class PolyVoxEntityItem : public EntityItem {
|
|||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
PolyVoxEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
|
||||
PolyVoxEntityItem(const EntityItemID& entityItemID);
|
||||
|
||||
ALLOW_INSTANTIATION // This class can be instantiated
|
||||
|
||||
|
|
|
@ -24,16 +24,14 @@
|
|||
#include "SphereEntityItem.h"
|
||||
|
||||
EntityItemPointer SphereEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer result { new SphereEntityItem(entityID, properties) };
|
||||
return result;
|
||||
EntityItemPointer entity { new SphereEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
// our non-pure virtual subclass for now...
|
||||
SphereEntityItem::SphereEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
EntityItem(entityItemID)
|
||||
{
|
||||
SphereEntityItem::SphereEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID) {
|
||||
_type = EntityTypes::Sphere;
|
||||
setProperties(properties);
|
||||
_volumeMultiplier *= PI / 6.0f;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ class SphereEntityItem : public EntityItem {
|
|||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
SphereEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
|
||||
SphereEntityItem(const EntityItemID& entityItemID);
|
||||
|
||||
ALLOW_INSTANTIATION // This class can be instantiated
|
||||
|
||||
|
|
|
@ -30,19 +30,18 @@ const xColor TextEntityItem::DEFAULT_BACKGROUND_COLOR = { 0, 0, 0};
|
|||
const bool TextEntityItem::DEFAULT_FACE_CAMERA = false;
|
||||
|
||||
EntityItemPointer TextEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
return std::make_shared<TextEntityItem>(entityID, properties);
|
||||
EntityItemPointer entity { new TextEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
TextEntityItem::TextEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
EntityItem(entityItemID)
|
||||
{
|
||||
TextEntityItem::TextEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID) {
|
||||
_type = EntityTypes::Text;
|
||||
setProperties(properties);
|
||||
}
|
||||
|
||||
const float TEXT_ENTITY_ITEM_FIXED_DEPTH = 0.01f;
|
||||
|
||||
void TextEntityItem::setDimensions(const glm::vec3& value) {
|
||||
void TextEntityItem::setDimensions(const glm::vec3 value) {
|
||||
// NOTE: Text Entities always have a "depth" of 1cm.
|
||||
EntityItem::setDimensions(glm::vec3(value.x, value.y, TEXT_ENTITY_ITEM_FIXED_DEPTH));
|
||||
}
|
||||
|
|
|
@ -18,12 +18,12 @@ class TextEntityItem : public EntityItem {
|
|||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
TextEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
|
||||
TextEntityItem(const EntityItemID& entityItemID);
|
||||
|
||||
ALLOW_INSTANTIATION // This class can be instantiated
|
||||
|
||||
/// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately
|
||||
virtual void setDimensions(const glm::vec3& value);
|
||||
virtual void setDimensions(const glm::vec3 value);
|
||||
virtual ShapeType getShapeType() const { return SHAPE_TYPE_BOX; }
|
||||
|
||||
// methods for getting/setting all properties of an entity
|
||||
|
|
|
@ -14,12 +14,12 @@
|
|||
UpdateEntityOperator::UpdateEntityOperator(EntityTreePointer tree,
|
||||
EntityTreeElementPointer containingElement,
|
||||
EntityItemPointer existingEntity,
|
||||
const EntityItemProperties& properties) :
|
||||
const BoundingBoxRelatedProperties& newProperties) :
|
||||
_tree(tree),
|
||||
_existingEntity(existingEntity),
|
||||
_containingElement(containingElement),
|
||||
_containingElementCube(containingElement->getAACube()),
|
||||
_properties(properties),
|
||||
_newProperties(newProperties),
|
||||
_entityItemID(existingEntity->getEntityItemID()),
|
||||
_foundOld(false),
|
||||
_foundNew(false),
|
||||
|
@ -44,83 +44,32 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTreePointer tree,
|
|||
_oldEntityCube = _existingEntity->getMaximumAACube();
|
||||
_oldEntityBox = _oldEntityCube.clamp((float)-HALF_TREE_SCALE, (float)HALF_TREE_SCALE); // clamp to domain bounds
|
||||
|
||||
// If the old properties doesn't contain the properties required to calculate a bounding box,
|
||||
// get them from the existing entity. Registration point is required to correctly calculate
|
||||
// the bounding box.
|
||||
if (!_properties.registrationPointChanged()) {
|
||||
_properties.setRegistrationPoint(_existingEntity->getRegistrationPoint());
|
||||
}
|
||||
|
||||
// If the new properties has position OR dimension changes, but not both, we need to
|
||||
// get the old property value and set it in our properties in order for our bounds
|
||||
// calculations to work.
|
||||
if (_properties.containsPositionChange() && !_properties.containsDimensionsChange()) {
|
||||
glm::vec3 oldDimensions= _existingEntity->getDimensions();
|
||||
_properties.setDimensions(oldDimensions);
|
||||
|
||||
if (_wantDebug) {
|
||||
qCDebug(entities) << " ** setting properties dimensions - had position change, no dimension change **";
|
||||
}
|
||||
|
||||
}
|
||||
if (!_properties.containsPositionChange() && _properties.containsDimensionsChange()) {
|
||||
glm::vec3 oldPosition= _existingEntity->getPosition();
|
||||
_properties.setPosition(oldPosition);
|
||||
|
||||
if (_wantDebug) {
|
||||
qCDebug(entities) << " ** setting properties position - had dimensions change, no position change **";
|
||||
}
|
||||
}
|
||||
|
||||
// If our new properties don't have bounds details (no change to position, etc) or if this containing element would
|
||||
// be the best fit for our new properties, then just do the new portion of the store pass, since the change path will
|
||||
// If our new properties don't have bounds details (no change to position, etc) or if this containing element would
|
||||
// be the best fit for our new properties, then just do the new portion of the store pass, since the change path will
|
||||
// be the same for both parts of the update
|
||||
bool oldElementBestFit = _containingElement->bestFitBounds(_properties);
|
||||
|
||||
// if we don't have bounds properties, then use our old clamped box to determine best fit
|
||||
if (!_properties.containsBoundsProperties()) {
|
||||
oldElementBestFit = _containingElement->bestFitBounds(_oldEntityBox);
|
||||
bool oldElementBestFit = _containingElement->bestFitBounds(newProperties.getMaximumAACube());
|
||||
|
||||
if (_wantDebug) {
|
||||
qCDebug(entities) << " ** old Element best fit - no dimensions change, no position change **";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// For some reason we've seen a case where the original containing element isn't a best fit for the old properties
|
||||
// in this case we want to move it, even if the properties haven't changed.
|
||||
if (!_properties.containsBoundsProperties() && !oldElementBestFit) {
|
||||
if (!oldElementBestFit) {
|
||||
_newEntityCube = _oldEntityCube;
|
||||
_removeOld = true; // our properties are going to move us, so remember this for later processing
|
||||
|
||||
if (_wantDebug) {
|
||||
qCDebug(entities) << " **** UNUSUAL CASE **** no changes, but not best fit... consider it a move.... **";
|
||||
}
|
||||
|
||||
|
||||
} else if (!_properties.containsBoundsProperties() || oldElementBestFit) {
|
||||
} else {
|
||||
_foundOld = true;
|
||||
_newEntityCube = _oldEntityCube;
|
||||
_dontMove = true;
|
||||
|
||||
if (_wantDebug) {
|
||||
qCDebug(entities) << " **** TYPICAL NO MOVE CASE ****";
|
||||
qCDebug(entities) << " _properties.containsBoundsProperties():" << _properties.containsBoundsProperties();
|
||||
qCDebug(entities) << " oldElementBestFit:" << oldElementBestFit;
|
||||
}
|
||||
|
||||
} else {
|
||||
_newEntityCube = _properties.getMaximumAACube();
|
||||
_removeOld = true; // our properties are going to move us, so remember this for later processing
|
||||
|
||||
if (_wantDebug) {
|
||||
qCDebug(entities) << " **** TYPICAL MOVE CASE ****";
|
||||
qCDebug(entities) << " **** TYPICAL NO MOVE CASE **** oldElementBestFit:" << oldElementBestFit;
|
||||
}
|
||||
}
|
||||
|
||||
_newEntityBox = _newEntityCube.clamp((float)-HALF_TREE_SCALE, (float)HALF_TREE_SCALE); // clamp to domain bounds
|
||||
|
||||
|
||||
if (_wantDebug) {
|
||||
qCDebug(entities) << " _entityItemID:" << _entityItemID;
|
||||
qCDebug(entities) << " _containingElementCube:" << _containingElementCube;
|
||||
|
@ -176,7 +125,7 @@ bool UpdateEntityOperator::subTreeContainsNewEntity(OctreeElementPointer element
|
|||
|
||||
bool UpdateEntityOperator::preRecursion(OctreeElementPointer element) {
|
||||
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
|
||||
|
||||
|
||||
// In Pre-recursion, we're generally deciding whether or not we want to recurse this
|
||||
// path of the tree. For this operation, we want to recurse the branch of the tree if
|
||||
// and of the following are true:
|
||||
|
@ -185,7 +134,7 @@ bool UpdateEntityOperator::preRecursion(OctreeElementPointer element) {
|
|||
//
|
||||
// Note: it's often the case that the branch in question contains both the old entity
|
||||
// and the new entity.
|
||||
|
||||
|
||||
bool keepSearching = false; // assume we don't need to search any more
|
||||
|
||||
bool subtreeContainsOld = subTreeContainsOldEntity(element);
|
||||
|
@ -257,7 +206,8 @@ bool UpdateEntityOperator::preRecursion(OctreeElementPointer element) {
|
|||
qCDebug(entities) << " NEW TREE CASE....";
|
||||
qCDebug(entities) << " entityTreeElement=" << entityTreeElement.get();
|
||||
qCDebug(entities) << " _containingElement=" << _containingElement.get();
|
||||
qCDebug(entities) << " entityTreeElement->bestFitBounds(_newEntityBox)=" << entityTreeElement->bestFitBounds(_newEntityBox);
|
||||
qCDebug(entities) << " entityTreeElement->bestFitBounds(_newEntityBox)="
|
||||
<< entityTreeElement->bestFitBounds(_newEntityBox);
|
||||
}
|
||||
|
||||
// If this element is the best fit for the new entity properties, then add/or update it
|
||||
|
@ -270,16 +220,9 @@ bool UpdateEntityOperator::preRecursion(OctreeElementPointer element) {
|
|||
EntityTreeElementPointer oldElement = _existingEntity->getElement();
|
||||
// if we are the existing containing element, then we can just do the update of the entity properties
|
||||
if (entityTreeElement == oldElement) {
|
||||
|
||||
if (_wantDebug) {
|
||||
qCDebug(entities) << " *** This is the same OLD ELEMENT ***";
|
||||
}
|
||||
|
||||
// set the entity properties and mark our element as changed.
|
||||
_existingEntity->setProperties(_properties);
|
||||
if (_wantDebug) {
|
||||
qCDebug(entities) << " *** set properties ***";
|
||||
}
|
||||
} else {
|
||||
// otherwise, this is an add case.
|
||||
if (oldElement) {
|
||||
|
@ -290,11 +233,6 @@ bool UpdateEntityOperator::preRecursion(OctreeElementPointer element) {
|
|||
}
|
||||
entityTreeElement->addEntityItem(_existingEntity);
|
||||
_tree->setContainingElement(_entityItemID, entityTreeElement);
|
||||
|
||||
_existingEntity->setProperties(_properties); // still need to update the properties!
|
||||
if (_wantDebug) {
|
||||
qCDebug(entities) << " *** ADDING ENTITY to ELEMENT and MAP and SETTING PROPERTIES ***";
|
||||
}
|
||||
}
|
||||
_foundNew = true; // we found the new element
|
||||
_removeOld = false; // and it has already been removed from the old
|
||||
|
@ -308,7 +246,6 @@ bool UpdateEntityOperator::preRecursion(OctreeElementPointer element) {
|
|||
qCDebug(entities) << "--------------------------------------------------";
|
||||
}
|
||||
|
||||
|
||||
return keepSearching; // if we haven't yet found it, keep looking
|
||||
}
|
||||
|
||||
|
@ -329,9 +266,9 @@ bool UpdateEntityOperator::postRecursion(OctreeElementPointer element) {
|
|||
}
|
||||
|
||||
// It's not OK to prune if we have the potential of deleting the original containig element.
|
||||
// because if we prune the containing element then new might end up reallocating the same memory later
|
||||
// because if we prune the containing element then new might end up reallocating the same memory later
|
||||
// and that will confuse our logic.
|
||||
//
|
||||
//
|
||||
// it's ok to prune if:
|
||||
// 1) we're not removing the old
|
||||
// 2) we are removing the old, but this subtree doesn't contain the old
|
||||
|
@ -340,17 +277,17 @@ bool UpdateEntityOperator::postRecursion(OctreeElementPointer element) {
|
|||
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
|
||||
entityTreeElement->pruneChildren(); // take this opportunity to prune any empty leaves
|
||||
}
|
||||
|
||||
|
||||
return keepSearching; // if we haven't yet found it, keep looking
|
||||
}
|
||||
|
||||
OctreeElementPointer UpdateEntityOperator::possiblyCreateChildAt(OctreeElementPointer element, int childIndex) {
|
||||
OctreeElementPointer UpdateEntityOperator::possiblyCreateChildAt(OctreeElementPointer element, int childIndex) {
|
||||
// If we're getting called, it's because there was no child element at this index while recursing.
|
||||
// We only care if this happens while still searching for the new entity location.
|
||||
// Check to see if
|
||||
// Check to see if
|
||||
if (!_foundNew) {
|
||||
float childElementScale = element->getScale() / 2.0f; // all of our children will be half our scale
|
||||
|
||||
|
||||
// Note: because the entity's bounds might have been clamped to the domain. We want to check if the
|
||||
// bounds of the clamped box would fit in our child elements. It may be the case that the actual
|
||||
// bounds of the element would hang outside of the child elements cells.
|
||||
|
@ -365,5 +302,5 @@ OctreeElementPointer UpdateEntityOperator::possiblyCreateChildAt(OctreeElementPo
|
|||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#ifndef hifi_UpdateEntityOperator_h
|
||||
#define hifi_UpdateEntityOperator_h
|
||||
|
||||
#include "BoundingBoxRelatedProperties.h"
|
||||
#include "EntitiesLogging.h"
|
||||
#include "EntityItem.h"
|
||||
#include "EntityItemProperties.h"
|
||||
|
@ -21,7 +22,8 @@
|
|||
class UpdateEntityOperator : public RecurseOctreeOperator {
|
||||
public:
|
||||
UpdateEntityOperator(EntityTreePointer tree, EntityTreeElementPointer containingElement,
|
||||
EntityItemPointer existingEntity, const EntityItemProperties& properties);
|
||||
EntityItemPointer existingEntity, const BoundingBoxRelatedProperties& newProperties);
|
||||
|
||||
~UpdateEntityOperator();
|
||||
|
||||
virtual bool preRecursion(OctreeElementPointer element);
|
||||
|
@ -32,7 +34,7 @@ private:
|
|||
EntityItemPointer _existingEntity;
|
||||
EntityTreeElementPointer _containingElement;
|
||||
AACube _containingElementCube; // we temporarily store our cube here in case we need to delete the containing element
|
||||
EntityItemProperties _properties;
|
||||
BoundingBoxRelatedProperties _newProperties;
|
||||
EntityItemID _entityItemID;
|
||||
bool _foundOld;
|
||||
bool _foundNew;
|
||||
|
|
|
@ -23,19 +23,18 @@
|
|||
const QString WebEntityItem::DEFAULT_SOURCE_URL("http://www.google.com");
|
||||
|
||||
EntityItemPointer WebEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
return std::make_shared<WebEntityItem>(entityID, properties);
|
||||
EntityItemPointer entity { new WebEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
WebEntityItem::WebEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
EntityItem(entityItemID)
|
||||
{
|
||||
WebEntityItem::WebEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID) {
|
||||
_type = EntityTypes::Web;
|
||||
setProperties(properties);
|
||||
}
|
||||
|
||||
const float WEB_ENTITY_ITEM_FIXED_DEPTH = 0.01f;
|
||||
|
||||
void WebEntityItem::setDimensions(const glm::vec3& value) {
|
||||
void WebEntityItem::setDimensions(const glm::vec3 value) {
|
||||
// NOTE: Web Entities always have a "depth" of 1cm.
|
||||
EntityItem::setDimensions(glm::vec3(value.x, value.y, WEB_ENTITY_ITEM_FIXED_DEPTH));
|
||||
}
|
||||
|
|
|
@ -17,12 +17,12 @@ public:
|
|||
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
WebEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
|
||||
WebEntityItem(const EntityItemID& entityItemID);
|
||||
|
||||
ALLOW_INSTANTIATION // This class can be instantiated
|
||||
|
||||
/// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately
|
||||
virtual void setDimensions(const glm::vec3& value);
|
||||
virtual void setDimensions(const glm::vec3 value);
|
||||
virtual ShapeType getShapeType() const { return SHAPE_TYPE_BOX; }
|
||||
|
||||
// methods for getting/setting all properties of an entity
|
||||
|
|
|
@ -27,20 +27,18 @@ const ShapeType ZoneEntityItem::DEFAULT_SHAPE_TYPE = SHAPE_TYPE_BOX;
|
|||
const QString ZoneEntityItem::DEFAULT_COMPOUND_SHAPE_URL = "";
|
||||
|
||||
EntityItemPointer ZoneEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
return std::make_shared<ZoneEntityItem>(entityID, properties);
|
||||
EntityItemPointer entity { new ZoneEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
ZoneEntityItem::ZoneEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
EntityItem(entityItemID)
|
||||
{
|
||||
ZoneEntityItem::ZoneEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID) {
|
||||
_type = EntityTypes::Zone;
|
||||
|
||||
_shapeType = DEFAULT_SHAPE_TYPE;
|
||||
_compoundShapeURL = DEFAULT_COMPOUND_SHAPE_URL;
|
||||
|
||||
_backgroundMode = BACKGROUND_MODE_INHERIT;
|
||||
|
||||
setProperties(properties);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ class ZoneEntityItem : public EntityItem {
|
|||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
ZoneEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
|
||||
ZoneEntityItem(const EntityItemID& entityItemID);
|
||||
|
||||
ALLOW_INSTANTIATION // This class can be instantiated
|
||||
|
||||
|
|
|
@ -41,9 +41,10 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
|||
case PacketType::EntityAdd:
|
||||
case PacketType::EntityEdit:
|
||||
case PacketType::EntityData:
|
||||
return VERSION_ENTITIES_POLYLINE_TEXTURE;
|
||||
return VERSION_ENTITIES_HAVE_PARENTS;
|
||||
case PacketType::AvatarData:
|
||||
case PacketType::BulkAvatarData:
|
||||
return 17;
|
||||
default:
|
||||
return 17;
|
||||
}
|
||||
|
|
|
@ -160,5 +160,6 @@ const PacketVersion VERSION_ENTITIES_KEYLIGHT_PROPERTIES_GROUP = 47;
|
|||
const PacketVersion VERSION_ENTITIES_KEYLIGHT_PROPERTIES_GROUP_BIS = 48;
|
||||
const PacketVersion VERSION_ENTITIES_PARTICLES_ADDITIVE_BLENDING = 49;
|
||||
const PacketVersion VERSION_ENTITIES_POLYLINE_TEXTURE = 50;
|
||||
const PacketVersion VERSION_ENTITIES_HAVE_PARENTS = 51;
|
||||
|
||||
#endif // hifi_PacketHeaders_h
|
||||
|
|
|
@ -455,8 +455,9 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, const Q
|
|||
EntityItemProperties properties;
|
||||
|
||||
// explicitly set the properties that changed so that they will be packed
|
||||
properties.setPosition(_serverPosition);
|
||||
properties.setRotation(_serverRotation);
|
||||
properties.setPosition(_entity->getLocalPosition());
|
||||
properties.setRotation(_entity->getLocalOrientation());
|
||||
|
||||
properties.setVelocity(_serverVelocity);
|
||||
properties.setAcceleration(_serverAcceleration);
|
||||
properties.setAngularVelocity(_serverAngularVelocity);
|
||||
|
|
|
@ -45,7 +45,7 @@ public:
|
|||
virtual int getBoundaryLevelAdjust() const = 0;
|
||||
virtual PickRay computePickRay(float x, float y) const = 0;
|
||||
|
||||
virtual const glm::vec3& getAvatarPosition() const = 0;
|
||||
virtual glm::vec3 getAvatarPosition() const = 0;
|
||||
|
||||
virtual void postLambdaEvent(std::function<void()> f) = 0;
|
||||
virtual qreal getDevicePixelRatio() = 0;
|
||||
|
|
|
@ -39,9 +39,14 @@ namespace render {
|
|||
|
||||
using namespace render;
|
||||
|
||||
MeshPartPayload::MeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex) :
|
||||
model(model), meshIndex(meshIndex), partIndex(partIndex), _shapeID(shapeIndex)
|
||||
{
|
||||
MeshPartPayload::MeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex,
|
||||
glm::vec3 position, glm::quat orientation) :
|
||||
model(model),
|
||||
meshIndex(meshIndex),
|
||||
partIndex(partIndex),
|
||||
_shapeID(shapeIndex),
|
||||
_modelPosition(position),
|
||||
_modelOrientation(orientation) {
|
||||
initCache();
|
||||
}
|
||||
|
||||
|
@ -66,6 +71,11 @@ void MeshPartPayload::initCache() {
|
|||
|
||||
}
|
||||
|
||||
void MeshPartPayload::updateModelLocation(glm::vec3 position, glm::quat orientation) {
|
||||
_modelPosition = position;
|
||||
_modelOrientation = orientation;
|
||||
}
|
||||
|
||||
render::ItemKey MeshPartPayload::getKey() const {
|
||||
ItemKey::Builder builder;
|
||||
builder.withTypeShape();
|
||||
|
@ -91,7 +101,7 @@ render::ItemKey MeshPartPayload::getKey() const {
|
|||
render::Item::Bound MeshPartPayload::getBound() const {
|
||||
// NOTE: we can't cache this bounds because we need to handle the case of a moving
|
||||
// entity or mesh part.
|
||||
return model->getPartBounds(meshIndex, partIndex);
|
||||
return model->getPartBounds(meshIndex, partIndex, _modelPosition, _modelOrientation);
|
||||
}
|
||||
|
||||
void MeshPartPayload::drawCall(gpu::Batch& batch) const {
|
||||
|
@ -222,7 +232,7 @@ void MeshPartPayload::bindTransform(gpu::Batch& batch, const ModelRender::Locati
|
|||
transform = Transform(state.clusterMatrices[0]);
|
||||
}
|
||||
}
|
||||
transform.preTranslate(model->_translation);
|
||||
transform.preTranslate(_modelPosition);
|
||||
batch.setModelTransform(transform);
|
||||
}
|
||||
|
||||
|
@ -247,7 +257,7 @@ void MeshPartPayload::render(RenderArgs* args) const {
|
|||
}
|
||||
|
||||
// Back to model to update the cluster matrices right now
|
||||
model->updateClusterMatrices();
|
||||
model->updateClusterMatrices(_modelPosition, _modelOrientation);
|
||||
|
||||
const FBXMesh& mesh = geometry.meshes.at(meshIndex);
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ class Model;
|
|||
|
||||
class MeshPartPayload {
|
||||
public:
|
||||
MeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex);
|
||||
MeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex, glm::vec3 position, glm::quat orientation);
|
||||
|
||||
typedef render::Payload<MeshPartPayload> Payload;
|
||||
typedef Payload::DataPointer Pointer;
|
||||
|
@ -33,7 +33,11 @@ public:
|
|||
int meshIndex;
|
||||
int partIndex;
|
||||
int _shapeID;
|
||||
|
||||
glm::vec3 _modelPosition;
|
||||
glm::quat _modelOrientation;
|
||||
|
||||
void updateModelLocation(glm::vec3 position, glm::quat orientation);
|
||||
|
||||
// Render Item interface
|
||||
render::ItemKey getKey() const;
|
||||
render::Item::Bound getBound() const;
|
||||
|
@ -63,4 +67,4 @@ namespace render {
|
|||
template <> void payloadRender(const MeshPartPayload::Pointer& payload, RenderArgs* args);
|
||||
}
|
||||
|
||||
#endif // hifi_MeshPartPayload_h
|
||||
#endif // hifi_MeshPartPayload_h
|
||||
|
|
|
@ -72,13 +72,16 @@ Model::~Model() {
|
|||
|
||||
AbstractViewStateInterface* Model::_viewState = NULL;
|
||||
|
||||
|
||||
void Model::setTranslation(const glm::vec3& translation) {
|
||||
_translation = translation;
|
||||
enqueueLocationChange();
|
||||
}
|
||||
|
||||
|
||||
void Model::setRotation(const glm::quat& rotation) {
|
||||
_rotation = rotation;
|
||||
}
|
||||
enqueueLocationChange();
|
||||
}
|
||||
|
||||
void Model::setScale(const glm::vec3& scale) {
|
||||
setScaleInternal(scale);
|
||||
|
@ -104,6 +107,20 @@ void Model::setOffset(const glm::vec3& offset) {
|
|||
_snappedToRegistrationPoint = false;
|
||||
}
|
||||
|
||||
void Model::enqueueLocationChange() {
|
||||
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
|
||||
|
||||
render::PendingChanges pendingChanges;
|
||||
foreach (auto itemID, _renderItems.keys()) {
|
||||
pendingChanges.updateItem<MeshPartPayload>(itemID, [=](MeshPartPayload& data) {
|
||||
data.updateModelLocation(_translation, _rotation);
|
||||
data.model->_needsUpdateClusterMatrices = true;
|
||||
});
|
||||
}
|
||||
|
||||
scene->enqueuePendingChanges(pendingChanges);
|
||||
}
|
||||
|
||||
void Model::initJointTransforms() {
|
||||
if (!_geometry || !_geometry->isLoaded()) {
|
||||
return;
|
||||
|
@ -337,7 +354,7 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) {
|
|||
_calculatedMeshPartBoxes.clear();
|
||||
for (int i = 0; i < numberOfMeshes; i++) {
|
||||
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||
Extents scaledMeshExtents = calculateScaledOffsetExtents(mesh.meshExtents);
|
||||
Extents scaledMeshExtents = calculateScaledOffsetExtents(mesh.meshExtents, _translation, _rotation);
|
||||
|
||||
_calculatedMeshBoxes[i] = AABox(scaledMeshExtents);
|
||||
|
||||
|
@ -624,7 +641,8 @@ Extents Model::getUnscaledMeshExtents() const {
|
|||
return scaledExtents;
|
||||
}
|
||||
|
||||
Extents Model::calculateScaledOffsetExtents(const Extents& extents) const {
|
||||
Extents Model::calculateScaledOffsetExtents(const Extents& extents,
|
||||
glm::vec3 modelPosition, glm::quat modelOrientation) const {
|
||||
// we need to include any fst scaling, translation, and rotation, which is captured in the offset matrix
|
||||
glm::vec3 minimum = glm::vec3(_geometry->getFBXGeometry().offset * glm::vec4(extents.minimum, 1.0f));
|
||||
glm::vec3 maximum = glm::vec3(_geometry->getFBXGeometry().offset * glm::vec4(extents.maximum, 1.0f));
|
||||
|
@ -632,17 +650,17 @@ Extents Model::calculateScaledOffsetExtents(const Extents& extents) const {
|
|||
Extents scaledOffsetExtents = { ((minimum + _offset) * _scale),
|
||||
((maximum + _offset) * _scale) };
|
||||
|
||||
Extents rotatedExtents = scaledOffsetExtents.getRotated(_rotation);
|
||||
Extents rotatedExtents = scaledOffsetExtents.getRotated(modelOrientation);
|
||||
|
||||
Extents translatedExtents = { rotatedExtents.minimum + _translation,
|
||||
rotatedExtents.maximum + _translation };
|
||||
Extents translatedExtents = { rotatedExtents.minimum + modelPosition,
|
||||
rotatedExtents.maximum + modelPosition };
|
||||
|
||||
return translatedExtents;
|
||||
}
|
||||
|
||||
/// Returns the world space equivalent of some box in model space.
|
||||
AABox Model::calculateScaledOffsetAABox(const AABox& box) const {
|
||||
return AABox(calculateScaledOffsetExtents(Extents(box)));
|
||||
AABox Model::calculateScaledOffsetAABox(const AABox& box, glm::vec3 modelPosition, glm::quat modelOrientation) const {
|
||||
return AABox(calculateScaledOffsetExtents(Extents(box), modelPosition, modelOrientation));
|
||||
}
|
||||
|
||||
glm::vec3 Model::calculateScaledOffsetPoint(const glm::vec3& point) const {
|
||||
|
@ -935,7 +953,7 @@ void Model::simulateInternal(float deltaTime) {
|
|||
glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset);
|
||||
updateRig(deltaTime, parentTransform);
|
||||
}
|
||||
void Model::updateClusterMatrices() {
|
||||
void Model::updateClusterMatrices(glm::vec3 modelPosition, glm::quat modelOrientation) {
|
||||
PerformanceTimer perfTimer("Model::updateClusterMatrices");
|
||||
|
||||
if (!_needsUpdateClusterMatrices) {
|
||||
|
@ -949,7 +967,7 @@ void Model::updateClusterMatrices() {
|
|||
glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
auto cauterizeMatrix = _rig->getJointTransform(geometry.neckJointIndex) * zeroScale;
|
||||
|
||||
glm::mat4 modelToWorld = glm::mat4_cast(_rotation);
|
||||
glm::mat4 modelToWorld = glm::mat4_cast(modelOrientation);
|
||||
for (int i = 0; i < _meshStates.size(); i++) {
|
||||
MeshState& state = _meshStates[i];
|
||||
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||
|
@ -971,16 +989,21 @@ void Model::updateClusterMatrices() {
|
|||
// Once computed the cluster matrices, update the buffer(s)
|
||||
if (mesh.clusters.size() > 1) {
|
||||
if (!state.clusterBuffer) {
|
||||
state.clusterBuffer = std::make_shared<gpu::Buffer>(state.clusterMatrices.size() * sizeof(glm::mat4), (const gpu::Byte*) state.clusterMatrices.constData());
|
||||
state.clusterBuffer = std::make_shared<gpu::Buffer>(state.clusterMatrices.size() * sizeof(glm::mat4),
|
||||
(const gpu::Byte*) state.clusterMatrices.constData());
|
||||
} else {
|
||||
state.clusterBuffer->setSubData(0, state.clusterMatrices.size() * sizeof(glm::mat4), (const gpu::Byte*) state.clusterMatrices.constData());
|
||||
state.clusterBuffer->setSubData(0, state.clusterMatrices.size() * sizeof(glm::mat4),
|
||||
(const gpu::Byte*) state.clusterMatrices.constData());
|
||||
}
|
||||
|
||||
if (!_cauterizeBoneSet.empty() && (state.cauterizedClusterMatrices.size() > 1)) {
|
||||
if (!state.cauterizedClusterBuffer) {
|
||||
state.cauterizedClusterBuffer = std::make_shared<gpu::Buffer>(state.cauterizedClusterMatrices.size() * sizeof(glm::mat4), (const gpu::Byte*) state.cauterizedClusterMatrices.constData());
|
||||
state.cauterizedClusterBuffer =
|
||||
std::make_shared<gpu::Buffer>(state.cauterizedClusterMatrices.size() * sizeof(glm::mat4),
|
||||
(const gpu::Byte*) state.cauterizedClusterMatrices.constData());
|
||||
} else {
|
||||
state.cauterizedClusterBuffer->setSubData(0, state.cauterizedClusterMatrices.size() * sizeof(glm::mat4), (const gpu::Byte*) state.cauterizedClusterMatrices.constData());
|
||||
state.cauterizedClusterBuffer->setSubData(0, state.cauterizedClusterMatrices.size() * sizeof(glm::mat4),
|
||||
(const gpu::Byte*) state.cauterizedClusterMatrices.constData());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1059,7 +1082,7 @@ void Model::deleteGeometry() {
|
|||
_blendedBlendshapeCoefficients.clear();
|
||||
}
|
||||
|
||||
AABox Model::getPartBounds(int meshIndex, int partIndex) {
|
||||
AABox Model::getPartBounds(int meshIndex, int partIndex, glm::vec3 modelPosition, glm::quat modelOrientation) {
|
||||
|
||||
if (!_geometry || !_geometry->isLoaded()) {
|
||||
return AABox();
|
||||
|
@ -1070,7 +1093,7 @@ AABox Model::getPartBounds(int meshIndex, int partIndex) {
|
|||
bool isSkinned = state.clusterMatrices.size() > 1;
|
||||
if (isSkinned) {
|
||||
// if we're skinned return the entire mesh extents because we can't know for sure our clusters don't move us
|
||||
return calculateScaledOffsetAABox(_geometry->getFBXGeometry().meshExtents);
|
||||
return calculateScaledOffsetAABox(_geometry->getFBXGeometry().meshExtents, modelPosition, modelOrientation);
|
||||
}
|
||||
}
|
||||
if (_geometry->getFBXGeometry().meshes.size() > meshIndex) {
|
||||
|
@ -1088,7 +1111,7 @@ AABox Model::getPartBounds(int meshIndex, int partIndex) {
|
|||
//
|
||||
// If we not skinned use the bounds of the subMesh for all it's parts
|
||||
const FBXMesh& mesh = _geometry->getFBXGeometry().meshes.at(meshIndex);
|
||||
return calculateScaledOffsetExtents(mesh.meshExtents);
|
||||
return calculateScaledOffsetExtents(mesh.meshExtents, modelPosition, modelOrientation);
|
||||
}
|
||||
return AABox();
|
||||
}
|
||||
|
@ -1123,7 +1146,7 @@ void Model::segregateMeshGroups() {
|
|||
// Create the render payloads
|
||||
int totalParts = mesh.parts.size();
|
||||
for (int partIndex = 0; partIndex < totalParts; partIndex++) {
|
||||
_renderItemsSet << std::make_shared<MeshPartPayload>(this, i, partIndex, shapeID);
|
||||
_renderItemsSet << std::make_shared<MeshPartPayload>(this, i, partIndex, shapeID, _translation, _rotation);
|
||||
shapeID++;
|
||||
}
|
||||
}
|
||||
|
@ -1143,6 +1166,7 @@ bool Model::initWhenReady(render::ScenePointer scene) {
|
|||
_renderItems.insert(item, renderPayload);
|
||||
pendingChanges.resetItem(item, renderPayload);
|
||||
pendingChanges.updateItem<MeshPartPayload>(item, [&](MeshPartPayload& data) {
|
||||
data.updateModelLocation(_translation, _rotation);
|
||||
data.model->_needsUpdateClusterMatrices = true;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -88,7 +88,8 @@ public:
|
|||
|
||||
bool isVisible() const { return _isVisible; }
|
||||
|
||||
AABox getPartBounds(int meshIndex, int partIndex);
|
||||
void updateRenderItems();
|
||||
AABox getPartBounds(int meshIndex, int partIndex, glm::vec3 modelPosition, glm::quat modelOrientation);
|
||||
|
||||
bool maybeStartBlender();
|
||||
|
||||
|
@ -111,7 +112,7 @@ public:
|
|||
bool getSnapModelToRegistrationPoint() { return _snapModelToRegistrationPoint; }
|
||||
|
||||
virtual void simulate(float deltaTime, bool fullUpdate = true);
|
||||
void updateClusterMatrices();
|
||||
void updateClusterMatrices(glm::vec3 modelPosition, glm::quat modelOrientation);
|
||||
|
||||
/// Returns a reference to the shared geometry.
|
||||
const QSharedPointer<NetworkGeometry>& getGeometry() const { return _geometry; }
|
||||
|
@ -185,6 +186,8 @@ public:
|
|||
void setScale(const glm::vec3& scale);
|
||||
const glm::vec3& getScale() const { return _scale; }
|
||||
|
||||
void enqueueLocationChange();
|
||||
|
||||
/// enables/disables scale to fit behavior, the model will be automatically scaled to the specified largest dimension
|
||||
bool getIsScaledToFit() const { return _scaledToFit; } /// is model scaled to fit
|
||||
const glm::vec3& getScaleToFitDimensions() const { return _scaleToFitDimensions; } /// the dimensions model is scaled to
|
||||
|
@ -216,10 +219,10 @@ protected:
|
|||
Extents getUnscaledMeshExtents() const;
|
||||
|
||||
/// Returns the scaled equivalent of some extents in model space.
|
||||
Extents calculateScaledOffsetExtents(const Extents& extents) const;
|
||||
Extents calculateScaledOffsetExtents(const Extents& extents, glm::vec3 modelPosition, glm::quat modelOrientation) const;
|
||||
|
||||
/// Returns the world space equivalent of some box in model space.
|
||||
AABox calculateScaledOffsetAABox(const AABox& box) const;
|
||||
AABox calculateScaledOffsetAABox(const AABox& box, glm::vec3 modelPosition, glm::quat modelOrientation) const;
|
||||
|
||||
/// Returns the scaled equivalent of a point in model space.
|
||||
glm::vec3 calculateScaledOffsetPoint(const glm::vec3& point) const;
|
||||
|
|
|
@ -109,7 +109,7 @@ public:
|
|||
|
||||
Q_INVOKABLE void setEngineDisplayItemStatus(int display) { _drawItemStatus = display; }
|
||||
Q_INVOKABLE int doEngineDisplayItemStatus() { return _drawItemStatus; }
|
||||
|
||||
|
||||
Q_INVOKABLE void setEngineDisplayHitEffect(bool display) { _drawHitEffect = display; }
|
||||
Q_INVOKABLE bool doEngineDisplayHitEffect() { return _drawHitEffect; }
|
||||
|
||||
|
@ -144,7 +144,7 @@ protected:
|
|||
int _maxDrawnOverlay3DItems = -1;
|
||||
|
||||
int _drawItemStatus = 0;
|
||||
|
||||
|
||||
bool _drawHitEffect = false;
|
||||
|
||||
};
|
||||
|
|
37
libraries/shared/src/SpatialParentFinder.h
Normal file
37
libraries/shared/src/SpatialParentFinder.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// SpatialParentFinder.h
|
||||
// libraries/shared/src/
|
||||
//
|
||||
// Created by Seth Alves on 2015-10-18
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_SpatialParentFinder_h
|
||||
#define hifi_SpatialParentFinder_h
|
||||
|
||||
#include <QUuid>
|
||||
|
||||
#include "DependencyManager.h"
|
||||
|
||||
class SpatiallyNestable;
|
||||
using SpatiallyNestableWeakPointer = std::weak_ptr<SpatiallyNestable>;
|
||||
using SpatiallyNestablePointer = std::shared_ptr<SpatiallyNestable>;
|
||||
class SpatialParentFinder : public Dependency {
|
||||
|
||||
|
||||
|
||||
// This interface is used to turn a QUuid into a pointer to a "parent" -- something that children can
|
||||
// be spatially relative to. At this point, this means either an EntityItem or an Avatar.
|
||||
|
||||
|
||||
public:
|
||||
SpatialParentFinder() { }
|
||||
virtual ~SpatialParentFinder() { }
|
||||
|
||||
virtual SpatiallyNestableWeakPointer find(QUuid parentID) const = 0;
|
||||
};
|
||||
|
||||
#endif // hifi_SpatialParentFinder_h
|
371
libraries/shared/src/SpatiallyNestable.cpp
Normal file
371
libraries/shared/src/SpatiallyNestable.cpp
Normal file
|
@ -0,0 +1,371 @@
|
|||
//
|
||||
// SpatiallyNestable.cpp
|
||||
// libraries/shared/src/
|
||||
//
|
||||
// Created by Seth Alves on 2015-10-18
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <QQueue>
|
||||
|
||||
#include "DependencyManager.h"
|
||||
#include "SpatiallyNestable.h"
|
||||
|
||||
|
||||
SpatiallyNestable::SpatiallyNestable(NestableTypes::NestableType nestableType, QUuid id) :
|
||||
_nestableType(nestableType),
|
||||
_id(id),
|
||||
_transform() {
|
||||
// set flags in _transform
|
||||
_transform.setTranslation(glm::vec3(0.0f));
|
||||
_transform.setRotation(glm::quat());
|
||||
}
|
||||
|
||||
Transform SpatiallyNestable::getParentTransform() const {
|
||||
Transform result;
|
||||
SpatiallyNestablePointer parent = getParentPointer();
|
||||
if (parent) {
|
||||
Transform parentTransform = parent->getTransform(_parentJointIndex);
|
||||
result = parentTransform.setScale(1.0f);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
SpatiallyNestablePointer SpatiallyNestable::getParentPointer() const {
|
||||
SpatiallyNestablePointer parent = _parent.lock();
|
||||
|
||||
if (!parent && _parentID.isNull()) {
|
||||
// no parent
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (parent && parent->getID() == _parentID) {
|
||||
// parent pointer is up-to-date
|
||||
if (!_parentKnowsMe) {
|
||||
parent->beParentOfChild(getThisPointer());
|
||||
_parentKnowsMe = true;
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
|
||||
SpatiallyNestablePointer thisPointer = getThisPointer();
|
||||
|
||||
if (parent) {
|
||||
// we have a parent pointer but our _parentID doesn't indicate this parent.
|
||||
parent->forgetChild(thisPointer);
|
||||
_parentKnowsMe = false;
|
||||
_parent.reset();
|
||||
}
|
||||
|
||||
// we have a _parentID but no parent pointer, or our parent pointer was to the wrong thing
|
||||
QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>();
|
||||
_parent = parentFinder->find(_parentID);
|
||||
parent = _parent.lock();
|
||||
if (parent) {
|
||||
parent->beParentOfChild(thisPointer);
|
||||
_parentKnowsMe = true;
|
||||
}
|
||||
|
||||
if (parent || _parentID.isNull()) {
|
||||
thisPointer->parentChanged();
|
||||
}
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
void SpatiallyNestable::beParentOfChild(SpatiallyNestablePointer newChild) const {
|
||||
_childrenLock.withWriteLock([&] {
|
||||
_children[newChild->getID()] = newChild;
|
||||
});
|
||||
}
|
||||
|
||||
void SpatiallyNestable::forgetChild(SpatiallyNestablePointer newChild) const {
|
||||
_childrenLock.withWriteLock([&] {
|
||||
_children.remove(newChild->getID());
|
||||
});
|
||||
}
|
||||
|
||||
void SpatiallyNestable::setParentID(const QUuid parentID) {
|
||||
if (_parentID != parentID) {
|
||||
_parentID = parentID;
|
||||
_parentKnowsMe = false;
|
||||
}
|
||||
parentChanged();
|
||||
}
|
||||
|
||||
glm::vec3 SpatiallyNestable::worldToLocal(glm::vec3 position, QUuid parentID, int parentJointIndex) {
|
||||
QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>();
|
||||
auto parentWP = parentFinder->find(parentID);
|
||||
auto parent = parentWP.lock();
|
||||
Transform parentTransform;
|
||||
if (parent) {
|
||||
parentTransform = parent->getTransform(parentJointIndex);
|
||||
parentTransform.setScale(1.0f);
|
||||
}
|
||||
|
||||
Transform positionTransform;
|
||||
positionTransform.setTranslation(position);
|
||||
Transform myWorldTransform;
|
||||
Transform::mult(myWorldTransform, parentTransform, positionTransform);
|
||||
|
||||
myWorldTransform.setTranslation(position);
|
||||
Transform result;
|
||||
Transform::inverseMult(result, parentTransform, myWorldTransform);
|
||||
return result.getTranslation();
|
||||
}
|
||||
|
||||
glm::quat SpatiallyNestable::worldToLocal(glm::quat orientation, QUuid parentID, int parentJointIndex) {
|
||||
QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>();
|
||||
auto parentWP = parentFinder->find(parentID);
|
||||
auto parent = parentWP.lock();
|
||||
Transform parentTransform;
|
||||
if (parent) {
|
||||
parentTransform = parent->getTransform(parentJointIndex);
|
||||
parentTransform.setScale(1.0f);
|
||||
}
|
||||
|
||||
Transform orientationTransform;
|
||||
orientationTransform.setRotation(orientation);
|
||||
Transform myWorldTransform;
|
||||
Transform::mult(myWorldTransform, parentTransform, orientationTransform);
|
||||
myWorldTransform.setRotation(orientation);
|
||||
Transform result;
|
||||
Transform::inverseMult(result, parentTransform, myWorldTransform);
|
||||
return result.getRotation();
|
||||
}
|
||||
|
||||
glm::vec3 SpatiallyNestable::localToWorld(glm::vec3 position, QUuid parentID, int parentJointIndex) {
|
||||
QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>();
|
||||
auto parentWP = parentFinder->find(parentID);
|
||||
auto parent = parentWP.lock();
|
||||
Transform parentTransform;
|
||||
if (parent) {
|
||||
parentTransform = parent->getTransform(parentJointIndex);
|
||||
parentTransform.setScale(1.0f);
|
||||
}
|
||||
Transform positionTransform;
|
||||
positionTransform.setTranslation(position);
|
||||
Transform result;
|
||||
Transform::mult(result, parentTransform, positionTransform);
|
||||
return result.getTranslation();
|
||||
}
|
||||
|
||||
glm::quat SpatiallyNestable::localToWorld(glm::quat orientation, QUuid parentID, int parentJointIndex) {
|
||||
QSharedPointer<SpatialParentFinder> parentFinder = DependencyManager::get<SpatialParentFinder>();
|
||||
auto parentWP = parentFinder->find(parentID);
|
||||
auto parent = parentWP.lock();
|
||||
Transform parentTransform;
|
||||
if (parent) {
|
||||
parentTransform = parent->getTransform(parentJointIndex);
|
||||
parentTransform.setScale(1.0f);
|
||||
}
|
||||
Transform orientationTransform;
|
||||
orientationTransform.setRotation(orientation);
|
||||
Transform result;
|
||||
Transform::mult(result, parentTransform, orientationTransform);
|
||||
return result.getRotation();
|
||||
}
|
||||
|
||||
glm::vec3 SpatiallyNestable::getPosition() const {
|
||||
return getTransform().getTranslation();
|
||||
}
|
||||
|
||||
glm::vec3 SpatiallyNestable::getPosition(int jointIndex) const {
|
||||
return getTransform(jointIndex).getTranslation();
|
||||
}
|
||||
|
||||
void SpatiallyNestable::setPosition(glm::vec3 position) {
|
||||
Transform parentTransform = getParentTransform();
|
||||
Transform myWorldTransform;
|
||||
_transformLock.withWriteLock([&] {
|
||||
Transform::mult(myWorldTransform, parentTransform, _transform);
|
||||
myWorldTransform.setTranslation(position);
|
||||
Transform::inverseMult(_transform, parentTransform, myWorldTransform);
|
||||
});
|
||||
locationChanged();
|
||||
}
|
||||
|
||||
glm::quat SpatiallyNestable::getOrientation() const {
|
||||
return getTransform().getRotation();
|
||||
}
|
||||
|
||||
glm::quat SpatiallyNestable::getOrientation(int jointIndex) const {
|
||||
return getTransform(jointIndex).getRotation();
|
||||
}
|
||||
|
||||
void SpatiallyNestable::setOrientation(glm::quat orientation) {
|
||||
Transform parentTransform = getParentTransform();
|
||||
Transform myWorldTransform;
|
||||
_transformLock.withWriteLock([&] {
|
||||
Transform::mult(myWorldTransform, parentTransform, _transform);
|
||||
myWorldTransform.setRotation(orientation);
|
||||
Transform::inverseMult(_transform, parentTransform, myWorldTransform);
|
||||
});
|
||||
locationChanged();
|
||||
}
|
||||
|
||||
const Transform SpatiallyNestable::getTransform() const {
|
||||
// return a world-space transform for this object's location
|
||||
Transform parentTransform = getParentTransform();
|
||||
Transform result;
|
||||
_transformLock.withReadLock([&] {
|
||||
Transform::mult(result, parentTransform, _transform);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
const Transform SpatiallyNestable::getTransform(int jointIndex) const {
|
||||
// this returns the world-space transform for this object. It finds its parent's transform (which may
|
||||
// cause this object's parent to query its parent, etc) and multiplies this object's local transform onto it.
|
||||
Transform worldTransform = getTransform();
|
||||
Transform jointInObjectFrame = getJointTransformInObjectFrame(jointIndex);
|
||||
Transform jointInWorldFrame;
|
||||
Transform::mult(jointInWorldFrame, worldTransform, jointInObjectFrame);
|
||||
return jointInWorldFrame;
|
||||
}
|
||||
|
||||
void SpatiallyNestable::setTransform(const Transform transform) {
|
||||
Transform parentTransform = getParentTransform();
|
||||
_transformLock.withWriteLock([&] {
|
||||
Transform::inverseMult(_transform, parentTransform, transform);
|
||||
});
|
||||
locationChanged();
|
||||
}
|
||||
|
||||
glm::vec3 SpatiallyNestable::getScale() const {
|
||||
glm::vec3 result;
|
||||
_transformLock.withReadLock([&] {
|
||||
result = _transform.getScale();
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
glm::vec3 SpatiallyNestable::getScale(int jointIndex) const {
|
||||
// XXX ... something with joints
|
||||
return getScale();
|
||||
}
|
||||
|
||||
void SpatiallyNestable::setScale(glm::vec3 scale) {
|
||||
_transformLock.withWriteLock([&] {
|
||||
_transform.setScale(scale);
|
||||
});
|
||||
dimensionsChanged();
|
||||
}
|
||||
|
||||
const Transform SpatiallyNestable::getLocalTransform() const {
|
||||
Transform result;
|
||||
_transformLock.withReadLock([&] {
|
||||
result =_transform;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
void SpatiallyNestable::setLocalTransform(const Transform transform) {
|
||||
_transformLock.withWriteLock([&] {
|
||||
_transform = transform;
|
||||
});
|
||||
locationChanged();
|
||||
}
|
||||
|
||||
glm::vec3 SpatiallyNestable::getLocalPosition() const {
|
||||
glm::vec3 result;
|
||||
_transformLock.withReadLock([&] {
|
||||
result = _transform.getTranslation();
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
void SpatiallyNestable::setLocalPosition(glm::vec3 position) {
|
||||
_transformLock.withWriteLock([&] {
|
||||
_transform.setTranslation(position);
|
||||
});
|
||||
locationChanged();
|
||||
}
|
||||
|
||||
glm::quat SpatiallyNestable::getLocalOrientation() const {
|
||||
glm::quat result;
|
||||
_transformLock.withReadLock([&] {
|
||||
result = _transform.getRotation();
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
void SpatiallyNestable::setLocalOrientation(glm::quat orientation) {
|
||||
_transformLock.withWriteLock([&] {
|
||||
_transform.setRotation(orientation);
|
||||
});
|
||||
locationChanged();
|
||||
}
|
||||
|
||||
glm::vec3 SpatiallyNestable::getLocalScale() const {
|
||||
glm::vec3 result;
|
||||
_transformLock.withReadLock([&] {
|
||||
result = _transform.getScale();
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
void SpatiallyNestable::setLocalScale(glm::vec3 scale) {
|
||||
_transformLock.withWriteLock([&] {
|
||||
_transform.setScale(scale);
|
||||
});
|
||||
dimensionsChanged();
|
||||
}
|
||||
|
||||
QList<SpatiallyNestablePointer> SpatiallyNestable::getChildren() const {
|
||||
QList<SpatiallyNestablePointer> children;
|
||||
_childrenLock.withReadLock([&] {
|
||||
foreach(SpatiallyNestableWeakPointer childWP, _children.values()) {
|
||||
SpatiallyNestablePointer child = childWP.lock();
|
||||
if (child) {
|
||||
children << child;
|
||||
}
|
||||
}
|
||||
});
|
||||
return children;
|
||||
}
|
||||
|
||||
const Transform SpatiallyNestable::getJointTransformInObjectFrame(int jointIndex) const {
|
||||
Transform jointInObjectFrame;
|
||||
glm::vec3 position = getJointTranslation(jointIndex);
|
||||
glm::quat orientation = getJointRotation(jointIndex);
|
||||
jointInObjectFrame.setRotation(orientation);
|
||||
jointInObjectFrame.setTranslation(position);
|
||||
return jointInObjectFrame;
|
||||
}
|
||||
|
||||
SpatiallyNestablePointer SpatiallyNestable::getThisPointer() const {
|
||||
SpatiallyNestableConstPointer constThisPointer = shared_from_this();
|
||||
SpatiallyNestablePointer thisPointer = std::const_pointer_cast<SpatiallyNestable>(constThisPointer); // ermahgerd !!!
|
||||
return thisPointer;
|
||||
}
|
||||
|
||||
void SpatiallyNestable::forEachChild(std::function<void(SpatiallyNestablePointer)> actor) {
|
||||
foreach(SpatiallyNestablePointer child, getChildren()) {
|
||||
actor(child);
|
||||
}
|
||||
}
|
||||
|
||||
void SpatiallyNestable::forEachDescendant(std::function<void(SpatiallyNestablePointer)> actor) {
|
||||
QQueue<SpatiallyNestablePointer> toProcess;
|
||||
foreach(SpatiallyNestablePointer child, getChildren()) {
|
||||
toProcess.enqueue(child);
|
||||
}
|
||||
|
||||
while (!toProcess.empty()) {
|
||||
SpatiallyNestablePointer object = toProcess.dequeue();
|
||||
actor(object);
|
||||
foreach (SpatiallyNestablePointer child, object->getChildren()) {
|
||||
toProcess.enqueue(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpatiallyNestable::locationChanged() {
|
||||
forEachChild([&](SpatiallyNestablePointer object) {
|
||||
object->locationChanged();
|
||||
});
|
||||
}
|
128
libraries/shared/src/SpatiallyNestable.h
Normal file
128
libraries/shared/src/SpatiallyNestable.h
Normal file
|
@ -0,0 +1,128 @@
|
|||
//
|
||||
// SpatiallyNestable.h
|
||||
// libraries/shared/src/
|
||||
//
|
||||
// Created by Seth Alves on 2015-10-18
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_SpatiallyNestable_h
|
||||
#define hifi_SpatiallyNestable_h
|
||||
|
||||
#include <QUuid>
|
||||
|
||||
#include "Transform.h"
|
||||
#include "SpatialParentFinder.h"
|
||||
#include "shared/ReadWriteLockable.h"
|
||||
|
||||
|
||||
class SpatiallyNestable;
|
||||
using SpatiallyNestableWeakPointer = std::weak_ptr<SpatiallyNestable>;
|
||||
using SpatiallyNestableWeakConstPointer = std::weak_ptr<const SpatiallyNestable>;
|
||||
using SpatiallyNestablePointer = std::shared_ptr<SpatiallyNestable>;
|
||||
using SpatiallyNestableConstPointer = std::shared_ptr<const SpatiallyNestable>;
|
||||
|
||||
class NestableTypes {
|
||||
public:
|
||||
using NestableType = enum NestableType_t {
|
||||
Entity,
|
||||
Avatar
|
||||
};
|
||||
};
|
||||
|
||||
class SpatiallyNestable : public std::enable_shared_from_this<SpatiallyNestable> {
|
||||
public:
|
||||
SpatiallyNestable(NestableTypes::NestableType nestableType, QUuid id);
|
||||
virtual ~SpatiallyNestable() { }
|
||||
|
||||
virtual const QUuid& getID() const { return _id; }
|
||||
virtual void setID(const QUuid& id) { _id = id; }
|
||||
|
||||
virtual const QUuid getParentID() const { return _parentID; }
|
||||
virtual void setParentID(const QUuid parentID);
|
||||
|
||||
virtual quint16 getParentJointIndex() const { return _parentJointIndex; }
|
||||
virtual void setParentJointIndex(quint16 parentJointIndex) { _parentJointIndex = parentJointIndex; }
|
||||
|
||||
static glm::vec3 worldToLocal(glm::vec3 position, QUuid parentID, int parentJointIndex);
|
||||
static glm::quat worldToLocal(glm::quat orientation, QUuid parentID, int parentJointIndex);
|
||||
|
||||
static glm::vec3 localToWorld(glm::vec3 position, QUuid parentID, int parentJointIndex);
|
||||
static glm::quat localToWorld(glm::quat orientation, QUuid parentID, int parentJointIndex);
|
||||
|
||||
// world frame
|
||||
virtual const Transform getTransform() const;
|
||||
virtual void setTransform(const Transform transform);
|
||||
|
||||
virtual Transform getParentTransform() const;
|
||||
|
||||
virtual glm::vec3 getPosition() const;
|
||||
virtual void setPosition(glm::vec3 position);
|
||||
|
||||
virtual glm::quat getOrientation() const;
|
||||
virtual glm::quat getOrientation(int jointIndex) const;
|
||||
virtual void setOrientation(glm::quat orientation);
|
||||
|
||||
virtual glm::vec3 getScale() const;
|
||||
virtual void setScale(glm::vec3 scale);
|
||||
|
||||
// get world-frame values for a specific joint
|
||||
virtual const Transform getTransform(int jointIndex) const;
|
||||
virtual glm::vec3 getPosition(int jointIndex) const;
|
||||
virtual glm::vec3 getScale(int jointIndex) const;
|
||||
|
||||
// object's parent's frame
|
||||
virtual const Transform getLocalTransform() const;
|
||||
virtual void setLocalTransform(const Transform transform);
|
||||
|
||||
virtual glm::vec3 getLocalPosition() const;
|
||||
virtual void setLocalPosition(glm::vec3 position);
|
||||
|
||||
virtual glm::quat getLocalOrientation() const;
|
||||
virtual void setLocalOrientation(glm::quat orientation);
|
||||
|
||||
virtual glm::vec3 getLocalScale() const;
|
||||
virtual void setLocalScale(glm::vec3 scale);
|
||||
|
||||
QList<SpatiallyNestablePointer> getChildren() const;
|
||||
NestableTypes::NestableType getNestableType() const { return _nestableType; }
|
||||
|
||||
// this object's frame
|
||||
virtual const Transform getJointTransformInObjectFrame(int jointIndex) const;
|
||||
virtual glm::quat getJointRotation(int index) const { assert(false); return glm::quat(); }
|
||||
virtual glm::vec3 getJointTranslation(int index) const { assert(false); return glm::vec3(); }
|
||||
|
||||
SpatiallyNestablePointer getThisPointer() const;
|
||||
|
||||
protected:
|
||||
NestableTypes::NestableType _nestableType; // EntityItem or an AvatarData
|
||||
QUuid _id;
|
||||
QUuid _parentID; // what is this thing's transform relative to?
|
||||
quint16 _parentJointIndex { 0 }; // which joint of the parent is this relative to?
|
||||
SpatiallyNestablePointer getParentPointer() const;
|
||||
mutable SpatiallyNestableWeakPointer _parent;
|
||||
|
||||
virtual void beParentOfChild(SpatiallyNestablePointer newChild) const;
|
||||
virtual void forgetChild(SpatiallyNestablePointer newChild) const;
|
||||
|
||||
mutable ReadWriteLockable _childrenLock;
|
||||
mutable QHash<QUuid, SpatiallyNestableWeakPointer> _children;
|
||||
|
||||
virtual void parentChanged() {} // called when parent pointer is updated
|
||||
virtual void locationChanged(); // called when a this object's location has changed
|
||||
virtual void dimensionsChanged() {} // called when a this object's dimensions have changed
|
||||
|
||||
void forEachChild(std::function<void(SpatiallyNestablePointer)> actor);
|
||||
void forEachDescendant(std::function<void(SpatiallyNestablePointer)> actor);
|
||||
|
||||
private:
|
||||
mutable ReadWriteLockable _transformLock;
|
||||
Transform _transform; // this is to be combined with parent's world-transform to produce this' world-transform.
|
||||
mutable bool _parentKnowsMe = false;
|
||||
};
|
||||
|
||||
|
||||
#endif // hifi_SpatiallyNestable_h
|
|
@ -165,8 +165,11 @@ void OculusLegacyDisplayPlugin::activate() {
|
|||
}
|
||||
});
|
||||
|
||||
ovrBool result = ovrHmd_ConfigureRendering(_hmd, &config.Config, distortionCaps, _eyeFovs, _eyeRenderDescs);
|
||||
Q_ASSERT(result);
|
||||
#ifndef NDEBUG
|
||||
ovrBool result =
|
||||
#endif
|
||||
ovrHmd_ConfigureRendering(_hmd, &config.Config, distortionCaps, _eyeFovs, _eyeRenderDescs);
|
||||
assert(result);
|
||||
}
|
||||
|
||||
void OculusLegacyDisplayPlugin::deactivate() {
|
||||
|
|
Loading…
Reference in a new issue