More work on animation loading.

This commit is contained in:
Andrzej Kapolka 2014-04-15 19:37:28 -07:00
parent 38c0e99cbe
commit 8cbad1bf54
8 changed files with 117 additions and 2 deletions

View file

@ -22,6 +22,8 @@ for (var i = 0; i < jointList.length; i++) {
}
print("# Joint list end");
var foo = AnimationCache.getAnimation("http://www.fungibleinsight.com/faces/hip_hop_dancing_2.fbx");
Script.update.connect(function(deltaTime) {
cumulativeTime += deltaTime;
MyAvatar.setJointData("joint_R_hip", Quat.fromPitchYawRollDegrees(0.0, 0.0, AMPLITUDE * Math.sin(cumulativeTime * FREQUENCY)));
@ -30,6 +32,18 @@ Script.update.connect(function(deltaTime) {
AMPLITUDE * (1.0 + Math.sin(cumulativeTime * FREQUENCY))));
MyAvatar.setJointData("joint_L_knee", Quat.fromPitchYawRollDegrees(0.0, 0.0,
AMPLITUDE * (1.0 - Math.sin(cumulativeTime * FREQUENCY))));
if (foo.jointNames.length > 0) {
print(foo.jointNames);
print(foo.frames.length);
if (foo.frames.length > 0) {
print(foo.frames[0].rotations.length);
if (foo.frames[0].rotations.length > 0) {
var rot = foo.frames[0].rotations[0];
print(rot.x + " " + rot.y + " " + rot.z + " " + rot.w);
}
}
}
});
Script.scriptEnding.connect(function() {

View file

@ -3387,6 +3387,7 @@ void Application::loadScript(const QString& scriptName) {
scriptEngine->registerGlobalObject("Menu", MenuScriptingInterface::getInstance());
scriptEngine->registerGlobalObject("Settings", SettingsScriptingInterface::getInstance());
scriptEngine->registerGlobalObject("AudioDevice", AudioDeviceScriptingInterface::getInstance());
scriptEngine->registerGlobalObject("AnimationCache", &_animationCache);
QThread* workerThread = new QThread(this);

View file

@ -468,6 +468,7 @@ private:
QSet<int> _keysPressed;
GeometryCache _geometryCache;
AnimationCache _animationCache;
TextureCache _textureCache;
GlowEffect _glowEffect;

View file

@ -72,6 +72,8 @@ bool FBXGeometry::hasBlendedMeshes() const {
}
static int fbxGeometryMetaTypeId = qRegisterMetaType<FBXGeometry>();
static int fbxAnimationFrameMetaTypeId = qRegisterMetaType<FBXAnimationFrame>();
static int fbxAnimationFrameVectorMetaTypeId = qRegisterMetaType<QVector<FBXAnimationFrame> >();
template<class T> QVariant readBinaryArray(QDataStream& in) {
quint32 arrayLength;

View file

@ -146,6 +146,9 @@ public:
QVector<glm::quat> rotations;
};
Q_DECLARE_METATYPE(FBXAnimationFrame)
Q_DECLARE_METATYPE(QVector<FBXAnimationFrame>)
/// An attachment to an FBX document.
class FBXAttachment {
public:

View file

@ -10,11 +10,20 @@
//
#include <QRunnable>
#include <QScriptEngine>
#include <QThreadPool>
#include "AnimationCache.h"
QSharedPointer<Animation> AnimationCache::getAnimation(const QUrl& url) {
static int animationPointerMetaTypeId = qRegisterMetaType<AnimationPointer>();
AnimationPointer AnimationCache::getAnimation(const QUrl& url) {
if (QThread::currentThread() != thread()) {
AnimationPointer result;
QMetaObject::invokeMethod(this, "getAnimation", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(AnimationPointer, result), Q_ARG(const QUrl&, url));
return result;
}
return getResource(url).staticCast<Animation>();
}
@ -54,6 +63,30 @@ void AnimationReader::run() {
_reply->deleteLater();
}
QStringList Animation::getJointNames() const {
if (QThread::currentThread() != thread()) {
QStringList result;
QMetaObject::invokeMethod(const_cast<Animation*>(this), "getJointNames", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QStringList, result));
return result;
}
QStringList names;
foreach (const FBXJoint& joint, _geometry.joints) {
names.append(joint.name);
}
return names;
}
QVector<FBXAnimationFrame> Animation::getFrames() const {
if (QThread::currentThread() != thread()) {
QVector<FBXAnimationFrame> result;
QMetaObject::invokeMethod(const_cast<Animation*>(this), "getFrames", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QVector<FBXAnimationFrame>, result));
return result;
}
return _geometry.animationFrames;
}
void Animation::setGeometry(const FBXGeometry& geometry) {
_geometry = geometry;
finishedLoading(true);
@ -63,3 +96,23 @@ void Animation::downloadFinished(QNetworkReply* reply) {
// send the reader off to the thread pool
QThreadPool::globalInstance()->start(new AnimationReader(_self, reply));
}
QStringList AnimationObject::getJointNames() const {
return qscriptvalue_cast<AnimationPointer>(thisObject())->getJointNames();
}
QVector<FBXAnimationFrame> AnimationObject::getFrames() const {
return qscriptvalue_cast<AnimationPointer>(thisObject())->getFrames();
}
QVector<glm::quat> AnimationFrameObject::getRotations() const {
return qscriptvalue_cast<FBXAnimationFrame>(thisObject()).rotations;
}
void registerAnimationTypes(QScriptEngine* engine) {
qScriptRegisterSequenceMetaType<QVector<FBXAnimationFrame> >(engine);
engine->setDefaultPrototype(qMetaTypeId<FBXAnimationFrame>(), engine->newQObject(
new AnimationFrameObject(), QScriptEngine::ScriptOwnership));
engine->setDefaultPrototype(qMetaTypeId<AnimationPointer>(), engine->newQObject(
new AnimationObject(), QScriptEngine::ScriptOwnership));
}

View file

@ -12,19 +12,27 @@
#ifndef hifi_AnimationCache_h
#define hifi_AnimationCache_h
#include <QScriptable>
#include <ResourceCache.h>
#include <FBXReader.h>
class QScriptEngine;
class Animation;
typedef QSharedPointer<Animation> AnimationPointer;
/// Scriptable interface for FBX animation loading.
class AnimationCache : public ResourceCache {
Q_OBJECT
public:
QSharedPointer<Animation> getAnimation(const QUrl& url);
Q_INVOKABLE AnimationPointer getAnimation(const QString& url) { return getAnimation(QUrl(url)); }
Q_INVOKABLE AnimationPointer getAnimation(const QUrl& url);
protected:
@ -32,6 +40,8 @@ protected:
const QSharedPointer<Resource>& fallback, bool delayLoad, const void* extra);
};
Q_DECLARE_METATYPE(AnimationPointer)
/// An animation loaded from the network.
class Animation : public Resource {
Q_OBJECT
@ -42,6 +52,10 @@ public:
const FBXGeometry& getGeometry() const { return _geometry; }
Q_INVOKABLE QStringList getJointNames() const;
Q_INVOKABLE QVector<FBXAnimationFrame> getFrames() const;
protected:
Q_INVOKABLE void setGeometry(const FBXGeometry& geometry);
@ -53,4 +67,29 @@ private:
FBXGeometry _geometry;
};
/// Scriptable wrapper for animation pointers.
class AnimationObject : public QObject, protected QScriptable {
Q_OBJECT
Q_PROPERTY(QStringList jointNames READ getJointNames)
Q_PROPERTY(QVector<FBXAnimationFrame> frames READ getFrames)
public:
Q_INVOKABLE QStringList getJointNames() const;
Q_INVOKABLE QVector<FBXAnimationFrame> getFrames() const;
};
/// Scriptable wrapper for animation frames.
class AnimationFrameObject : public QObject, protected QScriptable {
Q_OBJECT
Q_PROPERTY(QVector<glm::quat> rotations READ getRotations)
public:
Q_INVOKABLE QVector<glm::quat> getRotations() const;
};
void registerAnimationTypes(QScriptEngine* engine);
#endif // hifi_AnimationCache_h

View file

@ -180,11 +180,13 @@ void ScriptEngine::init() {
registerVoxelMetaTypes(&_engine);
registerEventTypes(&_engine);
registerMenuItemProperties(&_engine);
registerAnimationTypes(&_engine);
qScriptRegisterMetaType(&_engine, ParticlePropertiesToScriptValue, ParticlePropertiesFromScriptValue);
qScriptRegisterMetaType(&_engine, ParticleIDtoScriptValue, ParticleIDfromScriptValue);
qScriptRegisterSequenceMetaType<QVector<ParticleID> >(&_engine);
qScriptRegisterSequenceMetaType<QVector<glm::vec2> >(&_engine);
qScriptRegisterSequenceMetaType<QVector<glm::quat> >(&_engine);
qScriptRegisterSequenceMetaType<QVector<QString> >(&_engine);
QScriptValue soundConstructorValue = _engine.newFunction(soundConstructor);