ephysics: change quaternion API to avoid many free calls
authorBruno Dilly <bdilly@profusion.mobi>
Wed, 14 Nov 2012 20:01:20 +0000 (20:01 +0000)
committerBruno Dilly <bdilly@profusion.mobi>
Wed, 14 Nov 2012 20:01:20 +0000 (20:01 +0000)
It was really annoying and error prone (easy to leak).

SVN revision: 79299

legacy/ephysics/src/bin/ephysics_sandbox.c
legacy/ephysics/src/bin/test_bouncing_3d.c
legacy/ephysics/src/bin/test_cube_3d.c
legacy/ephysics/src/bin/test_rotating_forever.c
legacy/ephysics/src/lib/EPhysics.h
legacy/ephysics/src/lib/ephysics_body.cpp
legacy/ephysics/src/lib/ephysics_quaternion.cpp

index 5d29238..7bb0db2 100644 (file)
@@ -118,14 +118,14 @@ _type_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
    double mass, friction, restitution, lin_damping, ang_damping;
    double lin_sleeping, ang_sleeping;
    EPhysics_Body_Material material;
-   EPhysics_Quaternion *rotation;
+   EPhysics_Quaternion rotation;
    Evas_Object *body_image;
    EPhysics_World *world;
    Body_Data *bd = data;
    EPhysics_Body *body = bd->body;
 
    mass = ephysics_body_mass_get(body);
-   rotation = ephysics_body_rotation_get(body);
+   ephysics_body_rotation_get(body, &rotation);
    friction = ephysics_body_friction_get(body);
    restitution = ephysics_body_restitution_get(body);
    ephysics_body_damping_get(body, &lin_damping, &ang_damping);
@@ -152,7 +152,7 @@ _type_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
 
    ephysics_body_evas_object_set(body, body_image, EINA_TRUE);
    ephysics_body_mass_set(body, mass);
-   ephysics_body_rotation_set(body, rotation);
+   ephysics_body_rotation_set(body, &rotation);
    ephysics_body_friction_set(body, friction);
    ephysics_body_restitution_set(body, restitution);
    ephysics_body_damping_set(body, lin_damping, ang_damping);
@@ -168,7 +168,6 @@ _type_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
                              elm_slider_value_get(bd->controls.force.torque));
 
    bd->body = body;
-   free(rotation);
 }
 
 static void
@@ -229,13 +228,10 @@ _density_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
 static void
 _rotation_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
 {
-   EPhysics_Quaternion *quat;
+   EPhysics_Quaternion quat;
    Body_Data *bd = data;
-
-   quat = ephysics_quaternion_new(0, 0, 0, 0);
-   ephysics_quaternion_euler_set(quat, 0, 0, elm_slider_value_get(obj));
-   ephysics_body_rotation_set(bd->body, quat);
-   free(quat);
+   ephysics_quaternion_euler_set(&quat, 0, 0, elm_slider_value_get(obj));
+   ephysics_body_rotation_set(bd->body, &quat);
 }
 
 static void
index e239ab6..cfd3747 100644 (file)
@@ -7,18 +7,14 @@
 static void
 _pos_print_cb(void *data __UNUSED__, EPhysics_Body *body, void *event_info __UNUSED__)
 {
-   EPhysics_Quaternion *quat;
-   double rx, ry, rz, rw;
+   EPhysics_Quaternion quat;
    Evas_Coord x, y, z;
 
    ephysics_body_geometry_get(body, &x, &y, &z, NULL, NULL, NULL);
-
-   quat = ephysics_body_rotation_get(body);
-   ephysics_quaternion_get(quat, &rx, &ry, &rz, &rw);
-   free(quat);
+   ephysics_body_rotation_get(body, &quat);
 
    printf("Position X:%i Y:%i Z:%i\n", x, y, z);
-   printf("Rotation X:%lf Y:%lf Z:%lf W:%lf\n", rx, ry, rz, rw);
+   printf("Rotation X:%lf Y:%lf Z:%lf W:%lf\n", quat.x, quat.y, quat.z, quat.w);
 }
 
 static Eina_Bool
