diff --git a/03_IK.pdf b/03_IK.pdf new file mode 100644 index 0000000..f7c8a72 Binary files /dev/null and b/03_IK.pdf differ diff --git a/3-intro.pdf b/3-intro.pdf new file mode 100644 index 0000000..302a5e6 Binary files /dev/null and b/3-intro.pdf differ diff --git a/CGII/src/Animation.cpp b/CGII/src/Animation.cpp index fa13276..fdbc965 100644 --- a/CGII/src/Animation.cpp +++ b/CGII/src/Animation.cpp @@ -79,3 +79,13 @@ bool Animation::read_amc_file(std::string filename, Skeleton* s) 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]); + } + } +} \ No newline at end of file diff --git a/CGII/src/Animation.h b/CGII/src/Animation.h index fe60f0f..8c7e03d 100644 --- a/CGII/src/Animation.h +++ b/CGII/src/Animation.h @@ -16,7 +16,7 @@ public: bool read_amc_file(std::string filename, Skeleton*); int frame_count() const; - + void apply_frame(int frame) const; private: //Contains a std::vector for each frame, which contains animation data for a set of bones. diff --git a/CGII/src/AtomicTransform.cpp b/CGII/src/AtomicTransform.cpp index a575ca2..883925d 100644 --- a/CGII/src/AtomicTransform.cpp +++ b/CGII/src/AtomicTransform.cpp @@ -40,7 +40,45 @@ Mat4 AtomicRotationTransform::calculate_matrix() 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) { diff --git a/CGII/src/AtomicTransform.h b/CGII/src/AtomicTransform.h index 68f60cb..332f0d0 100644 --- a/CGII/src/AtomicTransform.h +++ b/CGII/src/AtomicTransform.h @@ -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) { 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; @@ -84,7 +87,8 @@ public: virtual Mat4 calculate_matrix(); 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: Vec3 axis; @@ -115,7 +119,8 @@ public: virtual Mat4 calculate_matrix(); 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: int dim; diff --git a/CGII/src/Bone.cpp b/CGII/src/Bone.cpp index 251b9c2..dae0a63 100644 --- a/CGII/src/Bone.cpp +++ b/CGII/src/Bone.cpp @@ -1,5 +1,5 @@ -// This source code is property of the Computer Graphics and Visualization -// chair of the TU Dresden. Do not distribute! +// This source code is property of the Computer Graphics and Visualization +// chair of the TU Dresden. Do not distribute! // Copyright (C) CGV TU Dresden - All Rights Reserved // #include "Bone.h" @@ -9,29 +9,9 @@ #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() : parent(nullptr), length(0.0f), direction_in_world_space(0.0, 0.0, 0.0), translationTransforms(0) -{ -} +{} Bone::~Bone() { @@ -49,93 +29,48 @@ Bone::~Bone() void Bone::calculate_matrices() { orientationTransformGlobalToLocal.identity(); - std::for_each(orientation.begin(), orientation.end(), [&](AtomicTransform *t) { - //std::cout << name << " orientation " << t->get_name() << ": " << t->get_value() << std::endl; - + std::for_each(orientation.begin(), orientation.end(), [&](AtomicTransform* t) { orientationTransformGlobalToLocal = orientationTransformGlobalToLocal * t->calculate_matrix(); }); - orientationTransformLocalToGlobal = cgv::math::inv(orientationTransformGlobalToLocal); - //std::cout << name << " direction " << from_Vec3(direction_in_world_space) << std::endl; - //std::cout << name << " length " << length << std::endl; - - /*Task 2.1: Implement matrix calculation */ - Vec3 vector = direction_in_world_space * length; - //translationTransformCurrentJointToNext = orientationTransformLocalToGlobal * translate(vector) * orientationTransformGlobalToLocal; - translationTransformCurrentJointToNext = translate(vector); - - if (parent == nullptr) + Vec4 globalDirection = Vec4(direction_in_world_space.x() * length, direction_in_world_space.y() * length, direction_in_world_space.z() * length, 0); + Vec4 localDirection = orientationTransformLocalToGlobal * globalDirection; + translationTransformCurrentJointToNext = translate(localDirection.x(), localDirection.y(), localDirection.z()); + if (parent != nullptr) { - orientationTransformPrevJointToCurrent.identity(); + orientationTransformPrevJointToCurrent = parent->orientationTransformLocalToGlobal * orientationTransformGlobalToLocal; + translationTransformGlobalToLocal = parent->translationTransformGlobalToLocal * translate(parent->direction_in_world_space * parent->length); } else { - Vec3 prev_dir = parent->get_direction_in_world_space(); - Vec3 &curr_dir = direction_in_world_space; - - 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); - } + orientationTransformPrevJointToCurrent = orientationTransformGlobalToLocal; + translationTransformGlobalToLocal.identity(); } - /*Task 4.6: Implement matrix calculation */ + /*Task 4.6: Implement matrix calculation */ } Mat4 Bone::calculate_transform_prev_to_current_with_dofs() { - //Task 2.1: Implement matrix calculation - if (parent == NULL) - { - Mat4 t; - t.identity(); - return t; - } - - Mat4 dofs_matrix; - dofs_matrix.identity(); - - std::for_each(dofs.begin(), dofs.end(), [&](std::shared_ptr &t) { - dofs_matrix = dofs_matrix * t->calculate_matrix(); - }); - - return parent->get_translation_transform_current_joint_to_next() * orientationTransformPrevJointToCurrent * dofs_matrix; + Mat4 t = calculate_transform_prev_to_current_without_dofs(); + for (unsigned int i = 0; i < dofs.size(); ++i) + t = t * dofs[i]->calculate_matrix(); + return t; } Mat4 Bone::calculate_transform_prev_to_current_without_dofs() { - //Task 2.1: Implement matrix calculation - return parent->get_translation_transform_current_joint_to_next() * orientationTransformPrevJointToCurrent; + Mat4 t = 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()); - if (dynamic_cast(dof)) + dof->set_index_in_amc(dofs.size()); + if (dynamic_cast(dof)) { dofs.push_front(std::shared_ptr(dof)); ++translationTransforms; @@ -144,40 +79,40 @@ void Bone::add_dof(AtomicTransform *dof) dofs.insert(dofs.begin() + translationTransforms, std::shared_ptr(dof)); } -void Bone::set_name(const std::string &name) { this->name = name; } -const std::string &Bone::get_name() const { return name; } +void Bone::set_name(const std::string& name) { this->name = 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; } -const Vec3 &Bone::get_direction_in_world_space() const { return direction_in_world_space; } +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; } void Bone::set_length(float l) { this->length = l; } float Bone::get_length() const { return length; } -void Bone::add_axis_rotation(AtomicTransform *transform) { orientation.push_front(transform); } -void Bone::add_child(Bone *child) +void Bone::add_axis_rotation(AtomicTransform* transform) { orientation.push_front(transform); } +void Bone::add_child(Bone* child) { child->set_parent(this); 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(); } -void Bone::set_parent(Bone *parent) +void Bone::set_parent(Bone* 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(); } std::shared_ptr 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; } -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_translation_transform_current_joint_to_next() const { return translationTransformCurrentJointToNext; } +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_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); } \ No newline at end of file diff --git a/CGII/src/SkeletonViewer.cpp b/CGII/src/SkeletonViewer.cpp index c09a414..17816db 100644 --- a/CGII/src/SkeletonViewer.cpp +++ b/CGII/src/SkeletonViewer.cpp @@ -1,5 +1,5 @@ -// This source code is property of the Computer Graphics and Visualization -// chair of the TU Dresden. Do not distribute! +// This source code is property of the Computer Graphics and Visualization +// chair of the TU Dresden. Do not distribute! // Copyright (C) CGV TU Dresden - All Rights Reserved // #include "SkeletonViewer.h" @@ -12,178 +12,86 @@ #include #include "math_helper.h" -#include using namespace cgv::utils; cgv::render::shader_program Mesh::prog; // The constructor of this class -SkeletonViewer::SkeletonViewer(DataStore *data) +SkeletonViewer::SkeletonViewer(DataStore* data) : node("Skeleton Viewer"), data(data) - -{ + , animation(nullptr), animationTime(0) +{ connect(data->skeleton_changed, this, &SkeletonViewer::skeleton_changed); 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(rand()) / static_cast(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 -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 - if (frame < animations.size()) + auto global_to_current_local = global_to_parent_local * node->calculate_transform_prev_to_current_with_dofs(); + 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 ¤t_step = animations[frame]; - auto it = current_step.find(node->get_name()); - - if (it != current_step.end()) + const GLubyte colors[][3] = { - std::vector &values = it->second; - - if (values.size() == node->dof_count()) - { - for (int i = 0; i < values.size(); i++) - { - node->get_dof(i)->set_value(values[i]); - } - } - } + { 27,158,119 }, + { 217,95,2 }, + { 117,112,179 }, + { 231,41,138 }, + { 102,166,30 }, + { 230,171,2 }, + { 166,118,29 }, + }; + glColor3ubv(colors[level % 7]); + c.tesselate_arrow(cgv::math::fvec(my_root_position.x(), my_root_position.y(), my_root_position.z()), + cgv::math::fvec(my_tip_position.x(), my_tip_position.y(), my_tip_position.z()), 0.1, 2.0, 0.5); } - - Mat4 local_transform = global_to_parent_local * node->calculate_transform_prev_to_current_with_dofs(); - - Vec4 zero = Vec4(0.0f, 0.0f, 0.0f, 1.0f); - - 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++) + Mat4 dof_matrix = global_to_parent_local * node->calculate_transform_prev_to_current_without_dofs(); + float indicatorSize = (data->get_skeleton()->getMax() - data->get_skeleton()->getMin()).length() * 0.05f; + //draw indicators for dofs + if (indicators) { - 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) { - /*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() -{ - frame = 0; - inc_frame = true; - post_redraw(); -} +void SkeletonViewer::start_animation() { playing = true; } +void SkeletonViewer::stop_animation() { playing = false; } -void SkeletonViewer::stop_animation() -{ - inc_frame = false; - //Task: Implement animation -} - -void SkeletonViewer::skeleton_changed(std::shared_ptr s) +void SkeletonViewer::skeleton_changed(std::shared_ptr s) { // This function is called whenever the according signal of the // data store has been called. @@ -192,10 +100,9 @@ void SkeletonViewer::skeleton_changed(std::shared_ptr s) generate_tree_view_nodes(); //Fit view to skeleton - std::vector view_ptrs; + std::vector view_ptrs; cgv::base::find_interface(get_node(), view_ptrs); - if (view_ptrs.empty()) - { + if (view_ptrs.empty()) { // If there is no view, we cannot update it cgv::gui::message("could not find a view to adjust!!"); } @@ -205,15 +112,15 @@ void SkeletonViewer::skeleton_changed(std::shared_ptr s) view_ptrs[0]->set_focus(center.x(), center.y(), center.z()); // Set the scene's size at the focus point view_ptrs[0]->set_y_extent_at_focus(s->getMax().y() - s->getMin().y()); - } + } - //connect signals - recursive_connect_signals(s->get_root()); + //connect signals + recursive_connect_signals(s->get_root()); 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) 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()); } -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) { @@ -259,7 +166,7 @@ void SkeletonViewer::generate_tree_view_nodes(gui_group_ptr parent, Bone *bone) void SkeletonViewer::start_choose_base() { - Bone *b = data->get_endeffector(); + Bone* b = data->get_endeffector(); data->set_endeffector(nullptr); data->set_base(b); } @@ -268,9 +175,9 @@ void SkeletonViewer::tree_selection_changed(base_ptr p, bool select) { bone_group->remove_all_children(); - if (select) + if (select) { - Bone *bone = gui_to_bone.at(p); + Bone* bone = gui_to_bone.at(p); generate_bone_gui(bone); data->set_endeffector(bone); } @@ -330,7 +237,7 @@ void SkeletonViewer::load_pinocchio() std::string filename = cgv::gui::file_open_dialog("Open", "Pinocchio skeleton (*.out):*.out"); if (!filename.empty()) { - data->get_skeleton()->read_pinocchio_file(filename); + data->get_skeleton()->read_pinocchio_file(filename); skeleton_changed(data->get_skeleton()); } } @@ -346,71 +253,35 @@ void SkeletonViewer::load_animation() std::string filename = cgv::gui::file_open_dialog("Open", "Animation File (*.amc):*.amc"); if (!filename.empty()) { - animations.clear(); - - std::ifstream file(filename); - - std::string line; - int current_index = -1; - - while (std::getline(file, line)) + if (animation) { - if (line[0] == '#' || line[0] == ':') - { - continue; - } - - int number = 0; - - std::istringstream sline(line); - sline >> number; - - if (number != 0) - { - current_index = number - 1; - - //std::map> tmp; - std::map> tmp; - animations.emplace_back(tmp); - } - else - { - if (current_index < 0) - abort(); - - std::string bone_name; - std::vector values; - - int first_blank = line.find_first_of(" "); - bone_name = line.substr(0, first_blank); - - auto ¤t_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; - } + delete animation; + animation = nullptr; + } + auto a = new Animation(); + if (a->read_amc_file(filename, data->get_skeleton().get())) + { + animationTime = 0; + animation = a; + playing = true; + } + else + { + delete a; + cgv::gui::message("Could not load specified AMC file."); } } } // Create the gui elements void SkeletonViewer::create_gui() -{ +{ //Bone tree view - parent_group->multi_set("layout='table';rows=3;spacings='normal';"); + parent_group->multi_set("layout='table';rows=3;spacings='normal';"); - tree_view = add_group("", "tree_group", "h=300;column_heading_0='Bones';column_width_0=-1", "f"); + tree_view = add_group("", "tree_group", "h=300;column_heading_0='Bones';column_width_0=-1", "f"); bone_group = add_group("", "align_group", "h=150", "f"); - + auto dock_group = add_group("", "dockable_group", "", "fF"); connect(tree_view->on_selection_change, this, &SkeletonViewer::tree_selection_changed); @@ -421,28 +292,28 @@ void SkeletonViewer::create_gui() auto gui_group = dock_group->add_group("", "align_group", "", "f"); 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, - rebind(this, &SkeletonViewer::load_animation)); + rebind(this, &SkeletonViewer::load_animation)); 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, - rebind(this, &SkeletonViewer::stop_animation)); + rebind(this, &SkeletonViewer::stop_animation)); 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, - rebind(this, &SkeletonViewer::write_pinocchio)); + rebind(this, &SkeletonViewer::write_pinocchio)); 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. // 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_CULL_FACE); @@ -466,11 +337,16 @@ void SkeletonViewer::draw(context &c) glBlendFunc(GL_SRC_ALPHA, GL_ONE); if (data->get_skeleton() != nullptr) - draw_skeleton_subtree(data->get_skeleton()->get_root(), data->get_skeleton()->get_origin(), c, 0); - - if (inc_frame) - frame++; - - if (frame >= animations.size()) - frame = 0; + { + glEnable(GL_LIGHTING); + glEnable(GL_CULL_FACE); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + draw_skeleton_subtree(data->get_skeleton()->get_root(), data->get_skeleton()->get_origin(), c, 0, true, false); + 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); + } } \ No newline at end of file diff --git a/CGII/src/SkeletonViewer.h b/CGII/src/SkeletonViewer.h index d95ec0a..0dab858 100644 --- a/CGII/src/SkeletonViewer.h +++ b/CGII/src/SkeletonViewer.h @@ -1,5 +1,5 @@ -// This source code is property of the Computer Graphics and Visualization -// chair of the TU Dresden. Do not distribute! +// This source code is property of the Computer Graphics and Visualization +// chair of the TU Dresden. Do not distribute! // Copyright (C) CGV TU Dresden - All Rights Reserved // #pragma once @@ -21,33 +21,25 @@ using namespace cgv::math; using namespace cgv::render; using namespace cgv::utils; -#define SKELETON_DEPTH 10 - class SkeletonViewer : public node, public drawable, public provider { - private: - DataStore *data; +private: + DataStore* data; gui_group_ptr tree_view; gui_group_ptr bone_group; - std::vector>> animations; - float colors[SKELETON_DEPTH][3]; - // Maps gui elements in the tree view to a specific bone - std::map gui_to_bone; - - bool inc_frame; - int frame; + std::map gui_to_bone; // slot for the signal void timer_event(double, double dt); void skeleton_changed(std::shared_ptr); 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 generate_bone_gui(Bone *bone); + void generate_bone_gui(Bone* bone); void load_skeleton(); void write_pinocchio(); @@ -55,22 +47,27 @@ class SkeletonViewer : public node, public drawable, public provider void load_animation(); 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 recursive_connect_signals(Bone *b); + void recursive_connect_signals(Bone* b); + + Animation* animation; + double animationTime; + bool playing; void start_animation(); void stop_animation(); - public: +public: // The constructor of this class - SkeletonViewer(DataStore *); + SkeletonViewer(DataStore*); // Create the gui elements void create_gui(); // Draw the scene - void draw(context &c); + void draw(context& c); std::string get_parent_type() const; }; + diff --git a/CGII/src/main.cpp b/CGII/src/main.cpp index 4671f98..fd166e0 100644 --- a/CGII/src/main.cpp +++ b/CGII/src/main.cpp @@ -1,5 +1,5 @@ -// This source code is property of the Computer Graphics and Visualization -// chair of the TU Dresden. Do not distribute! +// This source code is property of the Computer Graphics and Visualization +// chair of the TU Dresden. Do not distribute! // Copyright (C) CGV TU Dresden - All Rights Reserved // // The main file of the plugin. It defines a global register variable @@ -16,11 +16,11 @@ using namespace cgv::base; struct Initializer { - DataStore *data; + DataStore* data; Initializer() - { - //register_object(base_ptr(new CGVDemo()), ""); + { + data = new DataStore();