mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-16 10:33:52 +02:00
commit
3de7801463
17 changed files with 240 additions and 113 deletions
|
@ -28,7 +28,7 @@ enum CameraMode
|
|||
};
|
||||
|
||||
Q_DECLARE_METATYPE(CameraMode);
|
||||
static int cameraModeId = qRegisterMetaType<CameraMode>();
|
||||
// static int cameraModeId = qRegisterMetaType<CameraMode>();
|
||||
|
||||
class Camera : public QObject {
|
||||
Q_OBJECT
|
||||
|
|
|
@ -49,7 +49,6 @@ void FaceModel::simulate(float deltaTime, bool fullUpdate) {
|
|||
}
|
||||
|
||||
void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
|
||||
Avatar* owningAvatar = static_cast<Avatar*>(_owningHead->_owningAvatar);
|
||||
// get the rotation axes in joint space and use them to adjust the rotation
|
||||
glm::mat3 axes = glm::mat3_cast(glm::quat());
|
||||
glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getTransform() *
|
||||
|
|
|
@ -79,7 +79,7 @@ const float MyAvatar::ZOOM_MAX = 25.0f;
|
|||
const float MyAvatar::ZOOM_DEFAULT = 1.5f;
|
||||
|
||||
MyAvatar::MyAvatar() :
|
||||
Avatar(),
|
||||
Avatar(),
|
||||
_gravity(0.0f, 0.0f, 0.0f),
|
||||
_wasPushing(false),
|
||||
_isPushing(false),
|
||||
|
@ -102,7 +102,8 @@ MyAvatar::MyAvatar() :
|
|||
_eyeContactTarget(LEFT_EYE),
|
||||
_realWorldFieldOfView("realWorldFieldOfView",
|
||||
DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES),
|
||||
_firstPersonSkeletonModel(this),
|
||||
_rig(),
|
||||
_firstPersonSkeletonModel(this, nullptr, _rig),
|
||||
_prevShouldDrawHead(true)
|
||||
{
|
||||
_firstPersonSkeletonModel.setIsFirstPerson(true);
|
||||
|
@ -488,7 +489,7 @@ void MyAvatar::loadLastRecording() {
|
|||
}
|
||||
|
||||
AnimationHandlePointer MyAvatar::addAnimationHandle() {
|
||||
AnimationHandlePointer handle = _skeletonModel.createAnimationHandle();
|
||||
AnimationHandlePointer handle = _rig->createAnimationHandle();
|
||||
_animationHandles.append(handle);
|
||||
return handle;
|
||||
}
|
||||
|
@ -506,7 +507,7 @@ void MyAvatar::startAnimation(const QString& url, float fps, float priority,
|
|||
Q_ARG(float, lastFrame), Q_ARG(const QStringList&, maskedJoints));
|
||||
return;
|
||||
}
|
||||
AnimationHandlePointer handle = _skeletonModel.createAnimationHandle();
|
||||
AnimationHandlePointer handle = _rig->createAnimationHandle();
|
||||
handle->setURL(url);
|
||||
handle->setFPS(fps);
|
||||
handle->setPriority(priority);
|
||||
|
@ -534,7 +535,7 @@ void MyAvatar::startAnimationByRole(const QString& role, const QString& url, flo
|
|||
}
|
||||
}
|
||||
// no joy; use the parameters provided
|
||||
AnimationHandlePointer handle = _skeletonModel.createAnimationHandle();
|
||||
AnimationHandlePointer handle = _rig->createAnimationHandle();
|
||||
handle->setRole(role);
|
||||
handle->setURL(url);
|
||||
handle->setFPS(fps);
|
||||
|
|
|
@ -286,7 +286,7 @@ private:
|
|||
QString _bodyModelName;
|
||||
QString _fullAvatarModelName;
|
||||
|
||||
Rig _rig;
|
||||
RigPointer _rig;
|
||||
// used for rendering when in first person view or when in an HMD.
|
||||
SkeletonModel _firstPersonSkeletonModel;
|
||||
bool _prevShouldDrawHead;
|
||||
|
|
|
@ -29,8 +29,8 @@ enum StandingFootState {
|
|||
NO_FOOT
|
||||
};
|
||||
|
||||
SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent) :
|
||||
Model(parent),
|
||||
SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent, RigPointer rig) :
|
||||
Model(parent, rig),
|
||||
_triangleFanID(DependencyManager::get<GeometryCache>()->allocateID()),
|
||||
_owningAvatar(owningAvatar),
|
||||
_boundingShape(),
|
||||
|
|
|
@ -25,7 +25,7 @@ class SkeletonModel : public Model {
|
|||
|
||||
public:
|
||||
|
||||
SkeletonModel(Avatar* owningAvatar, QObject* parent = NULL);
|
||||
SkeletonModel(Avatar* owningAvatar, QObject* parent = nullptr, RigPointer rig = nullptr);
|
||||
~SkeletonModel();
|
||||
|
||||
virtual void initJointStates(QVector<JointState> states);
|
||||
|
|
|
@ -156,7 +156,7 @@ AnimationPanel::AnimationPanel(AnimationsDialog* dialog, const AnimationHandlePo
|
|||
buttons->addWidget(remove);
|
||||
connect(remove, SIGNAL(clicked(bool)), SLOT(removeHandle()));
|
||||
|
||||
_stop->connect(_handle.data(), SIGNAL(runningChanged(bool)), SLOT(setEnabled(bool)));
|
||||
_stop->connect(_handle.get(), SIGNAL(runningChanged(bool)), SLOT(setEnabled(bool)));
|
||||
_stop->setEnabled(_handle->isRunning());
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ void Cube3DOverlay::render(RenderArgs* args) {
|
|||
|
||||
// TODO: handle registration point??
|
||||
glm::vec3 position = getPosition();
|
||||
glm::vec3 center = getCenter();
|
||||
glm::vec3 dimensions = getDimensions();
|
||||
glm::quat rotation = getRotation();
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ void LocalModelsOverlay::update(float deltatime) {
|
|||
|
||||
void LocalModelsOverlay::render(RenderArgs* args) {
|
||||
if (_visible) {
|
||||
float glowLevel = getGlowLevel(); // FIXME, glowing removed for now
|
||||
// float glowLevel = getGlowLevel(); // FIXME, glowing removed for now
|
||||
|
||||
auto batch = args ->_batch;
|
||||
Application* app = Application::getInstance();
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
//
|
||||
|
||||
#include "AnimationHandle.h"
|
||||
#include "Model.h"
|
||||
|
||||
|
||||
void AnimationHandle::setURL(const QUrl& url) {
|
||||
if (_url != url) {
|
||||
|
@ -20,28 +20,17 @@ void AnimationHandle::setURL(const QUrl& url) {
|
|||
}
|
||||
}
|
||||
|
||||
static void insertSorted(QList<AnimationHandlePointer>& handles, const AnimationHandlePointer& handle) {
|
||||
for (QList<AnimationHandlePointer>::iterator it = handles.begin(); it != handles.end(); it++) {
|
||||
if (handle->getPriority() > (*it)->getPriority()) {
|
||||
handles.insert(it, handle);
|
||||
return;
|
||||
}
|
||||
}
|
||||
handles.append(handle);
|
||||
}
|
||||
|
||||
void AnimationHandle::setPriority(float priority) {
|
||||
if (_priority == priority) {
|
||||
return;
|
||||
}
|
||||
if (isRunning()) {
|
||||
_model->_runningAnimations.removeOne(_self);
|
||||
_rig->removeRunningAnimation(getAnimationHandlePointer());
|
||||
if (priority < _priority) {
|
||||
replaceMatchingPriorities(priority);
|
||||
}
|
||||
_priority = priority;
|
||||
insertSorted(_model->_runningAnimations, _self);
|
||||
|
||||
_rig->addRunningAnimation(getAnimationHandlePointer());
|
||||
} else {
|
||||
_priority = priority;
|
||||
}
|
||||
|
@ -68,21 +57,21 @@ void AnimationHandle::setRunning(bool running) {
|
|||
}
|
||||
_animationLoop.setRunning(running);
|
||||
if (isRunning()) {
|
||||
if (!_model->_runningAnimations.contains(_self)) {
|
||||
insertSorted(_model->_runningAnimations, _self);
|
||||
if (!_rig->isRunningAnimation(getAnimationHandlePointer())) {
|
||||
_rig->addRunningAnimation(getAnimationHandlePointer());
|
||||
}
|
||||
} else {
|
||||
_model->_runningAnimations.removeOne(_self);
|
||||
_rig->removeRunningAnimation(getAnimationHandlePointer());
|
||||
restoreJoints();
|
||||
replaceMatchingPriorities(0.0f);
|
||||
}
|
||||
emit runningChanged(isRunning());
|
||||
}
|
||||
|
||||
AnimationHandle::AnimationHandle(Model* model) :
|
||||
QObject(model),
|
||||
_model(model),
|
||||
_priority(1.0f)
|
||||
AnimationHandle::AnimationHandle(RigPointer rig) :
|
||||
QObject(rig.get()),
|
||||
_rig(rig),
|
||||
_priority(1.0f)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -110,42 +99,52 @@ void AnimationHandle::setAnimationDetails(const AnimationDetails& details) {
|
|||
}
|
||||
|
||||
|
||||
void AnimationHandle::setJointMappings(QVector<int> jointMappings) {
|
||||
_jointMappings = jointMappings;
|
||||
}
|
||||
|
||||
|
||||
void AnimationHandle::simulate(float deltaTime) {
|
||||
if (!_animation || !_animation->isLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
_animationLoop.simulate(deltaTime);
|
||||
|
||||
// update the joint mappings if necessary/possible
|
||||
|
||||
if (_jointMappings.isEmpty()) {
|
||||
if (_model && _model->isActive()) {
|
||||
_jointMappings = _model->getGeometry()->getJointMappings(_animation);
|
||||
}
|
||||
if (_jointMappings.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (!_maskedJoints.isEmpty()) {
|
||||
const FBXGeometry& geometry = _model->getGeometry()->getFBXGeometry();
|
||||
for (int i = 0; i < _jointMappings.size(); i++) {
|
||||
int& mapping = _jointMappings[i];
|
||||
if (mapping != -1 && _maskedJoints.contains(geometry.joints.at(mapping).name)) {
|
||||
mapping = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
qDebug() << "AnimationHandle::simulate -- _jointMappings.isEmpty()";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// // update the joint mappings if necessary/possible
|
||||
// if (_jointMappings.isEmpty()) {
|
||||
// if (_model && _model->isActive()) {
|
||||
// _jointMappings = _model->getGeometry()->getJointMappings(_animation);
|
||||
// }
|
||||
// if (_jointMappings.isEmpty()) {
|
||||
// return;
|
||||
// }
|
||||
// if (!_maskedJoints.isEmpty()) {
|
||||
// const FBXGeometry& geometry = _model->getGeometry()->getFBXGeometry();
|
||||
// for (int i = 0; i < _jointMappings.size(); i++) {
|
||||
// int& mapping = _jointMappings[i];
|
||||
// if (mapping != -1 && _maskedJoints.contains(geometry.joints.at(mapping).name)) {
|
||||
// mapping = -1;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
const FBXGeometry& animationGeometry = _animation->getGeometry();
|
||||
if (animationGeometry.animationFrames.isEmpty()) {
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (_animationLoop.getMaxFrameIndexHint() != animationGeometry.animationFrames.size()) {
|
||||
_animationLoop.setMaxFrameIndexHint(animationGeometry.animationFrames.size());
|
||||
}
|
||||
|
||||
|
||||
// blend between the closest two frames
|
||||
applyFrame(getFrameIndex());
|
||||
}
|
||||
|
@ -154,17 +153,21 @@ void AnimationHandle::applyFrame(float frameIndex) {
|
|||
if (!_animation || !_animation->isLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const FBXGeometry& animationGeometry = _animation->getGeometry();
|
||||
int frameCount = animationGeometry.animationFrames.size();
|
||||
const FBXAnimationFrame& floorFrame = animationGeometry.animationFrames.at((int)glm::floor(frameIndex) % frameCount);
|
||||
const FBXAnimationFrame& ceilFrame = animationGeometry.animationFrames.at((int)glm::ceil(frameIndex) % frameCount);
|
||||
float frameFraction = glm::fract(frameIndex);
|
||||
QVector<JointState> jointStates = _rig->getJointStates();
|
||||
for (int i = 0; i < _jointMappings.size(); i++) {
|
||||
int mapping = _jointMappings.at(i);
|
||||
if (mapping != -1) {
|
||||
JointState& state = _model->_jointStates[mapping];
|
||||
state.setRotationInConstrainedFrame(safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction), _priority);
|
||||
JointState& state = jointStates[mapping];
|
||||
state.setRotationInConstrainedFrame(safeMix(floorFrame.rotations.at(i),
|
||||
ceilFrame.rotations.at(i),
|
||||
frameFraction),
|
||||
_priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -173,7 +176,8 @@ void AnimationHandle::replaceMatchingPriorities(float newPriority) {
|
|||
for (int i = 0; i < _jointMappings.size(); i++) {
|
||||
int mapping = _jointMappings.at(i);
|
||||
if (mapping != -1) {
|
||||
JointState& state = _model->_jointStates[mapping];
|
||||
QVector<JointState> jointStates = _rig->getJointStates();
|
||||
JointState& state = jointStates[mapping];
|
||||
if (_priority == state._animationPriority) {
|
||||
state._animationPriority = newPriority;
|
||||
}
|
||||
|
@ -185,9 +189,9 @@ void AnimationHandle::restoreJoints() {
|
|||
for (int i = 0; i < _jointMappings.size(); i++) {
|
||||
int mapping = _jointMappings.at(i);
|
||||
if (mapping != -1) {
|
||||
JointState& state = _model->_jointStates[mapping];
|
||||
QVector<JointState> jointStates = _rig->getJointStates();
|
||||
JointState& state = jointStates[mapping];
|
||||
state.restoreRotation(1.0f, state._animationPriority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,22 +18,43 @@
|
|||
#include <QUrl>
|
||||
#include <QVector>
|
||||
|
||||
#include <AnimationCache.h>
|
||||
#include <AnimationLoop.h>
|
||||
#include "AnimationCache.h"
|
||||
#include "AnimationLoop.h"
|
||||
#include "Rig.h"
|
||||
|
||||
class AnimationHandle;
|
||||
class Model;
|
||||
|
||||
typedef QSharedPointer<AnimationHandle> AnimationHandlePointer;
|
||||
typedef QWeakPointer<AnimationHandle> WeakAnimationHandlePointer;
|
||||
typedef std::shared_ptr<AnimationHandle> AnimationHandlePointer;
|
||||
typedef std::weak_ptr<AnimationHandle> WeakAnimationHandlePointer;
|
||||
inline uint qHash(const std::shared_ptr<AnimationHandle>& a, uint seed) {
|
||||
// return qHash(a.get(), seed);
|
||||
AnimationHandle* strongRef = a ? a.get() : nullptr;
|
||||
return qHash(strongRef, seed);
|
||||
}
|
||||
inline uint qHash(const std::weak_ptr<AnimationHandle>& a, uint seed) {
|
||||
AnimationHandlePointer strongPointer = a.lock();
|
||||
AnimationHandle* strongRef = strongPointer ? strongPointer.get() : nullptr;
|
||||
return qHash(strongRef, seed);
|
||||
}
|
||||
|
||||
|
||||
// inline uint qHash(const WeakAnimationHandlePointer& handle, uint seed) {
|
||||
// return qHash(handle.data(), seed);
|
||||
// }
|
||||
|
||||
|
||||
|
||||
/// Represents a handle to a model animation.
|
||||
class AnimationHandle : public QObject {
|
||||
class AnimationHandle : public QObject, public std::enable_shared_from_this<AnimationHandle> {
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
public:
|
||||
|
||||
AnimationHandle(RigPointer rig);
|
||||
|
||||
AnimationHandlePointer getAnimationHandlePointer() { return shared_from_this(); }
|
||||
|
||||
void setRole(const QString& role) { _role = role; }
|
||||
const QString& getRole() const { return _role; }
|
||||
|
||||
|
@ -45,26 +66,26 @@ public:
|
|||
|
||||
void setMaskedJoints(const QStringList& maskedJoints);
|
||||
const QStringList& getMaskedJoints() const { return _maskedJoints; }
|
||||
|
||||
|
||||
|
||||
void setFPS(float fps) { _animationLoop.setFPS(fps); }
|
||||
float getFPS() const { return _animationLoop.getFPS(); }
|
||||
|
||||
void setLoop(bool loop) { _animationLoop.setLoop(loop); }
|
||||
bool getLoop() const { return _animationLoop.getLoop(); }
|
||||
|
||||
|
||||
void setHold(bool hold) { _animationLoop.setHold(hold); }
|
||||
bool getHold() const { return _animationLoop.getHold(); }
|
||||
|
||||
|
||||
void setStartAutomatically(bool startAutomatically);
|
||||
bool getStartAutomatically() const { return _animationLoop.getStartAutomatically(); }
|
||||
|
||||
|
||||
void setFirstFrame(float firstFrame) { _animationLoop.setFirstFrame(firstFrame); }
|
||||
float getFirstFrame() const { return _animationLoop.getFirstFrame(); }
|
||||
|
||||
|
||||
void setLastFrame(float lastFrame) { _animationLoop.setLastFrame(lastFrame); }
|
||||
float getLastFrame() const { return _animationLoop.getLastFrame(); }
|
||||
|
||||
|
||||
void setRunning(bool running);
|
||||
bool isRunning() const { return _animationLoop.isRunning(); }
|
||||
|
||||
|
@ -74,30 +95,25 @@ public:
|
|||
AnimationDetails getAnimationDetails() const;
|
||||
void setAnimationDetails(const AnimationDetails& details);
|
||||
|
||||
void setJointMappings(QVector<int> jointMappings);
|
||||
void simulate(float deltaTime);
|
||||
void applyFrame(float frameIndex);
|
||||
void replaceMatchingPriorities(float newPriority);
|
||||
void restoreJoints();
|
||||
void clearJoints() { _jointMappings.clear(); }
|
||||
|
||||
signals:
|
||||
|
||||
|
||||
void runningChanged(bool running);
|
||||
|
||||
public slots:
|
||||
|
||||
void start() { setRunning(true); }
|
||||
void stop() { setRunning(false); }
|
||||
|
||||
|
||||
private:
|
||||
|
||||
friend class Model;
|
||||
|
||||
AnimationHandle(Model* model);
|
||||
|
||||
void simulate(float deltaTime);
|
||||
void applyFrame(float frameIndex);
|
||||
void replaceMatchingPriorities(float newPriority);
|
||||
void restoreJoints();
|
||||
|
||||
void clearJoints() { _jointMappings.clear(); }
|
||||
|
||||
Model* _model;
|
||||
WeakAnimationHandlePointer _self;
|
||||
RigPointer _rig;
|
||||
AnimationPointer _animation;
|
||||
QString _role;
|
||||
QUrl _url;
|
||||
|
@ -105,8 +121,11 @@ private:
|
|||
|
||||
QStringList _maskedJoints;
|
||||
QVector<int> _jointMappings;
|
||||
|
||||
|
||||
AnimationLoop _animationLoop;
|
||||
|
||||
static QHash<QWeakPointer<Animation>, QVector<int>> _jointMappingsCache;
|
||||
static QVector<int> getJointMappings(const AnimationPointer& animation);
|
||||
};
|
||||
|
||||
|
|
@ -9,4 +9,85 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "AnimationHandle.h"
|
||||
|
||||
#include "Rig.h"
|
||||
|
||||
bool Rig::removeRunningAnimation(AnimationHandlePointer animationHandle) {
|
||||
return _runningAnimations.removeOne(animationHandle);
|
||||
}
|
||||
|
||||
static void insertSorted(QList<AnimationHandlePointer>& handles, const AnimationHandlePointer& handle) {
|
||||
for (QList<AnimationHandlePointer>::iterator it = handles.begin(); it != handles.end(); it++) {
|
||||
if (handle->getPriority() > (*it)->getPriority()) {
|
||||
handles.insert(it, handle);
|
||||
return;
|
||||
}
|
||||
}
|
||||
handles.append(handle);
|
||||
}
|
||||
|
||||
void Rig::addRunningAnimation(AnimationHandlePointer animationHandle) {
|
||||
insertSorted(_runningAnimations, animationHandle);
|
||||
}
|
||||
|
||||
bool Rig::isRunningAnimation(AnimationHandlePointer animationHandle) {
|
||||
return _runningAnimations.contains(animationHandle);
|
||||
}
|
||||
|
||||
void Rig::initJointStates(glm::vec3 scale, glm::vec3 offset, QVector<JointState> states) {
|
||||
_jointStates = states;
|
||||
initJointTransforms(scale, offset);
|
||||
|
||||
int numStates = _jointStates.size();
|
||||
float radius = 0.0f;
|
||||
for (int i = 0; i < numStates; ++i) {
|
||||
float distance = glm::length(_jointStates[i].getPosition());
|
||||
if (distance > radius) {
|
||||
radius = distance;
|
||||
}
|
||||
_jointStates[i].buildConstraint();
|
||||
}
|
||||
for (int i = 0; i < _jointStates.size(); i++) {
|
||||
_jointStates[i].slaveVisibleTransform();
|
||||
}
|
||||
|
||||
// XXX update AnimationHandles from here?
|
||||
}
|
||||
|
||||
void Rig::initJointTransforms(glm::vec3 scale, glm::vec3 offset) {
|
||||
// compute model transforms
|
||||
int numStates = _jointStates.size();
|
||||
for (int i = 0; i < numStates; ++i) {
|
||||
JointState& state = _jointStates[i];
|
||||
const FBXJoint& joint = state.getFBXJoint();
|
||||
int parentIndex = joint.parentIndex;
|
||||
if (parentIndex == -1) {
|
||||
// const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
// NOTE: in practice geometry.offset has a non-unity scale (rather than a translation)
|
||||
glm::mat4 parentTransform = glm::scale(scale) * glm::translate(offset); // * geometry.offset; XXX
|
||||
state.initTransform(parentTransform);
|
||||
} else {
|
||||
const JointState& parentState = _jointStates.at(parentIndex);
|
||||
state.initTransform(parentState.getTransform());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Rig::resetJoints() {
|
||||
if (_jointStates.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
for (int i = 0; i < _jointStates.size(); i++) {
|
||||
const FBXJoint& fbxJoint = _jointStates[i].getFBXJoint();
|
||||
_jointStates[i].setRotationInConstrainedFrame(fbxJoint.rotation, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
AnimationHandlePointer Rig::createAnimationHandle() {
|
||||
AnimationHandlePointer handle(new AnimationHandle(getRigPointer()));
|
||||
_animationHandles.insert(handle);
|
||||
return handle;
|
||||
}
|
||||
|
|
|
@ -16,8 +16,39 @@
|
|||
|
||||
#include <QObject>
|
||||
|
||||
class Rig : public QObject {
|
||||
#include "JointState.h"
|
||||
|
||||
class AnimationHandle;
|
||||
typedef std::shared_ptr<AnimationHandle> AnimationHandlePointer;
|
||||
// typedef QWeakPointer<AnimationHandle> WeakAnimationHandlePointer;
|
||||
|
||||
class Rig;
|
||||
typedef std::shared_ptr<Rig> RigPointer;
|
||||
|
||||
|
||||
class Rig : public QObject, public std::enable_shared_from_this<Rig> {
|
||||
|
||||
public:
|
||||
RigPointer getRigPointer() { return shared_from_this(); }
|
||||
|
||||
bool removeRunningAnimation(AnimationHandlePointer animationHandle);
|
||||
void addRunningAnimation(AnimationHandlePointer animationHandle);
|
||||
bool isRunningAnimation(AnimationHandlePointer animationHandle);
|
||||
const QList<AnimationHandlePointer>& getRunningAnimations() const { return _runningAnimations; }
|
||||
|
||||
void initJointStates(glm::vec3 scale, glm::vec3 offset, QVector<JointState> states);
|
||||
void initJointTransforms(glm::vec3 scale, glm::vec3 offset);
|
||||
void resetJoints();
|
||||
|
||||
QVector<JointState> getJointStates() { return _jointStates; }
|
||||
|
||||
AnimationHandlePointer createAnimationHandle();
|
||||
|
||||
protected:
|
||||
QVector<JointState> _jointStates;
|
||||
|
||||
QSet<AnimationHandlePointer> _animationHandles;
|
||||
QList<AnimationHandlePointer> _runningAnimations;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__Rig__) */
|
||||
|
|
|
@ -62,7 +62,7 @@ static int weakNetworkGeometryPointerTypeId = qRegisterMetaType<QWeakPointer<Net
|
|||
static int vec3VectorTypeId = qRegisterMetaType<QVector<glm::vec3> >();
|
||||
float Model::FAKE_DIMENSION_PLACEHOLDER = -1.0f;
|
||||
|
||||
Model::Model(QObject* parent) :
|
||||
Model::Model(QObject* parent, RigPointer rig) :
|
||||
QObject(parent),
|
||||
_scale(1.0f, 1.0f, 1.0f),
|
||||
_scaleToFit(false),
|
||||
|
@ -83,7 +83,8 @@ Model::Model(QObject* parent) :
|
|||
_calculatedMeshTrianglesValid(false),
|
||||
_meshGroupsKnown(false),
|
||||
_isWireframe(false),
|
||||
_renderCollisionHull(false) {
|
||||
_renderCollisionHull(false),
|
||||
_rig(rig) {
|
||||
|
||||
// we may have been created in the network thread, but we live in the main thread
|
||||
if (_viewState) {
|
||||
|
@ -1255,17 +1256,6 @@ QStringList Model::getJointNames() const {
|
|||
return isActive() ? _geometry->getFBXGeometry().getJointNames() : QStringList();
|
||||
}
|
||||
|
||||
uint qHash(const WeakAnimationHandlePointer& handle, uint seed) {
|
||||
return qHash(handle.data(), seed);
|
||||
}
|
||||
|
||||
AnimationHandlePointer Model::createAnimationHandle() {
|
||||
AnimationHandlePointer handle(new AnimationHandle(this));
|
||||
handle->_self = handle;
|
||||
_animationHandles.insert(handle);
|
||||
return handle;
|
||||
}
|
||||
|
||||
// virtual override from PhysicsEntity
|
||||
void Model::buildShapes() {
|
||||
// TODO: figure out how to load/build collision shapes for general models
|
||||
|
@ -1529,8 +1519,9 @@ void Model::updateVisibleJointStates() {
|
|||
}
|
||||
}
|
||||
|
||||
bool Model::setJointPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation, bool useRotation,
|
||||
int lastFreeIndex, bool allIntermediatesFree, const glm::vec3& alignment, float priority) {
|
||||
bool Model::setJointPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation,
|
||||
bool useRotation, int lastFreeIndex, bool allIntermediatesFree, const glm::vec3& alignment,
|
||||
float priority) {
|
||||
if (jointIndex == -1 || _jointStates.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1615,7 +1606,8 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& position, const gl
|
|||
return true;
|
||||
}
|
||||
|
||||
void Model::inverseKinematics(int endIndex, glm::vec3 targetPosition, const glm::quat& targetRotation, float priority) {
|
||||
void Model::inverseKinematics(int endIndex, glm::vec3 targetPosition,
|
||||
const glm::quat& targetRotation, float priority) {
|
||||
// NOTE: targetRotation is from bind- to model-frame
|
||||
|
||||
if (endIndex == -1 || _jointStates.isEmpty()) {
|
||||
|
@ -1830,9 +1822,9 @@ void Model::deleteGeometry() {
|
|||
clearShapes();
|
||||
|
||||
for (QSet<WeakAnimationHandlePointer>::iterator it = _animationHandles.begin(); it != _animationHandles.end(); ) {
|
||||
AnimationHandlePointer handle = it->toStrongRef();
|
||||
AnimationHandlePointer handle = it->lock();
|
||||
if (handle) {
|
||||
handle->_jointMappings.clear();
|
||||
handle->clearJoints();
|
||||
it++;
|
||||
} else {
|
||||
it = _animationHandles.erase(it);
|
||||
|
|
|
@ -67,7 +67,7 @@ public:
|
|||
|
||||
static void setAbstractViewStateInterface(AbstractViewStateInterface* viewState) { _viewState = viewState; }
|
||||
|
||||
Model(QObject* parent = NULL);
|
||||
Model(QObject* parent = NULL, RigPointer rig = nullptr);
|
||||
virtual ~Model();
|
||||
|
||||
/// enables/disables scale to fit behavior, the model will be automatically scaled to the specified largest dimension
|
||||
|
@ -209,7 +209,6 @@ public:
|
|||
|
||||
QStringList getJointNames() const;
|
||||
|
||||
AnimationHandlePointer createAnimationHandle();
|
||||
|
||||
const QList<AnimationHandlePointer>& getRunningAnimations() const { return _runningAnimations; }
|
||||
|
||||
|
@ -297,8 +296,8 @@ protected:
|
|||
/// \param alignment
|
||||
/// \return true if joint exists
|
||||
bool setJointPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation = glm::quat(),
|
||||
bool useRotation = false, int lastFreeIndex = -1, bool allIntermediatesFree = false,
|
||||
const glm::vec3& alignment = glm::vec3(0.0f, -1.0f, 0.0f), float priority = 1.0f);
|
||||
bool useRotation = false, int lastFreeIndex = -1, bool allIntermediatesFree = false,
|
||||
const glm::vec3& alignment = glm::vec3(0.0f, -1.0f, 0.0f), float priority = 1.0f);
|
||||
|
||||
/// Restores the indexed joint to its default position.
|
||||
/// \param fraction the fraction of the default position to apply (i.e., 0.25f to slerp one fourth of the way to
|
||||
|
@ -525,6 +524,8 @@ private:
|
|||
QMap<render::ItemID, render::PayloadPointer> _renderItems;
|
||||
bool _readyWhenAdded = false;
|
||||
bool _needsReload = true;
|
||||
|
||||
RigPointer _rig;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(QPointer<Model>)
|
||||
|
|
Loading…
Reference in a new issue