index cf10729..cf7156e 100644 (file)
@@ -9,7 +9,7 @@
 static void
 _mouse_move_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
 {
-   EPhysics_Quaternion *quat_prev, *quat_delta, *quat;
+   EPhysics_Quaternion quat_prev, quat_delta, quat;
    Evas_Event_Mouse_Move *mmove = event_info;
    EPhysics_Body *body = data;
    double rx, ry;
@@ -19,15 +19,10 @@ _mouse_move_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void
    rx = mmove->cur.output.y - mmove->prev.output.y;
    ry = mmove->cur.output.x - mmove->prev.output.x;
 
-   quat_prev = ephysics_body_rotation_get(body);
-   quat_delta = ephysics_quaternion_new(0, 0, 0, 0);
-   ephysics_quaternion_euler_set(quat_delta, -ry * 0.06, - rx * 0.04, 0);
-   quat = ephysics_quaternion_multiply(quat_prev, quat_delta);
-   ephysics_body_rotation_set(body, quat);
-
-   free(quat_prev);
-   free(quat_delta);
-   free(quat);
+   ephysics_body_rotation_get(body, &quat_prev);
+   ephysics_quaternion_euler_set(&quat_delta, -ry * 0.06, - rx * 0.04, 0);
+   ephysics_quaternion_multiply(&quat_prev, &quat_delta, &quat);
+   ephysics_body_rotation_set(body, &quat);
 }
 
 static void
index d0be41f..f044588 100644 (file)
@@ -7,19 +7,15 @@
 static Eina_Bool
 _rotate_cb(void *data)
 {
-   EPhysics_Quaternion *quat_prev, *quat_delta, *quat;
+   EPhysics_Quaternion *quat_prev, quat_delta, quat;
    EPhysics_Body *body = data;
 
-   quat_prev = ephysics_body_rotation_get(body);
-   quat_delta = ephysics_quaternion_new(0, 0, -0.15, 0.98);
-   ephysics_quaternion_normalize(quat_delta);
-   quat = ephysics_quaternion_multiply(quat_delta, quat_prev);
-
-   ephysics_body_rotation_set(body, quat);
-
+   quat_prev = ephysics_body_rotation_get(body, NULL);
+   ephysics_quaternion_set(&quat_delta, 0, 0, -0.15, 0.98);
+   ephysics_quaternion_normalize(&quat_delta);
+   ephysics_body_rotation_set(
+      body, ephysics_quaternion_multiply(&quat_delta, quat_prev, &quat));
    free(quat_prev);
-   free(quat_delta);
-   free(quat);
 
    return EINA_TRUE;
 }
