mirror of
https://github.com/recp/cglm.git
synced 2026-01-04 22:30:05 +00:00
add bezier helpers
This commit is contained in:
56
include/cglm/bezier.h
Normal file
56
include/cglm/bezier.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c), Recep Aslantas.
|
||||||
|
*
|
||||||
|
* MIT License (MIT), http://opensource.org/licenses/MIT
|
||||||
|
* Full license can be found in the LICENSE file
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef cglm_bezier_h
|
||||||
|
#define cglm_bezier_h
|
||||||
|
|
||||||
|
#define GLM_BEZIER_MAT_INIT {{-1.0f, 3.0f, -3.0f, 1.0f}, \
|
||||||
|
{ 3.0f, -6.0f, 3.0f, 0.0f}, \
|
||||||
|
{-3.0f, 3.0f, 0.0f, 0.0f}, \
|
||||||
|
{ 1.0f, 0.0f, 0.0f, 0.0f}}
|
||||||
|
|
||||||
|
/* for C only */
|
||||||
|
#define GLM_BEZIER_MAT ((mat4)GLM_BEZIER_MAT_INIT)
|
||||||
|
|
||||||
|
#define CGLM_DECASTEL_EPS 1e-9
|
||||||
|
#define CGLM_DECASTEL_MAX 1000
|
||||||
|
#define CGLM_DECASTEL_SMALL 1e-20
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief cubic bezier interpolation
|
||||||
|
*
|
||||||
|
* Formula:
|
||||||
|
* B(s) = P0*(1-s)^3 + 3*C0*s*(1-s)^2 + 3*C1*s^2*(1-s) + P1*s^3
|
||||||
|
*
|
||||||
|
* similar result using matrix:
|
||||||
|
* B(s) = glm_smc(t, GLM_BEZIER_MAT, (vec4){p0, c0, c1, p1})
|
||||||
|
*
|
||||||
|
* glm_eq(glm_smc(...), glm_bezier(...)) should return TRUE
|
||||||
|
*
|
||||||
|
* @param[in] s parameter between 0 and 1
|
||||||
|
* @param[in] p0 begin point
|
||||||
|
* @param[in] c0 control point 1
|
||||||
|
* @param[in] c1 control point 2
|
||||||
|
* @param[in] p1 end point
|
||||||
|
*
|
||||||
|
* @return B(s)
|
||||||
|
*/
|
||||||
|
CGLM_INLINE
|
||||||
|
float
|
||||||
|
glm_bezier(float s, float p0, float c0, float c1, float p1) {
|
||||||
|
float x, xx, ss, xs3, a;
|
||||||
|
|
||||||
|
x = 1.0f - s;
|
||||||
|
xx = x * x;
|
||||||
|
ss = s * s;
|
||||||
|
xs3 = (s - ss) * 3.0f;
|
||||||
|
a = p0 * xx + c0 * xs3;
|
||||||
|
|
||||||
|
return a + s * (c1 * xs3 + p1 * ss - a);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* cglm_bezier_h */
|
||||||
23
include/cglm/call/bezier.h
Normal file
23
include/cglm/call/bezier.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c), Recep Aslantas.
|
||||||
|
*
|
||||||
|
* MIT License (MIT), http://opensource.org/licenses/MIT
|
||||||
|
* Full license can be found in the LICENSE file
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef cglmc_curve_h
|
||||||
|
#define cglmc_curve_h
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "../cglm.h"
|
||||||
|
|
||||||
|
CGLM_EXPORT
|
||||||
|
float
|
||||||
|
glmc_bezier(float s, float p0, float c0, float c1, float p1);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* cglmc_curve_h */
|
||||||
@@ -27,5 +27,6 @@
|
|||||||
#include "sphere.h"
|
#include "sphere.h"
|
||||||
#include "ease.h"
|
#include "ease.h"
|
||||||
#include "curve.h"
|
#include "curve.h"
|
||||||
|
#include "bezier.h"
|
||||||
|
|
||||||
#endif /* cglm_h */
|
#endif /* cglm_h */
|
||||||
|
|||||||
15
src/bezier.c
Normal file
15
src/bezier.c
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c), Recep Aslantas.
|
||||||
|
*
|
||||||
|
* MIT License (MIT), http://opensource.org/licenses/MIT
|
||||||
|
* Full license can be found in the LICENSE file
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../include/cglm/cglm.h"
|
||||||
|
#include "../include/cglm/call.h"
|
||||||
|
|
||||||
|
CGLM_EXPORT
|
||||||
|
float
|
||||||
|
glmc_bezier(float s, float p0, float c0, float c1, float p1) {
|
||||||
|
return glm_bezier(s, p0, c0, c1, p1);
|
||||||
|
}
|
||||||
41
test/src/test_bezier.c
Normal file
41
test/src/test_bezier.c
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c), Recep Aslantas.
|
||||||
|
*
|
||||||
|
* MIT License (MIT), http://opensource.org/licenses/MIT
|
||||||
|
* Full license can be found in the LICENSE file
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "test_common.h"
|
||||||
|
|
||||||
|
CGLM_INLINE
|
||||||
|
float
|
||||||
|
test_bezier_plain(float s, float p0, float c0, float c1, float p1) {
|
||||||
|
float x, xx, xxx, ss, sss;
|
||||||
|
|
||||||
|
x = 1.0f - s;
|
||||||
|
xx = x * x;
|
||||||
|
xxx = xx * x;
|
||||||
|
ss = s * s;
|
||||||
|
sss = ss * s;
|
||||||
|
|
||||||
|
return p0 * xxx + 3.0f * (c0 * s * xx + c1 * ss * x) + p1 * sss;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_bezier(void **state) {
|
||||||
|
float s, p0, p1, c0, c1, smc, Bs, Bs_plain;
|
||||||
|
|
||||||
|
s = test_rand();
|
||||||
|
p0 = test_rand();
|
||||||
|
p1 = test_rand();
|
||||||
|
c0 = test_rand();
|
||||||
|
c1 = test_rand();
|
||||||
|
|
||||||
|
smc = glm_smc(s, GLM_BEZIER_MAT, (vec4){p0, c0, c1, p1});
|
||||||
|
Bs = glm_bezier(s, p0, c0, c1, p1);
|
||||||
|
Bs_plain = test_bezier_plain(s, p0, c0, c1, p1);
|
||||||
|
|
||||||
|
assert_true(glm_eq(Bs, Bs_plain));
|
||||||
|
assert_true(glm_eq(smc, Bs_plain));
|
||||||
|
assert_true(glm_eq(Bs, smc));
|
||||||
|
}
|
||||||
@@ -38,7 +38,10 @@ main(int argc, const char * argv[]) {
|
|||||||
cmocka_unit_test(test_vec3),
|
cmocka_unit_test(test_vec3),
|
||||||
|
|
||||||
/* affine */
|
/* affine */
|
||||||
cmocka_unit_test(test_affine)
|
cmocka_unit_test(test_affine),
|
||||||
|
|
||||||
|
/* bezier */
|
||||||
|
cmocka_unit_test(test_bezier)
|
||||||
};
|
};
|
||||||
|
|
||||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||||
|
|||||||
@@ -40,4 +40,7 @@ test_vec3(void **state);
|
|||||||
void
|
void
|
||||||
test_affine(void **state);
|
test_affine(void **state);
|
||||||
|
|
||||||
|
void
|
||||||
|
test_bezier(void **state);
|
||||||
|
|
||||||
#endif /* test_tests_h */
|
#endif /* test_tests_h */
|
||||||
|
|||||||
Reference in New Issue
Block a user