Commit 520af4d2 authored by Marek Dvoroznak's avatar Marek Dvoroznak Committed by Mikael Magnusson

libs: npd: add MLS-like deformation

parent bc4ddf9f
...@@ -59,7 +59,7 @@ npd_compute_ARSAP_transformation (gint num_of_points, ...@@ -59,7 +59,7 @@ npd_compute_ARSAP_transformation (gint num_of_points,
NPDPoint reference_points[], NPDPoint reference_points[],
NPDPoint current_points[], NPDPoint current_points[],
gfloat weights[], gfloat weights[],
gboolean ARAP) gboolean ASAP)
{ {
NPDPoint pc = {0, 0}, qc = {0, 0}; NPDPoint pc = {0, 0}, qc = {0, 0};
gfloat a = 0, b = 0, mu_part = 0, mu, r1, r2, x0, y0; gfloat a = 0, b = 0, mu_part = 0, mu, r1, r2, x0, y0;
...@@ -103,8 +103,8 @@ npd_compute_ARSAP_transformation (gint num_of_points, ...@@ -103,8 +103,8 @@ npd_compute_ARSAP_transformation (gint num_of_points,
} }
mu = 1; mu = 1;
if (ARAP) mu = sqrt(a * a + b * b); if (ASAP) mu = mu_part;
else mu = mu_part; else mu = sqrt(a * a + b * b);
r1 = a / mu; r1 = a / mu;
r2 = -b / mu; r2 = -b / mu;
...@@ -129,7 +129,8 @@ npd_compute_ARSAP_transformation (gint num_of_points, ...@@ -129,7 +129,8 @@ npd_compute_ARSAP_transformation (gint num_of_points,
void void
npd_compute_ARSAP_transformations (NPDHiddenModel *hidden_model) npd_compute_ARSAP_transformations (NPDHiddenModel *hidden_model)
{ {
gint i; gint i;
for (i = 0; i < hidden_model->num_of_bones; ++i) for (i = 0; i < hidden_model->num_of_bones; ++i)
{ {
NPDBone *reference_bones = &hidden_model->reference_bones[i]; NPDBone *reference_bones = &hidden_model->reference_bones[i];
...@@ -138,7 +139,7 @@ npd_compute_ARSAP_transformations (NPDHiddenModel *hidden_model) ...@@ -138,7 +139,7 @@ npd_compute_ARSAP_transformations (NPDHiddenModel *hidden_model)
reference_bones->points, reference_bones->points,
current_bones->points, current_bones->points,
current_bones->weights, current_bones->weights,
hidden_model->ARAP); hidden_model->ASAP);
} }
} }
......
...@@ -36,7 +36,7 @@ void npd_compute_ARSAP_transformation (gint num_of_points, ...@@ -36,7 +36,7 @@ void npd_compute_ARSAP_transformation (gint num_of_points,
NPDPoint reference_shape[], NPDPoint reference_shape[],
NPDPoint current_shape[], NPDPoint current_shape[],
gfloat weights[], gfloat weights[],
gboolean ARAP); gboolean ASAP);
void npd_compute_ARSAP_transformations (NPDHiddenModel *model); void npd_compute_ARSAP_transformations (NPDHiddenModel *model);
void npd_deform_model (NPDModel *model, void npd_deform_model (NPDModel *model,
gint rigidity); gint rigidity);
......
...@@ -30,21 +30,22 @@ npd_init_model (NPDModel *model) ...@@ -30,21 +30,22 @@ npd_init_model (NPDModel *model)
GArray *control_points; GArray *control_points;
/* init hidden model */ /* init hidden model */
hidden_model = g_new (NPDHiddenModel, 1); hidden_model = g_new (NPDHiddenModel, 1);
model->hidden_model = hidden_model; model->hidden_model = hidden_model;
hidden_model->ARAP = TRUE; hidden_model->ASAP = FALSE;
hidden_model->num_of_bones = 0; hidden_model->MLS_weights = FALSE;
hidden_model->num_of_bones = 0;
hidden_model->num_of_overlapping_points = 0; hidden_model->num_of_overlapping_points = 0;
/* init control points */ /* init control points */
control_points = g_array_new (FALSE, FALSE, sizeof (NPDControlPoint)); control_points = g_array_new (FALSE, FALSE, sizeof (NPDControlPoint));
model->control_points = control_points; model->control_points = control_points;
model->control_point_radius = 6; model->control_point_radius = 6;
model->control_points_visible = TRUE; model->control_points_visible = TRUE;
/* init other */ /* init other */
model->mesh_visible = TRUE; model->mesh_visible = TRUE;
model->texture_visible = TRUE; model->texture_visible = TRUE;
} }
void void
...@@ -133,6 +134,9 @@ npd_add_control_point (NPDModel *model, ...@@ -133,6 +134,9 @@ npd_add_control_point (NPDModel *model,
npd_set_point_coordinates (&cp.point, closest_point); npd_set_point_coordinates (&cp.point, closest_point);
g_array_append_val (model->control_points, cp); g_array_append_val (model->control_points, cp);
if (model->hidden_model->MLS_weights)
npd_compute_MLS_weights (model);
return &g_array_index (model->control_points, return &g_array_index (model->control_points,
NPDControlPoint, NPDControlPoint,
model->control_points->len - 1); model->control_points->len - 1);
...@@ -147,15 +151,19 @@ npd_remove_control_point (NPDModel *model, ...@@ -147,15 +151,19 @@ npd_remove_control_point (NPDModel *model,
{ {
gint i; gint i;
NPDControlPoint *cp; NPDControlPoint *cp;
for (i = 0; i < model->control_points->len; i++) for (i = 0; i < model->control_points->len; i++)
{ {
cp = &g_array_index (model->control_points, NPDControlPoint, i); cp = &g_array_index (model->control_points, NPDControlPoint, i);
if (cp == control_point) if (cp == control_point)
{ {
npd_set_control_point_weight (cp, 1.0); npd_set_control_point_weight (cp, 1.0);
g_array_remove_index (model->control_points, i); g_array_remove_index (model->control_points, i);
if (model->hidden_model->MLS_weights)
npd_compute_MLS_weights (model);
return; return;
} }
} }
...@@ -334,6 +342,82 @@ npd_set_point_coordinates (NPDPoint *target, ...@@ -334,6 +342,82 @@ npd_set_point_coordinates (NPDPoint *target,
target->y = source->y; target->y = source->y;
} }
/**
* Sets type of deformation. The function doesn't perform anything if supplied
* deformation type doesn't differ from currently set one.
*
* @param model
* @param ASAP TRUE = ASAP deformation, FALSE = ARAP deformation
* @param MLS_weights use weights from Moving Least Squares deformation method
*/
void
npd_set_deformation_type (NPDModel *model,
gboolean ASAP,
gboolean MLS_weights)
{
NPDHiddenModel *hm = model->hidden_model;
if (hm->ASAP == ASAP && hm->MLS_weights == MLS_weights) return;
if (MLS_weights)
npd_compute_MLS_weights (model);
else if (hm->MLS_weights)
npd_reset_weights (hm);
hm->ASAP = ASAP;
hm->MLS_weights = MLS_weights;
}
void
npd_compute_MLS_weights (NPDModel *model)
{
NPDHiddenModel *hm = model->hidden_model;
NPDControlPoint *cp;
NPDOverlappingPoints *op;
NPDPoint *cp_reference, *op_reference;
gfloat min, SED, MLS_weight;
gint i, j;
if (model->control_points->len == 0) return;
for (i = 0; i < hm->num_of_overlapping_points; i++)
{
op = &hm->list_of_overlapping_points[i];
op_reference = op->representative->counterpart;
min = INFINITY;
for (j = 0; j < model->control_points->len; j++)
{
cp = &g_array_index (model->control_points,
NPDControlPoint,
j);
cp_reference = cp->overlapping_points->representative->counterpart;
/* TODO - use geodetic distance */
SED = npd_SED (cp_reference,
op_reference);
if (SED < min) min = SED;
}
if (npd_equal_floats (min, 0.0)) min = 0.0000001;
MLS_weight = 1 / min;
npd_set_overlapping_points_weight (op, MLS_weight);
}
}
void
npd_reset_weights (NPDHiddenModel *hm)
{
NPDOverlappingPoints *op;
gint i;
for (i = 0; i < hm->num_of_overlapping_points; i++)
{
op = &hm->list_of_overlapping_points[i];
npd_set_overlapping_points_weight (op, 1.0);
}
}
void void
npd_print_hidden_model (NPDHiddenModel *hm, npd_print_hidden_model (NPDHiddenModel *hm,
gboolean print_bones, gboolean print_bones,
...@@ -342,7 +426,8 @@ npd_print_hidden_model (NPDHiddenModel *hm, ...@@ -342,7 +426,8 @@ npd_print_hidden_model (NPDHiddenModel *hm,
gint i; gint i;
g_printf ("NPDHiddenModel:\n"); g_printf ("NPDHiddenModel:\n");
g_printf ("number of bones: %d\n", hm->num_of_bones); g_printf ("number of bones: %d\n", hm->num_of_bones);
g_printf ("ARAP: %d\n", hm->ARAP); g_printf ("ASAP: %d\n", hm->ASAP);
g_printf ("MLS weights: %d\n", hm->MLS_weights);
g_printf ("number of overlapping points: %d\n", hm->num_of_overlapping_points); g_printf ("number of overlapping points: %d\n", hm->num_of_overlapping_points);
if (print_bones) if (print_bones)
......
...@@ -37,8 +37,7 @@ struct _NPDPoint ...@@ -37,8 +37,7 @@ struct _NPDPoint
gfloat x; gfloat x;
gfloat y; gfloat y;
gboolean fixed; gboolean fixed;
gfloat *weight; /* reference to weight in array gfloat *weight; /* pointer to weight in array of weights */
of weights */
gint index; gint index;
NPDBone *current_bone; NPDBone *current_bone;
NPDBone *reference_bone; NPDBone *reference_bone;
...@@ -56,27 +55,27 @@ struct _NPDBone ...@@ -56,27 +55,27 @@ struct _NPDBone
struct _NPDOverlappingPoints struct _NPDOverlappingPoints
{ {
gint num_of_points; gint num_of_points;
NPDPoint *representative; /* reference to representative NPDPoint *representative; /* pointer to representative of cluster */
of cluster */ NPDPoint **points; /* array of pointers to points */
NPDPoint **points; /* array of references to points */
}; };
typedef struct typedef struct
{ {
gint num_of_bones; gint num_of_bones;
gint num_of_overlapping_points; gint num_of_overlapping_points;
gboolean ARAP; gboolean ASAP; /* don't change directly!
* use npd_set_deformation_type function */
gboolean MLS_weights; /* don't change directly!
* use npd_set_deformation_type function */
NPDBone *current_bones; /* array of current bones */ NPDBone *current_bones; /* array of current bones */
NPDBone *reference_bones; /* array of reference bones */ NPDBone *reference_bones; /* array of reference bones */
NPDOverlappingPoints *list_of_overlapping_points; /* array of overlapping NPDOverlappingPoints *list_of_overlapping_points; /* array of overlapping points */
points */
} NPDHiddenModel; } NPDHiddenModel;
typedef struct typedef struct
{ {
NPDPoint point; NPDPoint point;
NPDOverlappingPoints *overlapping_points; /* reference to overlapping NPDOverlappingPoints *overlapping_points; /* pointer to overlapping points */
points */
} NPDControlPoint; } NPDControlPoint;
typedef struct typedef struct
...@@ -96,44 +95,45 @@ typedef struct ...@@ -96,44 +95,45 @@ typedef struct
npd_set_pixel_color = set_pixel;\ npd_set_pixel_color = set_pixel;\
npd_get_pixel_color = get_pixel npd_get_pixel_color = get_pixel
void npd_init_model (NPDModel *model); void npd_init_model (NPDModel *model);
void npd_destroy_hidden_model (NPDHiddenModel *model); void npd_destroy_hidden_model (NPDHiddenModel *model);
void npd_destroy_model (NPDModel *model); void npd_destroy_model (NPDModel *model);
NPDControlPoint *npd_add_control_point (NPDModel *model, NPDControlPoint *npd_add_control_point (NPDModel *model,
NPDPoint *coord); NPDPoint *coord);
void npd_remove_control_point (NPDModel *model, void npd_remove_control_point (NPDModel *model,
NPDControlPoint *control_point); NPDControlPoint *control_point);
void npd_remove_all_control_points void npd_remove_all_control_points (NPDModel *model);
(NPDModel *model); void npd_set_control_point_weight (NPDControlPoint *cp,
void npd_set_control_point_weight gfloat weight);
(NPDControlPoint *cp, gboolean npd_equal_coordinates (NPDPoint *p1,
gfloat weight); NPDPoint *p2);
gboolean npd_equal_coordinates (NPDPoint *p1, gboolean npd_equal_coordinates_epsilon (NPDPoint *p1,
NPDPoint *p2); NPDPoint *p2,
gboolean npd_equal_coordinates_epsilon gfloat epsilon);
(NPDPoint *p1, NPDControlPoint *npd_get_control_point_at (NPDModel *model,
NPDPoint *p2, NPDPoint *coord);
gfloat epsilon);
NPDControlPoint *npd_get_control_point_at (NPDModel *model,
NPDPoint *coord);
void npd_create_list_of_overlapping_points void npd_create_list_of_overlapping_points
(NPDHiddenModel *model); (NPDHiddenModel *model);
void add_point_to_suitable_cluster void add_point_to_suitable_cluster (GHashTable *coords_to_cluster,
(GHashTable *coords_to_cluster, NPDPoint *point,
NPDPoint *point, GPtrArray *list_of_overlapping_points);
GPtrArray *list_of_overlapping_points);
void npd_set_overlapping_points_weight void npd_set_overlapping_points_weight
(NPDOverlappingPoints *op, (NPDOverlappingPoints *op,
gfloat weight); gfloat weight);
void npd_set_point_coordinates (NPDPoint *target, void npd_set_point_coordinates (NPDPoint *target,
NPDPoint *source); NPDPoint *source);
void npd_print_hidden_model (NPDHiddenModel *hm, void npd_set_deformation_type (NPDModel *model,
gboolean print_bones, gboolean ASAP,
gboolean print_overlapping_points); gboolean MLS_weights);
void npd_print_bone (NPDBone *bone); void npd_compute_MLS_weights (NPDModel *model);
void npd_print_point (NPDPoint *point, void npd_reset_weights (NPDHiddenModel *hidden_model);
gboolean print_details);
void npd_print_overlapping_points void npd_print_hidden_model (NPDHiddenModel *hm,
(NPDOverlappingPoints *op); gboolean print_bones,
gboolean print_overlapping_points);
void npd_print_bone (NPDBone *bone);
void npd_print_point (NPDPoint *point,
gboolean print_details);
void npd_print_overlapping_points (NPDOverlappingPoints *op);
#endif /* __NPD_COMMON_H__ */ #endif /* __NPD_COMMON_H__ */
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment