mirror of https://github.com/google/pebble
264 lines
13 KiB
C
264 lines
13 KiB
C
/*
|
|
* Copyright 2024 Google LLC
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "gtypes.h"
|
|
#include "util/math_fixed.h"
|
|
|
|
//! @addtogroup Graphics
|
|
//! @{
|
|
//! @addtogroup GraphicsTransforms Transformation Matrices
|
|
//! \brief Types for creating transformation matrices and utility functions to manipulate and apply
|
|
//! the transformations.
|
|
//!
|
|
//! @{
|
|
|
|
//////////////////////////////////////
|
|
/// Creating Transforms
|
|
//////////////////////////////////////
|
|
//! Convenience macro for GTransformNumber equal to 0
|
|
#define GTransformNumberZero ((GTransformNumber){ .integer = 0, .fraction = 0 })
|
|
|
|
//! Convenience macro for GTransformNumber equal to 1
|
|
#define GTransformNumberOne ((GTransformNumber){ .integer = 1, .fraction = 0 })
|
|
|
|
//! Convenience macro to convert from a number (i.e. char, int, float, etc.) to GTransformNumber
|
|
//! @param x The number to convert
|
|
#define GTransformNumberFromNumber(x) \
|
|
((GTransformNumber){ .raw_value = (int32_t)((x)*(GTransformNumberOne.raw_value)) })
|
|
|
|
//! This macro returns the transformation matrix for the corresponding input coefficients.
|
|
//! Below is the equivalent resulting matrix:
|
|
//! t = [ a b 0 ]
|
|
//! [ c d 0 ]
|
|
//! [ tx ty 1 ]
|
|
//! @param a Coefficient corresponding to X scale (type is GTransformNumber)
|
|
//! @param b Coefficient corresponding to X shear (type is GTransformNumber)
|
|
//! @param c Coefficient corresponding to Y shear (type is GTransformNumber)
|
|
//! @param d Coefficient corresponding to Y scale (type is GTransformNumber)
|
|
//! @param tx Coefficient corresponding to X translation (type is GTransformNumber)
|
|
//! @param ty Coefficient corresponding to Y translation (type is GTransformNumber)
|
|
#define GTransform(a, b, c, d, tx, ty) (GTransform) { (a), (b), (c), (d), (tx), (ty) }
|
|
//! @param a Coefficient corresponding to X scale (type is char, int, float, etc)
|
|
//! @param b Coefficient corresponding to X shear (type is char, int, float, etc)
|
|
//! @param c Coefficient corresponding to Y shear (type is char, int, float, etc)
|
|
//! @param d Coefficient corresponding to Y scale (type is char, int, float, etc)
|
|
//! @param tx Coefficient corresponding to X translation (type is char, int, float, etc)
|
|
//! @param ty Coefficient corresponding to Y translation (type is char, int, float, etc)
|
|
#define GTransformFromNumbers(a, b, c, d, tx, ty) GTransform(GTransformNumberFromNumber(a), \
|
|
GTransformNumberFromNumber(b), \
|
|
GTransformNumberFromNumber(c), \
|
|
GTransformNumberFromNumber(d), \
|
|
GTransformNumberFromNumber(tx), \
|
|
GTransformNumberFromNumber(ty))
|
|
|
|
//! This macro returns the identity transformation matrix.
|
|
//! Below is the equivalent resulting matrix:
|
|
//! t = [ 1 0 0 ]
|
|
//! [ 0 1 0 ]
|
|
//! [ 0 0 1 ]
|
|
#define GTransformIdentity() \
|
|
(GTransform) { .a = GTransformNumberOne, \
|
|
.b = GTransformNumberZero, \
|
|
.c = GTransformNumberZero, \
|
|
.d = GTransformNumberOne, \
|
|
.tx = GTransformNumberZero, \
|
|
.ty = GTransformNumberZero }
|
|
|
|
//! This macro returns a scaling transformation matrix for the corresponding input coefficients.
|
|
//! Below is the equivalent resulting matrix:
|
|
//! t = [ sx 0 0 ]
|
|
//! [ 0 sy 0 ]
|
|
//! [ 0 0 1 ]
|
|
//! @param sx X scaling factor (type is GTransformNumber)
|
|
//! @param sy Y scaling factor (type is GTransformNumber)
|
|
#define GTransformScale(sx, sy) \
|
|
(GTransform) { .a = sx, \
|
|
.b = GTransformNumberZero, \
|
|
.c = GTransformNumberZero, \
|
|
.d = sy, \
|
|
.tx = GTransformNumberZero, \
|
|
.ty = GTransformNumberZero }
|
|
//! @param sx X scaling factor (type is char, int, float, etc)
|
|
//! @param sy Y scaling factor (type is char, int, float, etc)
|
|
#define GTransformScaleFromNumber(sx, sy) \
|
|
GTransformScale(GTransformNumberFromNumber(sx), GTransformNumberFromNumber(sy))
|
|
|
|
//! This macro returns a translation transformation matrix for the corresponding input coefficients.
|
|
//! Below is the equivalent resulting matrix:
|
|
//! t = [ 1 0 0 ]
|
|
//! [ 0 1 0 ]
|
|
//! [ tx ty 1 ]
|
|
//! @param tx_v X translation factor (type is GTransformNumber)
|
|
//! @param ty_v Y translation factor (type is GTransformNumber)
|
|
#define GTransformTranslation(tx_v, ty_v) \
|
|
(GTransform) { .a = GTransformNumberOne, \
|
|
.b = GTransformNumberZero, \
|
|
.c = GTransformNumberZero, \
|
|
.d = GTransformNumberOne, \
|
|
.tx = tx_v, \
|
|
.ty = ty_v }
|
|
//! @param tx_v X translation factor (type is char, int, float, etc)
|
|
//! @param ty_v Y translation factor (type is char, int, float, etc)
|
|
#define GTransformTranslationFromNumber(tx, ty) \
|
|
GTransformTranslation(GTransformNumberFromNumber(tx), GTransformNumberFromNumber(ty))
|
|
|
|
|
|
//! @internal
|
|
//! Function that returns the rotation matrix as defined below by GTransformRotation
|
|
GTransform gtransform_init_rotation(int32_t angle);
|
|
|
|
//! This macro returns the transformation matrix for the corresponding rotation angle.
|
|
//! Below is the equivalent resulting matrix:
|
|
//! t = [ cos(angle) -sin(angle) 0 ]
|
|
//! [ sin(angle) cos(angle) 0 ]
|
|
//! [ 0 0 1 ]
|
|
//
|
|
//! The input angle corresponds to the rotation angle applied during transformation.
|
|
//! If this angle is set to 0, then the identity matrix is returned.
|
|
//! @param angle Rotation angle to apply (type is in same format as trig angle 0..TRIG_MAX_ANGLE)
|
|
#define GTransformRotation(angle) gtransform_init_rotation(angle)
|
|
|
|
//////////////////////////////////////
|
|
/// Evaluating Transforms
|
|
//////////////////////////////////////
|
|
//! Returns whether the input matrix is an identity matrix or not
|
|
//! @param t Pointer to transformation matrix to test
|
|
//! @return True if input matrix is identity; False if NULL or not identity.
|
|
bool gtransform_is_identity(const GTransform * const t);
|
|
|
|
//! Returns whether the input matrix is strictly a scaling matrix
|
|
//! @param t Pointer to transformation matrix to test
|
|
//! @return True if input matrix is only scaling X or Y; False if NULL or other coefficients set.
|
|
bool gtransform_is_only_scale(const GTransform * const t);
|
|
|
|
//! Returns whether the input matrix is strictly a translation matrix
|
|
//! @param t Pointer to transformation matrix to test
|
|
//! @return True if input matrix is only translating X or Y; False if NULL or other
|
|
//! coefficients set.
|
|
bool gtransform_is_only_translation(const GTransform * const t);
|
|
|
|
//! Returns whether the input matrix has coefficients b and c set to 0.
|
|
//! This does not check whether any other coefficients are set or not.
|
|
//! @param t Pointer to transformation matrix to test
|
|
//! @return True if input matrix is only scaling or translating X or Y; False if NULL or other.
|
|
//! coefficients set.
|
|
bool gtransform_is_only_scale_or_translation(const GTransform * const t);
|
|
|
|
//! Returns true if the two matrices are equal; false otherwise
|
|
//! Returns false if either parameter is NULL
|
|
//! @param t1 Pointer to first transformation matrix
|
|
//! @param t2 Pointer to second transformation matrix
|
|
//! @return True if both matrices are equal; False if any are NULL or if not equal.
|
|
bool gtransform_is_equal(const GTransform * const t1, const GTransform * const t2);
|
|
|
|
//////////////////////////////////////
|
|
/// Modifying Transforms
|
|
//////////////////////////////////////
|
|
//! Concatenates two transformation matrices and returns the resulting matrix in t1
|
|
//! The operation performed is t_new = t1*t2. This order is not commutative so be careful
|
|
//! when concatenating the matrices.
|
|
//! Note t_new can safely be be the same pointer as t1 or t2.
|
|
//! @param t_new Pointer to destination transformation matrix
|
|
//! @param t1 Pointer to transformation matrix to concatenate with t2 where t_new = t1*t2
|
|
//! @param t2 Pointer to transformation matrix to concatenate with t1 where t_new = t1*t2
|
|
void gtransform_concat(GTransform *t_new, const GTransform *t1, const GTransform * t2);
|
|
|
|
//! Updates the input transformation matrix by applying a translation.
|
|
//! This results in applying the following matrix below (i.e. t_new = t_scale*t):
|
|
//! t_scale = [ sx 0 0 ]
|
|
//! [ 0 sy 0 ]
|
|
//! [ 0 0 1 ]
|
|
//! Note t_new can safely be be the same pointer as t.
|
|
//! @param t_new Pointer to destination transformation matrix
|
|
//! @param t Pointer to transformation matrix that will be scaled
|
|
//! @param sx X scaling factor
|
|
//! @param sy Y scaling factor
|
|
void gtransform_scale(GTransform *t_new, GTransform *t, GTransformNumber sx, GTransformNumber sy);
|
|
|
|
//! Similar to gtransform_scale but with native number types (i.e. char, int, float, etc)
|
|
//! @param t_new Pointer to destination transformation matrix
|
|
//! @param t Pointer to transformation matrix that will be scaled
|
|
//! @param sx X scaling factor (type is char, int, float, etc)
|
|
//! @param sy Y scaling factor (type is char, int, float, etc)
|
|
#define gtransform_scale_number(t_new, t, sx, sy) \
|
|
gtransform_scale(t_new, t, \
|
|
GTransformNumberFromNumber(sx), GTransformNumberFromNumber(sy))
|
|
|
|
//! Updates the input transformation matrix by applying a translation.
|
|
//! This results in applying the following matrix below (i.e. t_new = t_translation*t):
|
|
//! t_translation = [ 1 0 0 ]
|
|
//! [ 0 1 0 ]
|
|
//! [ tx ty 1 ]
|
|
//! Note t_new can safely be be the same pointer as t.
|
|
//! @param t_new Pointer to destination transformation matrix
|
|
//! @param t Pointer to transformation matrix that will be translated
|
|
//! @param tx X translation factor
|
|
//! @param ty Y translation factor
|
|
void gtransform_translate(GTransform *t_new, GTransform *t,
|
|
GTransformNumber tx, GTransformNumber ty);
|
|
|
|
//! Similar to gtransform_translate but with native number types (i.e. char, int, float, etc)
|
|
//! @param t_new Pointer to destination transformation matrix
|
|
//! @param t Pointer to transformation matrix that will be translated
|
|
//! @param tx X translation factor (type is char, int, float, etc)
|
|
//! @param ty Y translation factor (type is char, int, float, etc)
|
|
#define gtransform_translate_number(t_new, t, tx, ty) \
|
|
gtransform_translate(t_new, t, \
|
|
GTransformNumberFromNumber(tx), GTransformNumberFromNumber(ty))
|
|
|
|
//! Updates the input transformation matrix by applying a rotation of angle degrees.
|
|
//! This results in applying the following matrix below (i.e. t_new = tr*t):
|
|
//! tr = [ cos(angle) -sin(angle) 0 ]
|
|
//! [ sin(angle) cos(angle) 0 ]
|
|
//! [ 0 0 1 ]
|
|
//! Note t_new can safely be be the same pointer as t.
|
|
//! @param t_new Pointer to destination transformation matrix
|
|
//! @param t Pointer to transformation matrix that will be rotated
|
|
//! @param angle Rotation angle to apply (type is in same format as trig angle 0..TRIG_MAX_ANGLE)
|
|
void gtransform_rotate(GTransform *t_new, GTransform *t, int32_t angle);
|
|
|
|
//! Returns the inversion of a given transformation matrix t in t_new.
|
|
//! Function returns true if operation is successful; false if the matrix cannot be inverted
|
|
//! If the matrix cannot be inverted, then the contents of t will be copied to t_new.
|
|
//! Note t_new can safely be be the same pointer as t.
|
|
//! @param t_new Pointer to destination transformation matrix
|
|
//! @param t Pointer to transformation matrix that will be inverted
|
|
//! @return True if inversion of input t matrix exists; False otherwise or if t is NULL.
|
|
bool gtransform_invert(GTransform *t_new, GTransform *t);
|
|
|
|
//////////////////////////////////////
|
|
/// Applying Transformations
|
|
//////////////////////////////////////
|
|
//! Transforms a single GPoint (x,y) based on the transformation matrix
|
|
//! @param point GPoint to be transformed
|
|
//! @param t Pointer to transformation matrix to apply to the GPoint
|
|
//! @return GPointPrecise after transforming the GPoint; if t is NULL then just convert the
|
|
//! GPoint to a GPointPrecise.
|
|
GPointPrecise gpoint_transform(GPoint point, const GTransform * const t);
|
|
|
|
//! Transforms a single GVector (dx,dy) based on the transformation matrix
|
|
//! @param point GVector to be transformed
|
|
//! @param t Pointer to transformation matrix to apply to the GVector
|
|
//! @return GVectorPrecise after transforming the GVector; if t is NULL then just convert the
|
|
//! GVector to a GVectorPrecise.
|
|
GVectorPrecise gvector_transform(GVector vector, const GTransform * const t);
|
|
|
|
//! @} // end addtogroup GraphicsTransforms
|
|
//! @} // end addtogroup Graphics
|
|
|