Merge solution and next task

This commit is contained in:
hodasemi 2018-06-05 17:53:50 +02:00
parent b5748c2902
commit 3b55561ce2
10 changed files with 225 additions and 364 deletions

BIN
03_IK.pdf Normal file

Binary file not shown.

BIN
3-intro.pdf Normal file

Binary file not shown.

View file

@ -79,3 +79,13 @@ bool Animation::read_amc_file(std::string filename, Skeleton* s)
int Animation::frame_count() const { return frames.size(); } int Animation::frame_count() const { return frames.size(); }
void Animation::apply_frame(int frame) const
{
for (auto& bone : frames.at(frame))
{
for (int i = 0; i < bone.bone->dof_count(); ++i)
{
bone.bone->get_dof(i)->set_value(bone.dof_values[i]);
}
}
}

View file

@ -16,7 +16,7 @@ public:
bool read_amc_file(std::string filename, Skeleton*); bool read_amc_file(std::string filename, Skeleton*);
int frame_count() const; int frame_count() const;
void apply_frame(int frame) const;
private: private:
//Contains a std::vector<AnimationFrameBone> for each frame, which contains animation data for a set of bones. //Contains a std::vector<AnimationFrameBone> for each frame, which contains animation data for a set of bones.

View file

@ -40,7 +40,45 @@ Mat4 AtomicRotationTransform::calculate_matrix()
return rotate(axis, (float)value); return rotate(axis, (float)value);
} }
void AtomicRotationTransform::drawIndicator(float size)
{
if (lower_limit == upper_limit)
return;
//Calculate rotation matrix from x-axis to current axis
Vec3 rot_axis = cgv::math::cross(Vec3(1, 0, 0), axis);
float angle = acosf(axis.x() / axis.length());
Mat4 t;
if (angle == 0)
t.identity();
else
t = rotate(rot_axis, angle * 180.0f / 3.1415926f);
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0, 0, 0);
for (float v = (float)lower_limit; v <= upper_limit; v += 5)
{
auto p = t * size * Vec4(0, -cosf(v * PI / 180.0f), -sinf(v * PI / 180.0f), 0);
glVertex3f(p.x(), p.y(), p.z());
}
auto end = t * size * Vec4(0, -cosf((float)upper_limit * PI / 180.0f), -sinf((float)upper_limit * PI / 180.0f), 0);
glVertex3f(end.x(), end.y(), end.z());
glEnd();
}
void AtomicRotationTransform::drawActualIndicator(float size)
{
//Calculate rotation matrix from x-axis to current axis
Vec3 rot_axis = cgv::math::cross(Vec3(1, 0, 0), axis);
float angle = acosf(axis.x() / axis.length());
Mat4 t;
if (angle == 0)
t.identity();
else
t = rotate(rot_axis, angle * 180.0f / 3.1415926f);
glBegin(GL_LINES);
glVertex3f(0, 0, 0);
auto p = t * size * Vec4(0, -cosf((float)value * PI / 180.0f), -sinf((float)value * PI / 180.0f), 0);
glVertex3f(p.x(), p.y(), p.z());
glEnd();
}
void AtomicRotationTransform::optimize_value(const Vec3& local_vector, const Vec3& target, bool inverse) void AtomicRotationTransform::optimize_value(const Vec3& local_vector, const Vec3& target, bool inverse)
{ {

View file

@ -57,7 +57,10 @@ public:
virtual void optimize_value(const Vec3& local_vector, const Vec3& target, bool inverse = false) = 0; virtual void optimize_value(const Vec3& local_vector, const Vec3& target, bool inverse = false) = 0;
virtual void optimize_value(const Vec3& local_vector, const Vec3& target) { optimize_value(local_vector, target, false); } virtual void optimize_value(const Vec3& local_vector, const Vec3& target) { optimize_value(local_vector, target, false); }
//Draws an indicator that visualizes the transform, including its limits.
virtual void drawIndicator(float size) = 0;
//Draws an indicator that visualizes the current scalar parameter.
virtual void drawActualIndicator(float size) = 0;
std::string get_name() const; std::string get_name() const;
@ -84,7 +87,8 @@ public:
virtual Mat4 calculate_matrix(); virtual Mat4 calculate_matrix();
virtual void optimize_value(const Vec3& local_vector, const Vec3& target, bool inverse = false); virtual void optimize_value(const Vec3& local_vector, const Vec3& target, bool inverse = false);
virtual void drawIndicator(float size);
virtual void drawActualIndicator(float size);
protected: protected:
Vec3 axis; Vec3 axis;
@ -115,7 +119,8 @@ public:
virtual Mat4 calculate_matrix(); virtual Mat4 calculate_matrix();
virtual void optimize_value(const Vec3& local_vector, const Vec3& target, bool inverse = false); virtual void optimize_value(const Vec3& local_vector, const Vec3& target, bool inverse = false);
virtual void drawIndicator(float size) { };
virtual void drawActualIndicator(float size) { };
private: private:
int dim; int dim;

View file

@ -9,29 +9,9 @@
#include "math_helper.h" #include "math_helper.h"
std::string from_Vec3(Vec3 &v)
{
std::stringstream is;
is << "(" << v.x() << ", " << v.y() << ", " << v.z() << ")";
return is.str();
}
float calc_angle(Vec3 dir_vec, Vec3 axis)
{
float dot_result = dot(dir_vec, axis);
float length_v1 = length(dir_vec);
float length_v2 = length(axis);
return acos(dot_result / (length_v1 * length_v2));
}
Bone::Bone() Bone::Bone()
: parent(nullptr), length(0.0f), direction_in_world_space(0.0, 0.0, 0.0), translationTransforms(0) : parent(nullptr), length(0.0f), direction_in_world_space(0.0, 0.0, 0.0), translationTransforms(0)
{ {}
}
Bone::~Bone() Bone::~Bone()
{ {
@ -49,46 +29,23 @@ Bone::~Bone()
void Bone::calculate_matrices() void Bone::calculate_matrices()
{ {
orientationTransformGlobalToLocal.identity(); orientationTransformGlobalToLocal.identity();
std::for_each(orientation.begin(), orientation.end(), [&](AtomicTransform *t) { std::for_each(orientation.begin(), orientation.end(), [&](AtomicTransform* t) {
//std::cout << name << " orientation " << t->get_name() << ": " << t->get_value() << std::endl;
orientationTransformGlobalToLocal = orientationTransformGlobalToLocal * t->calculate_matrix(); orientationTransformGlobalToLocal = orientationTransformGlobalToLocal * t->calculate_matrix();
}); });
orientationTransformLocalToGlobal = cgv::math::inv(orientationTransformGlobalToLocal); orientationTransformLocalToGlobal = cgv::math::inv(orientationTransformGlobalToLocal);
//std::cout << name << " direction " << from_Vec3(direction_in_world_space) << std::endl; Vec4 globalDirection = Vec4(direction_in_world_space.x() * length, direction_in_world_space.y() * length, direction_in_world_space.z() * length, 0);
//std::cout << name << " length " << length << std::endl; Vec4 localDirection = orientationTransformLocalToGlobal * globalDirection;
translationTransformCurrentJointToNext = translate(localDirection.x(), localDirection.y(), localDirection.z());
/*Task 2.1: Implement matrix calculation */ if (parent != nullptr)
Vec3 vector = direction_in_world_space * length;
//translationTransformCurrentJointToNext = orientationTransformLocalToGlobal * translate(vector) * orientationTransformGlobalToLocal;
translationTransformCurrentJointToNext = translate(vector);
if (parent == nullptr)
{ {
orientationTransformPrevJointToCurrent.identity(); orientationTransformPrevJointToCurrent = parent->orientationTransformLocalToGlobal * orientationTransformGlobalToLocal;
translationTransformGlobalToLocal = parent->translationTransformGlobalToLocal * translate(parent->direction_in_world_space * parent->length);
} }
else else
{ {
Vec3 prev_dir = parent->get_direction_in_world_space(); orientationTransformPrevJointToCurrent = orientationTransformGlobalToLocal;
Vec3 &curr_dir = direction_in_world_space; translationTransformGlobalToLocal.identity();
if (prev_dir.x() == 0.0f && prev_dir.y() == 0.0f && prev_dir.z() == 0.0f)
{
orientationTransformPrevJointToCurrent.identity();
}
else if (prev_dir == curr_dir)
{
orientationTransformPrevJointToCurrent.identity();
}
else
{
float angle = calc_angle(curr_dir, prev_dir);
Vec3 axis = cross(curr_dir, prev_dir);
orientationTransformPrevJointToCurrent = rotate(axis, angle);
}
} }
/*Task 4.6: Implement matrix calculation */ /*Task 4.6: Implement matrix calculation */
@ -96,46 +53,24 @@ void Bone::calculate_matrices()
Mat4 Bone::calculate_transform_prev_to_current_with_dofs() Mat4 Bone::calculate_transform_prev_to_current_with_dofs()
{ {
//Task 2.1: Implement matrix calculation Mat4 t = calculate_transform_prev_to_current_without_dofs();
if (parent == NULL) for (unsigned int i = 0; i < dofs.size(); ++i)
{ t = t * dofs[i]->calculate_matrix();
Mat4 t; return t;
t.identity();
return t;
}
Mat4 dofs_matrix;
dofs_matrix.identity();
std::for_each(dofs.begin(), dofs.end(), [&](std::shared_ptr<AtomicTransform> &t) {
dofs_matrix = dofs_matrix * t->calculate_matrix();
});
return parent->get_translation_transform_current_joint_to_next() * orientationTransformPrevJointToCurrent * dofs_matrix;
} }
Mat4 Bone::calculate_transform_prev_to_current_without_dofs() Mat4 Bone::calculate_transform_prev_to_current_without_dofs()
{ {
//Task 2.1: Implement matrix calculation Mat4 t = orientationTransformPrevJointToCurrent;
return parent->get_translation_transform_current_joint_to_next() * orientationTransformPrevJointToCurrent; if (parent != nullptr)
t = parent->translationTransformCurrentJointToNext * t;
return t;
} }
Mat4 Bone::get_total_orientation() void Bone::add_dof(AtomicTransform* dof)
{
Mat4 parent_orientation;
if (parent != NULL)
parent_orientation = parent->get_total_orientation();
else
parent_orientation.identity();
return orientationTransformPrevJointToCurrent * parent_orientation;
}
void Bone::add_dof(AtomicTransform *dof)
{ {
dof->set_index_in_amc(dofs.size()); dof->set_index_in_amc(dofs.size());
if (dynamic_cast<AtomicTranslationTransform *>(dof)) if (dynamic_cast<AtomicTranslationTransform*>(dof))
{ {
dofs.push_front(std::shared_ptr<AtomicTransform>(dof)); dofs.push_front(std::shared_ptr<AtomicTransform>(dof));
++translationTransforms; ++translationTransforms;
@ -144,40 +79,40 @@ void Bone::add_dof(AtomicTransform *dof)
dofs.insert(dofs.begin() + translationTransforms, std::shared_ptr<AtomicTransform>(dof)); dofs.insert(dofs.begin() + translationTransforms, std::shared_ptr<AtomicTransform>(dof));
} }
void Bone::set_name(const std::string &name) { this->name = name; } void Bone::set_name(const std::string& name) { this->name = name; }
const std::string &Bone::get_name() const { return name; } const std::string& Bone::get_name() const { return name; }
void Bone::set_direction_in_world_space(const Vec3 &direction) { this->direction_in_world_space = direction; } void Bone::set_direction_in_world_space(const Vec3& direction) { this->direction_in_world_space = direction; }
const Vec3 &Bone::get_direction_in_world_space() const { return direction_in_world_space; } const Vec3& Bone::get_direction_in_world_space() const { return direction_in_world_space; }
void Bone::set_length(float l) { this->length = l; } void Bone::set_length(float l) { this->length = l; }
float Bone::get_length() const { return length; } float Bone::get_length() const { return length; }
void Bone::add_axis_rotation(AtomicTransform *transform) { orientation.push_front(transform); } void Bone::add_axis_rotation(AtomicTransform* transform) { orientation.push_front(transform); }
void Bone::add_child(Bone *child) void Bone::add_child(Bone* child)
{ {
child->set_parent(this); child->set_parent(this);
children.push_back(child); children.push_back(child);
} }
Bone *Bone::child_at(int i) const { return children[i]; } Bone* Bone::child_at(int i) const { return children[i]; }
int Bone::childCount() const { return children.size(); } int Bone::childCount() const { return children.size(); }
void Bone::set_parent(Bone *parent) void Bone::set_parent(Bone* parent)
{ {
this->parent = parent; this->parent = parent;
} }
Bone *Bone::get_parent() const { return parent; } Bone* Bone::get_parent() const { return parent; }
int Bone::dof_count() const { return dofs.size(); } int Bone::dof_count() const { return dofs.size(); }
std::shared_ptr<AtomicTransform> Bone::get_dof(int dofIndex) const { return dofs[dofIndex]; } std::shared_ptr<AtomicTransform> Bone::get_dof(int dofIndex) const { return dofs[dofIndex]; }
const Mat4 &Bone::get_binding_pose_matrix() const const Mat4& Bone::get_binding_pose_matrix() const
{ {
return transformLocalToGlobal; return transformLocalToGlobal;
} }
const Mat4 &Bone::get_translation_transform_current_joint_to_next() const { return translationTransformCurrentJointToNext; } const Mat4& Bone::get_translation_transform_current_joint_to_next() const { return translationTransformCurrentJointToNext; }
const Mat4 &Bone::get_orientation_transform_prev_joint_to_current() const { return orientationTransformPrevJointToCurrent; } const Mat4& Bone::get_orientation_transform_prev_joint_to_current() const { return orientationTransformPrevJointToCurrent; }
Vec4 Bone::get_bone_local_root_position() const { return Vec4(0, 0, 0, 1); } Vec4 Bone::get_bone_local_root_position() const { return Vec4(0, 0, 0, 1); }
Vec4 Bone::get_bone_local_tip_position() const { return translationTransformCurrentJointToNext * Vec4(0, 0, 0, 1); } Vec4 Bone::get_bone_local_tip_position() const { return translationTransformCurrentJointToNext * Vec4(0, 0, 0, 1); }

View file

@ -12,176 +12,84 @@
#include <cgv/base/find_action.h> #include <cgv/base/find_action.h>
#include "math_helper.h" #include "math_helper.h"
#include <fstream>
using namespace cgv::utils; using namespace cgv::utils;
cgv::render::shader_program Mesh::prog; cgv::render::shader_program Mesh::prog;
// The constructor of this class // The constructor of this class
SkeletonViewer::SkeletonViewer(DataStore *data) SkeletonViewer::SkeletonViewer(DataStore* data)
: node("Skeleton Viewer"), data(data) : node("Skeleton Viewer"), data(data)
, animation(nullptr), animationTime(0)
{ {
connect(data->skeleton_changed, this, &SkeletonViewer::skeleton_changed); connect(data->skeleton_changed, this, &SkeletonViewer::skeleton_changed);
connect(get_animation_trigger().shoot, this, &SkeletonViewer::timer_event); connect(get_animation_trigger().shoot, this, &SkeletonViewer::timer_event);
for (int i = 0; i < SKELETON_DEPTH; i++)
{
for (int j = 0; j < 3; j++)
{
colors[i][j] = static_cast<float>(rand()) / static_cast<float>(RAND_MAX);
}
}
frame = 0;
inc_frame = false;
}
double winkel_to_bogenmass(float v)
{
return (v * 2 * PI) / 360;
}
void draw_dof(Bone *node, Vec4 start_point)
{
for (int i = 0; i < node->dof_count(); i++)
{
Vec3 point_joint = Vec3(start_point.x(), start_point.y(), start_point.z());
auto bonelength = node->get_length();
double lower_limit = node->get_dof(i)->get_lower_limit();
double upper_limit = node->get_dof(i)->get_upper_limit();
// lowerlimit
auto bog_lower_limit = winkel_to_bogenmass(lower_limit);
auto tan_lower_limit = std::tan(bog_lower_limit);
auto cos_lower_limit = std::cos(bog_lower_limit);
// upperlimit
auto bog_upper_limit = winkel_to_bogenmass(upper_limit);
auto tan_upper_limit = std::tan(bog_upper_limit);
auto cos_upper_limit = std::cos(bog_upper_limit);
auto pt_min = bonelength * cos_lower_limit;
auto pt_max = bonelength * cos_upper_limit;
glBegin(GL_TRIANGLE_STRIP);
if (node->get_dof(i)->get_name() == "X-Rotation")
{
// drawing x movement (local)
glColor4f(0, 128, 0, 128);
glVertex3f(point_joint.x(), point_joint.y(), point_joint.z());
glVertex3f(point_joint.x(), point_joint.y() - 5, point_joint.z() + pt_max);
glVertex3f(point_joint.x(), point_joint.y() - 5, point_joint.z() - pt_min);
}
/*
if(node->get_dof(i)->get_name() == "Y-Rotation") {
// drawing y movement (local)
glColor4f(0, 128, 0, 128);
glVertex3f(point_joint.x(), point_joint.y(), point_joint.z());
glVertex3f(point_joint.x(), point_joint.y()+pt_max, point_joint.z());
glVertex3f(point_joint.x(), point_joint.y()-pt_min, point_joint.z());
std::cout « "X:" « point_joint.x() « " Y:" « point_joint.y()+pt_max « " Z:" « point_joint.z() « std::endl;
std::cout « pt_max « std::endl;
}
if(node->get_dof(i)->get_name() == "Z-Rotation") {
// drawing z movement (local)
glColor4f(0, 128, 0, 128);
glVertex3f(point_joint.x(), point_joint.y(), point_joint.z());
glVertex3f(point_joint.x(), point_joint.y(), point_joint.z()+pt_max);
glVertex3f(point_joint.x(), point_joint.y(), point_joint.z()-pt_min);
}
/*
// drawing y movement (local)
glColor4f(128, 0, 0, 128);
glVertex3f(start_point.x(), start_point.y(), start_point.z());
glVertex3f(end_point.x(), end_point.y() - 5, end_point.z());
glVertex3f(end_point.x(), end_point.y() + 5, end_point.z());
// drawing z movement (local)
glColor4f(0, 0, 128, 128);
glVertex3f(start_point.x(), start_point.y(), start_point.z());
glVertex3f(end_point.x(), end_point.y(), end_point.z() - 5);
glVertex3f(end_point.x() + 5, end_point.y(), end_point.z() + 5);
*/
glEnd();
}
} }
//draws a part of a skeleton, represented by the given root node //draws a part of a skeleton, represented by the given root node
void SkeletonViewer::draw_skeleton_subtree(Bone *node, const Mat4 &global_to_parent_local, context &c, int depth) void SkeletonViewer::draw_skeleton_subtree(Bone* node, const Mat4& global_to_parent_local, context& c, int level, bool arrows, bool indicators)
{ {
//Task: Draw skeleton auto global_to_current_local = global_to_parent_local * node->calculate_transform_prev_to_current_with_dofs();
if (frame < animations.size()) auto my_root_position = global_to_current_local * node->get_bone_local_root_position();
auto my_tip_position = global_to_current_local * node->get_bone_local_tip_position();
if (arrows)
{ {
auto &current_step = animations[frame]; const GLubyte colors[][3] =
auto it = current_step.find(node->get_name());
if (it != current_step.end())
{ {
std::vector<float> &values = it->second; { 27,158,119 },
{ 217,95,2 },
if (values.size() == node->dof_count()) { 117,112,179 },
{ { 231,41,138 },
for (int i = 0; i < values.size(); i++) { 102,166,30 },
{ { 230,171,2 },
node->get_dof(i)->set_value(values[i]); { 166,118,29 },
} };
} glColor3ubv(colors[level % 7]);
} c.tesselate_arrow(cgv::math::fvec<double, 3u>(my_root_position.x(), my_root_position.y(), my_root_position.z()),
cgv::math::fvec<double, 3u>(my_tip_position.x(), my_tip_position.y(), my_tip_position.z()), 0.1, 2.0, 0.5);
} }
Mat4 dof_matrix = global_to_parent_local * node->calculate_transform_prev_to_current_without_dofs();
Mat4 local_transform = global_to_parent_local * node->calculate_transform_prev_to_current_with_dofs(); float indicatorSize = (data->get_skeleton()->getMax() - data->get_skeleton()->getMin()).length() * 0.05f;
//draw indicators for dofs
Vec4 zero = Vec4(0.0f, 0.0f, 0.0f, 1.0f); if (indicators)
Vec4 p1 = global_to_parent_local * zero;
Vec4 p2 = local_transform * zero;
Vec3 p1_v3 = Vec3(p1.x(), p1.y(), p1.z());
Vec3 p2_v3 = Vec3(p2.x(), p2.y(), p2.z());
glColor3f(colors[depth][0], colors[depth][1], colors[depth][2]);
c.tesselate_arrow(p1_v3, p2_v3);
draw_dof(node, p1);
depth++;
for (int i = 0; i < node->childCount(); i++)
{ {
draw_skeleton_subtree(node->child_at(i), local_transform, c, depth); glDepthMask(false);
int i = 0;
for (int i = 0; i < node->dof_count(); ++i)
{
auto t = node->get_dof(i);
glPushMatrix();
glMultMatrixf(dof_matrix);
glColor4f(0, 1, 0, 0.2f);
t->drawIndicator(indicatorSize);
glColor4f(0.5f, 1, 0.5f, 1);
t->drawActualIndicator(indicatorSize);
glPopMatrix();
dof_matrix = dof_matrix * node->get_dof(i)->calculate_matrix();
}
glDepthMask(true);
}
int n = node->childCount();
for (int i = 0; i < n; ++i)
{
auto child = node->child_at(i);
draw_skeleton_subtree(child, global_to_current_local, c, level + 1, arrows, indicators);
} }
} }
void SkeletonViewer::timer_event(double, double dt) void SkeletonViewer::timer_event(double, double dt)
{ {
/*Task: Implement animation */ if (animation && playing)
{
animationTime += dt;
int frame = (int)std::round(animationTime * 120.0) % animation->frame_count();
animation->apply_frame(frame);
}
} }
void SkeletonViewer::start_animation() void SkeletonViewer::start_animation() { playing = true; }
{ void SkeletonViewer::stop_animation() { playing = false; }
frame = 0;
inc_frame = true;
post_redraw();
}
void SkeletonViewer::stop_animation()
{
inc_frame = false;
//Task: Implement animation
}
void SkeletonViewer::skeleton_changed(std::shared_ptr<Skeleton> s) void SkeletonViewer::skeleton_changed(std::shared_ptr<Skeleton> s)
{ {
@ -192,10 +100,9 @@ void SkeletonViewer::skeleton_changed(std::shared_ptr<Skeleton> s)
generate_tree_view_nodes(); generate_tree_view_nodes();
//Fit view to skeleton //Fit view to skeleton
std::vector<cgv::render::view *> view_ptrs; std::vector<cgv::render::view*> view_ptrs;
cgv::base::find_interface<cgv::render::view>(get_node(), view_ptrs); cgv::base::find_interface<cgv::render::view>(get_node(), view_ptrs);
if (view_ptrs.empty()) if (view_ptrs.empty()) {
{
// If there is no view, we cannot update it // If there is no view, we cannot update it
cgv::gui::message("could not find a view to adjust!!"); cgv::gui::message("could not find a view to adjust!!");
} }
@ -213,7 +120,7 @@ void SkeletonViewer::skeleton_changed(std::shared_ptr<Skeleton> s)
post_redraw(); post_redraw();
} }
void SkeletonViewer::recursive_connect_signals(Bone *b) void SkeletonViewer::recursive_connect_signals(Bone* b)
{ {
for (int i = 0; i < b->dof_count(); ++i) for (int i = 0; i < b->dof_count(); ++i)
connect(b->get_dof(i)->changed_signal, this, &SkeletonViewer::dof_changed); connect(b->get_dof(i)->changed_signal, this, &SkeletonViewer::dof_changed);
@ -239,7 +146,7 @@ void SkeletonViewer::generate_tree_view_nodes()
generate_tree_view_nodes(tree_view, data->get_skeleton()->get_root()); generate_tree_view_nodes(tree_view, data->get_skeleton()->get_root());
} }
void SkeletonViewer::generate_tree_view_nodes(gui_group_ptr parent, Bone *bone) void SkeletonViewer::generate_tree_view_nodes(gui_group_ptr parent, Bone* bone)
{ {
if (bone->childCount() == 0) if (bone->childCount() == 0)
{ {
@ -259,7 +166,7 @@ void SkeletonViewer::generate_tree_view_nodes(gui_group_ptr parent, Bone *bone)
void SkeletonViewer::start_choose_base() void SkeletonViewer::start_choose_base()
{ {
Bone *b = data->get_endeffector(); Bone* b = data->get_endeffector();
data->set_endeffector(nullptr); data->set_endeffector(nullptr);
data->set_base(b); data->set_base(b);
} }
@ -270,7 +177,7 @@ void SkeletonViewer::tree_selection_changed(base_ptr p, bool select)
if (select) if (select)
{ {
Bone *bone = gui_to_bone.at(p); Bone* bone = gui_to_bone.at(p);
generate_bone_gui(bone); generate_bone_gui(bone);
data->set_endeffector(bone); data->set_endeffector(bone);
} }
@ -346,58 +253,22 @@ void SkeletonViewer::load_animation()
std::string filename = cgv::gui::file_open_dialog("Open", "Animation File (*.amc):*.amc"); std::string filename = cgv::gui::file_open_dialog("Open", "Animation File (*.amc):*.amc");
if (!filename.empty()) if (!filename.empty())
{ {
animations.clear(); if (animation)
std::ifstream file(filename);
std::string line;
int current_index = -1;
while (std::getline(file, line))
{ {
if (line[0] == '#' || line[0] == ':') delete animation;
{ animation = nullptr;
continue; }
} auto a = new Animation();
if (a->read_amc_file(filename, data->get_skeleton().get()))
int number = 0; {
animationTime = 0;
std::istringstream sline(line); animation = a;
sline >> number; playing = true;
}
if (number != 0) else
{ {
current_index = number - 1; delete a;
cgv::gui::message("Could not load specified AMC file.");
//std::map<std::string, std::vector<AtomicTransform *>> tmp;
std::map<std::string, std::vector<float>> tmp;
animations.emplace_back(tmp);
}
else
{
if (current_index < 0)
abort();
std::string bone_name;
std::vector<float> values;
int first_blank = line.find_first_of(" ");
bone_name = line.substr(0, first_blank);
auto &current_map = animations[current_index];
std::string rest = line.substr(first_blank + 1, line.size());
std::stringstream sstream(rest);
float value;
while (sstream >> value)
{
values.push_back(value);
}
// test if values alone are enough
current_map[bone_name] = values;
}
} }
} }
} }
@ -421,28 +292,28 @@ void SkeletonViewer::create_gui()
auto gui_group = dock_group->add_group("", "align_group", "", "f"); auto gui_group = dock_group->add_group("", "align_group", "", "f");
connect_copy(gui_group->add_button("Load ASF skeleton", "", "\n")->click, connect_copy(gui_group->add_button("Load ASF skeleton", "", "\n")->click,
rebind(this, &SkeletonViewer::load_skeleton)); rebind(this, &SkeletonViewer::load_skeleton));
connect_copy(gui_group->add_button("Load Animation", "", "\n")->click, connect_copy(gui_group->add_button("Load Animation", "", "\n")->click,
rebind(this, &SkeletonViewer::load_animation)); rebind(this, &SkeletonViewer::load_animation));
connect_copy(gui_group->add_button("Start Animation", "", "\n")->click, connect_copy(gui_group->add_button("Start Animation", "", "\n")->click,
rebind(this, &SkeletonViewer::start_animation)); rebind(this, &SkeletonViewer::start_animation));
connect_copy(gui_group->add_button("Stop Animation", "", "\n")->click, connect_copy(gui_group->add_button("Stop Animation", "", "\n")->click,
rebind(this, &SkeletonViewer::stop_animation)); rebind(this, &SkeletonViewer::stop_animation));
connect_copy(gui_group->add_button("Choose IK Base", "", "\n")->click, connect_copy(gui_group->add_button("Choose IK Base", "", "\n")->click,
rebind(this, &SkeletonViewer::start_choose_base)); rebind(this, &SkeletonViewer::start_choose_base));
connect_copy(gui_group->add_button("Write Pinocchio skeleton", "", "\n")->click, connect_copy(gui_group->add_button("Write Pinocchio skeleton", "", "\n")->click,
rebind(this, &SkeletonViewer::write_pinocchio)); rebind(this, &SkeletonViewer::write_pinocchio));
connect_copy(gui_group->add_button("Load Pinocchio skeleton", "", "\n")->click, connect_copy(gui_group->add_button("Load Pinocchio skeleton", "", "\n")->click,
rebind(this, &SkeletonViewer::load_pinocchio)); rebind(this, &SkeletonViewer::load_pinocchio));
} }
void SkeletonViewer::generate_bone_gui(Bone *bone) void SkeletonViewer::generate_bone_gui(Bone* bone)
{ {
// Add bone-specific gui elements to bone_group. // Add bone-specific gui elements to bone_group.
// Use the layout "\n" to specify vertical alignment // Use the layout "\n" to specify vertical alignment
@ -458,7 +329,7 @@ void SkeletonViewer::generate_bone_gui(Bone *bone)
} }
} }
void SkeletonViewer::draw(context &c) void SkeletonViewer::draw(context& c)
{ {
glDisable(GL_LIGHTING); glDisable(GL_LIGHTING);
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
@ -466,11 +337,16 @@ void SkeletonViewer::draw(context &c)
glBlendFunc(GL_SRC_ALPHA, GL_ONE); glBlendFunc(GL_SRC_ALPHA, GL_ONE);
if (data->get_skeleton() != nullptr) if (data->get_skeleton() != nullptr)
draw_skeleton_subtree(data->get_skeleton()->get_root(), data->get_skeleton()->get_origin(), c, 0); {
glEnable(GL_LIGHTING);
if (inc_frame) glEnable(GL_CULL_FACE);
frame++; glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
if (frame >= animations.size()) draw_skeleton_subtree(data->get_skeleton()->get_root(), data->get_skeleton()->get_origin(), c, 0, true, false);
frame = 0; glDisable(GL_LIGHTING);
glDisable(GL_CULL_FACE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
draw_skeleton_subtree(data->get_skeleton()->get_root(), data->get_skeleton()->get_origin(), c, 0, false, true);
}
} }

View file

@ -21,33 +21,25 @@ using namespace cgv::math;
using namespace cgv::render; using namespace cgv::render;
using namespace cgv::utils; using namespace cgv::utils;
#define SKELETON_DEPTH 10
class SkeletonViewer : public node, public drawable, public provider class SkeletonViewer : public node, public drawable, public provider
{ {
private: private:
DataStore *data; DataStore* data;
gui_group_ptr tree_view; gui_group_ptr tree_view;
gui_group_ptr bone_group; gui_group_ptr bone_group;
std::vector<std::map<std::string, std::vector<float>>> animations;
float colors[SKELETON_DEPTH][3];
// Maps gui elements in the tree view to a specific bone // Maps gui elements in the tree view to a specific bone
std::map<base_ptr, Bone *> gui_to_bone; std::map<base_ptr, Bone*> gui_to_bone;
bool inc_frame;
int frame;
// slot for the signal // slot for the signal
void timer_event(double, double dt); void timer_event(double, double dt);
void skeleton_changed(std::shared_ptr<Skeleton>); void skeleton_changed(std::shared_ptr<Skeleton>);
void generate_tree_view_nodes(); void generate_tree_view_nodes();
void generate_tree_view_nodes(gui_group_ptr parent, Bone *bone); void generate_tree_view_nodes(gui_group_ptr parent, Bone* bone);
void tree_selection_changed(base_ptr p, bool select); void tree_selection_changed(base_ptr p, bool select);
void generate_bone_gui(Bone *bone); void generate_bone_gui(Bone* bone);
void load_skeleton(); void load_skeleton();
void write_pinocchio(); void write_pinocchio();
@ -55,22 +47,27 @@ class SkeletonViewer : public node, public drawable, public provider
void load_animation(); void load_animation();
void start_choose_base(); void start_choose_base();
void draw_skeleton_subtree(Bone *node, const Mat4 &global_to_parent_local, context &c, int depth); void draw_skeleton_subtree(Bone* node, const Mat4& global_to_parent_local, context& c, int level, bool arrows, bool indicators);
void dof_changed(double new_value); void dof_changed(double new_value);
void recursive_connect_signals(Bone *b); void recursive_connect_signals(Bone* b);
Animation* animation;
double animationTime;
bool playing;
void start_animation(); void start_animation();
void stop_animation(); void stop_animation();
public: public:
// The constructor of this class // The constructor of this class
SkeletonViewer(DataStore *); SkeletonViewer(DataStore*);
// Create the gui elements // Create the gui elements
void create_gui(); void create_gui();
// Draw the scene // Draw the scene
void draw(context &c); void draw(context& c);
std::string get_parent_type() const; std::string get_parent_type() const;
}; };

View file

@ -16,11 +16,11 @@ using namespace cgv::base;
struct Initializer struct Initializer
{ {
DataStore *data; DataStore* data;
Initializer() Initializer()
{ {
//register_object(base_ptr(new CGVDemo()), "");
data = new DataStore(); data = new DataStore();