WIP, animNode rendering

This commit is contained in:
Anthony J. Thibault 2015-08-02 12:50:14 -07:00 committed by Anthony J. Thibault
parent d1fdbe32d2
commit df79463750
9 changed files with 136 additions and 46 deletions

View file

@ -51,6 +51,7 @@
#include "AnimDebugDraw.h"
#include "AnimSkeleton.h"
#include "AnimClip.h"
using namespace std;
@ -147,6 +148,11 @@ void MyAvatar::reset() {
}
void MyAvatar::update(float deltaTime) {
if (_animNode) {
_animNode->evaluate(deltaTime);
}
if (_referential) {
_referential->update();
}
@ -1206,6 +1212,8 @@ void MyAvatar::preRender(RenderArgs* renderArgs) {
initHeadBones();
_skeletonModel.setCauterizeBoneSet(_headBoneSet);
// AJT: SETUP DEBUG RENDERING OF NEW ANIMATION SYSTEM
// create a skeleton and hand it over to the debug draw instance
auto geom = _skeletonModel.getGeometry()->getFBXGeometry();
std::vector<FBXJoint> joints;
@ -1213,7 +1221,11 @@ void MyAvatar::preRender(RenderArgs* renderArgs) {
joints.push_back(joint);
}
auto skeleton = make_shared<AnimSkeleton>(joints);
AnimDebugDraw::getInstance().addSkeleton("my-avatar", skeleton, Transform());
//AnimDebugDraw::getInstance().addSkeleton("my-avatar", skeleton, AnimPose::identity);
_animNode = make_shared<AnimClip>("clip", "https://hifi-public.s3.amazonaws.com/ozan/support/FightClubBotTest1/Animations/standard_idle.fbx", 0.0f, 90.0f, 1.0f, true);
_animNode->setSkeleton(skeleton);
AnimDebugDraw::getInstance().addAnimNode("clip", _animNode, AnimPose::identity);
}
if (shouldDrawHead != _prevShouldDrawHead) {

View file

@ -19,6 +19,7 @@
#include "Avatar.h"
class ModelItemID;
class AnimNode;
enum eyeContactTarget {
LEFT_EYE,
@ -281,6 +282,8 @@ private:
RigPointer _rig;
bool _prevShouldDrawHead;
std::unordered_set<int> _headBoneSet;
std::shared_ptr<AnimNode> _animNode;
};
#endif // hifi_MyAvatar_h

View file

@ -13,14 +13,13 @@
AnimClip::AnimClip(const std::string& id, const std::string& url, float startFrame, float endFrame, float timeScale, bool loopFlag) :
AnimNode(AnimNode::ClipType, id),
_url(url),
_startFrame(startFrame),
_endFrame(endFrame),
_timeScale(timeScale),
_loopFlag(loopFlag),
_frame(startFrame)
{
setURL(url);
}
AnimClip::~AnimClip() {
@ -128,6 +127,9 @@ void AnimClip::copyFromNetworkAnim() {
jointMap.reserve(animJointCount);
for (int i = 0; i < animJointCount; i++) {
int skeletonJoint = _skeleton->nameToJointIndex(joints.at(i).name);
if (skeletonJoint == -1) {
qCWarning(animation) << "animation contains joint =" << joints.at(i).name << " which is not in the skeleton, url =" << _url.c_str();
}
jointMap.push_back(skeletonJoint);
}
@ -151,4 +153,10 @@ void AnimClip::copyFromNetworkAnim() {
}
}
}
_poses.resize(skeletonJointCount);
}
const std::vector<AnimPose>& AnimClip::getPosesInternal() const {
return _poses;
}

View file

@ -19,7 +19,7 @@ public:
friend class AnimClipTests;
AnimClip(const std::string& id, const std::string& url, float startFrame, float endFrame, float timeScale, bool loopFlag);
virtual ~AnimClip();
virtual ~AnimClip() override;
void setURL(const std::string& url);
const std::string& getURL() const { return _url; }
@ -36,12 +36,15 @@ public:
void setLoopFlag(bool loopFlag);
bool getLoopFlag() const { return _loopFlag; }
virtual const std::vector<AnimPose>& evaluate(float dt);
virtual const std::vector<AnimPose>& evaluate(float dt) override;
protected:
float accumulateTime(float frame, float dt) const;
void copyFromNetworkAnim();
// for AnimDebugDraw rendering
virtual const std::vector<AnimPose>& getPosesInternal() const override;
AnimationPointer _networkAnim;
std::vector<AnimPose> _poses;

View file

@ -23,6 +23,8 @@ class QJsonObject;
class AnimNode {
public:
friend class AnimDebugDraw;
enum Type {
ClipType = 0,
NumTypes
@ -55,6 +57,9 @@ public:
virtual const std::vector<AnimPose>& evaluate(float dt) = 0;
protected:
// for AnimDebugDraw rendering
virtual const std::vector<AnimPose>& getPosesInternal() const = 0;
Type _type;
std::string _id;
std::vector<AnimNode::Pointer> _children;

View file

@ -10,6 +10,10 @@
#include "AnimSkeleton.h"
#include "glmHelpers.h"
const AnimPose AnimPose::identity = AnimPose(glm::vec3(1.0f),
glm::quat(),
glm::vec3(0.0f));
AnimSkeleton::AnimSkeleton(const std::vector<FBXJoint>& joints) {
_joints = joints;

View file

@ -17,6 +17,11 @@
struct AnimPose {
AnimPose() {}
AnimPose(const glm::vec3& scaleIn, const glm::quat& rotIn, const glm::vec3& transIn) : scale(scaleIn), rot(rotIn), trans(transIn) {}
static const AnimPose identity;
glm::vec3 operator*(const glm::vec3& pos) const {
return trans + (rot * (scale * pos));
}
glm::vec3 scale;
glm::quat rot;

View file

@ -58,7 +58,7 @@ public:
typedef render::Payload<AnimDebugDrawData> AnimDebugDrawPayload;
namespace render {
template <> const ItemKey payloadGetKey(const AnimDebugDrawData::Pointer& data) { return ItemKey::Builder::transparentShape(); }
template <> const ItemKey payloadGetKey(const AnimDebugDrawData::Pointer& data) { return ItemKey::Builder::opaqueShape(); }
template <> const Item::Bound payloadGetBound(const AnimDebugDrawData::Pointer& data) { return Item::Bound(); }
template <> void payloadRender(const AnimDebugDrawData::Pointer& data, RenderArgs* args) {
data->render(args);
@ -143,14 +143,65 @@ AnimDebugDraw::~AnimDebugDraw() {
}
}
void AnimDebugDraw::addSkeleton(std::string key, AnimSkeleton::Pointer skeleton, const Transform& worldTransform) {
_skeletons[key] = SkeletonInfo(skeleton, worldTransform);
void AnimDebugDraw::addSkeleton(std::string key, AnimSkeleton::Pointer skeleton, const AnimPose& rootPose) {
_skeletons[key] = SkeletonInfo(skeleton, rootPose);
}
void AnimDebugDraw::removeSkeleton(std::string key) {
_skeletons.erase(key);
}
void AnimDebugDraw::addAnimNode(std::string key, AnimNode::Pointer animNode, const AnimPose& rootPose) {
_animNodes[key] = AnimNodeInfo(animNode, rootPose);
}
void AnimDebugDraw::removeAnimNode(std::string key) {
_animNodes.erase(key);
}
static const uint32_t red = toRGBA(255, 0, 0, 255);
static const uint32_t green = toRGBA(0, 255, 0, 255);
static const uint32_t blue = toRGBA(0, 0, 255, 255);
static const uint32_t cyan = toRGBA(0, 128, 128, 255);
static void addWireframeSphereWithAxes(const AnimPose& rootPose, const AnimPose& pose, float radius, Vertex*& v) {
// x-axis
v->pos = rootPose * pose.trans;
v->rgba = red;
v++;
v->pos = rootPose * (pose.trans + pose.rot * glm::vec3(radius * 2.0f, 0.0f, 0.0f));
v->rgba = red;
v++;
// y-axis
v->pos = rootPose * pose.trans;
v->rgba = green;
v++;
v->pos = rootPose * (pose.trans + pose.rot * glm::vec3(0.0f, radius * 2.0f, 0.0f));
v->rgba = green;
v++;
// z-axis
v->pos = rootPose * pose.trans;
v->rgba = blue;
v++;
v->pos = rootPose * (pose.trans + pose.rot * glm::vec3(0.0f, 0.0f, radius * 2.0f));
v->rgba = blue;
v++;
}
static void addWireframeBoneAxis(const AnimPose& rootPose, const AnimPose& pose,
const AnimPose& parentPose, float radius, Vertex*& v) {
v->pos = rootPose * pose.trans;
v->rgba = cyan;
v++;
v->pos = rootPose * parentPose.trans;
v->rgba = cyan;
v++;
}
void AnimDebugDraw::update() {
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
@ -173,59 +224,53 @@ void AnimDebugDraw::update() {
}
}
const uint32_t red = toRGBA(255, 0, 0, 255);
const uint32_t green = toRGBA(0, 255, 0, 255);
const uint32_t blue = toRGBA(0, 0, 255, 255);
const uint32_t gray = toRGBA(64, 64, 64, 255);
for (auto&& iter : _animNodes) {
AnimNode::Pointer& animNode = iter.second.first;
auto poses = animNode->getPosesInternal();
numVerts += poses.size() * 6;
/*
for (int i = 0; i < poses.size(); i++) {
// TODO: need skeleton!
if (skeleton->getParentIndex(i) >= 0) {
numVerts += 2;
}
}
*/
}
data._vertexBuffer->resize(sizeof(Vertex) * numVerts);
Vertex* verts = (Vertex*)data._vertexBuffer->editData();
Vertex* v = verts;
for (auto&& iter : _skeletons) {
AnimSkeleton::Pointer& skeleton = iter.second.first;
Transform& xform = iter.second.second;
AnimPose& rootPose = iter.second.second;
for (int i = 0; i < skeleton->getNumJoints(); i++) {
AnimPose pose = skeleton->getBindPose(i);
glm::vec3 base = xform.transform(pose.trans);
// x-axis
v->pos = base;
v->rgba = red;
v++;
v->pos = base + pose.rot * glm::vec3(1.0f, 0.0f, 0.0f);
v->rgba = red;
v++;
// y-axis
v->pos = xform.transform(pose.trans);
v->rgba = green;
v++;
v->pos = base + pose.rot * glm::vec3(0.0f, 1.0f, 0.0f);
v->rgba = green;
v++;
// z-axis
v->pos = base;
v->rgba = blue;
v++;
v->pos = base + pose.rot * glm::vec3(0.0f, 0.0f, 1.0f);
v->rgba = blue;
v++;
// draw axes
const float radius = 1.0f;
addWireframeSphereWithAxes(rootPose, pose, radius, v);
// line to parent.
if (skeleton->getParentIndex(i) >= 0) {
AnimPose parentPose = skeleton->getBindPose(skeleton->getParentIndex(i));
v->pos = base;
v->rgba = gray;
v++;
v->pos = xform.transform(parentPose.trans);
v->rgba = gray;
v++;
addWireframeBoneAxis(rootPose, pose, parentPose, radius, v);
}
}
}
for (auto&& iter : _animNodes) {
AnimNode::Pointer& animNode = iter.second.first;
AnimPose& rootPose = iter.second.second;
auto poses = animNode->getPosesInternal();
for (size_t i = 0; i < poses.size(); i++) {
// draw axes
const float radius = 1.0f;
addWireframeSphereWithAxes(rootPose, poses[i], radius, v);
}
}
data._indexBuffer->resize(sizeof(uint16_t) * numVerts);
uint16_t* indices = (uint16_t*)data._indexBuffer->editData();
for (int i = 0; i < numVerts; i++) {

View file

@ -25,9 +25,12 @@ public:
AnimDebugDraw();
~AnimDebugDraw();
void addSkeleton(std::string key, AnimSkeleton::Pointer skeleton, const Transform& worldTransform);
void addSkeleton(std::string key, AnimSkeleton::Pointer skeleton, const AnimPose& rootPose);
void removeSkeleton(std::string key);
void addAnimNode(std::string key, AnimNode::Pointer skeleton, const AnimPose& rootPose);
void removeAnimNode(std::string key);
void update();
protected:
@ -37,9 +40,11 @@ protected:
static gpu::PipelinePointer _pipeline;
typedef std::pair<AnimSkeleton::Pointer, Transform> SkeletonInfo;
typedef std::pair<AnimSkeleton::Pointer, AnimPose> SkeletonInfo;
typedef std::pair<AnimNode::Pointer, AnimPose> AnimNodeInfo;
std::unordered_map<std::string, SkeletonInfo> _skeletons;
std::unordered_map<std::string, AnimNodeInfo> _animNodes;
};
#endif // hifi_AnimDebugDraw