aboutsummaryrefslogtreecommitdiffstats
path: root/legacy/ephysics/src/lib
diff options
context:
space:
mode:
authorBruno Dilly <bdilly@profusion.mobi>2012-11-13 22:18:16 +0000
committerBruno Dilly <bdilly@profusion.mobi>2012-11-13 22:18:16 +0000
commiteab0f812905fd16c7012827ffebc28d55d4adb00 (patch)
tree481935f63534a9c6565981d3f8e8a7d5a9e83e08 /legacy/ephysics/src/lib
parentcbf0049a643860c0662d0e044219e53f44225b2b (diff)
downloadefl-eab0f812905fd16c7012827ffebc28d55d4adb00.tar.gz
efl-eab0f812905fd16c7012827ffebc28d55d4adb00.tar.xz
efl-eab0f812905fd16c7012827ffebc28d55d4adb00.zip
ephysics: wrap bullet's quaternion
Useful for 3d rotations. Avoid issues found when using euler angles, like gimbal locks. SVN revision: 79252
Diffstat (limited to 'legacy/ephysics/src/lib')
-rw-r--r--legacy/ephysics/src/lib/EPhysics.h356
-rw-r--r--legacy/ephysics/src/lib/Makefile.am1
-rw-r--r--legacy/ephysics/src/lib/ephysics_body.cpp61
-rw-r--r--legacy/ephysics/src/lib/ephysics_quaternion.cpp336
4 files changed, 683 insertions, 71 deletions
diff --git a/legacy/ephysics/src/lib/EPhysics.h b/legacy/ephysics/src/lib/EPhysics.h
index a4409a34d..df2b3da0d 100644
--- a/legacy/ephysics/src/lib/EPhysics.h
+++ b/legacy/ephysics/src/lib/EPhysics.h
@@ -120,6 +120,319 @@ EAPI int ephysics_shutdown(void);
*/
/**
+ * @defgroup EPhysics_Quaternion EPhysics Quaternion
+ * @ingroup EPhysics
+ *
+ * @{
+ *
+ * Quaternions are used to perform linear algebra rotations.
+ *
+ * Functions regarding rotation, like @ref ephysics_body_rotation_set()
+ * and @ref ephysics_body_rotation_get() would need that. Quaternions
+ * can be used to rotate evas maps as well, with evas_map_util_quat_rotate(),
+ * but in this case quaternion values need to be get with
+ * @ref ephysics_quaternion_get(), since evas don't accept
+ * EPhysics_Quaternion type.
+ *
+ * A quaternion can be created with ephysics_quaternion_new(), and many
+ * operations can be performed with that, as:
+ * @li Sum: @ref ephysics_quaternion_sum()
+ * @li Difference: @ref ephysics_quaternion_diff()
+ * @li Multiple by another quaternion: @ref ephysics_quaternion_multiply()
+ * @li Multiply by scalar: @ref ephysics_quaternion_scale()
+ * @li Divide by scalar: @ref ephysics_quaternion_inverse_scale()
+ * @li Calculate length: @ref ephysics_quaternion_length_get()
+ * @li Calculate angle between quaternions: @ref ephysics_quaternion_angle_get()
+ */
+
+/**
+ * @typedef EPhysics_Quaternion
+ *
+ * Quaternion handle, represents a quaternion to be used to rotate bodies.
+ *
+ * Created with @ref ephysics_quaternion_new() and deleted with free().
+ *
+ * @ingroup EPhysics_Quaternion
+ */
+typedef struct _EPhysics_Quaternion EPhysics_Quaternion;
+
+/**
+ * @brief
+ * Create a new quaternion.
+ *
+ * @note It should be deleted with free() after usage is concluded.
+ *
+ * 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.
+ *
+ * @see ephysics_quaternion_set();
+ * @see ephysics_quaternion_axis_angle_set();
+ * @see ephysics_quaternion_euler_set();
+ * @see ephysics_quaternion_scale();
+ * @see ephysics_quaternion_sum();
+ *
+ * @ingroup EPhysics_Quaternion
+ */
+EAPI EPhysics_Quaternion *ephysics_quaternion_new(double x, double y, double z, double w);
+
+/**
+ * @brief
+ * Get quaternion values.
+ *
+ * @param quat Quaternion to get values from.
+ * @param x The x coordinate.
+ * @param y The y coordinate.
+ * @param z The z coordinate.
+ * @param w The rotation.
+ *
+ * @see ephysics_quaternion_set();
+ *
+ * @ingroup EPhysics_Quaternion
+ */
+EAPI void ephysics_quaternion_get(const EPhysics_Quaternion *quat, double *x, double *y, double *z, double *w);
+
+/**
+ * @brief
+ * Get quaternion axis and angle.
+ *
+ * @param quat Quaternion to get values from.
+ * @param nx The x component of the axis of rotation.
+ * @param ny The y component of the axis of rotation.
+ * @param nz The z component of the axis of rotation.
+ * @param a The angle of rotation.
+ *
+ * @see ephysics_quaternion_axis_angle_set();
+ * @see ephysics_quaternion_get();
+ * @see ephysics_quaternion_set();
+ *
+ * @ingroup EPhysics_Quaternion
+ */
+EAPI void ephysics_quaternion_axis_angle_get(const EPhysics_Quaternion *quat, double *nx, double *ny, double *nz, double *a);
+
+/**
+ * @brief
+ * Set quaternion values.
+ *
+ * @param quat Quaternion to be set.
+ * @param x The x coordinate.
+ * @param y The y coordinate.
+ * @param z The z coordinate.
+ * @param w The rotation.
+ *
+ * @see ephysics_quaternion_get();
+ * @see ephysics_quaternion_euler_set();
+ *
+ * @ingroup EPhysics_Quaternion
+ */
+EAPI void ephysics_quaternion_set(EPhysics_Quaternion *quat, double x, double y, double z, double w);
+
+/**
+ * @brief
+ * Set quaternion using axis angle notation.
+ *
+ * [w, x, y, z] = [cos(a/2), sin(a/2) * nx, sin(a/2)* ny, sin(a/2) * nz]
+ *
+ * @param quat Quaternion to be set.
+ * @param nx The x component of the axis of rotation.
+ * @param ny The y component of the axis of rotation.
+ * @param nz The z component of the axis of rotation.
+ * @param a The angle of rotation.
+ *
+ * @see ephysics_quaternion_axis_angle_get();
+ * @see ephysics_quaternion_set();
+ * @see ephysics_quaternion_euler_set();
+ *
+ * @ingroup EPhysics_Quaternion
+ */
+EAPI void ephysics_quaternion_axis_angle_set(EPhysics_Quaternion *quat, double nx, double ny, double nz, double a);
+
+/**
+ * @brief
+ * Set quaternion using Euler angles.
+ *
+ * It's an alternative to @ref ephysics_quaternion_set() usage. Euler angles
+ * will be converted.
+ *
+ * @param quat Quaternion to be set.
+ * @param yaw The angle around Y axis.
+ * @param pitch The angle around X axis.
+ * @param roll The angle around Z axis.
+ *
+ * @see ephysics_quaternion_get();
+ * @see ephysics_quaternion_set();
+ *
+ * @ingroup EPhysics_Quaternion
+ */
+EAPI void ephysics_quaternion_euler_set(EPhysics_Quaternion *quat, double yaw, double pitch, double roll);
+
+/**
+ * @brief
+ * Normalize the quaternion.
+ *
+ * A normalized quaternion is such that x^2 + y^2 + z^2 + w^2 = 1.
+ *
+ * @param quat Quaternion to be normalized.
+ *
+ * @ingroup EPhysics_Quaternion
+ */
+EAPI void ephysics_quaternion_normalize(EPhysics_Quaternion *quat);
+
+/**
+ * @brief
+ * Invert the quaternion.
+ *
+ * @param quat Quaternion to be inverted.
+ *
+ * @ingroup EPhysics_Quaternion
+ */
+EAPI void ephysics_quaternion_invert(EPhysics_Quaternion *quat);
+
+/**
+ * @brief
+ * Scale the quaternion.
+ *
+ * @param quat Quaternion to be scaled.
+ * @param scale The scale factor.
+ *
+ * @see ephysics_quaternion_inverse_scale()
+ *
+ * @ingroup EPhysics_Quaternion
+ */
+EAPI void ephysics_quaternion_scale(EPhysics_Quaternion *quat, double scale);
+
+/**
+ * @brief
+ * Inversely scale the quaternion.
+ *
+ * @param quat Quaternion to be scaled.
+ * @param scale The scale factor.
+ *
+ * @see ephysics_quaternion_scale()
+ *
+ * @ingroup EPhysics_Quaternion
+ */
+EAPI void ephysics_quaternion_inverse_scale(EPhysics_Quaternion *quat, double scale);
+
+/**
+ * @brief
+ * Returns a sum of two quaternions.
+ *
+ * @param quat1 First quaternion to sum.
+ * @param quat2 Second quaternion to sum.
+ * @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);
+
+/**
+ * @brief
+ * Returns a difference between two quaternions.
+ *
+ * @param quat1 First quaternion.
+ * @param quat2 Second quaternion.
+ * @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);
+
+/**
+ * @brief
+ * Multiply two quaternions.
+ *
+ * @param quat1 First quaternion.
+ * @param quat2 Second quaternion.
+ * @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);
+
+/**
+ * @brief
+ * Return the quaternion which is the result of Spherical Linear Interpolation
+ * between two quaternions.
+ *
+ * Slerp interpolates assuming constant velocity.
+ *
+ * @param quat1 First quaternion.
+ * @param quat2 Second 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.
+ * @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);
+
+/**
+ * @brief
+ * Return the dot product between two quaternions.
+ *
+ * @param quat1 First quaternion.
+ * @param quat2 Second quaternion.
+ * @return The dot product between @p quat1 and @p quat2 or @c 0 on error.
+ *
+ * @ingroup EPhysics_Quaternion
+ */
+EAPI double ephysics_quaternion_dot(const EPhysics_Quaternion *quat1, const EPhysics_Quaternion *quat2);
+
+/**
+ * @brief
+ * Return the angle between two quaternions.
+ *
+ * @param quat1 First quaternion.
+ * @param quat2 Second quaternion.
+ * @return The angle between @p quat1 and @p quat2 or @c 0 on error.
+ *
+ * @ingroup EPhysics_Quaternion
+ */
+EAPI double ephysics_quaternion_angle_get(const EPhysics_Quaternion *quat1, const EPhysics_Quaternion *quat2);
+
+/**
+ * @brief
+ * Return the length of the quaternion.
+ *
+ * @param quat Quaternion to get length of.
+ * @return The lenght of @p quat or @c 0 on error.
+ *
+ * @ingroup EPhysics_Quaternion
+ */
+EAPI double ephysics_quaternion_length_get(const EPhysics_Quaternion *quat);
+
+/**
+ * @brief
+ * Return the length squared of the quaternion.
+ *
+ * @param quat Quaternion to get length of.
+ * @return The lenght of @p quat or @c 0 on error.
+ *
+ * @ingroup EPhysics_Quaternion
+ */
+EAPI double ephysics_quaternion_length2_get(const EPhysics_Quaternion *quat);
+
+/**
+ * @}
+ */
+
+/**
* @defgroup EPhysics_Shape EPhysics Shape
* @ingroup EPhysics
*
@@ -3422,61 +3735,36 @@ EAPI void ephysics_body_linear_movement_enable_get(const EPhysics_Body *body, Ei
/**
* @brief
- * Get body's rotation on x, y and z axes.
+ * Get body's rotation quaternion.
*
* By default rotation is 0 degree on all axes.
*
- * @note The unit used for rotation is degrees.
- *
* @param body The physics body.
- * @param rot_x The amount of degrees @p body is rotated on x axis.
- * @param rot_y The amount of degrees @p body is rotated on y axis.
- * @param rot_z The amount of degrees @p body is rotated on z axis.
+ * @return A quaternion or @c NULL on error. It should be freed with free()
+ * after usage.
*
* @see ephysics_body_rotation_set()
- * @see ephysics_body_rotation_quaternion_get()
+ * @see ephysics_quaternion_get()
*
* @ingroup EPhysics_Body
*/
-EAPI void ephysics_body_rotation_get(const EPhysics_Body *body, double *rot_x, double *rot_y, double *rot_z);
+EAPI EPhysics_Quaternion *ephysics_body_rotation_get(const EPhysics_Body *body);
/**
* @brief
- * Set body's rotation on z axis.
+ * Set body's rotation.
*
* By default rotation is 0 degrees on all axes.
- * Negative values indicates rotation on counter clockwise direction.
- *
- * @note The unit used for rotation is degrees.
*
* @param body The physics body.
- * @param rot_x The amount of degrees @p body should be rotated on x axis.
- * @param rot_y The amount of degrees @p body should be rotated on y axis.
- * @param rot_z The amount of degrees @p body should be rotated on z axis.
+ * @param quat Quaternion representing the rotation.
*
* @see ephysics_body_rotation_get()
+ * @see ephysics_quaternion_new()
*
* @ingroup EPhysics_Body
*/
-EAPI void ephysics_body_rotation_set(EPhysics_Body *body, double rot_x, double rot_y, double rot_z);
-
-/**
- * @brief
- * Get body's normalized rotation quaternion (x, y, z and w).
- *
- * @param body The physics body.
- * @param x the x component of the imaginary part of the quaternion.
- * @param y the y component of the imaginary part of the quaternion.
- * @param z the z component of the imaginary part of the quaternion.
- * @param w the w component of the real part of the quaternion.
- *
- * @see ephysics_body_rotation_set()
- * @see ephysics_body_rotation_get()
- *
- * @ingroup EPhysics_Body
- */
-EAPI void
-ephysics_body_rotation_quaternion_get(const EPhysics_Body *body, double *x, double *y, double *z, double *w);
+EAPI void ephysics_body_rotation_set(EPhysics_Body *body, EPhysics_Quaternion *quat);
/**
* @brief
diff --git a/legacy/ephysics/src/lib/Makefile.am b/legacy/ephysics/src/lib/Makefile.am
index c91e5fb78..071b6fbc9 100644
--- a/legacy/ephysics/src/lib/Makefile.am
+++ b/legacy/ephysics/src/lib/Makefile.am
@@ -18,6 +18,7 @@ base_sources = \
ephysics_camera.cpp \
ephysics_constraints.cpp \
ephysics_main.cpp \
+ ephysics_quaternion.cpp \
ephysics_shape.cpp \
ephysics_world.cpp
diff --git a/legacy/ephysics/src/lib/ephysics_body.cpp b/legacy/ephysics/src/lib/ephysics_body.cpp
index 472ce8009..2054e4952 100644
--- a/legacy/ephysics/src/lib/ephysics_body.cpp
+++ b/legacy/ephysics/src/lib/ephysics_body.cpp
@@ -21,6 +21,7 @@ typedef struct _EPhysics_Body_Callback EPhysics_Body_Callback;
typedef struct _EPhysics_Body_Evas_Stacking EPhysics_Body_Evas_Stacking;
typedef struct _EPhysics_Body_Soft_Body_Slice EPhysics_Body_Soft_Body_Slice;
typedef struct _EPhysics_Body_Face_Obj EPhysics_Body_Face_Obj;
+typedef struct _EPhysics_Quaternion EPhysics_Quaternion;
struct _EPhysics_Body_Callback {
EINA_INLIST;
@@ -3266,31 +3267,32 @@ ephysics_body_angular_movement_enable_get(const EPhysics_Body *body, Eina_Bool *
if (enable_z) *enable_z = !!body->rigid_body->getAngularFactor().z();
}
-EAPI void
-ephysics_body_rotation_get(const EPhysics_Body *body, double *rot_x, double *rot_y, double *rot_z)
+EAPI EPhysics_Quaternion *
+ephysics_body_rotation_get(const EPhysics_Body *body)
{
- btScalar yaw, pitch, roll;
+ EPhysics_Quaternion *quat;
btTransform trans;
if (!body)
{
ERR("Can't get rotation, body is null.");
- return;
+ return NULL;
}
trans = _ephysics_body_transform_get(body);
-
- trans.getBasis().getEulerYPR(yaw, pitch, roll);
- if (rot_x) *rot_x = -roll * RAD_TO_DEG;
- if (rot_y) *rot_y = -pitch * RAD_TO_DEG;
- if (rot_z) *rot_z = -yaw * RAD_TO_DEG;
+ quat = ephysics_quaternion_new(trans.getRotation().x(),
+ trans.getRotation().y(),
+ trans.getRotation().z(),
+ trans.getRotation().getW());
+ return quat;
}
EAPI void
-ephysics_body_rotation_set(EPhysics_Body *body, double rot_x, double rot_y, double rot_z)
+ephysics_body_rotation_set(EPhysics_Body *body, EPhysics_Quaternion *quat)
{
+ btQuaternion bt_quat;
btTransform trans;
- btQuaternion quat;
+ double x, y, z, w;
if (!body)
{
@@ -3298,48 +3300,33 @@ ephysics_body_rotation_set(EPhysics_Body *body, double rot_x, double rot_y, doub
return;
}
+ if (!quat)
+ {
+ ERR("Can't set rotation, quaternion is null.");
+ return;
+ }
+
+ ephysics_quaternion_get(quat, &x, &y, &z, &w);
+
ephysics_world_lock_take(body->world);
ephysics_body_activate(body, EINA_TRUE);
- quat.setEuler(-rot_y / RAD_TO_DEG, -rot_x / RAD_TO_DEG, -rot_z / RAD_TO_DEG);
+ bt_quat = btQuaternion(x, y, z, w);
if (body->soft_body)
- body->soft_body->rotate(quat);
+ body->soft_body->rotate(bt_quat);
else
{
trans = _ephysics_body_transform_get(body);
- trans.setRotation(quat);
+ trans.setRotation(bt_quat);
body->rigid_body->proceedToTransform(trans);
body->rigid_body->getMotionState()->setWorldTransform(trans);
}
- DBG("Body %p rotation set to (%lf, %lf, %lf)", body, rot_x, rot_y, rot_z);
ephysics_world_lock_release(body->world);
}
EAPI void
-ephysics_body_rotation_quaternion_get(const EPhysics_Body *body, double *x, double *y, double *z, double *w)
-{
- btTransform trans;
- btQuaternion quat;
-
- if (!body)
- {
- ERR("Can't get rotation, body is null.");
- return;
- }
-
- trans = _ephysics_body_transform_get(body);
- quat = trans.getRotation();
- quat.normalize();
-
- if (x) *x = quat.x();
- if (y) *y = quat.y();
- if (z) *z = quat.z();
- if (w) *w = -quat.w();
-}
-
-EAPI void
ephysics_body_data_set(EPhysics_Body *body, void *data)
{
if (!body)
diff --git a/legacy/ephysics/src/lib/ephysics_quaternion.cpp b/legacy/ephysics/src/lib/ephysics_quaternion.cpp
new file mode 100644
index 000000000..f00876983
--- /dev/null
+++ b/legacy/ephysics/src/lib/ephysics_quaternion.cpp
@@ -0,0 +1,336 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "ephysics_private.h"
+
+#ifdef __cplusplus
+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)
+{
+ quat->x = bt_quat->x();
+ quat->y = bt_quat->y();
+ quat->z = bt_quat->z();
+ quat->w = bt_quat->getW();
+}
+
+EAPI EPhysics_Quaternion *
+ephysics_quaternion_new(double x, double y, double z, double w)
+{
+ EPhysics_Quaternion *quat;
+
+ quat = (EPhysics_Quaternion *)calloc(1, sizeof(EPhysics_Quaternion));
+
+ if (!quat)
+ {
+ ERR("Could not allocate ephysics quaternion.");
+ return NULL;
+ }
+
+ quat->x = x;
+ quat->y = y;
+ quat->z = z;
+ quat->w = w;
+
+ return quat;
+}
+
+EAPI void
+ephysics_quaternion_get(const EPhysics_Quaternion *quat, double *x, double *y, double *z, double *w)
+{
+ if (!quat)
+ {
+ ERR("Can't get quaternion's values, it is null.");
+ return;
+ }
+
+ if (x) *x = quat->x;
+ if (y) *y = quat->y;
+ if (z) *z = quat->z;
+ if (w) *w = quat->w;
+}
+
+EAPI void
+ephysics_quaternion_axis_angle_get(const EPhysics_Quaternion *quat, double *nx, double *ny, double *nz, double *a)
+{
+ btQuaternion bt_quat;
+
+ if (!quat)
+ {
+ ERR("Can't get quaternion's values, it is null.");
+ return;
+ }
+
+ bt_quat = btQuaternion(quat->x, quat->y, quat->z, quat->w);
+
+ if (nx) *nx = bt_quat.getAxis().getX();
+ if (ny) *ny = bt_quat.getAxis().getY();
+ if (nz) *nz = bt_quat.getAxis().getZ();
+ if (a) *a = bt_quat.getAngle();
+}
+
+EAPI void
+ephysics_quaternion_set(EPhysics_Quaternion *quat, double x, double y, double z, double w)
+{
+ if (!quat)
+ {
+ ERR("Could not set a null quaternion.");
+ return;
+ }
+
+ quat->x = x;
+ quat->y = y;
+ quat->z = z;
+ quat->w = w;
+}
+
+EAPI void
+ephysics_quaternion_axis_angle_set(EPhysics_Quaternion *quat, double nx, double ny, double nz, double a)
+{
+ btQuaternion bt_quat;
+ btVector3 axis;
+
+ if (!quat)
+ {
+ ERR("Could not set a null quaternion.");
+ return;
+ }
+
+ axis = btVector3(nx, ny, nz);
+ bt_quat = btQuaternion(axis, a);
+ _ephysics_quaternion_update(quat, &bt_quat);
+}
+
+EAPI void
+ephysics_quaternion_euler_set(EPhysics_Quaternion *quat, double yaw, double pitch, double roll)
+{
+ btQuaternion bt_quat;
+
+ if (!quat)
+ {
+ ERR("Could not set a null quaternion.");
+ return;
+ }
+
+ bt_quat = btQuaternion();
+ bt_quat.setEuler(yaw, pitch, roll);
+ _ephysics_quaternion_update(quat, &bt_quat);
+}
+
+EAPI void
+ephysics_quaternion_normalize(EPhysics_Quaternion *quat)
+{
+ btQuaternion bt_quat;
+
+ if (!quat)
+ {
+ ERR("Can't normalize a null quaternion.");
+ return;
+ }
+
+ bt_quat = btQuaternion(quat->x, quat->y, quat->z, quat->w);
+ bt_quat.normalize();
+ _ephysics_quaternion_update(quat, &bt_quat);
+}
+
+EAPI void
+ephysics_quaternion_invert(EPhysics_Quaternion *quat)
+{
+ btQuaternion bt_quat;
+
+ if (!quat)
+ {
+ ERR("Can't normalize a null quaternion.");
+ return;
+ }
+
+ bt_quat = btQuaternion(quat->x, quat->y, quat->z, quat->w);
+ bt_quat.inverse();
+ _ephysics_quaternion_update(quat, &bt_quat);
+}
+
+EAPI void
+ephysics_quaternion_scale(EPhysics_Quaternion *quat, double scale)
+{
+ btQuaternion bt_quat;
+
+ if (!quat)
+ {
+ ERR("Can't operate over a null quaternion.");
+ return;
+ }
+
+ bt_quat = btQuaternion(quat->x, quat->y, quat->z, quat->w);
+ bt_quat *= scale;
+ _ephysics_quaternion_update(quat, &bt_quat);
+}
+
+EAPI void
+ephysics_quaternion_inverse_scale(EPhysics_Quaternion *quat, double scale)
+{
+ btQuaternion bt_quat;
+
+ if (!quat)
+ {
+ ERR("Can't operate over a null quaternion.");
+ return;
+ }
+
+ bt_quat = btQuaternion(quat->x, quat->y, quat->z, quat->w);
+ bt_quat /= scale;
+ _ephysics_quaternion_update(quat, &bt_quat);
+}
+
+EAPI EPhysics_Quaternion *
+ephysics_quaternion_sum(const EPhysics_Quaternion *quat1, const EPhysics_Quaternion *quat2)
+{
+ btQuaternion bt_quat1, bt_quat2, bt_quat;
+
+ if ((!quat1) || (!quat2))
+ {
+ ERR("Can't operate over null quaternions.");
+ 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());
+}
+
+EAPI EPhysics_Quaternion *
+ephysics_quaternion_diff(const EPhysics_Quaternion *quat1, const EPhysics_Quaternion *quat2)
+{
+ btQuaternion bt_quat1, bt_quat2, bt_quat;
+
+ if ((!quat1) || (!quat2))
+ {
+ ERR("Can't operate over null quaternions.");
+ 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());
+}
+
+EAPI EPhysics_Quaternion *
+ephysics_quaternion_multiply(const EPhysics_Quaternion *quat1, const EPhysics_Quaternion *quat2)
+{
+ btQuaternion bt_quat1, bt_quat2, bt_quat;
+
+ if ((!quat1) || (!quat2))
+ {
+ ERR("Can't operate over null quaternions.");
+ 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());
+}
+
+EAPI EPhysics_Quaternion *
+ephysics_quaternion_slerp(const EPhysics_Quaternion *quat1, const EPhysics_Quaternion *quat2, double ratio)
+{
+ btQuaternion bt_quat1, bt_quat2;
+
+ if ((!quat1) || (!quat2))
+ {
+ ERR("Can't operate over null quaternions.");
+ 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());
+}
+
+EAPI double
+ephysics_quaternion_dot(const EPhysics_Quaternion *quat1, const EPhysics_Quaternion *quat2)
+{
+ btQuaternion bt_quat1, bt_quat2;
+
+ if ((!quat1) || (!quat2))
+ {
+ ERR("Can't operate over null quaternions.");
+ return 0;
+ }
+
+ bt_quat1 = btQuaternion(quat1->x, quat1->y, quat1->z, quat1->w);
+ bt_quat2 = btQuaternion(quat2->x, quat2->y, quat2->z, quat2->w);
+
+ return bt_quat1.dot(bt_quat2);
+}
+
+EAPI double
+ephysics_quaternion_angle_get(const EPhysics_Quaternion *quat1, const EPhysics_Quaternion *quat2)
+{
+ btQuaternion bt_quat1, bt_quat2;
+
+ if ((!quat1) || (!quat2))
+ {
+ ERR("Can't operate over null quaternions.");
+ return 0;
+ }
+
+ bt_quat1 = btQuaternion(quat1->x, quat1->y, quat1->z, quat1->w);
+ bt_quat2 = btQuaternion(quat2->x, quat2->y, quat2->z, quat2->w);
+
+ return bt_quat1.angle(bt_quat2);
+}
+
+EAPI double
+ephysics_quaternion_length_get(const EPhysics_Quaternion *quat)
+{
+ btQuaternion bt_quat;
+
+ if (!quat)
+ {
+ ERR("Can't operate over a null quaternion.");
+ return 0;
+ }
+
+ bt_quat = btQuaternion(quat->x, quat->y, quat->z, quat->w);
+ return bt_quat.length();
+}
+
+EAPI double
+ephysics_quaternion_length2_get(const EPhysics_Quaternion *quat)
+{
+ btQuaternion bt_quat;
+
+ if (!quat)
+ {
+ ERR("Can't operate over a null quaternion.");
+ return 0;
+ }
+
+ bt_quat = btQuaternion(quat->x, quat->y, quat->z, quat->w);
+ return bt_quat.length2();
+}
+
+#ifdef __cplusplus
+}
+#endif