mirror of
https://github.com/lubosz/overte.git
synced 2025-04-08 10:43:56 +02:00
Further joint bits.
This commit is contained in:
parent
c5ab32235f
commit
44374732fa
12 changed files with 204 additions and 8 deletions
23
examples/crazylegs.js
Normal file
23
examples/crazylegs.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// crazylegs.js
|
||||
// hifi
|
||||
//
|
||||
// Created by Andrzej Kapolka on 3/6/14.
|
||||
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
var FREQUENCY = 5.0;
|
||||
|
||||
var AMPLITUDE = 45.0;
|
||||
|
||||
var cumulativeTime = 0.0;
|
||||
|
||||
Script.update.connect(function(deltaTime) {
|
||||
cumulativeTime += deltaTime;
|
||||
MyAvatar.setJointData("joint_R_hip", Quat.fromPitchYawRoll(0.0, 0.0, AMPLITUDE * Math.sin(cumulativeTime * FREQUENCY)));
|
||||
MyAvatar.setJointData("joint_L_hip", Quat.fromPitchYawRoll(0.0, 0.0, -AMPLITUDE * Math.sin(cumulativeTime * FREQUENCY)));
|
||||
MyAvatar.setJointData("joint_R_knee", Quat.fromPitchYawRoll(0.0, 0.0,
|
||||
AMPLITUDE * (1.0 + Math.sin(cumulativeTime * FREQUENCY))));
|
||||
MyAvatar.setJointData("joint_L_knee", Quat.fromPitchYawRoll(0.0, 0.0,
|
||||
AMPLITUDE * (1.0 - Math.sin(cumulativeTime * FREQUENCY))));
|
||||
});
|
|
@ -121,6 +121,8 @@ void messageHandler(QtMsgType type, const QMessageLogContext& context, const QSt
|
|||
QString& Application::resourcesPath() {
|
||||
#ifdef Q_OS_MAC
|
||||
static QString staticResourcePath = QCoreApplication::applicationDirPath() + "/../Resources/";
|
||||
#elif defined Q_OS_LINUX
|
||||
static QString staticResourcePath = "resources/";
|
||||
#else
|
||||
static QString staticResourcePath = QCoreApplication::applicationDirPath() + "/resources/";
|
||||
#endif
|
||||
|
|
|
@ -581,6 +581,35 @@ bool Avatar::findParticleCollisions(const glm::vec3& particleCenter, float parti
|
|||
return collided;
|
||||
}
|
||||
|
||||
glm::quat Avatar::getJointRotation(int index) const {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
return AvatarData::getJointRotation(index);
|
||||
}
|
||||
glm::quat rotation;
|
||||
_skeletonModel.getJointState(index, rotation);
|
||||
return rotation;
|
||||
}
|
||||
|
||||
int Avatar::getJointIndex(const QString& name) const {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
int result;
|
||||
QMetaObject::invokeMethod(const_cast<Avatar*>(this), "getJointIndex", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(int, result), Q_ARG(const QString&, name));
|
||||
return result;
|
||||
}
|
||||
return _skeletonModel.isActive() ? _skeletonModel.getGeometry()->getFBXGeometry().getJointIndex(name) : -1;
|
||||
}
|
||||
|
||||
QStringList Avatar::getJointNames() const {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QStringList result;
|
||||
QMetaObject::invokeMethod(const_cast<Avatar*>(this), "getJointNames", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(QStringList, result));
|
||||
return result;
|
||||
}
|
||||
return _skeletonModel.isActive() ? _skeletonModel.getGeometry()->getFBXGeometry().getJointNames() : QStringList();
|
||||
}
|
||||
|
||||
void Avatar::setFaceModelURL(const QUrl& faceModelURL) {
|
||||
AvatarData::setFaceModelURL(faceModelURL);
|
||||
const QUrl DEFAULT_FACE_MODEL_URL = QUrl::fromLocalFile(Application::resourcesPath() + "meshes/defaultAvatar_head.fst");
|
||||
|
|
|
@ -122,6 +122,10 @@ public:
|
|||
|
||||
virtual bool isMyAvatar() { return false; }
|
||||
|
||||
virtual glm::quat getJointRotation(int index) const;
|
||||
virtual int getJointIndex(const QString& name) const;
|
||||
virtual QStringList getJointNames() const;
|
||||
|
||||
virtual void setFaceModelURL(const QUrl& faceModelURL);
|
||||
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL);
|
||||
virtual void setDisplayName(const QString& displayName);
|
||||
|
|
|
@ -672,6 +672,20 @@ glm::vec3 MyAvatar::getUprightHeadPosition() const {
|
|||
return _position + getWorldAlignedOrientation() * glm::vec3(0.0f, getPelvisToHeadLength(), 0.0f);
|
||||
}
|
||||
|
||||
void MyAvatar::setJointData(int index, const glm::quat& rotation) {
|
||||
Avatar::setJointData(index, rotation);
|
||||
if (QThread::currentThread() == thread()) {
|
||||
_skeletonModel.setJointState(index, true, rotation);
|
||||
}
|
||||
}
|
||||
|
||||
void MyAvatar::clearJointData(int index) {
|
||||
Avatar::clearJointData(index);
|
||||
if (QThread::currentThread() == thread()) {
|
||||
_skeletonModel.setJointState(index, false);
|
||||
}
|
||||
}
|
||||
|
||||
void MyAvatar::setFaceModelURL(const QUrl& faceModelURL) {
|
||||
Avatar::setFaceModelURL(faceModelURL);
|
||||
_billboardValid = false;
|
||||
|
|
|
@ -81,6 +81,8 @@ public:
|
|||
void updateLookAtTargetAvatar();
|
||||
void clearLookAtTargetAvatar();
|
||||
|
||||
virtual void setJointData(int index, const glm::quat& rotation);
|
||||
virtual void clearJointData(int index);
|
||||
virtual void setFaceModelURL(const QUrl& faceModelURL);
|
||||
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL);
|
||||
public slots:
|
||||
|
|
|
@ -46,6 +46,14 @@ void Extents::addPoint(const glm::vec3& point) {
|
|||
maximum = glm::max(maximum, point);
|
||||
}
|
||||
|
||||
QStringList FBXGeometry::getJointNames() const {
|
||||
QStringList names;
|
||||
foreach (const FBXJoint& joint, joints) {
|
||||
names.append(joint.name);
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
static int fbxGeometryMetaTypeId = qRegisterMetaType<FBXGeometry>();
|
||||
|
||||
template<class T> QVariant readBinaryArray(QDataStream& in) {
|
||||
|
|
|
@ -81,7 +81,7 @@ public:
|
|||
glm::quat inverseDefaultRotation;
|
||||
glm::quat inverseBindRotation;
|
||||
glm::mat4 bindTransform;
|
||||
QString name; // temp field for debugging
|
||||
QString name;
|
||||
glm::vec3 shapePosition; // in joint frame
|
||||
glm::quat shapeRotation; // in joint frame
|
||||
int shapeType;
|
||||
|
@ -152,7 +152,7 @@ class FBXGeometry {
|
|||
public:
|
||||
|
||||
QVector<FBXJoint> joints;
|
||||
QHash<QString, int> jointIndices;
|
||||
QHash<QString, int> jointIndices; ///< 1-based, so as to more easily detect missing indices
|
||||
|
||||
QVector<FBXMesh> meshes;
|
||||
|
||||
|
@ -181,6 +181,9 @@ public:
|
|||
Extents staticExtents;
|
||||
|
||||
QVector<FBXAttachment> attachments;
|
||||
|
||||
int getJointIndex(const QString& name) const { return jointIndices.value(name) - 1; }
|
||||
QStringList getJointNames() const;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(FBXGeometry)
|
||||
|
|
|
@ -379,7 +379,7 @@ Extents Model::getStaticExtents() const {
|
|||
}
|
||||
|
||||
bool Model::getJointState(int index, glm::quat& rotation) const {
|
||||
if (index >= _jointStates.size()) {
|
||||
if (index == -1 || index >= _jointStates.size()) {
|
||||
return false;
|
||||
}
|
||||
rotation = _jointStates.at(index).rotation;
|
||||
|
@ -391,7 +391,7 @@ bool Model::getJointState(int index, glm::quat& rotation) const {
|
|||
}
|
||||
|
||||
void Model::setJointState(int index, bool valid, const glm::quat& rotation) {
|
||||
if (index < _jointStates.size()) {
|
||||
if (index != -1 && index < _jointStates.size()) {
|
||||
_jointStates[index].rotation = valid ? rotation : _geometry->getFBXGeometry().joints.at(index).rotation;
|
||||
}
|
||||
}
|
||||
|
@ -896,9 +896,10 @@ QVector<Model::JointState> Model::updateGeometry(bool delayLoad) {
|
|||
newJointStates = createJointStates(newGeometry);
|
||||
for (QHash<QString, int>::const_iterator it = oldGeometry.jointIndices.constBegin();
|
||||
it != oldGeometry.jointIndices.constEnd(); it++) {
|
||||
int newIndex = newGeometry.jointIndices.value(it.key());
|
||||
if (newIndex != 0) {
|
||||
newJointStates[newIndex - 1] = _jointStates.at(it.value() - 1);
|
||||
int oldIndex = it.value() - 1;
|
||||
int newIndex = newGeometry.getJointIndex(it.key());
|
||||
if (newIndex != -1) {
|
||||
newJointStates[newIndex] = _jointStates.at(oldIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ public:
|
|||
bool getJointState(int index, glm::quat& rotation) const;
|
||||
|
||||
/// Sets the joint state at the specified index.
|
||||
void setJointState(int index, bool valid, const glm::quat& rotation);
|
||||
void setJointState(int index, bool valid, const glm::quat& rotation = glm::quat());
|
||||
|
||||
/// Returns the index of the left hand joint, or -1 if not found.
|
||||
int getLeftHandJointIndex() const { return isActive() ? _geometry->getFBXGeometry().leftHandJointIndex : -1; }
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include <QtCore/QDataStream>
|
||||
#include <QtCore/QThread>
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
#include <QtNetwork/QNetworkRequest>
|
||||
|
@ -314,6 +315,99 @@ int AvatarData::parseData(const QByteArray& packet) {
|
|||
return sourceBuffer - startPosition;
|
||||
}
|
||||
|
||||
void AvatarData::setJointData(int index, const glm::quat& rotation) {
|
||||
if (index == -1) {
|
||||
return;
|
||||
}
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setJointData", Q_ARG(int, index), Q_ARG(const glm::quat&, rotation));
|
||||
return;
|
||||
}
|
||||
if (_jointData.size() <= index) {
|
||||
_jointData.resize(index + 1);
|
||||
}
|
||||
JointData& data = _jointData[index];
|
||||
data.valid = true;
|
||||
data.rotation = rotation;
|
||||
}
|
||||
|
||||
void AvatarData::clearJointData(int index) {
|
||||
if (index == -1) {
|
||||
return;
|
||||
}
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "clearJointData", Q_ARG(int, index));
|
||||
return;
|
||||
}
|
||||
if (_jointData.size() <= index) {
|
||||
_jointData.resize(index + 1);
|
||||
}
|
||||
_jointData[index].valid = false;
|
||||
}
|
||||
|
||||
bool AvatarData::isJointDataValid(int index) const {
|
||||
if (index == -1) {
|
||||
return false;
|
||||
}
|
||||
if (QThread::currentThread() != thread()) {
|
||||
bool result;
|
||||
QMetaObject::invokeMethod(const_cast<AvatarData*>(this), "isJointDataValid", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(bool, result), Q_ARG(int, index));
|
||||
return result;
|
||||
}
|
||||
return index < _jointData.size() && _jointData.at(index).valid;
|
||||
}
|
||||
|
||||
glm::quat AvatarData::getJointRotation(int index) const {
|
||||
if (index == -1) {
|
||||
return glm::quat();
|
||||
}
|
||||
if (QThread::currentThread() != thread()) {
|
||||
glm::quat result;
|
||||
QMetaObject::invokeMethod(const_cast<AvatarData*>(this), "getJointRotation", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(glm::quat, result), Q_ARG(int, index));
|
||||
return result;
|
||||
}
|
||||
return index < _jointData.size() ? _jointData.at(index).rotation : glm::quat();
|
||||
}
|
||||
|
||||
void AvatarData::setJointData(const QString& name, const glm::quat& rotation) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setJointData", Q_ARG(const QString&, name),
|
||||
Q_ARG(const glm::quat&, rotation));
|
||||
return;
|
||||
}
|
||||
setJointData(getJointIndex(name), rotation);
|
||||
}
|
||||
|
||||
void AvatarData::clearJointData(const QString& name) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "clearJointData", Q_ARG(const QString&, name));
|
||||
return;
|
||||
}
|
||||
clearJointData(getJointIndex(name));
|
||||
}
|
||||
|
||||
bool AvatarData::isJointDataValid(const QString& name) const {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
bool result;
|
||||
QMetaObject::invokeMethod(const_cast<AvatarData*>(this), "isJointDataValid", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(bool, result), Q_ARG(const QString&, name));
|
||||
return result;
|
||||
}
|
||||
return isJointDataValid(getJointIndex(name));
|
||||
}
|
||||
|
||||
glm::quat AvatarData::getJointRotation(const QString& name) const {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
glm::quat result;
|
||||
QMetaObject::invokeMethod(const_cast<AvatarData*>(this), "getJointRotation", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(glm::quat, result), Q_ARG(const QString&, name));
|
||||
return result;
|
||||
}
|
||||
return getJointRotation(getJointIndex(name));
|
||||
}
|
||||
|
||||
bool AvatarData::hasIdentityChangedAfterParsing(const QByteArray &packet) {
|
||||
QDataStream packetStream(packet);
|
||||
packetStream.skipRawData(numBytesForPacketHeader(packet));
|
||||
|
|
|
@ -31,6 +31,7 @@ typedef unsigned long long quint64;
|
|||
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QUrl>
|
||||
#include <QtCore/QUuid>
|
||||
#include <QtCore/QVector>
|
||||
|
@ -143,6 +144,21 @@ public:
|
|||
const QVector<JointData>& getJointData() const { return _jointData; }
|
||||
void setJointData(const QVector<JointData>& jointData) { _jointData = jointData; }
|
||||
|
||||
Q_INVOKABLE virtual void setJointData(int index, const glm::quat& rotation);
|
||||
Q_INVOKABLE virtual void clearJointData(int index);
|
||||
Q_INVOKABLE bool isJointDataValid(int index) const;
|
||||
Q_INVOKABLE virtual glm::quat getJointRotation(int index) const;
|
||||
|
||||
Q_INVOKABLE void setJointData(const QString& name, const glm::quat& rotation);
|
||||
Q_INVOKABLE void clearJointData(const QString& name);
|
||||
Q_INVOKABLE bool isJointDataValid(const QString& name) const;
|
||||
Q_INVOKABLE glm::quat getJointRotation(const QString& name) const;
|
||||
|
||||
/// Returns the index of the joint with the specified name, or -1 if not found/unknown.
|
||||
Q_INVOKABLE virtual int getJointIndex(const QString& name) const { return -1; }
|
||||
|
||||
Q_INVOKABLE virtual QStringList getJointNames() const { return QStringList(); }
|
||||
|
||||
// key state
|
||||
void setKeyState(KeyState s) { _keyState = s; }
|
||||
KeyState keyState() const { return _keyState; }
|
||||
|
|
Loading…
Reference in a new issue