mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 11:42:55 +02:00
WIP, animNode rendering
This commit is contained in:
parent
d1fdbe32d2
commit
df79463750
9 changed files with 136 additions and 46 deletions
|
@ -51,6 +51,7 @@
|
||||||
|
|
||||||
#include "AnimDebugDraw.h"
|
#include "AnimDebugDraw.h"
|
||||||
#include "AnimSkeleton.h"
|
#include "AnimSkeleton.h"
|
||||||
|
#include "AnimClip.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -147,6 +148,11 @@ void MyAvatar::reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::update(float deltaTime) {
|
void MyAvatar::update(float deltaTime) {
|
||||||
|
|
||||||
|
if (_animNode) {
|
||||||
|
_animNode->evaluate(deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
if (_referential) {
|
if (_referential) {
|
||||||
_referential->update();
|
_referential->update();
|
||||||
}
|
}
|
||||||
|
@ -1206,6 +1212,8 @@ void MyAvatar::preRender(RenderArgs* renderArgs) {
|
||||||
initHeadBones();
|
initHeadBones();
|
||||||
_skeletonModel.setCauterizeBoneSet(_headBoneSet);
|
_skeletonModel.setCauterizeBoneSet(_headBoneSet);
|
||||||
|
|
||||||
|
// AJT: SETUP DEBUG RENDERING OF NEW ANIMATION SYSTEM
|
||||||
|
|
||||||
// create a skeleton and hand it over to the debug draw instance
|
// create a skeleton and hand it over to the debug draw instance
|
||||||
auto geom = _skeletonModel.getGeometry()->getFBXGeometry();
|
auto geom = _skeletonModel.getGeometry()->getFBXGeometry();
|
||||||
std::vector<FBXJoint> joints;
|
std::vector<FBXJoint> joints;
|
||||||
|
@ -1213,7 +1221,11 @@ void MyAvatar::preRender(RenderArgs* renderArgs) {
|
||||||
joints.push_back(joint);
|
joints.push_back(joint);
|
||||||
}
|
}
|
||||||
auto skeleton = make_shared<AnimSkeleton>(joints);
|
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) {
|
if (shouldDrawHead != _prevShouldDrawHead) {
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "Avatar.h"
|
#include "Avatar.h"
|
||||||
|
|
||||||
class ModelItemID;
|
class ModelItemID;
|
||||||
|
class AnimNode;
|
||||||
|
|
||||||
enum eyeContactTarget {
|
enum eyeContactTarget {
|
||||||
LEFT_EYE,
|
LEFT_EYE,
|
||||||
|
@ -281,6 +282,8 @@ private:
|
||||||
RigPointer _rig;
|
RigPointer _rig;
|
||||||
bool _prevShouldDrawHead;
|
bool _prevShouldDrawHead;
|
||||||
std::unordered_set<int> _headBoneSet;
|
std::unordered_set<int> _headBoneSet;
|
||||||
|
|
||||||
|
std::shared_ptr<AnimNode> _animNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_MyAvatar_h
|
#endif // hifi_MyAvatar_h
|
||||||
|
|
|
@ -13,14 +13,13 @@
|
||||||
|
|
||||||
AnimClip::AnimClip(const std::string& id, const std::string& url, float startFrame, float endFrame, float timeScale, bool loopFlag) :
|
AnimClip::AnimClip(const std::string& id, const std::string& url, float startFrame, float endFrame, float timeScale, bool loopFlag) :
|
||||||
AnimNode(AnimNode::ClipType, id),
|
AnimNode(AnimNode::ClipType, id),
|
||||||
_url(url),
|
|
||||||
_startFrame(startFrame),
|
_startFrame(startFrame),
|
||||||
_endFrame(endFrame),
|
_endFrame(endFrame),
|
||||||
_timeScale(timeScale),
|
_timeScale(timeScale),
|
||||||
_loopFlag(loopFlag),
|
_loopFlag(loopFlag),
|
||||||
_frame(startFrame)
|
_frame(startFrame)
|
||||||
{
|
{
|
||||||
|
setURL(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimClip::~AnimClip() {
|
AnimClip::~AnimClip() {
|
||||||
|
@ -128,6 +127,9 @@ void AnimClip::copyFromNetworkAnim() {
|
||||||
jointMap.reserve(animJointCount);
|
jointMap.reserve(animJointCount);
|
||||||
for (int i = 0; i < animJointCount; i++) {
|
for (int i = 0; i < animJointCount; i++) {
|
||||||
int skeletonJoint = _skeleton->nameToJointIndex(joints.at(i).name);
|
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);
|
jointMap.push_back(skeletonJoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,4 +153,10 @@ void AnimClip::copyFromNetworkAnim() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_poses.resize(skeletonJointCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const std::vector<AnimPose>& AnimClip::getPosesInternal() const {
|
||||||
|
return _poses;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ public:
|
||||||
friend class AnimClipTests;
|
friend class AnimClipTests;
|
||||||
|
|
||||||
AnimClip(const std::string& id, const std::string& url, float startFrame, float endFrame, float timeScale, bool loopFlag);
|
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);
|
void setURL(const std::string& url);
|
||||||
const std::string& getURL() const { return _url; }
|
const std::string& getURL() const { return _url; }
|
||||||
|
@ -36,12 +36,15 @@ public:
|
||||||
void setLoopFlag(bool loopFlag);
|
void setLoopFlag(bool loopFlag);
|
||||||
bool getLoopFlag() const { return _loopFlag; }
|
bool getLoopFlag() const { return _loopFlag; }
|
||||||
|
|
||||||
virtual const std::vector<AnimPose>& evaluate(float dt);
|
virtual const std::vector<AnimPose>& evaluate(float dt) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
float accumulateTime(float frame, float dt) const;
|
float accumulateTime(float frame, float dt) const;
|
||||||
void copyFromNetworkAnim();
|
void copyFromNetworkAnim();
|
||||||
|
|
||||||
|
// for AnimDebugDraw rendering
|
||||||
|
virtual const std::vector<AnimPose>& getPosesInternal() const override;
|
||||||
|
|
||||||
AnimationPointer _networkAnim;
|
AnimationPointer _networkAnim;
|
||||||
std::vector<AnimPose> _poses;
|
std::vector<AnimPose> _poses;
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,8 @@ class QJsonObject;
|
||||||
|
|
||||||
class AnimNode {
|
class AnimNode {
|
||||||
public:
|
public:
|
||||||
|
friend class AnimDebugDraw;
|
||||||
|
|
||||||
enum Type {
|
enum Type {
|
||||||
ClipType = 0,
|
ClipType = 0,
|
||||||
NumTypes
|
NumTypes
|
||||||
|
@ -55,6 +57,9 @@ public:
|
||||||
virtual const std::vector<AnimPose>& evaluate(float dt) = 0;
|
virtual const std::vector<AnimPose>& evaluate(float dt) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
// for AnimDebugDraw rendering
|
||||||
|
virtual const std::vector<AnimPose>& getPosesInternal() const = 0;
|
||||||
|
|
||||||
Type _type;
|
Type _type;
|
||||||
std::string _id;
|
std::string _id;
|
||||||
std::vector<AnimNode::Pointer> _children;
|
std::vector<AnimNode::Pointer> _children;
|
||||||
|
|
|
@ -10,6 +10,10 @@
|
||||||
#include "AnimSkeleton.h"
|
#include "AnimSkeleton.h"
|
||||||
#include "glmHelpers.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) {
|
AnimSkeleton::AnimSkeleton(const std::vector<FBXJoint>& joints) {
|
||||||
_joints = joints;
|
_joints = joints;
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,11 @@
|
||||||
struct AnimPose {
|
struct AnimPose {
|
||||||
AnimPose() {}
|
AnimPose() {}
|
||||||
AnimPose(const glm::vec3& scaleIn, const glm::quat& rotIn, const glm::vec3& transIn) : scale(scaleIn), rot(rotIn), trans(transIn) {}
|
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::vec3 scale;
|
||||||
glm::quat rot;
|
glm::quat rot;
|
||||||
|
|
|
@ -58,7 +58,7 @@ public:
|
||||||
typedef render::Payload<AnimDebugDrawData> AnimDebugDrawPayload;
|
typedef render::Payload<AnimDebugDrawData> AnimDebugDrawPayload;
|
||||||
|
|
||||||
namespace render {
|
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 <> const Item::Bound payloadGetBound(const AnimDebugDrawData::Pointer& data) { return Item::Bound(); }
|
||||||
template <> void payloadRender(const AnimDebugDrawData::Pointer& data, RenderArgs* args) {
|
template <> void payloadRender(const AnimDebugDrawData::Pointer& data, RenderArgs* args) {
|
||||||
data->render(args);
|
data->render(args);
|
||||||
|
@ -143,14 +143,65 @@ AnimDebugDraw::~AnimDebugDraw() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimDebugDraw::addSkeleton(std::string key, AnimSkeleton::Pointer skeleton, const Transform& worldTransform) {
|
void AnimDebugDraw::addSkeleton(std::string key, AnimSkeleton::Pointer skeleton, const AnimPose& rootPose) {
|
||||||
_skeletons[key] = SkeletonInfo(skeleton, worldTransform);
|
_skeletons[key] = SkeletonInfo(skeleton, rootPose);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimDebugDraw::removeSkeleton(std::string key) {
|
void AnimDebugDraw::removeSkeleton(std::string key) {
|
||||||
_skeletons.erase(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() {
|
void AnimDebugDraw::update() {
|
||||||
|
|
||||||
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
|
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
|
||||||
|
@ -173,59 +224,53 @@ void AnimDebugDraw::update() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32_t red = toRGBA(255, 0, 0, 255);
|
for (auto&& iter : _animNodes) {
|
||||||
const uint32_t green = toRGBA(0, 255, 0, 255);
|
AnimNode::Pointer& animNode = iter.second.first;
|
||||||
const uint32_t blue = toRGBA(0, 0, 255, 255);
|
auto poses = animNode->getPosesInternal();
|
||||||
const uint32_t gray = toRGBA(64, 64, 64, 255);
|
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);
|
data._vertexBuffer->resize(sizeof(Vertex) * numVerts);
|
||||||
Vertex* verts = (Vertex*)data._vertexBuffer->editData();
|
Vertex* verts = (Vertex*)data._vertexBuffer->editData();
|
||||||
Vertex* v = verts;
|
Vertex* v = verts;
|
||||||
for (auto&& iter : _skeletons) {
|
for (auto&& iter : _skeletons) {
|
||||||
AnimSkeleton::Pointer& skeleton = iter.second.first;
|
AnimSkeleton::Pointer& skeleton = iter.second.first;
|
||||||
Transform& xform = iter.second.second;
|
AnimPose& rootPose = iter.second.second;
|
||||||
for (int i = 0; i < skeleton->getNumJoints(); i++) {
|
for (int i = 0; i < skeleton->getNumJoints(); i++) {
|
||||||
AnimPose pose = skeleton->getBindPose(i);
|
AnimPose pose = skeleton->getBindPose(i);
|
||||||
|
|
||||||
glm::vec3 base = xform.transform(pose.trans);
|
// draw axes
|
||||||
|
const float radius = 1.0f;
|
||||||
// x-axis
|
addWireframeSphereWithAxes(rootPose, pose, radius, v);
|
||||||
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++;
|
|
||||||
|
|
||||||
// line to parent.
|
// line to parent.
|
||||||
if (skeleton->getParentIndex(i) >= 0) {
|
if (skeleton->getParentIndex(i) >= 0) {
|
||||||
AnimPose parentPose = skeleton->getBindPose(skeleton->getParentIndex(i));
|
AnimPose parentPose = skeleton->getBindPose(skeleton->getParentIndex(i));
|
||||||
v->pos = base;
|
addWireframeBoneAxis(rootPose, pose, parentPose, radius, v);
|
||||||
v->rgba = gray;
|
|
||||||
v++;
|
|
||||||
v->pos = xform.transform(parentPose.trans);
|
|
||||||
v->rgba = gray;
|
|
||||||
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);
|
data._indexBuffer->resize(sizeof(uint16_t) * numVerts);
|
||||||
uint16_t* indices = (uint16_t*)data._indexBuffer->editData();
|
uint16_t* indices = (uint16_t*)data._indexBuffer->editData();
|
||||||
for (int i = 0; i < numVerts; i++) {
|
for (int i = 0; i < numVerts; i++) {
|
||||||
|
|
|
@ -25,9 +25,12 @@ public:
|
||||||
AnimDebugDraw();
|
AnimDebugDraw();
|
||||||
~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 removeSkeleton(std::string key);
|
||||||
|
|
||||||
|
void addAnimNode(std::string key, AnimNode::Pointer skeleton, const AnimPose& rootPose);
|
||||||
|
void removeAnimNode(std::string key);
|
||||||
|
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -37,9 +40,11 @@ protected:
|
||||||
|
|
||||||
static gpu::PipelinePointer _pipeline;
|
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, SkeletonInfo> _skeletons;
|
||||||
|
std::unordered_map<std::string, AnimNodeInfo> _animNodes;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_AnimDebugDraw
|
#endif // hifi_AnimDebugDraw
|
||||||
|
|
Loading…
Reference in a new issue