[gegl/soc-2013-n-point-deformation: 11/22] libs: npd: add MLS-like deformation



commit d59c3d1516efaebad6bd0f83b4e8bd459dfc6e85
Author: Marek Dvoroznak <dvoromar gmail com>
Date:   Thu Aug 8 17:37:22 2013 +0200

    libs: npd: add MLS-like deformation

 libs/npd/deformation.c |   11 +++--
 libs/npd/deformation.h |    2 +-
 libs/npd/npd_common.c  |  107 +++++++++++++++++++++++++++++++++++++++++++-----
 libs/npd/npd_common.h  |   94 +++++++++++++++++++++---------------------
 4 files changed, 150 insertions(+), 64 deletions(-)
---
diff --git a/libs/npd/deformation.c b/libs/npd/deformation.c
index 415e53b..068e7d8 100644
--- a/libs/npd/deformation.c
+++ b/libs/npd/deformation.c
@@ -59,7 +59,7 @@ npd_compute_ARSAP_transformation (gint     num_of_points,
                                   NPDPoint reference_points[],
                                   NPDPoint current_points[],
                                   gfloat   weights[],
-                                  gboolean ARAP)
+                                  gboolean ASAP)
 {
   NPDPoint pc = {0, 0}, qc = {0, 0};
   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,
     }
 
   mu = 1;
-  if (ARAP) mu = sqrt(a * a + b * b);
-  else      mu = mu_part;
+  if (ASAP) mu = mu_part;
+  else      mu = sqrt(a * a + b * b);
 
   r1 =  a / mu;
   r2 = -b / mu;
@@ -129,7 +129,8 @@ npd_compute_ARSAP_transformation (gint     num_of_points,
 void
 npd_compute_ARSAP_transformations (NPDHiddenModel *hidden_model)
 {
-  gint i;
+  gint     i;
+  
   for (i = 0; i < hidden_model->num_of_bones; ++i)
     {
       NPDBone *reference_bones = &hidden_model->reference_bones[i];
@@ -138,7 +139,7 @@ npd_compute_ARSAP_transformations (NPDHiddenModel *hidden_model)
                                         reference_bones->points,
                                         current_bones->points,
                                         current_bones->weights,
-                                        hidden_model->ARAP);
+                                        hidden_model->ASAP);
     }
 }
 
diff --git a/libs/npd/deformation.h b/libs/npd/deformation.h
index 326d14f..6c5c746 100644
--- a/libs/npd/deformation.h
+++ b/libs/npd/deformation.h
@@ -36,7 +36,7 @@ void  npd_compute_ARSAP_transformation  (gint              num_of_points,
                                          NPDPoint          reference_shape[],
                                          NPDPoint          current_shape[],
                                          gfloat            weights[],
-                                         gboolean          ARAP);
+                                         gboolean          ASAP);
 void  npd_compute_ARSAP_transformations (NPDHiddenModel   *model);
 void  npd_deform_model                  (NPDModel         *model,
                                          gint              rigidity);
diff --git a/libs/npd/npd_common.c b/libs/npd/npd_common.c
index ee52825..e9f856e 100644
--- a/libs/npd/npd_common.c
+++ b/libs/npd/npd_common.c
@@ -30,21 +30,22 @@ npd_init_model (NPDModel *model)
   GArray         *control_points;
   
   /* init hidden model */
-  hidden_model = g_new (NPDHiddenModel, 1);
+  hidden_model        = g_new (NPDHiddenModel, 1);
   model->hidden_model = hidden_model;
-  hidden_model->ARAP = TRUE;
-  hidden_model->num_of_bones = 0;
+  hidden_model->ASAP                      = FALSE;
+  hidden_model->MLS_weights               = FALSE;
+  hidden_model->num_of_bones              = 0;
   hidden_model->num_of_overlapping_points = 0;
 
   /* 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_point_radius = 6;
-  model->control_points_visible = TRUE;
+  model->control_point_radius             = 6;
+  model->control_points_visible           = TRUE;
 
   /* init other */
-  model->mesh_visible = TRUE;
-  model->texture_visible = TRUE;
+  model->mesh_visible                     = TRUE;
+  model->texture_visible                  = TRUE;
 }
 
 void
@@ -133,6 +134,9 @@ npd_add_control_point (NPDModel *model,
       npd_set_point_coordinates (&cp.point, closest_point);
       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,
                              NPDControlPoint,
                              model->control_points->len - 1);
