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(); }
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*);
int frame_count() const;
void apply_frame(int frame) const;
private:
//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);
}
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)
{

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) { 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;

View file

@ -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()
{
@ -50,45 +30,22 @@ 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;
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 */
@ -96,40 +53,18 @@ void Bone::calculate_matrices()
Mat4 Bone::calculate_transform_prev_to_current_with_dofs()
{
//Task 2.1: Implement matrix calculation
if (parent == NULL)
{
Mat4 t;
t.identity();
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 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()
{
//Task 2.1: Implement matrix calculation
return parent->get_translation_transform_current_joint_to_next() * orientationTransformPrevJointToCurrent;
}
Mat4 Bone::get_total_orientation()
{
Mat4 parent_orientation;
if (parent != NULL)
parent_orientation = parent->get_total_orientation();
else
parent_orientation.identity();
return orientationTransformPrevJointToCurrent * parent_orientation;
Mat4 t = orientationTransformPrevJointToCurrent;
if (parent != nullptr)
t = parent->translationTransformCurrentJointToNext * t;
return t;
}
void Bone::add_dof(AtomicTransform* dof)

View file

@ -12,7 +12,6 @@
#include <cgv/base/find_action.h>
#include "math_helper.h"
#include <fstream>
using namespace cgv::utils;
@ -21,167 +20,76 @@ cgv::render::shader_program Mesh::prog;
// The constructor of this class
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<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
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 &current_step = animations[frame];
auto it = current_step.find(node->get_name());
if (it != current_step.end())
const GLubyte colors[][3] =
{
std::vector<float> &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<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 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::stop_animation()
{
inc_frame = false;
//Task: Implement animation
}
void SkeletonViewer::start_animation() { playing = true; }
void SkeletonViewer::stop_animation() { playing = false; }
void SkeletonViewer::skeleton_changed(std::shared_ptr<Skeleton> s)
{
@ -194,8 +102,7 @@ void SkeletonViewer::skeleton_changed(std::shared_ptr<Skeleton> s)
//Fit view to skeleton
std::vector<cgv::render::view*> 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
cgv::gui::message("could not find a view to adjust!!");
}
@ -346,58 +253,22 @@ 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;
delete animation;
animation = nullptr;
}
int number = 0;
std::istringstream sline(line);
sline >> number;
if (number != 0)
auto a = new Animation();
if (a->read_amc_file(filename, data->get_skeleton().get()))
{
current_index = number - 1;
//std::map<std::string, std::vector<AtomicTransform *>> tmp;
std::map<std::string, std::vector<float>> tmp;
animations.emplace_back(tmp);
animationTime = 0;
animation = a;
playing = true;
}
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;
}
delete a;
cgv::gui::message("Could not load specified AMC file.");
}
}
}
@ -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);
}
}

View file

@ -21,8 +21,6 @@ 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:
@ -30,15 +28,9 @@ class SkeletonViewer : public node, public drawable, public provider
gui_group_ptr tree_view;
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
std::map<base_ptr, Bone*> gui_to_bone;
bool inc_frame;
int frame;
// slot for the signal
void timer_event(double, double dt);
void skeleton_changed(std::shared_ptr<Skeleton>);
@ -55,11 +47,15 @@ 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);
Animation* animation;
double animationTime;
bool playing;
void start_animation();
void stop_animation();
@ -74,3 +70,4 @@ class SkeletonViewer : public node, public drawable, public provider
std::string get_parent_type() const;
};

View file

@ -20,7 +20,7 @@ struct Initializer
Initializer()
{
//register_object(base_ptr(new CGVDemo()), "");
data = new DataStore();