From bb2d088cb1c9c1341dc70c4b779bc6ccb57f10e2 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Thu, 20 May 2010 14:54:44 +0100 Subject: [PATCH] math: Adds an experimental cogl_vector3_* API This adds a math utility API for handling 3 component, single precision float vectors with the following; mostly self explanatory functions: cogl_vector3_init cogl_vector3_init_zero cogl_vector3_equal cogl_vector3_equal_with_epsilon cogl_vector3_copy cogl_vector3_free cogl_vector3_invert cogl_vector3_add cogl_vector3_subtract cogl_vector3_multiply_scalar cogl_vector3_divide_scalar cogl_vector3_normalize cogl_vector3_magnitude cogl_vector3_cross_product cogl_vector3_dot_product cogl_vector3_distance Since the API is experimental you will need to define COGL_ENABLE_EXPERIMENTAL_API before including cogl.h if you want to use the API. --- clutter/cogl/cogl/Makefile.am | 2 + clutter/cogl/cogl/cogl-vector.c | 284 +++++++++++++++++++++ clutter/cogl/cogl/cogl-vector.h | 367 +++++++++++++++++++++++++++ clutter/cogl/cogl/cogl.h | 2 + doc/reference/cogl/cogl-docs.xml.in | 1 + doc/reference/cogl/cogl-sections.txt | 20 ++ 6 files changed, 676 insertions(+) create mode 100644 clutter/cogl/cogl/cogl-vector.c create mode 100644 clutter/cogl/cogl/cogl-vector.h diff --git a/clutter/cogl/cogl/Makefile.am b/clutter/cogl/cogl/Makefile.am index 41ac43197..4a8f92fa6 100644 --- a/clutter/cogl/cogl/Makefile.am +++ b/clutter/cogl/cogl/Makefile.am @@ -59,6 +59,7 @@ cogl_public_h = \ $(srcdir)/cogl-debug.h \ $(srcdir)/cogl-fixed.h \ $(srcdir)/cogl-material.h \ + $(srcdir)/cogl-vector.h \ $(srcdir)/cogl-matrix.h \ $(srcdir)/cogl-offscreen.h \ $(srcdir)/cogl-primitives.h \ @@ -104,6 +105,7 @@ cogl_sources_c = \ $(srcdir)/cogl-vertex-buffer-private.h \ $(srcdir)/cogl-vertex-buffer.c \ $(srcdir)/cogl-matrix.c \ + $(srcdir)/cogl-vector.c \ $(srcdir)/cogl-matrix-private.h \ $(srcdir)/cogl-matrix-stack.c \ $(srcdir)/cogl-matrix-stack.h \ diff --git a/clutter/cogl/cogl/cogl-vector.c b/clutter/cogl/cogl/cogl-vector.c new file mode 100644 index 000000000..7436053ca --- /dev/null +++ b/clutter/cogl/cogl/cogl-vector.c @@ -0,0 +1,284 @@ +/* + * Cogl + * + * An object oriented GL/GLES Abstraction/Utility Layer + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Authors: + * Robert Bragg + */ + +#include +#include + +#include +#include +#include + +void +cogl_vector3_init (CoglVector3 *vector, float x, float y, float z) +{ + vector->x = x; + vector->y = y; + vector->z = z; +} + +void +cogl_vector3_init_zero (CoglVector3 *vector) +{ + memset (vector, 0, sizeof (CoglVector3)); +} + +gboolean +cogl_vector3_equal (gconstpointer v1, gconstpointer v2) +{ + CoglVector3 *vector0 = (CoglVector3 *)v1; + CoglVector3 *vector1 = (CoglVector3 *)v2; + + g_return_val_if_fail (v1 != NULL, FALSE); + g_return_val_if_fail (v2 != NULL, FALSE); + + /* There's no point picking an arbitrary epsilon that's appropriate + * for comparing the components so we just use == that will at least + * consider -0 and 0 to be equal. */ + return + vector0->x == vector1->x && + vector0->y == vector1->y && + vector0->z == vector1->z; +} + +gboolean +cogl_vector3_equal_with_epsilon (const CoglVector3 *vector0, + const CoglVector3 *vector1, + float epsilon) +{ + g_return_val_if_fail (vector0 != NULL, FALSE); + g_return_val_if_fail (vector1 != NULL, FALSE); + + if (fabsf (vector0->x - vector1->x) < epsilon && + fabsf (vector0->y - vector1->y) < epsilon && + fabsf (vector0->z - vector1->z) < epsilon) + return TRUE; + else + return FALSE; +} + +CoglVector3 * +cogl_vector3_copy (const CoglVector3 *vector) +{ + if (vector) + return g_slice_dup (CoglVector3, vector); + return NULL; +} + +void +cogl_vector3_free (CoglVector3 *vector) +{ + g_slice_free (CoglVector3, vector); +} + +void +cogl_vector3_invert (CoglVector3 *vector) +{ + vector->x = -vector->x; + vector->y = -vector->y; + vector->z = -vector->z; +} + +void +cogl_vector3_add (CoglVector3 *result, + const CoglVector3 *a, + const CoglVector3 *b) +{ + result->x = a->x + b->x; + result->y = a->y + b->y; + result->z = a->z + b->z; +} + +void +cogl_vector3_subtract (CoglVector3 *result, + const CoglVector3 *a, + const CoglVector3 *b) +{ + result->x = a->x - b->x; + result->y = a->y - b->y; + result->z = a->z - b->z; +} + +void +cogl_vector3_multiply_scalar (CoglVector3 *vector, + float scalar) +{ + vector->x *= scalar; + vector->y *= scalar; + vector->z *= scalar; +} + +void +cogl_vector3_divide_scalar (CoglVector3 *vector, + float scalar) +{ + float one_over_scalar = 1.0f / scalar; + vector->x *= one_over_scalar; + vector->y *= one_over_scalar; + vector->z *= one_over_scalar; +} + +void +cogl_vector3_normalize (CoglVector3 *vector) +{ + float mag_squared = + vector->x * vector->x + + vector->y * vector->y + + vector->z * vector->z; + + if (mag_squared > 0.0f) + { + float one_over_mag = 1.0f / sqrtf (mag_squared); + vector->x *= one_over_mag; + vector->y *= one_over_mag; + vector->z *= one_over_mag; + } +} + +float +cogl_vector3_magnitude (const CoglVector3 *vector) +{ + return sqrtf (vector->x * vector->x + + vector->y * vector->y + + vector->z * vector->z); +} + +void +cogl_vector3_cross_product (CoglVector3 *result, + const CoglVector3 *a, + const CoglVector3 *b) +{ + CoglVector3 tmp; + + tmp.x = a->y * b->z - a->z * b->y; + tmp.y = a->z * b->x - a->x * b->z; + tmp.z = a->x * b->y - a->y * b->x; + *result = tmp; +} + +float +cogl_vector3_dot_product (const CoglVector3 *a, const CoglVector3 *b) +{ + return a->x * b->x + a->y * b->y + a->z * b->z; +} + +float +cogl_vector3_distance (const CoglVector3 *a, const CoglVector3 *b) +{ + float dx = b->x - a->x; + float dy = b->y - a->y; + float dz = b->z - a->z; + + return sqrtf (dx * dx + dy * dy + dz * dz); +} + +#if 0 +void +cogl_vector4_init (CoglVector4 *vector, float x, float y, float z) +{ + vector->x = x; + vector->y = y; + vector->z = z; + vector->w = w; +} + +void +cogl_vector4_init_zero (CoglVector4 *vector) +{ + memset (vector, 0, sizeof (CoglVector4)); +} + +void +cogl_vector4_init_from_vector4 (CoglVector4 *vector, CoglVector4 *src) +{ + *vector4 = *src; +} + +gboolean +cogl_vector4_equal (gconstpointer *v0, gconstpointer *v1) +{ + g_return_val_if_fail (v1 != NULL, FALSE); + g_return_val_if_fail (v2 != NULL, FALSE); + + return memcmp (v1, v2, sizeof (float) * 4) == 0 ? TRUE : FALSE; +} + +CoglVector4 * +cogl_vector4_copy (CoglVector4 *vector) +{ + if (vector) + return g_slice_dup (CoglVector4, vector); + return NULL; +} + +void +cogl_vector4_free (CoglVector4 *vector) +{ + g_slice_free (CoglVector4, vector); +} + +void +cogl_vector4_invert (CoglVector4 *vector) +{ + vector.x = -vector.x; + vector.y = -vector.y; + vector.z = -vector.z; + vector.w = -vector.w; +} + +void +cogl_vector4_add (CoglVector4 *result, + CoglVector4 *a, + CoglVector4 *b) +{ + result.x = a.x + b.x; + result.y = a.y + b.y; + result.z = a.z + b.z; + result.w = a.w + b.w; +} + +void +cogl_vector4_subtract (CoglVector4 *result, + CoglVector4 *a, + CoglVector4 *b) +{ + result.x = a.x - b.x; + result.y = a.y - b.y; + result.z = a.z - b.z; + result.w = a.w - b.w; +} + +void +cogl_vector4_divide (CoglVector4 *vector, + float scalar) +{ + float one_over_scalar = 1.0f / scalar; + result.x *= one_over_scalar; + result.y *= one_over_scalar; + result.z *= one_over_scalar; + result.w *= one_over_scalar; +} + +#endif diff --git a/clutter/cogl/cogl/cogl-vector.h b/clutter/cogl/cogl/cogl-vector.h new file mode 100644 index 000000000..dfc5dfb5b --- /dev/null +++ b/clutter/cogl/cogl/cogl-vector.h @@ -0,0 +1,367 @@ +/* + * Cogl + * + * An object oriented GL/GLES Abstraction/Utility Layer + * + * Copyright (C) 2008,2009,2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Authors: + * Robert Bragg + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_VECTOR_H +#define __COGL_VECTOR_H + +#include + +G_BEGIN_DECLS + +/** + * SECTION:cogl-vector + * @short_description: Functions for handling single precision float + * vectors. + * + * This exposes a utility API that can be used for basic manipulation of 3 + * component float vectors. + */ + +typedef struct +{ + /* FIXME: add sse alignment constraint? */ + float x; + float y; + float z; +} CoglVector3; + +#if 0 +typedef struct +{ + /* FIXME: add sse alignment constraint? */ + float x; + float y; + float z; + float w; +} CoglVector4; +#endif + +/** + * cogl_vector3_init: + * @vector: The CoglVector3 you want to initialize + * @x: The x component + * @y: The y component + * @z: The z component + * + * Initializes a 3 component, single precision float vector which can + * then be manipulated with the cogl_vector convenience APIs. Vectors + * can also be used in places where a "point" is often desired. + * + * Since: 1.4 + * Stability: Unstable + */ +void +cogl_vector3_init (CoglVector3 *vector, float x, float y, float z); + +/** + * cogl_vector3_init_zero: + * @vector: The CoglVector3 you want to initialize + * + * Initializes a 3 component, single precision float vector with zero + * for each component. + * + * Since: 1.4 + * Stability: Unstable + */ +void +cogl_vector3_init_zero (CoglVector3 *vector); + +/** + * cogl_vector3_equal: + * @v1: The first CoglVector3 you want to compare + * @v2: The second CoglVector3 you want to compare + * + * Compares the components of two vectors and returns TRUE if they are + * the same. + * + * The comparison of the components is done with the '==' operator + * such that -0 is considered equal to 0, but otherwise there is no + * fuzziness such as an epsilon to consider vectors that are + * essentially identical except for some minor precision error + * differences due to the way they have been manipulated. + * + * Returns: TRUE if the vectors are equal else FALSE. + * + * Since: 1.4 + * Stability: Unstable + */ +gboolean +cogl_vector3_equal (gconstpointer v1, gconstpointer v2); + +/** + * cogl_vector3_equal_with_epsilon: + * @vector0: The first CoglVector3 you want to compare + * @vector1: The second CoglVector3 you want to compare + * @epsilon: The allowable difference between components to still be + * considered equal + * + * Compares the components of two vectors using the given epsilon and + * returns TRUE if they are the same, using an internal epsilon for + * comparing the floats. + * + * Each component is compared against the epsilon value in this way: + * |[ + * if (fabsf (vector0->x - vector1->x) < epsilon) + * ]| + * + * Returns: TRUE if the vectors are equal else FALSE. + * + * Since: 1.4 + * Stability: Unstable + */ +gboolean +cogl_vector3_equal_with_epsilon (const CoglVector3 *vector0, + const CoglVector3 *vector1, + float epsilon); + +/** + * cogl_vector3_copy: + * @vector: The CoglVector3 you want to copy + * + * Allocates a new #CoglVector3 structure on the heap initializing the + * components from the given @vector and returns a pointer to the newly + * allocated vector. You should free the memory using + * cogl_vector3_free() + * + * Returns: A newly allocated #CoglVector3. + * + * Since: 1.4 + * Stability: Unstable + */ +CoglVector3 * +cogl_vector3_copy (const CoglVector3 *vector); + +/** + * cogl_vector3_free: + * @vector: The CoglVector3 you want to free + * + * Frees a #CoglVector3 that was previously allocated with + * cogl_vector_copy() + * + * Since: 1.4 + * Stability: Unstable + */ +void +cogl_vector3_free (CoglVector3 *vector); + +/** + * cogl_vector3_invert: + * @vector: The CoglVector3 you want to manipulate + * + * Inverts/negates all the components of the given @vector. + * + * Since: 1.4 + * Stability: Unstable + */ +void +cogl_vector3_invert (CoglVector3 *vector); + +/** + * cogl_vector3_add: + * @result: Where you want the result written + * @a: The first vector operand + * @b: The second vector operand + * + * Adds each of the corresponding components in vectors @a and @b + * storing the results in @result. + * + * Since: 1.4 + * Stability: Unstable + */ +void +cogl_vector3_add (CoglVector3 *result, + const CoglVector3 *a, + const CoglVector3 *b); + +/** + * cogl_vector3_subtract: + * @result: Where you want the result written + * @a: The first vector operand + * @b: The second vector operand + * + * Subtracts each of the corresponding components in vector @b from + * @a storing the results in @result. + * + * Since: 1.4 + * Stability: Unstable + */ +void +cogl_vector3_subtract (CoglVector3 *result, + const CoglVector3 *a, + const CoglVector3 *b); + +/** + * cogl_vector3_multiply_scalar: + * @vector: The CoglVector3 you want to manipulate + * @scalar: The scalar you want to multiply the vector components by + * + * Multiplies each of the @vector components by the given scalar. + * + * Since: 1.4 + * Stability: Unstable + */ +void +cogl_vector3_multiply_scalar (CoglVector3 *vector, + float scalar); + +/** + * cogl_vector3_divide_scalar: + * @vector: The CoglVector3 you want to manipulate + * @scalar: The scalar you want to divide the vector components by + * + * Divides each of the @vector components by the given scalar. + * + * Since: 1.4 + * Stability: Unstable + */ +void +cogl_vector3_divide_scalar (CoglVector3 *vector, + float scalar); + +/** + * cogl_vector3_normalize: + * @vector: The CoglVector3 you want to manipulate + * + * Updates the vector so it is a "unit vector" such that the + * @vectors magnitude or length is equal to 1. + * + * Since: 1.4 + * Stability: Unstable + */ +void +cogl_vector3_normalize (CoglVector3 *vector); + +/** + * cogl_vector3_magnitude: + * @vector: The CoglVector3 you want the magnitude for + * + * Calculates the scalar magnitude or length of @vector. + * + * Returns: The magnitude of @vector. + * + * Since: 1.4 + * Stability: Unstable + */ +float +cogl_vector3_magnitude (const CoglVector3 *vector); + +/** + * cogl_vector3_cross_product: + * @result: Where you want the result written + * @u: Your first CoglVector3 + * @v: Your second CoglVector3 + * + * Calculates the cross product between the two vectors @u and @v. + * + * The cross product is a vector perpendicular to both @u and @v. This + * can be useful for calculating the normal of a polygon by creating + * two vectors in its plane using the polygons vertices and taking + * their cross product. + * + * If the two vectors are parallel then the cross product is 0. + * + * You can use a right hand rule to determine which direction the + * perpendicular vector will point: If you place the two vectors tail, + * to tail and imagine grabbing the perpendicular line that extends + * through the common tail with your right hand such that you fingers + * rotate in the direction from @u to @v then the resulting vector + * points along your extended thumb. + * + * Returns: The cross product between two vectors @u and @v. + * + * Since: 1.4 + * Stability: Unstable + */ +void +cogl_vector3_cross_product (CoglVector3 *result, + const CoglVector3 *u, + const CoglVector3 *v); + +/** + * cogl_vector3_dot_product: + * @a: Your first CoglVector3 + * @b: Your second CoglVector3 + * + * Calculates the dot product of the two #CoglVector3s. This + * can be used to determine the magnitude of one vector projected onto + * another. (for example a surface normal) + * + * For example if you have a polygon with a given normal vector and + * some other point for which you want to calculate its distance from + * the polygon, you can create a vector between one of the polygon + * vertices and that point and use the dot product to calculate the + * magnitude for that vector but projected onto the normal of the + * polygon. This way you don't just get the distance from the point to + * the edge of the polygon you get the distance from the point to the + * nearest part of the polygon. + * + * If you don't use a unit length normal in the above example + * then you would then also have to divide the result by the magnitude + * of the normal + * + * The dot product is calculated as: + * |[ + * (a->x * b->x + a->y * b->y + a->z * b->z) + * ]| + * + * For reference, the dot product can also be calculated from the + * angle between two vectors as: + * |[ + * |a||b|cos𝜃 + * ]| + * + * Returns: The dot product of two vectors. + * + * Since: 1.4 + * Stability: Unstable + */ +float +cogl_vector3_dot_product (const CoglVector3 *a, const CoglVector3 *b); + +/** + * cogl_vector3_distance: + * @a: The first point + * @b: The second point + * + * If you consider the two given vectors as (x,y,z) points instead + * then this will compute the distance between those two points. + * + * Returns: The distance between two points given as @CoglVector3s + * + * Since: 1.4 + * Stability: Unstable + */ +float +cogl_vector3_distance (const CoglVector3 *a, const CoglVector3 *b); + +G_END_DECLS + +#endif /* __COGL_VECTOR_H */ + diff --git a/clutter/cogl/cogl/cogl.h b/clutter/cogl/cogl/cogl.h index ff0e1f9a1..234f64cee 100644 --- a/clutter/cogl/cogl/cogl.h +++ b/clutter/cogl/cogl/cogl.h @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,7 @@ #if defined (COGL_ENABLE_EXPERIMENTAL_API) #include #include +#include #endif G_BEGIN_DECLS diff --git a/doc/reference/cogl/cogl-docs.xml.in b/doc/reference/cogl/cogl-docs.xml.in index 1f368ac28..98bc47b1b 100644 --- a/doc/reference/cogl/cogl-docs.xml.in +++ b/doc/reference/cogl/cogl-docs.xml.in @@ -90,6 +90,7 @@ + diff --git a/doc/reference/cogl/cogl-sections.txt b/doc/reference/cogl/cogl-sections.txt index 770d4f68d..900a88253 100644 --- a/doc/reference/cogl/cogl-sections.txt +++ b/doc/reference/cogl/cogl-sections.txt @@ -501,6 +501,26 @@ cogl_is_pixel_buffer cogl_texture_new_from_buffer +
+cogl-vector +Vectors +cogl_vector3_init +cogl_vector3_init_zero +cogl_vector3_equal +cogl_vector3_equal_with_epsilon +cogl_vector3_copy +cogl_vector3_free +cogl_vector3_invert +cogl_vector3_add +cogl_vector3_subtract +cogl_vector3_multiply_scalar +cogl_vector3_divide_scalar +cogl_vector3_normalize +cogl_vector3_magnitude +cogl_vector3_cross_product +cogl_vector3_dot_product +cogl_vector3_distance + cogl_buffer_access_get_type cogl_buffer_update_hint_get_type