@@ -147,15 +151,19 @@ npd_remove_control_point (NPDModel        *model,
 {
   gint i;
   NPDControlPoint *cp;
-  
+
   for (i = 0; i < model->control_points->len; i++)
     {
       cp = &g_array_index (model->control_points, NPDControlPoint, i);
-      
+
       if (cp == control_point)
         {
           npd_set_control_point_weight (cp, 1.0);
           g_array_remove_index (model->control_points, i);
+
+          if (model->hidden_model->MLS_weights)
+            npd_compute_MLS_weights (model);
+
           return;
         }
     }
@@ -334,6 +342,82 @@ npd_set_point_coordinates (NPDPoint *target,
   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
 npd_print_hidden_model (NPDHiddenModel *hm,
                         gboolean        print_bones,
@@ -342,7 +426,8 @@ npd_print_hidden_model (NPDHiddenModel *hm,
   gint i;
   g_printf ("NPDHiddenModel:\n");
   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);
   
   if (print_bones)
diff --git a/libs/npd/npd_common.h b/libs/npd/npd_common.h
index 4414cc5..06f4bc8 100644
--- a/libs/npd/npd_common.h
+++ b/libs/npd/npd_common.h
@@ -37,8 +37,7 @@ struct _NPDPoint
   gfloat                x;
   gfloat                y;
   gboolean              fixed;
-  gfloat               *weight;            /* reference to weight in array
-                                              of weights */
+  gfloat               *weight;            /* pointer to weight in array of weights */
   gint                  index;
   NPDBone              *current_bone;
   NPDBone              *reference_bone;
@@ -56,27 +55,27 @@ struct _NPDBone
 struct _NPDOverlappingPoints
 {
   gint                  num_of_points;
-  NPDPoint             *representative;    /* reference to representative
-                                              of cluster */
-  NPDPoint            **points;            /* array of references to points */
+  NPDPoint             *representative;    /* pointer to representative of cluster */
+  NPDPoint            **points;            /* array of pointers to points */
 };
 
 typedef struct
 {
   gint                  num_of_bones;
   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              *reference_bones;   /* array of reference bones */
-  NPDOverlappingPoints *list_of_overlapping_points; /* array of overlapping
-                                                       points */
+  NPDOverlappingPoints *list_of_overlapping_points; /* array of overlapping points */
 } NPDHiddenModel;
 
 typedef struct
 {
   NPDPoint              point;
-  NPDOverlappingPoints *overlapping_points; /* reference to overlapping
-                                               points */
+  NPDOverlappingPoints *overlapping_points; /* pointer to overlapping points */
 } NPDControlPoint;
 
 typedef struct
@@ -96,44 +95,45 @@ typedef struct
 npd_set_pixel_color = set_pixel;\
 npd_get_pixel_color = get_pixel
 
-void             npd_init_model             (NPDModel        *model);
-void             npd_destroy_hidden_model   (NPDHiddenModel  *model);
-void             npd_destroy_model          (NPDModel        *model);
+void             npd_init_model                 (NPDModel        *model);
+void             npd_destroy_hidden_model       (NPDHiddenModel  *model);
+void             npd_destroy_model              (NPDModel        *model);
 
-NPDControlPoint *npd_add_control_point      (NPDModel        *model,
-                                             NPDPoint        *coord);
-void             npd_remove_control_point   (NPDModel        *model,
-                                             NPDControlPoint *control_point);
-void             npd_remove_all_control_points
-                                            (NPDModel        *model);
-void             npd_set_control_point_weight
-                                            (NPDControlPoint *cp,
-                                             gfloat           weight);
-gboolean         npd_equal_coordinates      (NPDPoint        *p1,
-                                             NPDPoint        *p2);
-gboolean         npd_equal_coordinates_epsilon
-                                            (NPDPoint        *p1,
-                                             NPDPoint        *p2,
-                                             gfloat           epsilon);
-NPDControlPoint *npd_get_control_point_at   (NPDModel        *model,
-                                             NPDPoint        *coord);
+NPDControlPoint *npd_add_control_point          (NPDModel        *model,
+                                                 NPDPoint        *coord);
+void             npd_remove_control_point       (NPDModel        *model,
+                                                 NPDControlPoint *control_point);
+void             npd_remove_all_control_points  (NPDModel        *model);
+void             npd_set_control_point_weight   (NPDControlPoint *cp,
+                                                 gfloat           weight);
+gboolean         npd_equal_coordinates          (NPDPoint        *p1,
+                                                 NPDPoint        *p2);
+gboolean         npd_equal_coordinates_epsilon  (NPDPoint        *p1,
+                                                 NPDPoint        *p2,
+                                                 gfloat           epsilon);
+NPDControlPoint *npd_get_control_point_at       (NPDModel        *model,
+                                                 NPDPoint        *coord);
 void             npd_create_list_of_overlapping_points
-                                            (NPDHiddenModel  *model);
-void             add_point_to_suitable_cluster
-                                            (GHashTable      *coords_to_cluster,
-                                             NPDPoint        *point,
-                                             GPtrArray       *list_of_overlapping_points);
+                                                (NPDHiddenModel  *model);
+void             add_point_to_suitable_cluster  (GHashTable      *coords_to_cluster,
+                                                 NPDPoint        *point,
+                                                 GPtrArray       *list_of_overlapping_points);
 void             npd_set_overlapping_points_weight
-                                            (NPDOverlappingPoints *op,
-                                             gfloat           weight);
-void             npd_set_point_coordinates  (NPDPoint        *target,
-                                             NPDPoint        *source);
-void             npd_print_hidden_model     (NPDHiddenModel  *hm,
-                                             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);
+                                                (NPDOverlappingPoints *op,
+                                                 gfloat           weight);
+void             npd_set_point_coordinates      (NPDPoint        *target,
+                                                 NPDPoint        *source);
+void             npd_set_deformation_type       (NPDModel        *model,
+                                                 gboolean         ASAP,
+                                                 gboolean         MLS_weights);
+void             npd_compute_MLS_weights        (NPDModel        *model);
+void             npd_reset_weights              (NPDHiddenModel  *hidden_model);
+
+void             npd_print_hidden_model         (NPDHiddenModel  *hm,
+                                                 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__ */
\ No newline at end of file


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]