mirror of
https://github.com/Armored-Dragon/overte.git
synced 2025-03-11 16:13:16 +01:00
commit
2653b33b67
18 changed files with 638 additions and 46 deletions
|
@ -89,7 +89,12 @@ var sittingDownAnimation = function(deltaTime) {
|
|||
|
||||
var pos = { x: startPosition.x - 0.3 * factor, y: startPosition.y - 0.5 * factor, z: startPosition.z};
|
||||
MyAvatar.position = pos;
|
||||
}
|
||||
} else {
|
||||
Script.update.disconnect(sittingDownAnimation);
|
||||
if (seat.model) {
|
||||
MyAvatar.setModelReferential(seat.model.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var standingUpAnimation = function(deltaTime) {
|
||||
|
@ -103,7 +108,10 @@ var standingUpAnimation = function(deltaTime) {
|
|||
|
||||
var pos = { x: startPosition.x + 0.3 * (passedTime/animationLenght), y: startPosition.y + 0.5 * (passedTime/animationLenght), z: startPosition.z};
|
||||
MyAvatar.position = pos;
|
||||
}
|
||||
} else {
|
||||
Script.update.disconnect(standingUpAnimation);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
var goToSeatAnimation = function(deltaTime) {
|
||||
|
@ -147,7 +155,8 @@ function standUp() {
|
|||
print("standUp sitting status: " + Settings.getValue(sittingSettingsHandle, false));
|
||||
passedTime = 0.0;
|
||||
startPosition = MyAvatar.position;
|
||||
try{
|
||||
MyAvatar.clearReferential();
|
||||
try{
|
||||
Script.update.disconnect(sittingDownAnimation);
|
||||
} catch (e){}
|
||||
Script.update.connect(standingUpAnimation);
|
||||
|
@ -197,8 +206,10 @@ Controller.mousePressEvent.connect(function(event) {
|
|||
var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y});
|
||||
|
||||
if (clickedOverlay == sitDownButton) {
|
||||
seat.model = null;
|
||||
sitDown();
|
||||
} else if (clickedOverlay == standUpButton) {
|
||||
seat.model = null;
|
||||
standUp();
|
||||
} else {
|
||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||
|
@ -214,6 +225,7 @@ Controller.mousePressEvent.connect(function(event) {
|
|||
model.properties.sittingPoints[i].indicator.position,
|
||||
model.properties.sittingPoints[i].indicator.scale / 2)) {
|
||||
clickedOnSeat = true;
|
||||
seat.model = model;
|
||||
seat.position = model.properties.sittingPoints[i].indicator.position;
|
||||
seat.rotation = model.properties.sittingPoints[i].indicator.orientation;
|
||||
}
|
||||
|
@ -355,6 +367,7 @@ Script.update.connect(update);
|
|||
Controller.keyPressEvent.connect(keyPressEvent);
|
||||
|
||||
Script.scriptEnding.connect(function() {
|
||||
MyAvatar.clearReferential();
|
||||
for (var i = 0; i < pose.length; i++){
|
||||
MyAvatar.clearJointData(pose[i].joint);
|
||||
}
|
||||
|
|
|
@ -2139,12 +2139,6 @@ void Application::update(float deltaTime) {
|
|||
_prioVR.update(deltaTime);
|
||||
|
||||
}
|
||||
{
|
||||
PerformanceTimer perfTimer("myAvatar");
|
||||
updateMyAvatarLookAtPosition();
|
||||
updateMyAvatar(deltaTime); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes
|
||||
}
|
||||
|
||||
|
||||
// Dispatch input events
|
||||
_controllerScriptingInterface.updateInputControllers();
|
||||
|
@ -2176,6 +2170,12 @@ void Application::update(float deltaTime) {
|
|||
PerformanceTimer perfTimer("overlays");
|
||||
_overlays.update(deltaTime);
|
||||
}
|
||||
|
||||
{
|
||||
PerformanceTimer perfTimer("myAvatar");
|
||||
updateMyAvatarLookAtPosition();
|
||||
updateMyAvatar(deltaTime); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes
|
||||
}
|
||||
|
||||
{
|
||||
PerformanceTimer perfTimer("emitSimulating");
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "Hand.h"
|
||||
#include "Head.h"
|
||||
#include "Menu.h"
|
||||
#include "ModelReferential.h"
|
||||
#include "Physics.h"
|
||||
#include "world.h"
|
||||
#include "devices/OculusManager.h"
|
||||
|
@ -102,6 +103,31 @@ float Avatar::getLODDistance() const {
|
|||
|
||||
void Avatar::simulate(float deltaTime) {
|
||||
PerformanceTimer perfTimer("simulate");
|
||||
|
||||
// update the avatar's position according to its referential
|
||||
if (_referential) {
|
||||
if (_referential->hasExtraData()) {
|
||||
ModelTree* tree = Application::getInstance()->getModels()->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:
|
||||
qDebug() << "[WARNING] Avatar::simulate(): Unknown referential type.";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_referential->update();
|
||||
}
|
||||
|
||||
if (_scale != _targetScale) {
|
||||
setScale(_targetScale);
|
||||
}
|
||||
|
@ -218,6 +244,9 @@ static TextRenderer* textRenderer(TextRendererType type) {
|
|||
}
|
||||
|
||||
void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) {
|
||||
if (_referential) {
|
||||
_referential->update();
|
||||
}
|
||||
|
||||
if (glm::distance(Application::getInstance()->getAvatar()->getPosition(),
|
||||
_position) < 10.0f) {
|
||||
|
@ -268,7 +297,7 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) {
|
|||
float boundingRadius = getBillboardSize();
|
||||
ViewFrustum* frustum = (renderMode == Avatar::SHADOW_RENDER_MODE) ?
|
||||
Application::getInstance()->getShadowViewFrustum() : Application::getInstance()->getViewFrustum();
|
||||
if (frustum->sphereInFrustum(_position, boundingRadius) == ViewFrustum::OUTSIDE) {
|
||||
if (frustum->sphereInFrustum(getPosition(), boundingRadius) == ViewFrustum::OUTSIDE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -209,7 +209,7 @@ protected:
|
|||
virtual void renderAttachments(RenderMode renderMode);
|
||||
|
||||
virtual void updateJointMappings();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
bool _initialized;
|
||||
|
|
189
interface/src/avatar/ModelReferential.cpp
Normal file
189
interface/src/avatar/ModelReferential.cpp
Normal file
|
@ -0,0 +1,189 @@
|
|||
//
|
||||
// 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 "ModelTree.h"
|
||||
#include "../renderer/Model.h"
|
||||
|
||||
#include "ModelReferential.h"
|
||||
|
||||
ModelReferential::ModelReferential(Referential* referential, ModelTree* tree, AvatarData* avatar) :
|
||||
Referential(MODEL, avatar),
|
||||
_tree(tree) {
|
||||
_translation = referential->getTranslation();
|
||||
_rotation = referential->getRotation();
|
||||
_scale = referential->getScale();
|
||||
unpackExtraData(reinterpret_cast<unsigned char*>(referential->getExtraData().data()),
|
||||
referential->getExtraData().size());
|
||||
|
||||
if (!isValid()) {
|
||||
qDebug() << "ModelReferential::copyConstructor(): Not Valid";
|
||||
return;
|
||||
}
|
||||
|
||||
const ModelItem* item = _tree->findModelByID(_modelID);
|
||||
if (item != NULL) {
|
||||
_refScale = item->getRadius();
|
||||
_refRotation = item->getModelRotation();
|
||||
_refPosition = item->getPosition() * (float)TREE_SCALE;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
ModelReferential::ModelReferential(uint32_t modelID, ModelTree* tree, AvatarData* avatar) :
|
||||
Referential(MODEL, avatar),
|
||||
_modelID(modelID),
|
||||
_tree(tree)
|
||||
{
|
||||
const ModelItem* item = _tree->findModelByID(_modelID);
|
||||
if (!isValid() || item == NULL) {
|
||||
qDebug() << "ModelReferential::constructor(): Not Valid";
|
||||
_isValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
_refScale = item->getRadius();
|
||||
_refRotation = item->getModelRotation();
|
||||
_refPosition = item->getPosition() * (float)TREE_SCALE;
|
||||
|
||||
glm::quat refInvRot = glm::inverse(_refRotation);
|
||||
_scale = _avatar->getTargetScale() / _refScale;
|
||||
_rotation = refInvRot * _avatar->getOrientation();
|
||||
_translation = refInvRot * (avatar->getPosition() - _refPosition) / _refScale;
|
||||
}
|
||||
|
||||
void ModelReferential::update() {
|
||||
const ModelItem* item = _tree->findModelByID(_modelID);
|
||||
if (!isValid() || item == NULL || _avatar == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool somethingChanged = false;
|
||||
if (item->getRadius() != _refScale) {
|
||||
_refScale = item->getRadius();
|
||||
_avatar->setTargetScale(_refScale * _scale, true);
|
||||
somethingChanged = true;
|
||||
}
|
||||
if (item->getModelRotation() != _refRotation) {
|
||||
_refRotation = item->getModelRotation();
|
||||
_avatar->setOrientation(_refRotation * _rotation, true);
|
||||
somethingChanged = true;
|
||||
}
|
||||
if (item->getPosition() != _refPosition || somethingChanged) {
|
||||
_refPosition = item->getPosition();
|
||||
_avatar->setPosition(_refPosition * (float)TREE_SCALE + _refRotation * (_translation * _refScale), true);
|
||||
}
|
||||
}
|
||||
|
||||
int ModelReferential::packExtraData(unsigned char* destinationBuffer) const {
|
||||
memcpy(destinationBuffer, &_modelID, sizeof(_modelID));
|
||||
return sizeof(_modelID);
|
||||
}
|
||||
|
||||
int ModelReferential::unpackExtraData(const unsigned char *sourceBuffer, int size) {
|
||||
memcpy(&_modelID, sourceBuffer, sizeof(_modelID));
|
||||
return sizeof(_modelID);
|
||||
}
|
||||
|
||||
JointReferential::JointReferential(Referential* referential, ModelTree* tree, AvatarData* avatar) :
|
||||
ModelReferential(referential, tree, avatar)
|
||||
{
|
||||
_type = JOINT;
|
||||
if (!isValid()) {
|
||||
qDebug() << "JointReferential::copyConstructor(): Not Valid";
|
||||
return;
|
||||
}
|
||||
|
||||
const ModelItem* item = _tree->findModelByID(_modelID);
|
||||
const Model* model = getModel(item);
|
||||
if (!isValid() || model == NULL || _jointIndex >= model->getJointStateCount()) {
|
||||
_refScale = item->getRadius();
|
||||
model->getJointRotationInWorldFrame(_jointIndex, _refRotation);
|
||||
model->getJointPositionInWorldFrame(_jointIndex, _refPosition);
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
JointReferential::JointReferential(uint32_t jointIndex, uint32_t modelID, ModelTree* tree, AvatarData* avatar) :
|
||||
ModelReferential(modelID, tree, avatar),
|
||||
_jointIndex(jointIndex)
|
||||
{
|
||||
_type = JOINT;
|
||||
const ModelItem* item = _tree->findModelByID(_modelID);
|
||||
const Model* model = getModel(item);
|
||||
if (!isValid() || model == NULL || _jointIndex >= model->getJointStateCount()) {
|
||||
qDebug() << "JointReferential::constructor(): Not Valid";
|
||||
_isValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
_refScale = item->getRadius();
|
||||
model->getJointRotationInWorldFrame(_jointIndex, _refRotation);
|
||||
model->getJointPositionInWorldFrame(_jointIndex, _refPosition);
|
||||
|
||||
glm::quat refInvRot = glm::inverse(_refRotation);
|
||||
_scale = _avatar->getTargetScale() / _refScale;
|
||||
_rotation = refInvRot * _avatar->getOrientation();
|
||||
_translation = refInvRot * (avatar->getPosition() - _refPosition) / _refScale;
|
||||
}
|
||||
|
||||
void JointReferential::update() {
|
||||
const ModelItem* item = _tree->findModelByID(_modelID);
|
||||
const Model* model = getModel(item);
|
||||
if (!isValid() || model == NULL || _jointIndex >= model->getJointStateCount()) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool somethingChanged = false;
|
||||
if (item->getRadius() != _refScale) {
|
||||
_refScale = item->getRadius();
|
||||
_avatar->setTargetScale(_refScale * _scale, true);
|
||||
somethingChanged = true;
|
||||
}
|
||||
if (item->getModelRotation() != _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 * _refScale), true);
|
||||
}
|
||||
}
|
||||
|
||||
const Model* JointReferential::getModel(const ModelItem* item) {
|
||||
ModelItemFBXService* fbxService = _tree->getFBXService();
|
||||
if (item != NULL && fbxService != NULL) {
|
||||
return fbxService->getModelForModelItem(*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;
|
||||
}
|
48
interface/src/avatar/ModelReferential.h
Normal file
48
interface/src/avatar/ModelReferential.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
//
|
||||
// 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 ModelTree;
|
||||
class Model;
|
||||
|
||||
class ModelReferential : public Referential {
|
||||
public:
|
||||
ModelReferential(Referential* ref, ModelTree* tree, AvatarData* avatar);
|
||||
ModelReferential(uint32_t modelID, ModelTree* tree, AvatarData* avatar);
|
||||
virtual void update();
|
||||
|
||||
protected:
|
||||
virtual int packExtraData(unsigned char* destinationBuffer) const;
|
||||
virtual int unpackExtraData(const unsigned char* sourceBuffer, int size);
|
||||
|
||||
uint32_t _modelID;
|
||||
ModelTree* _tree;
|
||||
};
|
||||
|
||||
class JointReferential : public ModelReferential {
|
||||
public:
|
||||
JointReferential(Referential* ref, ModelTree* tree, AvatarData* avatar);
|
||||
JointReferential(uint32_t jointIndex, uint32_t modelID, ModelTree* tree, AvatarData* avatar);
|
||||
virtual void update();
|
||||
|
||||
protected:
|
||||
const Model* getModel(const ModelItem* item);
|
||||
virtual int packExtraData(unsigned char* destinationBuffer) const;
|
||||
virtual int unpackExtraData(const unsigned char* sourceBuffer, int size);
|
||||
|
||||
uint32_t _jointIndex;
|
||||
};
|
||||
|
||||
#endif // hifi_ModelReferential_h
|
|
@ -32,6 +32,7 @@
|
|||
#include "Audio.h"
|
||||
#include "Environment.h"
|
||||
#include "Menu.h"
|
||||
#include "ModelReferential.h"
|
||||
#include "MyAvatar.h"
|
||||
#include "Physics.h"
|
||||
#include "devices/Faceshift.h"
|
||||
|
@ -108,6 +109,10 @@ void MyAvatar::reset() {
|
|||
}
|
||||
|
||||
void MyAvatar::update(float deltaTime) {
|
||||
if (_referential) {
|
||||
_referential->update();
|
||||
}
|
||||
|
||||
Head* head = getHead();
|
||||
head->relaxLean(deltaTime);
|
||||
updateFromTrackers(deltaTime);
|
||||
|
@ -444,6 +449,32 @@ glm::vec3 MyAvatar::getRightPalmPosition() {
|
|||
return rightHandPosition;
|
||||
}
|
||||
|
||||
void MyAvatar::clearReferential() {
|
||||
changeReferential(NULL);
|
||||
}
|
||||
|
||||
bool MyAvatar::setModelReferential(int id) {
|
||||
ModelTree* tree = Application::getInstance()->getModels()->getTree();
|
||||
changeReferential(new ModelReferential(id, tree, this));
|
||||
if (_referential->isValid()) {
|
||||
return true;
|
||||
} else {
|
||||
changeReferential(NULL);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool MyAvatar::setJointReferential(int id, int jointIndex) {
|
||||
ModelTree* tree = Application::getInstance()->getModels()->getTree();
|
||||
changeReferential(new JointReferential(jointIndex, id, tree, this));
|
||||
if (!_referential->isValid()) {
|
||||
return true;
|
||||
} else {
|
||||
changeReferential(NULL);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void MyAvatar::setLocalGravity(glm::vec3 gravity) {
|
||||
_motionBehaviors |= AVATAR_MOTION_OBEY_LOCAL_GRAVITY;
|
||||
// Environmental and Local gravities are incompatible. Since Local is being set here
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
#include "Avatar.h"
|
||||
|
||||
class ModelItemID;
|
||||
|
||||
enum AvatarHandState
|
||||
{
|
||||
HAND_STATE_NULL = 0,
|
||||
|
@ -149,6 +151,10 @@ public slots:
|
|||
glm::vec3 getLeftPalmPosition();
|
||||
glm::vec3 getRightPalmPosition();
|
||||
|
||||
void clearReferential();
|
||||
bool setModelReferential(int id);
|
||||
bool setJointReferential(int id, int jointIndex);
|
||||
|
||||
signals:
|
||||
void transformChanged();
|
||||
|
||||
|
|
|
@ -76,6 +76,10 @@ const FBXGeometry* ModelTreeRenderer::getGeometryForModel(const ModelItem& model
|
|||
return result;
|
||||
}
|
||||
|
||||
const Model* ModelTreeRenderer::getModelForModelItem(const ModelItem& modelItem) {
|
||||
return getModel(modelItem);
|
||||
}
|
||||
|
||||
Model* ModelTreeRenderer::getModel(const ModelItem& modelItem) {
|
||||
Model* model = NULL;
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ public:
|
|||
virtual void render(RenderMode renderMode = DEFAULT_RENDER_MODE);
|
||||
|
||||
virtual const FBXGeometry* getGeometryForModel(const ModelItem& modelItem);
|
||||
|
||||
virtual const Model* getModelForModelItem(const ModelItem& modelItem);
|
||||
/// clears the tree
|
||||
virtual void clear();
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ using namespace std;
|
|||
AvatarData::AvatarData() :
|
||||
_sessionUUID(),
|
||||
_handPosition(0,0,0),
|
||||
_referential(NULL),
|
||||
_bodyYaw(-90.f),
|
||||
_bodyPitch(0.0f),
|
||||
_bodyRoll(0.0f),
|
||||
|
@ -62,6 +63,59 @@ AvatarData::AvatarData() :
|
|||
AvatarData::~AvatarData() {
|
||||
delete _headData;
|
||||
delete _handData;
|
||||
delete _referential;
|
||||
}
|
||||
|
||||
const glm::vec3& AvatarData::getPosition() {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
float AvatarData::getTargetScale() const {
|
||||
if (_referential) {
|
||||
_referential->update();
|
||||
}
|
||||
|
||||
return _targetScale;
|
||||
}
|
||||
|
||||
void AvatarData::setTargetScale(float targetScale, bool overideReferential) {
|
||||
if (!_referential || overideReferential) {
|
||||
_targetScale = targetScale;
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarData::setClampedTargetScale(float targetScale, bool overideReferential) {
|
||||
|
||||
targetScale = glm::clamp(targetScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE);
|
||||
|
||||
setTargetScale(targetScale, overideReferential);
|
||||
qDebug() << "Changed scale to " << _targetScale;
|
||||
}
|
||||
|
||||
glm::vec3 AvatarData::getHandPosition() const {
|
||||
|
@ -135,11 +189,21 @@ QByteArray AvatarData::toByteArray() {
|
|||
// hand state
|
||||
setSemiNibbleAt(bitItems,HAND_STATE_START_BIT,_handState);
|
||||
// faceshift state
|
||||
if (_headData->_isFaceshiftConnected) { setAtBit(bitItems, IS_FACESHIFT_CONNECTED); }
|
||||
if (_headData->_isFaceshiftConnected) {
|
||||
setAtBit(bitItems, IS_FACESHIFT_CONNECTED);
|
||||
}
|
||||
if (_isChatCirclingEnabled) {
|
||||
setAtBit(bitItems, IS_CHAT_CIRCLING_ENABLED);
|
||||
}
|
||||
if (_referential != NULL && _referential->isValid()) {
|
||||
setAtBit(bitItems, HAS_REFERENTIAL);
|
||||
}
|
||||
*destinationBuffer++ = bitItems;
|
||||
|
||||
// Add referential
|
||||
if (_referential != NULL && _referential->isValid()) {
|
||||
destinationBuffer += _referential->packReferential(destinationBuffer);
|
||||
}
|
||||
|
||||
// If it is connected, pack up the data
|
||||
if (_headData->_isFaceshiftConnected) {
|
||||
|
@ -370,18 +434,32 @@ int AvatarData::parseDataAtOffset(const QByteArray& packet, int offset) {
|
|||
} // 1 + chatMessageSize bytes
|
||||
|
||||
{ // bitFlags and face data
|
||||
unsigned char bitItems = 0;
|
||||
bitItems = (unsigned char)*sourceBuffer++;
|
||||
|
||||
unsigned char bitItems = *sourceBuffer++;
|
||||
|
||||
// key state, stored as a semi-nibble in the bitItems
|
||||
_keyState = (KeyState)getSemiNibbleAt(bitItems,KEY_STATE_START_BIT);
|
||||
|
||||
// hand state, stored as a semi-nibble in the bitItems
|
||||
_handState = getSemiNibbleAt(bitItems,HAND_STATE_START_BIT);
|
||||
|
||||
_headData->_isFaceshiftConnected = oneAtBit(bitItems, IS_FACESHIFT_CONNECTED);
|
||||
_isChatCirclingEnabled = oneAtBit(bitItems, IS_CHAT_CIRCLING_ENABLED);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
if (_headData->_isFaceshiftConnected) {
|
||||
float leftEyeBlink, rightEyeBlink, averageLoudness, browAudioLift;
|
||||
minPossibleSize += sizeof(leftEyeBlink) + sizeof(rightEyeBlink) + sizeof(averageLoudness) + sizeof(browAudioLift);
|
||||
|
@ -503,6 +581,15 @@ int AvatarData::parseDataAtOffset(const QByteArray& packet, int offset) {
|
|||
return sourceBuffer - startPosition;
|
||||
}
|
||||
|
||||
bool AvatarData::hasReferential() {
|
||||
return _referential != NULL;
|
||||
}
|
||||
|
||||
void AvatarData::changeReferential(Referential *ref) {
|
||||
delete _referential;
|
||||
_referential = ref;
|
||||
}
|
||||
|
||||
void AvatarData::setJointData(int index, const glm::quat& rotation) {
|
||||
if (index == -1) {
|
||||
return;
|
||||
|
@ -803,21 +890,6 @@ void AvatarData::setJointMappingsFromNetworkReply() {
|
|||
networkReply->deleteLater();
|
||||
}
|
||||
|
||||
void AvatarData::setClampedTargetScale(float targetScale) {
|
||||
|
||||
targetScale = glm::clamp(targetScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE);
|
||||
|
||||
_targetScale = targetScale;
|
||||
qDebug() << "Changed scale to " << _targetScale;
|
||||
}
|
||||
|
||||
void AvatarData::setOrientation(const glm::quat& orientation) {
|
||||
glm::vec3 eulerAngles = glm::degrees(safeEulerAngles(orientation));
|
||||
_bodyPitch = eulerAngles.x;
|
||||
_bodyYaw = eulerAngles.y;
|
||||
_bodyRoll = eulerAngles.z;
|
||||
}
|
||||
|
||||
void AvatarData::sendIdentityPacket() {
|
||||
QByteArray identityPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarIdentity);
|
||||
identityPacket.append(identityByteArray());
|
||||
|
|
|
@ -49,6 +49,7 @@ typedef unsigned long long quint64;
|
|||
|
||||
#include <Node.h>
|
||||
|
||||
#include "Referential.h"
|
||||
#include "HeadData.h"
|
||||
#include "HandData.h"
|
||||
|
||||
|
@ -80,7 +81,8 @@ const quint32 AVATAR_MOTION_SCRIPTABLE_BITS =
|
|||
const int KEY_STATE_START_BIT = 0; // 1st and 2nd bits
|
||||
const int HAND_STATE_START_BIT = 2; // 3rd and 4th bits
|
||||
const int IS_FACESHIFT_CONNECTED = 4; // 5th bit
|
||||
const int IS_CHAT_CIRCLING_ENABLED = 5;
|
||||
const int IS_CHAT_CIRCLING_ENABLED = 5; // 6th bit
|
||||
const int HAS_REFERENTIAL = 6; // 7th bit
|
||||
|
||||
static const float MAX_AVATAR_SCALE = 1000.f;
|
||||
static const float MIN_AVATAR_SCALE = .005f;
|
||||
|
@ -141,8 +143,8 @@ public:
|
|||
|
||||
const QUuid& getSessionUUID() { return _sessionUUID; }
|
||||
|
||||
const glm::vec3& getPosition() const { return _position; }
|
||||
void setPosition(const glm::vec3 position) { _position = position; }
|
||||
const glm::vec3& getPosition();
|
||||
void setPosition(const glm::vec3 position, bool overideReferential = false);
|
||||
|
||||
glm::vec3 getHandPosition() const;
|
||||
void setHandPosition(const glm::vec3& handPosition);
|
||||
|
@ -165,8 +167,8 @@ public:
|
|||
float getBodyRoll() const { return _bodyRoll; }
|
||||
void setBodyRoll(float bodyRoll) { _bodyRoll = bodyRoll; }
|
||||
|
||||
glm::quat getOrientation() const { return glm::quat(glm::radians(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll))); }
|
||||
void setOrientation(const glm::quat& orientation);
|
||||
glm::quat getOrientation() const;
|
||||
void setOrientation(const glm::quat& orientation, bool overideReferential = false);
|
||||
|
||||
glm::quat getHeadOrientation() const { return _headData->getOrientation(); }
|
||||
void setHeadOrientation(const glm::quat& orientation) { _headData->setOrientation(orientation); }
|
||||
|
@ -188,9 +190,9 @@ public:
|
|||
void setAudioAverageLoudness(float value) { _headData->setAudioAverageLoudness(value); }
|
||||
|
||||
// Scale
|
||||
float getTargetScale() const { return _targetScale; }
|
||||
void setTargetScale(float targetScale) { _targetScale = targetScale; }
|
||||
void setClampedTargetScale(float targetScale);
|
||||
float getTargetScale() const;
|
||||
void setTargetScale(float targetScale, bool overideReferential = false);
|
||||
void setClampedTargetScale(float targetScale, bool overideReferential = false);
|
||||
|
||||
// Hand State
|
||||
Q_INVOKABLE void setHandState(char s) { _handState = s; }
|
||||
|
@ -280,6 +282,8 @@ public:
|
|||
QElapsedTimer& getLastUpdateTimer() { return _lastUpdateTimer; }
|
||||
|
||||
virtual float getBoundingRadius() const { return 1.f; }
|
||||
|
||||
const Referential* getReferential() const { return _referential; }
|
||||
|
||||
public slots:
|
||||
void sendIdentityPacket();
|
||||
|
@ -287,10 +291,14 @@ public slots:
|
|||
void setBillboardFromNetworkReply();
|
||||
void setJointMappingsFromNetworkReply();
|
||||
void setSessionUUID(const QUuid& id) { _sessionUUID = id; }
|
||||
bool hasReferential();
|
||||
|
||||
protected:
|
||||
QUuid _sessionUUID;
|
||||
glm::vec3 _position;
|
||||
glm::vec3 _handPosition;
|
||||
|
||||
Referential* _referential;
|
||||
|
||||
// Body rotation
|
||||
float _bodyYaw; // degrees
|
||||
|
@ -340,6 +348,7 @@ protected:
|
|||
|
||||
/// Loads the joint indices, names from the FST file (if any)
|
||||
virtual void updateJointMappings();
|
||||
void changeReferential(Referential* ref);
|
||||
|
||||
private:
|
||||
// privatize the copy constructor and assignment operator so they cannot be called
|
||||
|
|
113
libraries/avatars/src/Referential.cpp
Normal file
113
libraries/avatars/src/Referential.cpp
Normal file
|
@ -0,0 +1,113 @@
|
|||
//
|
||||
// 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 <SharedUtil.h>
|
||||
|
||||
#include "AvatarData.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
|
||||
qDebug() << "[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);
|
||||
destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, _scale, 0);
|
||||
return destinationBuffer - startPosition;
|
||||
}
|
||||
|
||||
int Referential::unpack(const unsigned char* sourceBuffer) {
|
||||
const unsigned char* startPosition = sourceBuffer;
|
||||
_type = (Type)*sourceBuffer++;
|
||||
if (_type < 0 || _type >= NUM_TYPE) {
|
||||
_type = UNKNOWN;
|
||||
}
|
||||
memcpy(&_version, sourceBuffer, sizeof(_version));
|
||||
sourceBuffer += sizeof(_version);
|
||||
|
||||
sourceBuffer += unpackFloatVec3FromSignedTwoByteFixed(sourceBuffer, _translation, 0);
|
||||
sourceBuffer += unpackOrientationQuatFromBytes(sourceBuffer, _rotation);
|
||||
sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((const int16_t*) sourceBuffer, &_scale, 0);
|
||||
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.setRawData(reinterpret_cast<const char*>(sourceBuffer), size);
|
||||
return size;
|
||||
}
|
||||
|
75
libraries/avatars/src/Referential.h
Normal file
75
libraries/avatars/src/Referential.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
//
|
||||
// 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_TYPE
|
||||
};
|
||||
|
||||
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; }
|
||||
float getScale() const {return _scale; }
|
||||
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;
|
||||
glm::quat _refRotation;
|
||||
float _refScale;
|
||||
|
||||
glm::vec3 _translation;
|
||||
glm::quat _rotation;
|
||||
float _scale;
|
||||
};
|
||||
|
||||
|
||||
#endif // hifi_Referential_h
|
|
@ -179,7 +179,6 @@ void ModelItemIDfromScriptValue(const QScriptValue &object, ModelItemID& propert
|
|||
|
||||
/// ModelItem class - this is the actual model item class.
|
||||
class ModelItem {
|
||||
|
||||
public:
|
||||
ModelItem();
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#include <Octree.h>
|
||||
#include "ModelTreeElement.h"
|
||||
|
||||
class Model;
|
||||
|
||||
class NewlyCreatedModelHook {
|
||||
public:
|
||||
virtual void modelCreated(const ModelItem& newModel, const SharedNodePointer& senderNode) = 0;
|
||||
|
@ -23,6 +25,7 @@ public:
|
|||
class ModelItemFBXService {
|
||||
public:
|
||||
virtual const FBXGeometry* getGeometryForModel(const ModelItem& modelItem) = 0;
|
||||
virtual const Model* getModelForModelItem(const ModelItem& modelItem) = 0;
|
||||
};
|
||||
|
||||
class ModelTree : public Octree {
|
||||
|
@ -80,6 +83,7 @@ public:
|
|||
void processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode);
|
||||
void handleAddModelResponse(const QByteArray& packet);
|
||||
|
||||
ModelItemFBXService* getFBXService() const { return _fbxService; }
|
||||
void setFBXService(ModelItemFBXService* service) { _fbxService = service; }
|
||||
const FBXGeometry* getGeometryForModel(const ModelItem& modelItem) {
|
||||
return _fbxService ? _fbxService->getGeometryForModel(modelItem) : NULL;
|
||||
|
|
|
@ -167,7 +167,7 @@ bool oneAtBit(unsigned char byte, int bitIndex) {
|
|||
}
|
||||
|
||||
void setAtBit(unsigned char& byte, int bitIndex) {
|
||||
byte += (1 << (7 - bitIndex));
|
||||
byte |= (1 << (7 - bitIndex));
|
||||
}
|
||||
|
||||
void clearAtBit(unsigned char& byte, int bitIndex) {
|
||||
|
@ -176,7 +176,7 @@ void clearAtBit(unsigned char& byte, int bitIndex) {
|
|||
}
|
||||
}
|
||||
|
||||
int getSemiNibbleAt(unsigned char& byte, int bitIndex) {
|
||||
int getSemiNibbleAt(unsigned char byte, int bitIndex) {
|
||||
return (byte >> (6 - bitIndex) & 3); // semi-nibbles store 00, 01, 10, or 11
|
||||
}
|
||||
|
||||
|
@ -207,7 +207,7 @@ bool isBetween(int64_t value, int64_t max, int64_t min) {
|
|||
|
||||
void setSemiNibbleAt(unsigned char& byte, int bitIndex, int value) {
|
||||
//assert(value <= 3 && value >= 0);
|
||||
byte += ((value & 3) << (6 - bitIndex)); // semi-nibbles store 00, 01, 10, or 11
|
||||
byte |= ((value & 3) << (6 - bitIndex)); // semi-nibbles store 00, 01, 10, or 11
|
||||
}
|
||||
|
||||
bool isInEnvironment(const char* environment) {
|
||||
|
@ -496,7 +496,7 @@ int packFloatScalarToSignedTwoByteFixed(unsigned char* buffer, float scalar, int
|
|||
return sizeof(uint16_t);
|
||||
}
|
||||
|
||||
int unpackFloatScalarFromSignedTwoByteFixed(int16_t* byteFixedPointer, float* destinationPointer, int radix) {
|
||||
int unpackFloatScalarFromSignedTwoByteFixed(const int16_t* byteFixedPointer, float* destinationPointer, int radix) {
|
||||
*destinationPointer = *byteFixedPointer / (float)(1 << radix);
|
||||
return sizeof(int16_t);
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ int numberOfOnes(unsigned char byte);
|
|||
bool oneAtBit(unsigned char byte, int bitIndex);
|
||||
void setAtBit(unsigned char& byte, int bitIndex);
|
||||
void clearAtBit(unsigned char& byte, int bitIndex);
|
||||
int getSemiNibbleAt(unsigned char& byte, int bitIndex);
|
||||
int getSemiNibbleAt(unsigned char byte, int bitIndex);
|
||||
void setSemiNibbleAt(unsigned char& byte, int bitIndex, int value);
|
||||
|
||||
int getNthBit(unsigned char byte, int ordinal); /// determines the bit placement 0-7 of the ordinal set bit
|
||||
|
|
Loading…
Reference in a new issue