@@ -74,14 +70,13 @@ static void
 _update_object_cb(void *data __UNUSED__, EPhysics_Body *body, void *event_info __UNUSED__)
 {
    double rx, ry, rz, rw, vrot, torque;
-   EPhysics_Quaternion *quat;
+   EPhysics_Quaternion quat;
 
    ephysics_body_angular_velocity_get(body, NULL, NULL, &vrot);
    ephysics_body_torques_get(body, NULL, NULL, &torque);
 
-   quat = ephysics_body_rotation_get(body);
-   ephysics_quaternion_get(quat, &rx, &ry, &rz, &rw);
-   free(quat);
+   ephysics_body_rotation_get(body, &quat);
+   ephysics_quaternion_get(&quat, &rx, &ry, &rz, &rw);
 
    ephysics_body_evas_object_update(body);
 
index 5a92796..04179df 100644 (file)
@@ -158,19 +158,29 @@ EAPI int ephysics_shutdown(void);
 typedef struct _EPhysics_Quaternion EPhysics_Quaternion;
 
 /**
+ * @struct _EPhysics_Quaternion
+ *
+ * Quaternion coordinates and rotation (w, x, y, z)
+ */
+struct _EPhysics_Quaternion
+{
+   double w; /**< rotation */
+   double x; /**< x coordinate */
+   double y; /**< y coordinate */
+   double z; /**< z coordinate */
+};
+
+/**
  * @brief
  * Create a new quaternion.
  *
- * @note It should be deleted with free() after usage is concluded.
- *
+ * By default a quaternion is created as identity  (w = 1, x = 0, y = 0, z = 0).
  * This values can be modified later by quaternion operations or set directly.
  *
- * @param x The x coordinate.
- * @param y The y coordinate.
- * @param z The z coordinate.
- * @param w The rotation.
  * @return The created quaternion or @c NULL on error.
  *
+ * @note It should be deleted with free() after usage is concluded.
+ *
  * @see ephysics_quaternion_set();
  * @see ephysics_quaternion_axis_angle_set();
  * @see ephysics_quaternion_euler_set();
@@ -179,7 +189,7 @@ typedef struct _EPhysics_Quaternion EPhysics_Quaternion;
  *
  * @ingroup EPhysics_Quaternion
  */
-EAPI EPhysics_Quaternion *ephysics_quaternion_new(double x, double y, double z, double w);
+EAPI EPhysics_Quaternion *ephysics_quaternion_new(void);
 
 /**
  * @brief
@@ -325,13 +335,13 @@ EAPI void ephysics_quaternion_inverse_scale(EPhysics_Quaternion *quat, double sc
  *
  * @param quat1 First quaternion to sum.
  * @param quat2 Second quaternion to sum.
+ * @param result Quaternion used to store the result. If it's @c NULL, a new
+ * quaternion will be allocated (and should be freed after usage).
  * @return The sum quaternion or @c NULL on error.
  *
- * @note It should be freed after usage.
- *
  * @ingroup EPhysics_Quaternion
  */
-EAPI EPhysics_Quaternion *ephysics_quaternion_sum(const EPhysics_Quaternion *quat1, const EPhysics_Quaternion *quat2);
+EAPI EPhysics_Quaternion *ephysics_quaternion_sum(const EPhysics_Quaternion *quat1, const EPhysics_Quaternion *quat2, EPhysics_Quaternion *result);
 
 /**
  * @brief
@@ -339,13 +349,13 @@ EAPI EPhysics_Quaternion *ephysics_quaternion_sum(const EPhysics_Quaternion *qua
  *
  * @param quat1 First quaternion.
  * @param quat2 Second quaternion.
+ * @param result Quaternion used to store the result. If it's @c NULL, a new
+ * quaternion will be allocated (and should be freed after usage).
  * @return The difference between @p quat1 and @p quat2, or @c NULL on error.
  *
- * @note It should be freed after usage.
- *
  * @ingroup EPhysics_Quaternion
  */
-EAPI EPhysics_Quaternion *ephysics_quaternion_diff(const EPhysics_Quaternion *quat1, const EPhysics_Quaternion *quat2);
+EAPI EPhysics_Quaternion *ephysics_quaternion_diff(const EPhysics_Quaternion *quat1, const EPhysics_Quaternion *quat2, EPhysics_Quaternion *result);
 
 /**
  * @brief
@@ -353,14 +363,14 @@ EAPI EPhysics_Quaternion *ephysics_quaternion_diff(const EPhysics_Quaternion *qu
  *
  * @param quat1 First quaternion.
  * @param quat2 Second quaternion.
+ * @param result Quaternion used to store the result. If it's @c NULL, a new
+ * quaternion will be allocated (and should be freed after usage).
  * @return The @p quat1 multiplied by @p quat2 on the right, or @c NULL
  * on error.
  *
- * @note It should be freed after usage.
- *
  * @ingroup EPhysics_Quaternion
  */
-EAPI EPhysics_Quaternion *ephysics_quaternion_multiply(const EPhysics_Quaternion *quat1, const EPhysics_Quaternion *quat2);
+EAPI EPhysics_Quaternion *ephysics_quaternion_multiply(const EPhysics_Quaternion *quat1, const EPhysics_Quaternion *quat2, EPhysics_Quaternion *result);
 
 /**
  * @brief
@@ -374,14 +384,14 @@ EAPI EPhysics_Quaternion *ephysics_quaternion_multiply(const EPhysics_Quaternion
  * @param ratio The ratio between @p quat1 and @p quat2 to interpolate. If
  * @p ratio = 0, the result is @p quat1, if @p ratio = 1, the result is
  * @p quat2.
+ * @param result Quaternion used to store the result. If it's @c NULL, a new
+ * quaternion will be allocated (and should be freed after usage).
  * @return The result of slerp between @p quat1 and @p quat2, or @c NULL
  * on error.
  *
- * @note It should be freed after usage.
- *
  * @ingroup EPhysics_Quaternion
  */
-EAPI EPhysics_Quaternion *ephysics_quaternion_slerp(const EPhysics_Quaternion *quat1, const EPhysics_Quaternion *quat2, double ratio);
+EAPI EPhysics_Quaternion *ephysics_quaternion_slerp(const EPhysics_Quaternion *quat1, const EPhysics_Quaternion *quat2, double ratio, EPhysics_Quaternion *result);
 
 /**
  * @brief
@@ -3738,18 +3748,19 @@ EAPI void ephysics_body_linear_movement_enable_get(const EPhysics_Body *body, Ei
  * @brief
  * Get body's rotation quaternion.
  *
- * By default rotation is 0 degree on all axes.
+ * By default rotation is 0 degree on all axes (1, 0, 0, 0).
  *
  * @param body The physics body.
- * @return A quaternion or @c NULL on error. It should be freed with free()
- * after usage.
+ * @param rotation Quaternion used to store the result. If it's @c NULL, a new
+ * quaternion will be allocated (and should be freed after usage).
+ * @return A quaternion or @c NULL on error.
  *
  * @see ephysics_body_rotation_set()
  * @see ephysics_quaternion_get()
  *
  * @ingroup EPhysics_Body
  */
-EAPI EPhysics_Quaternion *ephysics_body_rotation_get(const EPhysics_Body *body);
+EAPI EPhysics_Quaternion *ephysics_body_rotation_get(const EPhysics_Body *body, EPhysics_Quaternion *rotation);
 
 /**
  * @brief
index 2054e49..5ad3fdb 100644 (file)
@@ -3268,7 +3268,7 @@ ephysics_body_angular_movement_enable_get(const EPhysics_Body *body, Eina_Bool *
 }
 
 EAPI EPhysics_Quaternion *
-ephysics_body_rotation_get(const EPhysics_Body *body)
+ephysics_body_rotation_get(const EPhysics_Body *body, EPhysics_Quaternion *rotation)
 {
    EPhysics_Quaternion *quat;
    btTransform trans;
@@ -3279,11 +3279,20 @@ ephysics_body_rotation_get(const EPhysics_Body *body)
         return NULL;
      }
 
+   if (!rotation)
+     {
+        quat = ephysics_quaternion_new();
+        if (!quat) return NULL;
+     }
+   else
+     quat = rotation;
+
    trans = _ephysics_body_transform_get(body);
-   quat = ephysics_quaternion_new(trans.getRotation().x(),
-                                  trans.getRotation().y(),
-                                  trans.getRotation().z(),
-                                  trans.getRotation().getW());
+   quat->x = trans.getRotation().x();
+   quat->y = trans.getRotation().y();
+   quat->z = trans.getRotation().z();
+   quat->w = trans.getRotation().getW();
+
    return quat;
 }
 
index f008769..c5abcd0 100644 (file)
@@ -8,13 +8,6 @@
 extern "C" {
 #endif
 
-struct _EPhysics_Quaternion {
-     double x;
-     double y;
-     double z;
-     double w;
-};
-
 static void
 _ephysics_quaternion_update(EPhysics_Quaternion *quat, btQuaternion *bt_quat)
 {
@@ -24,8 +17,23 @@ _ephysics_quaternion_update(EPhysics_Quaternion *quat, btQuaternion *bt_quat)
    quat->w = bt_quat->getW();
 }
 
+static EPhysics_Quaternion *
+_ephysics_quaternion_params_check(const EPhysics_Quaternion *quat1, const EPhysics_Quaternion *quat2, EPhysics_Quaternion *result)
+{
+   if ((!quat1) || (!quat2))
+     {
+        ERR("Can't operate over null quaternions.");
+        return NULL;
+     }
+
+   if (result)
+     return result;
+
+   return ephysics_quaternion_new();
+}
+
 EAPI EPhysics_Quaternion *
-ephysics_quaternion_new(double x, double y, double z, double w)
+ephysics_quaternion_new(void)
 {
    EPhysics_Quaternion *quat;
 
@@ -37,11 +45,7 @@ ephysics_quaternion_new(double x, double y, double z, double w)
         return NULL;
      }
 
-   quat->x = x;
-   quat->y = y;
-   quat->z = z;
-   quat->w = w;
-
+   quat->w = 1;
    return quat;
 }
 
@@ -192,79 +196,71 @@ ephysics_quaternion_inverse_scale(EPhysics_Quaternion *quat, double scale)
 }
 
 EAPI EPhysics_Quaternion *
-ephysics_quaternion_sum(const EPhysics_Quaternion *quat1, const EPhysics_Quaternion *quat2)
+ephysics_quaternion_sum(const EPhysics_Quaternion *quat1, const EPhysics_Quaternion *quat2, EPhysics_Quaternion *result)
 {
    btQuaternion bt_quat1, bt_quat2, bt_quat;
+   EPhysics_Quaternion *quat;
 
-   if ((!quat1) || (!quat2))
-     {
-        ERR("Can't operate over null quaternions.");
-        return NULL;
-     }
+   quat = _ephysics_quaternion_params_check(quat1, quat2, result);
+   if (!quat) return NULL;
 
    bt_quat1 = btQuaternion(quat1->x, quat1->y, quat1->z, quat1->w);
    bt_quat2 = btQuaternion(quat2->x, quat2->y, quat2->z, quat2->w);
    bt_quat = bt_quat1 + bt_quat2;
 
-   return ephysics_quaternion_new(bt_quat.x(), bt_quat.y(), bt_quat.z(),
-                                  bt_quat.getW());
+   _ephysics_quaternion_update(quat, &bt_quat);
+   return quat;
 }
 
 EAPI EPhysics_Quaternion *
-ephysics_quaternion_diff(const EPhysics_Quaternion *quat1, const EPhysics_Quaternion *quat2)
+ephysics_quaternion_diff(const EPhysics_Quaternion *quat1, const EPhysics_Quaternion *quat2, EPhysics_Quaternion *result)
 {
    btQuaternion bt_quat1, bt_quat2, bt_quat;
+   EPhysics_Quaternion *quat;
 
-   if ((!quat1) || (!quat2))
-     {
-        ERR("Can't operate over null quaternions.");
-        return NULL;
-     }
+   quat = _ephysics_quaternion_params_check(quat1, quat2, result);
+   if (!quat) return NULL;
 
    bt_quat1 = btQuaternion(quat1->x, quat1->y, quat1->z, quat1->w);
    bt_quat2 = btQuaternion(quat2->x, quat2->y, quat2->z, quat2->w);
    bt_quat = bt_quat1 - bt_quat2;
 
-   return ephysics_quaternion_new(bt_quat.x(), bt_quat.y(), bt_quat.z(),
-                                  bt_quat.getW());
+   _ephysics_quaternion_update(quat, &bt_quat);
+   return quat;
 }
 
 EAPI EPhysics_Quaternion *
-ephysics_quaternion_multiply(const EPhysics_Quaternion *quat1, const EPhysics_Quaternion *quat2)
+ephysics_quaternion_multiply(const EPhysics_Quaternion *quat1, const EPhysics_Quaternion *quat2, EPhysics_Quaternion *result)
 {
    btQuaternion bt_quat1, bt_quat2, bt_quat;
+   EPhysics_Quaternion *quat;
 
-   if ((!quat1) || (!quat2))
-     {
-        ERR("Can't operate over null quaternions.");
-        return NULL;
-     }
+   quat = _ephysics_quaternion_params_check(quat1, quat2, result);
+   if (!quat) return NULL;
 
    bt_quat1 = btQuaternion(quat1->x, quat1->y, quat1->z, quat1->w);
    bt_quat2 = btQuaternion(quat2->x, quat2->y, quat2->z, quat2->w);
    bt_quat = bt_quat1 * bt_quat2;
 
-   return ephysics_quaternion_new(bt_quat.x(), bt_quat.y(), bt_quat.z(),
-                                  bt_quat.getW());
+   _ephysics_quaternion_update(quat, &bt_quat);
+   return quat;
 }
 
 EAPI EPhysics_Quaternion *
-ephysics_quaternion_slerp(const EPhysics_Quaternion *quat1, const EPhysics_Quaternion *quat2, double ratio)
+ephysics_quaternion_slerp(const EPhysics_Quaternion *quat1, const EPhysics_Quaternion *quat2, double ratio, EPhysics_Quaternion *result)
 {
    btQuaternion bt_quat1, bt_quat2;
+   EPhysics_Quaternion *quat;
 
-   if ((!quat1) || (!quat2))
-     {
-        ERR("Can't operate over null quaternions.");
-        return NULL;
-     }
+   quat = _ephysics_quaternion_params_check(quat1, quat2, result);
+   if (!quat) return NULL;
 
    bt_quat1 = btQuaternion(quat1->x, quat1->y, quat1->z, quat1->w);
    bt_quat2 = btQuaternion(quat2->x, quat2->y, quat2->z, quat2->w);
    bt_quat1.slerp(bt_quat2, ratio);
 
-   return ephysics_quaternion_new(bt_quat1.x(), bt_quat1.y(), bt_quat1.z(),
-                                  bt_quat1.getW());
+   _ephysics_quaternion_update(quat, &bt_quat1);
+   return quat;
 }
 
 EAPI double