Provide a means of supplying the joint mappings in the FST file so that agent

scripts can address joints by name.  Closes #2526.
This commit is contained in:
Andrzej Kapolka 2014-04-07 17:55:36 -07:00
parent 0011276b0b
commit fa05a48270
5 changed files with 67 additions and 4 deletions

View file

@ -12,9 +12,12 @@ var AMPLITUDE = 45.0;
var cumulativeTime = 0.0; var cumulativeTime = 0.0;
print("Joint List:"); print("# Joint list start");
var jointList = MyAvatar.getJointNames(); var jointList = MyAvatar.getJointNames();
print(jointList); for (var i = 0; i < jointList.length; i++) {
print("jointIndex = " + jointList[i] + " = " + i);
}
print("# Joint list end");
Script.update.connect(function(deltaTime) { Script.update.connect(function(deltaTime) {
cumulativeTime += deltaTime; cumulativeTime += deltaTime;

View file

@ -331,6 +331,10 @@ void Avatar::renderBody(RenderMode renderMode) {
getHand()->render(false); getHand()->render(false);
} }
void Avatar::updateJointMappings() {
// no-op; joint mappings come from skeleton model
}
void Avatar::renderBillboard() { void Avatar::renderBillboard() {
if (_billboard.isEmpty()) { if (_billboard.isEmpty()) {
return; return;

View file

@ -187,6 +187,8 @@ protected:
void renderDisplayName(); void renderDisplayName();
virtual void renderBody(RenderMode renderMode); virtual void renderBody(RenderMode renderMode);
virtual void updateJointMappings();
private: private:
bool _initialized; bool _initialized;

View file

@ -639,6 +639,8 @@ void AvatarData::setSkeletonModelURL(const QUrl& skeletonModelURL) {
_skeletonModelURL = skeletonModelURL.isEmpty() ? DEFAULT_BODY_MODEL_URL : skeletonModelURL; _skeletonModelURL = skeletonModelURL.isEmpty() ? DEFAULT_BODY_MODEL_URL : skeletonModelURL;
qDebug() << "Changing skeleton model for avatar to" << _skeletonModelURL.toString(); qDebug() << "Changing skeleton model for avatar to" << _skeletonModelURL.toString();
updateJointMappings();
} }
void AvatarData::setDisplayName(const QString& displayName) { void AvatarData::setDisplayName(const QString& displayName) {
@ -673,6 +675,40 @@ void AvatarData::setBillboardFromURL(const QString &billboardURL) {
void AvatarData::setBillboardFromNetworkReply() { void AvatarData::setBillboardFromNetworkReply() {
QNetworkReply* networkReply = reinterpret_cast<QNetworkReply*>(sender()); QNetworkReply* networkReply = reinterpret_cast<QNetworkReply*>(sender());
setBillboard(networkReply->readAll()); setBillboard(networkReply->readAll());
networkReply->deleteLater();
}
void AvatarData::setJointMappingsFromNetworkReply() {
QNetworkReply* networkReply = static_cast<QNetworkReply*>(sender());
QByteArray line;
while (!(line = networkReply->readLine()).isEmpty()) {
if (!(line = line.trimmed()).startsWith("jointIndex")) {
continue;
}
int jointNameIndex = line.indexOf('=') + 1;
if (jointNameIndex == 0) {
continue;
}
int secondSeparatorIndex = line.indexOf('=', jointNameIndex);
if (secondSeparatorIndex == -1) {
continue;
}
QString jointName = line.mid(jointNameIndex, secondSeparatorIndex - jointNameIndex).trimmed();
bool ok;
int jointIndex = line.mid(secondSeparatorIndex + 1).trimmed().toInt(&ok);
if (ok) {
while (_jointNames.size() < jointIndex + 1) {
_jointNames.append(QString());
}
_jointNames[jointIndex] = jointName;
}
}
for (int i = 0; i < _jointNames.size(); i++) {
_jointIndices.insert(_jointNames.at(i), i + 1);
}
networkReply->deleteLater();
} }
void AvatarData::setClampedTargetScale(float targetScale) { void AvatarData::setClampedTargetScale(float targetScale) {
@ -705,3 +741,13 @@ void AvatarData::sendBillboardPacket() {
NodeList::getInstance()->broadcastToNodes(billboardPacket, NodeSet() << NodeType::AvatarMixer); NodeList::getInstance()->broadcastToNodes(billboardPacket, NodeSet() << NodeType::AvatarMixer);
} }
} }
void AvatarData::updateJointMappings() {
_jointIndices.clear();
_jointNames.clear();
if (networkAccessManager && _skeletonModelURL.fileName().toLower().endsWith(".fst")) {
QNetworkReply* networkReply = networkAccessManager->get(QNetworkRequest(_skeletonModelURL));
connect(networkReply, SIGNAL(finished()), this, SLOT(setJointMappingsFromNetworkReply()));
}
}

View file

@ -30,6 +30,7 @@ typedef unsigned long long quint64;
#include <glm/gtc/quaternion.hpp> #include <glm/gtc/quaternion.hpp>
#include <QtCore/QByteArray> #include <QtCore/QByteArray>
#include <QtCore/QHash>
#include <QtCore/QObject> #include <QtCore/QObject>
#include <QtCore/QStringList> #include <QtCore/QStringList>
#include <QtCore/QUrl> #include <QtCore/QUrl>
@ -160,9 +161,9 @@ public:
Q_INVOKABLE glm::quat getJointRotation(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. /// 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 int getJointIndex(const QString& name) const { return _jointIndices.value(name) - 1; }
Q_INVOKABLE virtual QStringList getJointNames() const { return QStringList(); } Q_INVOKABLE virtual QStringList getJointNames() const { return _jointNames; }
// key state // key state
void setKeyState(KeyState s) { _keyState = s; } void setKeyState(KeyState s) { _keyState = s; }
@ -217,6 +218,7 @@ public slots:
void sendIdentityPacket(); void sendIdentityPacket();
void sendBillboardPacket(); void sendBillboardPacket();
void setBillboardFromNetworkReply(); void setBillboardFromNetworkReply();
void setJointMappingsFromNetworkReply();
protected: protected:
glm::vec3 _position; glm::vec3 _position;
glm::vec3 _handPosition; glm::vec3 _handPosition;
@ -258,10 +260,16 @@ protected:
QByteArray _billboard; QByteArray _billboard;
QString _billboardURL; QString _billboardURL;
QHash<QString, int> _jointIndices; ///< 1-based, since zero is returned for missing keys
QStringList _jointNames; ///< in order of depth-first traversal
static QNetworkAccessManager* networkAccessManager; static QNetworkAccessManager* networkAccessManager;
quint64 _errorLogExpiry; ///< time in future when to log an error quint64 _errorLogExpiry; ///< time in future when to log an error
/// Loads the joint indices, names from the FST file (if any)
virtual void updateJointMappings();
private: private:
// privatize the copy constructor and assignment operator so they cannot be called // privatize the copy constructor and assignment operator so they cannot be called
AvatarData(const AvatarData&); AvatarData(const AvatarData&);