This repository has been archived on 2026-04-17. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
bhlib/src/math.c

1779 lines
44 KiB
C
Raw Normal View History

2025-01-18 17:24:36 +03:00
#include <bh/math.h>
#include <math.h>
bh_point4f_t *bh_point4f_add(const bh_point4f_t *a,
const bh_point4f_t *b,
bh_point4f_t *result)
{
result->x = a->x + b->x;
result->y = a->y + b->y;
result->z = a->z + b->z;
result->w = a->w + b->w;
return result;
}
bh_point4f_t *bh_point4f_sub(const bh_point4f_t *a,
const bh_point4f_t *b,
bh_point4f_t *result)
{
result->x = a->x - b->x;
result->y = a->y - b->y;
result->z = a->z - b->z;
result->w = a->w - b->w;
return result;
}
bh_point4f_t *bh_point4f_mul(const bh_point4f_t *a,
const bh_point4f_t *b,
bh_point4f_t *result)
{
result->x = a->x * b->x;
result->y = a->y * b->y;
result->z = a->z * b->z;
result->w = a->w * b->w;
return result;
}
bh_point4f_t *bh_point4f_scale(const bh_point4f_t *a,
float b,
bh_point4f_t *result)
{
result->x = a->x * b;
result->y = a->y * b;
result->z = a->z * b;
result->w = a->w * b;
return result;
}
bh_point4f_t *bh_point4f_madd(const bh_point4f_t *a,
const bh_point4f_t *b,
const bh_point4f_t *c,
bh_point4f_t *result)
{
result->x = a->x * b->x + c->x;
result->y = a->y * b->y + c->y;
result->z = a->z * b->z + c->z;
result->w = a->w * b->w + c->w;
return result;
}
bh_point4f_t *bh_point4f_negate(const bh_point4f_t *in,
bh_point4f_t *result)
{
result->x = -in->x;
result->y = -in->y;
result->z = -in->z;
result->w = -in->w;
return result;
}
float bh_point4f_dot(const bh_point4f_t *a,
const bh_point4f_t *b)
{
return a->x * b->x + a->y * b->y + a->z * b->y + a->w * b->w;
}
float bh_point4f_dot3(const bh_point4f_t *a,
const bh_point4f_t *b)
{
return a->x * b->x + a->y * b->y + a->z * b->y;
}
bh_point4f_t *bh_point4f_cross(const bh_point4f_t *a,
const bh_point4f_t *b,
bh_point4f_t *result)
{
bh_point4f_t 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;
tmp.w = 0.0f;
*result = tmp;
return result;
}
float bh_point4f_length(const bh_point4f_t *in)
{
return sqrtf(bh_point4f_dot(in, in));
}
bh_point4f_t *bh_point4f_normal(const bh_point4f_t *in,
bh_point4f_t *result)
{
float length;
length = 1.0f / bh_point4f_length(in);
return bh_point4f_scale(in, length, result);
}
bh_point4f_t *bh_point4f_min(const bh_point4f_t *a,
const bh_point4f_t *b,
bh_point4f_t *result)
{
if (a->x < b->x) result->x = a->x; else result->x = b->x;
if (a->y < b->y) result->y = a->y; else result->y = b->y;
if (a->z < b->z) result->z = a->z; else result->z = b->z;
if (a->w < b->w) result->w = a->w; else result->w = b->w;
return result;
}
bh_point4f_t *bh_point4f_max(const bh_point4f_t *a,
const bh_point4f_t *b,
bh_point4f_t *result)
{
if (a->x > b->x) result->x = a->x; else result->x = b->x;
if (a->y > b->y) result->y = a->y; else result->y = b->y;
if (a->z > b->z) result->z = a->z; else result->z = b->z;
if (a->w > b->w) result->w = a->w; else result->w = b->w;
return result;
}
bh_point4f_t *bh_point4f_lerp(const bh_point4f_t *a,
const bh_point4f_t *b,
float t,
bh_point4f_t *result)
{
bh_point4f_t tmp;
bh_point4f_scale(bh_point4f_sub(b, a, &tmp), t, &tmp);
return bh_point4f_add(a, &tmp, result);
}
bh_point4f_t *bh_point4f_slerp(const bh_point4f_t *a,
const bh_point4f_t *b,
float t,
bh_point4f_t *result)
{
float angle, denom;
bh_point4f_t from, to;
angle = acosf(bh_point4f_dot(a, b));
/* Special case - reducing to linear interpolation */
if (angle == 0.0f)
return bh_point4f_lerp(a, b, t, result);
denom = 1.0f / sinf(angle);
bh_point4f_scale(a, sinf((1 - t) * angle) * denom, &from);
bh_point4f_scale(b, sinf(t * angle) * denom, &to);
return bh_point4f_add(&from, &to, result);
}
bh_point3f_t *bh_point3f_add(const bh_point3f_t *a,
const bh_point3f_t *b,
bh_point3f_t *result)
{
result->x = a->x + b->x;
result->y = a->y + b->y;
result->z = a->z + b->z;
return result;
}
bh_point3f_t *bh_point3f_sub(const bh_point3f_t *a,
const bh_point3f_t *b,
bh_point3f_t *result)
{
result->x = a->x - b->x;
result->y = a->y - b->y;
result->z = a->z - b->z;
return result;
}
bh_point3f_t *bh_point3f_mul(const bh_point3f_t *a,
const bh_point3f_t *b,
bh_point3f_t *result)
{
result->x = a->x * b->x;
result->y = a->y * b->y;
result->z = a->z * b->z;
return result;
}
bh_point3f_t *bh_point3f_scale(const bh_point3f_t *a,
float b,
bh_point3f_t *result)
{
result->x = a->x * b;
result->y = a->y * b;
result->z = a->z * b;
return result;
}
bh_point3f_t *bh_point3f_madd(const bh_point3f_t *a,
const bh_point3f_t *b,
const bh_point3f_t *c,
bh_point3f_t *result)
{
result->x = a->x * b->x + c->x;
result->y = a->y * b->y + c->y;
result->z = a->z * b->z + c->z;
return result;
}
bh_point3f_t *bh_point3f_negate(const bh_point3f_t *in,
bh_point3f_t *result)
{
result->x = -in->x;
result->y = -in->y;
result->z = -in->z;
return result;
}
float bh_point3f_dot(const bh_point3f_t *a,
const bh_point3f_t *b)
{
return a->x * b->x + a->y * b->y + a->z * b->y;
}
bh_point3f_t *bh_point3f_cross(const bh_point3f_t *a,
const bh_point3f_t *b,
bh_point3f_t *result)
{
bh_point3f_t 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;
return result;
}
float bh_point3f_length(const bh_point3f_t *in)
{
return sqrtf(bh_point3f_dot(in, in));
}
bh_point3f_t *bh_point3f_normal(const bh_point3f_t *in,
bh_point3f_t *result)
{
float length;
length = 1.0f / bh_point3f_length(in);
return bh_point3f_scale(in, length, result);
}
bh_point3f_t *bh_point3f_min(const bh_point3f_t *a,
const bh_point3f_t *b,
bh_point3f_t *result)
{
if (a->x < b->x) result->x = a->x; else result->x = b->x;
if (a->y < b->y) result->y = a->y; else result->y = b->y;
if (a->z < b->z) result->z = a->z; else result->z = b->z;
return result;
}
bh_point3f_t *bh_point3f_max(const bh_point3f_t *a,
const bh_point3f_t *b,
bh_point3f_t *result)
{
if (a->x > b->x) result->x = a->x; else result->x = b->x;
if (a->y > b->y) result->y = a->y; else result->y = b->y;
if (a->z > b->z) result->z = a->z; else result->z = b->z;
return result;
}
bh_point3f_t *bh_point3f_lerp(const bh_point3f_t *a,
const bh_point3f_t *b,
float t,
bh_point3f_t *result)
{
bh_point3f_t tmp;
bh_point3f_scale(bh_point3f_sub(b, a, &tmp), t, &tmp);
return bh_point3f_add(a, &tmp, result);
}
bh_point3f_t *bh_point3f_slerp(const bh_point3f_t *a,
const bh_point3f_t *b,
float t,
bh_point3f_t *result)
{
float angle, denom;
bh_point3f_t from, to;
angle = acosf(bh_point3f_dot(a, b));
/* Special case - reducing to linear interpolation */
if (angle == 0.0f)
return bh_point3f_lerp(a, b, t, result);
denom = 1.0f / sinf(angle);
bh_point3f_scale(a, sinf((1 - t) * angle) * denom, &from);
bh_point3f_scale(b, sinf(t * angle) * denom, &to);
return bh_point3f_add(&from, &to, result);
}
bh_point2f_t *bh_point2f_add(const bh_point2f_t *a,
const bh_point2f_t *b,
bh_point2f_t *result)
{
result->x = a->x + b->x;
result->y = a->y + b->y;
return result;
}
bh_point2f_t *bh_point2f_sub(const bh_point2f_t *a,
const bh_point2f_t *b,
bh_point2f_t *result)
{
result->x = a->x - b->x;
result->y = a->y - b->y;
return result;
}
bh_point2f_t *bh_point2f_mul(const bh_point2f_t *a,
const bh_point2f_t *b,
bh_point2f_t *result)
{
result->x = a->x * b->x;
result->y = a->y * b->y;
return result;
}
bh_point2f_t *bh_point2f_scale(const bh_point2f_t *a,
float b,
bh_point2f_t *result)
{
result->x = a->x * b;
result->y = a->y * b;
return result;
}
bh_point2f_t *bh_point2f_madd(const bh_point2f_t *a,
const bh_point2f_t *b,
const bh_point2f_t *c,
bh_point2f_t *result)
{
result->x = a->x * b->x + c->x;
result->y = a->y * b->y + c->y;
return result;
}
bh_point2f_t *bh_point2f_negate(const bh_point2f_t *in,
bh_point2f_t *result)
{
result->x = -in->x;
result->y = -in->y;
return result;
}
float bh_point2f_dot(const bh_point2f_t *a,
const bh_point2f_t *b)
{
return a->x * b->x + a->y * b->y;
}
float bh_point2f_cross(const bh_point2f_t *a,
const bh_point2f_t *b)
{
return a->x * b->y - a->y * b->x;
}
float bh_point2f_length(const bh_point2f_t *in)
{
return sqrtf(bh_point2f_dot(in, in));
}
bh_point2f_t *bh_point2f_normal(const bh_point2f_t *in,
bh_point2f_t *result)
{
float length;
length = 1.0f / bh_point2f_length(in);
return bh_point2f_scale(in, length, result);
}
bh_point2f_t *bh_point2f_min(const bh_point2f_t *a,
const bh_point2f_t *b,
bh_point2f_t *result)
{
if (a->x < b->x) result->x = a->x; else result->x = b->x;
if (a->y < b->y) result->y = a->y; else result->y = b->y;
return result;
}
bh_point2f_t *bh_point2f_max(const bh_point2f_t *a,
const bh_point2f_t *b,
bh_point2f_t *result)
{
if (a->x > b->x) result->x = a->x; else result->x = b->x;
if (a->y > b->y) result->y = a->y; else result->y = b->y;
return result;
}
bh_point2f_t *bh_point2f_lerp(const bh_point2f_t *a,
const bh_point2f_t *b,
float t,
bh_point2f_t *result)
{
bh_point2f_t tmp;
bh_point2f_scale(bh_point2f_sub(b, a, &tmp), t, &tmp);
return bh_point2f_add(a, &tmp, result);
}
bh_point2f_t *bh_point2f_slerp(const bh_point2f_t *a,
const bh_point2f_t *b,
float t,
bh_point2f_t *result)
{
float angle, denom;
bh_point2f_t from, to;
angle = acosf(bh_point2f_dot(a, b));
/* Special case - reducing to linear interpolation */
if (angle == 0.0f)
return bh_point2f_lerp(a, b, t, result);
denom = 1.0f / sinf(angle);
bh_point2f_scale(a, sinf((1 - t) * angle) * denom, &from);
bh_point2f_scale(b, sinf(t * angle) * denom, &to);
return bh_point2f_add(&from, &to, result);
}
bh_point4i_t *bh_point4i_add(const bh_point4i_t *a,
const bh_point4i_t *b,
bh_point4i_t *result)
{
result->x = a->x + b->x;
result->y = a->y + b->y;
result->z = a->z + b->z;
result->w = a->w + b->w;
return result;
}
bh_point4i_t *bh_point4i_sub(const bh_point4i_t *a,
const bh_point4i_t *b,
bh_point4i_t *result)
{
result->x = a->x - b->x;
result->y = a->y - b->y;
result->z = a->z - b->z;
result->w = a->w - b->w;
return result;
}
bh_point4i_t *bh_point4i_mul(const bh_point4i_t *a,
const bh_point4i_t *b,
bh_point4i_t *result)
{
result->x = a->x * b->x;
result->y = a->y * b->y;
result->z = a->z * b->z;
result->w = a->w * b->w;
return result;
}
bh_point4i_t *bh_point4i_scale(const bh_point4i_t *a,
int b,
bh_point4i_t *result)
{
result->x = a->x * b;
result->y = a->y * b;
result->z = a->z * b;
result->w = a->w * b;
return result;
}
bh_point4i_t *bh_point4i_madd(const bh_point4i_t *a,
const bh_point4i_t *b,
const bh_point4i_t *c,
bh_point4i_t *result)
{
result->x = a->x * b->x + c->x;
result->y = a->y * b->y + c->y;
result->z = a->z * b->z + c->z;
result->w = a->w * b->w + c->w;
return result;
}
bh_point4i_t *bh_point4i_negate(const bh_point4i_t *in,
bh_point4i_t *result)
{
result->x = -in->x;
result->y = -in->y;
result->z = -in->z;
result->w = -in->w;
return result;
}
bh_point4i_t *bh_point4i_min(const bh_point4i_t *a,
const bh_point4i_t *b,
bh_point4i_t *result)
{
if (a->x < b->x) result->x = a->x; else result->x = b->x;
if (a->y < b->y) result->y = a->y; else result->y = b->y;
if (a->z < b->z) result->z = a->z; else result->z = b->z;
if (a->w < b->w) result->w = a->w; else result->w = b->w;
return result;
}
bh_point4i_t *bh_point4i_max(const bh_point4i_t *a,
const bh_point4i_t *b,
bh_point4i_t *result)
{
if (a->x > b->x) result->x = a->x; else result->x = b->x;
if (a->y > b->y) result->y = a->y; else result->y = b->y;
if (a->z > b->z) result->z = a->z; else result->z = b->z;
if (a->w > b->w) result->w = a->w; else result->w = b->w;
return result;
}
bh_point4i_t *bh_point4i_lerp(const bh_point4i_t *a,
const bh_point4i_t *b,
float t,
bh_point4i_t *result)
{
bh_point4i_t tmp;
tmp.x = (b->x - a->x) * t;
tmp.y = (b->y - a->y) * t;
tmp.z = (b->z - a->z) * t;
tmp.w = (b->w - a->w) * t;
return bh_point4i_add(a, &tmp, result);
}
bh_point3i_t *bh_point3i_add(const bh_point3i_t *a,
const bh_point3i_t *b,
bh_point3i_t *result)
{
result->x = a->x + b->x;
result->y = a->y + b->y;
result->z = a->z + b->z;
return result;
}
bh_point3i_t *bh_point3i_sub(const bh_point3i_t *a,
const bh_point3i_t *b,
bh_point3i_t *result)
{
result->x = a->x - b->x;
result->y = a->y - b->y;
result->z = a->z - b->z;
return result;
}
bh_point3i_t *bh_point3i_mul(const bh_point3i_t *a,
const bh_point3i_t *b,
bh_point3i_t *result)
{
result->x = a->x * b->x;
result->y = a->y * b->y;
result->z = a->z * b->z;
return result;
}
bh_point3i_t *bh_point3i_scale(const bh_point3i_t *a,
int b,
bh_point3i_t *result)
{
result->x = a->x * b;
result->y = a->y * b;
result->z = a->z * b;
return result;
}
bh_point3i_t *bh_point3i_madd(const bh_point3i_t *a,
const bh_point3i_t *b,
const bh_point3i_t *c,
bh_point3i_t *result)
{
result->x = a->x * b->x + c->x;
result->y = a->y * b->y + c->y;
result->z = a->z * b->z + c->z;
return result;
}
bh_point3i_t *bh_point3i_negate(const bh_point3i_t *in,
bh_point3i_t *result)
{
result->x = -in->x;
result->y = -in->y;
result->z = -in->z;
return result;
}
bh_point3i_t *bh_point3i_min(const bh_point3i_t *a,
const bh_point3i_t *b,
bh_point3i_t *result)
{
if (a->x < b->x) result->x = a->x; else result->x = b->x;
if (a->y < b->y) result->y = a->y; else result->y = b->y;
if (a->z < b->z) result->z = a->z; else result->z = b->z;
return result;
}
bh_point3i_t *bh_point3i_max(const bh_point3i_t *a,
const bh_point3i_t *b,
bh_point3i_t *result)
{
if (a->x > b->x) result->x = a->x; else result->x = b->x;
if (a->y > b->y) result->y = a->y; else result->y = b->y;
if (a->z > b->z) result->z = a->z; else result->z = b->z;
return result;
}
bh_point3i_t *bh_point3i_lerp(const bh_point3i_t *a,
const bh_point3i_t *b,
float t,
bh_point3i_t *result)
{
bh_point3i_t tmp;
tmp.x = (b->x - a->x) * t;
tmp.y = (b->y - a->y) * t;
tmp.z = (b->z - a->z) * t;
return bh_point3i_add(a, &tmp, result);
}
bh_point2i_t *bh_point2i_add(const bh_point2i_t *a,
const bh_point2i_t *b,
bh_point2i_t *result)
{
result->x = a->x + b->x;
result->y = a->y + b->y;
return result;
}
bh_point2i_t *bh_point2i_sub(const bh_point2i_t *a,
const bh_point2i_t *b,
bh_point2i_t *result)
{
result->x = a->x - b->x;
result->y = a->y - b->y;
return result;
}
bh_point2i_t *bh_point2i_mul(const bh_point2i_t *a,
const bh_point2i_t *b,
bh_point2i_t *result)
{
result->x = a->x * b->x;
result->y = a->y * b->y;
return result;
}
bh_point2i_t *bh_point2i_scale(const bh_point2i_t *a,
int b,
bh_point2i_t *result)
{
result->x = a->x * b;
result->y = a->y * b;
return result;
}
bh_point2i_t *bh_point2i_madd(const bh_point2i_t *a,
const bh_point2i_t *b,
const bh_point2i_t *c,
bh_point2i_t *result)
{
result->x = a->x * b->x + c->x;
result->y = a->y * b->y + c->y;
return result;
}
bh_point2i_t *bh_point2i_negate(const bh_point2i_t *in,
bh_point2i_t *result)
{
result->x = -in->x;
result->y = -in->y;
return result;
}
bh_point2i_t *bh_point2i_min(const bh_point2i_t *a,
const bh_point2i_t *b,
bh_point2i_t *result)
{
if (a->x < b->x) result->x = a->x; else result->x = b->x;
if (a->y < b->y) result->y = a->y; else result->y = b->y;
return result;
}
bh_point2i_t *bh_point2i_max(const bh_point2i_t *a,
const bh_point2i_t *b,
bh_point2i_t *result)
{
if (a->x > b->x) result->x = a->x; else result->x = b->x;
if (a->y > b->y) result->y = a->y; else result->y = b->y;
return result;
}
bh_point2i_t *bh_point2i_lerp(const bh_point2i_t *a,
const bh_point2i_t *b,
float t,
bh_point2i_t *result)
{
bh_point2i_t tmp;
tmp.x = (b->x - a->x) * t;
tmp.y = (b->y - a->y) * t;
return bh_point2i_add(a, &tmp, result);
}
bh_quat_t *bh_quat_identity(bh_quat_t *result)
{
static const bh_quat_t ident = {0.0f, 0.0f, 0.0f, 1.0f};
*result = ident;
return result;
}
bh_quat_t *bh_quat_conjugate(const bh_quat_t *in,
bh_quat_t *result)
{
result->x = -in->x;
result->y = -in->y;
result->z = -in->z;
result->w = in->w;
return result;
}
bh_quat_t *bh_quat_inverse(const bh_quat_t *in,
bh_quat_t *result)
{
float length;
length = bh_quat_dot(in, in);
bh_quat_conjugate(in, result);
return bh_quat_scale(result, 1.0f / length, result);
}
bh_quat_t *bh_quat_mul(const bh_quat_t *a,
const bh_quat_t *b,
bh_quat_t *result)
{
bh_quat_t tmp1, tmp2, tmp3;
float w;
w = a->w * b->w - bh_point4f_dot3(a, b);
bh_point4f_scale(a, b->w, &tmp1);
bh_point4f_scale(b, a->w, &tmp2);
bh_point4f_cross(a, b, &tmp3);
bh_point4f_add(&tmp1, &tmp2, result);
bh_point4f_add(&tmp3, result, result);
result->w = w;
return result;
}
bh_quat_t *bh_quat_set_euler(float roll,
float pitch,
float yaw,
bh_quat_t *result)
{
float cr, cp, cy, sr, sp, sy;
cr = cosf(roll / 2.0f);
cp = cosf(pitch / 2.0f);
cy = cosf(yaw / 2.0f);
sr = sinf(roll / 2.0f);
sp = sinf(pitch / 2.0f);
sy = sinf(yaw / 2.0f);
result->x = sr * cp * cy - cr * sp * sy;
result->y = cr * sp * cy + sr * cp * sy;
result->z = cr * cp * sy - sr * sp * cy;
result->w = cr * cp * cy + sr * sp * sy;
return result;
}
bh_quat_t *bh_quat_set_rotation(const bh_point3f_t *axis,
float angle,
bh_quat_t *result)
{
float c, s;
c = cosf(angle / 2.0f);
s = sinf(angle / 2.0f);
result->x = axis->x * s;
result->y = axis->y * s;
result->z = axis->z * s;
result->w = c;
return result;
}
void bh_quat_euler(const bh_quat_t *in,
float *roll,
float *pitch,
float *yaw)
{
float ww, xw, yw, zw, xx, xy, xz, yy, yz, zz, angle;
xx = in->x * in->x;
xy = in->x * in->y;
xz = in->x * in->z;
xw = in->x * in->w;
yy = in->y * in->y;
yz = in->y * in->z;
yw = in->y * in->w;
zz = in->z * in->z;
zw = in->z * in->w;
ww = in->w * in->w;
angle = 2.0f * (yw - xz);
if (angle > 1.0f)
angle = 1.0f;
if (angle < -1.0f)
angle = -1.0f;
*pitch = asinf(angle);
if (*pitch == (M_PI / 2.0f))
{
*roll = 0.0f;
*yaw = -2.0f * atan2f(in->x, in->w);
}
else if (*pitch == (M_PI / -2.0f))
{
*roll = 0.0f;
*yaw = 2.0f * atan2f(in->x, in->w);
}
else
{
*roll = atan2f(2.0f * (xw + yz), ww - xx - yy + zz);
*yaw = atan2f(2.0f * (zw + xy), ww + xx - yy - zz);
}
}
void bh_quat_rotation(const bh_quat_t *in,
bh_point3f_t *axis,
float *angle)
{
float tmp;
*angle = 2.0f * acosf(in->w);
tmp = sqrtf(1.0f - in->w * in->w);
if (*angle == 0.0f)
{
axis->x = 1.0f;
axis->y = 0.0f;
axis->z = 0.0f;
}
else
{
axis->x = in->x / tmp;
axis->y = in->y / tmp;
axis->z = in->z / tmp;
}
}
bh_matrix4f_t *bh_quat_matrix(const bh_quat_t *in,
bh_matrix4f_t *result)
{
float xx, xy, xz, xw, yy, yz, yw, zz, zw;
xx = in->x * in->x;
xy = in->x * in->y;
xz = in->x * in->z;
xw = in->x * in->w;
yy = in->y * in->y;
yz = in->y * in->z;
yw = in->y * in->w;
zz = in->z * in->z;
zw = in->z * in->w;
bh_matrix4f_identity(result);
result->x.x = 1.0f - 2.0f * (yy + zz);
result->x.y = 2.0f * (xy + zw);
result->x.z = 2.0f * (xz - yw);
result->y.x = 2.0f * (xy - zw);
result->y.y = 1.0f - 2.0f * (xx + zz);
result->y.z = 2.0f * (yz + xw);
result->z.x = 2.0f * (xz + yw);
result->z.y = 2.0f * (yz - xw);
result->z.z = 1.0f - 2.0f * (xx + yy);
return result;
}
bh_matrix4f_t *bh_matrix4f_identity(bh_matrix4f_t *result)
{
static const bh_matrix4f_t ident = {
{1.0f, 0.0f, 0.0f, 0.0f},
{0.0f, 1.0f, 0.0f, 0.0f},
{0.0f, 0.0f, 1.0f, 0.0f},
{0.0f, 0.0f, 0.0f, 1.0f}
};
*result = ident;
return result;
}
bh_matrix4f_t *bh_matrix4f_add(const bh_matrix4f_t *a,
const bh_matrix4f_t *b,
bh_matrix4f_t *result)
{
bh_point4f_add(&a->x, &b->x, &result->x);
bh_point4f_add(&a->y, &b->y, &result->y);
bh_point4f_add(&a->z, &b->z, &result->z);
bh_point4f_add(&a->w, &b->w, &result->w);
return result;
}
bh_matrix4f_t *bh_matrix4f_sub(const bh_matrix4f_t *a,
const bh_matrix4f_t *b,
bh_matrix4f_t *result)
{
bh_point4f_sub(&a->x, &b->x, &result->x);
bh_point4f_sub(&a->y, &b->y, &result->y);
bh_point4f_sub(&a->z, &b->z, &result->z);
bh_point4f_sub(&a->w, &b->w, &result->w);
return result;
}
bh_matrix4f_t *bh_matrix4f_mul(const bh_matrix4f_t *a,
const bh_matrix4f_t *b,
bh_matrix4f_t *result)
{
bh_matrix4f_t tmp;
bh_point4f_t row;
row.x = row.y = row.z = row.w = b->x.x; bh_point4f_mul(&a->x, &row, &tmp.x);
row.x = row.y = row.z = row.w = b->x.y; bh_point4f_madd(&a->y, &row, &tmp.x, &tmp.x);
row.x = row.y = row.z = row.w = b->x.z; bh_point4f_madd(&a->z, &row, &tmp.x, &tmp.x);
row.x = row.y = row.z = row.w = b->x.w; bh_point4f_madd(&a->w, &row, &tmp.x, &tmp.x);
row.x = row.y = row.z = row.w = b->y.x; bh_point4f_mul(&a->x, &row, &tmp.y);
row.x = row.y = row.z = row.w = b->y.y; bh_point4f_madd(&a->y, &row, &tmp.y, &tmp.y);
row.x = row.y = row.z = row.w = b->y.z; bh_point4f_madd(&a->z, &row, &tmp.y, &tmp.y);
row.x = row.y = row.z = row.w = b->y.w; bh_point4f_madd(&a->w, &row, &tmp.y, &tmp.y);
row.x = row.y = row.z = row.w = b->z.x; bh_point4f_mul(&a->x, &row, &tmp.z);
row.x = row.y = row.z = row.w = b->z.y; bh_point4f_madd(&a->y, &row, &tmp.z, &tmp.z);
row.x = row.y = row.z = row.w = b->z.z; bh_point4f_madd(&a->z, &row, &tmp.z, &tmp.z);
row.x = row.y = row.z = row.w = b->z.w; bh_point4f_madd(&a->w, &row, &tmp.z, &tmp.z);
row.x = row.y = row.z = row.w = b->w.x; bh_point4f_mul(&a->x, &row, &tmp.w);
row.x = row.y = row.z = row.w = b->w.y; bh_point4f_madd(&a->y, &row, &tmp.w, &tmp.w);
row.x = row.y = row.z = row.w = b->w.z; bh_point4f_madd(&a->z, &row, &tmp.w, &tmp.w);
row.x = row.y = row.z = row.w = b->w.w; bh_point4f_madd(&a->w, &row, &tmp.w, &tmp.w);
*result = tmp;
return result;
}
bh_matrix4f_t *bh_matrix4f_scale(const bh_matrix4f_t *a,
float b,
bh_matrix4f_t *result)
{
bh_point4f_scale(&a->x, b, &result->x);
bh_point4f_scale(&a->y, b, &result->y);
bh_point4f_scale(&a->z, b, &result->z);
bh_point4f_scale(&a->w, b, &result->w);
return result;
}
bh_matrix4f_t *bh_matrix4f_transpose(const bh_matrix4f_t *in,
bh_matrix4f_t *result)
{
bh_matrix4f_t tmp;
tmp.x.x = in->x.x;
tmp.x.y = in->y.x;
tmp.x.z = in->z.x;
tmp.x.w = in->w.x;
tmp.y.x = in->x.y;
tmp.y.y = in->y.y;
tmp.y.z = in->z.y;
tmp.y.w = in->w.y;
tmp.z.x = in->x.z;
tmp.z.y = in->y.z;
tmp.z.z = in->z.z;
tmp.z.w = in->w.z;
tmp.w.x = in->x.w;
tmp.w.y = in->y.w;
tmp.w.z = in->z.w;
tmp.w.w = in->w.w;
*result = tmp;
return result;
}
float bh_matrix4f_trace(const bh_matrix4f_t *in)
{
return in->x.x + in->y.y + in->z.z + in->w.w;
}
float bh_matrix4f_determinant(const bh_matrix4f_t *in)
{
float a, b, c, d, e, f, result;
a = in->x.z * in->y.w - in->x.w * in->y.z;
b = in->x.z * in->z.w - in->x.w * in->z.z;
c = in->x.z * in->w.w - in->x.w * in->w.z;
d = in->y.z * in->z.w - in->y.w * in->z.z;
e = in->y.z * in->w.w - in->y.w * in->w.z;
f = in->z.z * in->w.w - in->z.w * in->w.z;
result = 0.0f;
result += in->x.x * (in->y.y * f - in->z.y * e + in->w.y * d);
result -= in->y.x * (in->x.y * f - in->z.y * c + in->w.y * b);
result += in->z.x * (in->x.y * e - in->y.y * c + in->w.y * a);
result -= in->w.x * (in->x.y * d - in->y.y * b + in->z.y * a);
return result;
}
bh_matrix4f_t *bh_matrix4f_inverse(const bh_matrix4f_t *in,
bh_matrix4f_t *result)
{
float a, b, c, d, e, f, det;
bh_matrix4f_t tmp;
a = in->x.z * in->y.w - in->x.w * in->y.z;
b = in->x.z * in->z.w - in->x.w * in->z.z;
c = in->x.z * in->w.w - in->x.w * in->w.z;
d = in->y.z * in->z.w - in->y.w * in->z.z;
e = in->y.z * in->w.w - in->y.w * in->w.z;
f = in->z.z * in->w.w - in->z.w * in->w.z;
tmp.x.x = (in->y.y * f - in->z.y * e + in->w.y * d);
tmp.x.y = -(in->x.y * f - in->z.y * c + in->w.y * b);
tmp.x.z = (in->x.y * e - in->y.y * c + in->w.y * a);
tmp.x.w = -(in->x.y * d - in->y.y * b + in->z.y * a);
det = 0.0f;
det += in->x.x * tmp.x.x;
det += in->y.x * tmp.x.y;
det += in->z.x * tmp.x.z;
det += in->w.x * tmp.x.w;
if (det == 0.0f)
return bh_matrix4f_identity(result);
tmp.y.x = -(in->y.x * f - in->z.x * e + in->w.x * d);
tmp.y.y = (in->x.x * f - in->z.x * c + in->w.x * b);
tmp.y.z = -(in->x.x * e - in->y.x * c + in->w.x * a);
tmp.y.w = (in->x.x * d - in->y.x * b + in->z.x * a);
a = in->x.y * in->y.w - in->x.w * in->y.y;
b = in->x.y * in->z.w - in->x.w * in->z.y;
c = in->x.y * in->w.w - in->x.w * in->w.y;
d = in->y.y * in->z.w - in->y.w * in->z.y;
e = in->y.y * in->w.w - in->y.w * in->w.y;
f = in->z.y * in->w.w - in->z.w * in->w.y;
tmp.z.x = (in->y.x * f - in->z.x * e + in->w.x * d);
tmp.z.y = -(in->x.x * f - in->z.x * c + in->w.x * b);
tmp.z.z = (in->x.x * e - in->y.x * c + in->w.x * a);
tmp.z.w = -(in->x.x * d - in->y.x * b + in->z.x * a);
a = in->x.y * in->y.z - in->x.z * in->y.y;
b = in->x.y * in->z.z - in->x.z * in->z.y;
c = in->x.y * in->w.z - in->x.z * in->w.y;
d = in->y.y * in->z.z - in->y.z * in->z.y;
e = in->y.y * in->w.z - in->y.z * in->w.y;
f = in->z.y * in->w.z - in->z.z * in->w.y;
tmp.w.x = -(in->y.x * f - in->z.x * e + in->w.x * d);
tmp.w.y = (in->x.x * f - in->z.x * c + in->w.x * b);
tmp.w.z = -(in->x.x * e - in->y.x * c + in->w.x * a);
tmp.w.w = (in->x.x * d - in->y.x * b + in->z.x * a);
return bh_matrix4f_scale(&tmp, 1.0f / det, result);
}
bh_matrix4f_t *bh_matrix4f_scaling(float x,
float y,
float z,
bh_matrix4f_t *result)
{
bh_matrix4f_identity(result);
result->x.x = x;
result->y.y = y;
result->z.z = z;
return result;
}
bh_matrix4f_t *bh_matrix4f_translation(float x,
float y,
float z,
bh_matrix4f_t *result)
{
bh_matrix4f_identity(result);
result->w.x = x;
result->w.y = y;
result->w.z = z;
return result;
}
bh_matrix4f_t *bh_matrix4f_rotation_x(float angle,
bh_matrix4f_t *result)
{
float c, s;
c = cosf(angle);
s = sinf(angle);
bh_matrix4f_identity(result);
result->y.y = c;
result->z.z = c;
result->z.y = -s;
result->y.z = s;
return result;
}
bh_matrix4f_t *bh_matrix4f_rotation_y(float angle,
bh_matrix4f_t *result)
{
float c, s;
c = cosf(angle);
s = sinf(angle);
bh_matrix4f_identity(result);
result->x.x = c;
result->z.z = c;
result->z.x = s;
result->x.z = -s;
return result;
}
bh_matrix4f_t *bh_matrix4f_rotation_z(float angle,
bh_matrix4f_t *result)
{
float c, s;
c = cosf(angle);
s = sinf(angle);
bh_matrix4f_identity(result);
result->x.x = c;
result->y.y = c;
result->y.x = -s;
result->x.y = s;
return result;
}
bh_matrix4f_t *bh_matrix4f_rotation(const bh_point3f_t *axis,
float angle,
bh_matrix4f_t *result)
{
float x, y, z, length;
float c, s, moc, xx, xy, xz, yy, yz, zz;
length = bh_point3f_length(axis);
if (length == 0.0f)
return bh_matrix4f_identity(result);
x = axis->x / length;
y = axis->y / length;
z = axis->z / length;
/* Handle simple axis aligned rotations */
if (x == 0.0f)
{
if (y == 0.0f)
{
if (z != 0.0f)
{
if (z < 0.0f)
return bh_matrix4f_rotation_z(-angle, result);
return bh_matrix4f_rotation_z(angle, result);
}
}
else if (z == 0.0f)
{
if (y < 0.0f)
return bh_matrix4f_rotation_y(-angle, result);
return bh_matrix4f_rotation_y(angle, result);
}
}
else if (y == 0.0f && z == 0.0f)
{
if (x < 0.0f)
return bh_matrix4f_rotation_x(-angle, result);
return bh_matrix4f_rotation_x(angle, result);
}
/* Rotate around arbitrary axis */
bh_matrix4f_identity(result);
c = cosf(angle);
s = sinf(angle);
moc = 1.0f - c;
xx = x * x;
xy = x * y;
xz = x * z;
yy = y * y;
yz = y * z;
zz = z * z;
result->x.x = c + xx * moc;
result->y.x = xy * moc - z * s;
result->z.x = xz * moc + y * s;
result->x.y = xy * moc + z * s;
result->y.y = c + yy * moc;
result->z.y = yz * moc - x * s;
result->x.z = xz * moc - y * s;
result->y.z = yz * moc + x * s;
result->z.z = c + zz * moc;
return result;
}
bh_matrix4f_t *bh_matrix4f_rotation_euler(float roll,
float pitch,
float yaw,
bh_matrix4f_t *result)
{
float rs, rc, ys, yc, ps, pc;
rs = sinf(roll);
rc = cosf(roll);
ps = sinf(pitch);
pc = cosf(pitch);
ys = sinf(yaw);
yc = cosf(yaw);
bh_matrix4f_identity(result);
result->x.x = pc * yc;
result->x.y = pc * ys;
result->x.z = -ps;
result->y.x = ps * rs * yc - rc * ys;
result->y.y = ps * rs * ys + rc * yc;
result->y.z = pc * rs;
result->z.x = rs * ys + ps * rc * yc;
result->z.y = ps * rc * ys - rs * yc;
result->z.z = pc * rc;
return result;
}
bh_matrix4f_t *bh_matrix4f_rotation_quat(bh_quat_t *rotation,
bh_matrix4f_t *result)
{
return bh_quat_matrix(rotation, result);
}
bh_matrix4f_t *bh_matrix4f_ortho(float x_min,
float x_max,
float y_min,
float y_max,
float z_min,
float z_max,
bh_matrix4f_t *result)
{
float dx, dy, dz;
dx = x_max - x_min;
dy = y_max - y_min;
dz = z_max - z_min;
bh_matrix4f_identity(result);
result->x.x = 2.0f / dx;
result->y.y = 2.0f / dy;
result->z.z = -2.0f / dz;
result->w.x = -(x_max + x_min) / dx;
result->w.y = -(y_max + y_min) / dy;
result->w.z = -(z_max + z_min) / dz;
return result;
}
bh_matrix4f_t *bh_matrix4f_perspective(float fov,
float aspect,
float z_min,
float z_max,
bh_matrix4f_t *result)
{
float t, dz;
dz = z_max - z_min;
t = tanf(fov / 2.0f);
bh_matrix4f_identity(result);
result->x.x = 1.0f / (aspect * t);
result->y.y = 1.0f / t;
result->z.z = -(z_max + z_min) / dz;
result->z.w = -1.0f;
result->w.z = -(2.0f * z_max * z_min) / dz;
result->w.w = 0.0f;
return result;
}
bh_matrix4f_t *bh_matrix4f_lookat(const bh_point3f_t *camera,
const bh_point3f_t *at,
const bh_point3f_t *up,
bh_matrix4f_t *result)
{
bh_point3f_t cdir, cright, cup;
bh_point3f_sub(camera, at, &cdir); bh_point3f_normal(&cdir, &cdir);
bh_point3f_cross(up, &cdir, &cright); bh_point3f_normal(&cright, &cright);
bh_point3f_cross(&cdir, &cright, &cup);
result->x.x = cright.x;
result->x.y = cup.x;
result->x.z = cdir.x;
result->x.w = 0.0f;
result->y.x = cright.y;
result->y.y = cup.y;
result->y.z = cdir.y;
result->y.w = 0.0f;
result->z.x = cright.z;
result->z.y = cup.z;
result->z.z = cdir.z;
result->z.w = 0.0f;
result->w.x = -bh_point3f_dot(&cright, camera);
result->w.y = -bh_point3f_dot(&cup, camera);
result->w.z = -bh_point3f_dot(&cdir, camera);
result->w.w = 1.0f;
return result;
}
bh_point3f_t *bh_matrix4f_transform_point3f(const bh_matrix4f_t *a,
const bh_point3f_t *b,
bh_point3f_t *result)
{
bh_point4f_t tmp, row;
row.x = row.y = row.z = row.w = b->x; bh_point4f_mul(&a->x, &row, &tmp);
row.x = row.y = row.z = row.w = b->y; bh_point4f_madd(&a->y, &row, &tmp, &tmp);
row.x = row.y = row.z = row.w = b->z; bh_point4f_madd(&a->z, &row, &tmp, &tmp);
row.x = row.y = row.z = row.w = 1.0f; bh_point4f_madd(&a->w, &row, &tmp, &tmp);
result->x = tmp.x;
result->y = tmp.y;
result->z = tmp.z;
return result;
}
bh_point4f_t *bh_matrix4f_transform_point4f(const bh_matrix4f_t *a,
const bh_point4f_t *b,
bh_point4f_t *result)
{
bh_point4f_t tmp, row;
row.x = row.y = row.z = row.w = b->x; bh_point4f_mul(&a->x, &row, &tmp);
row.x = row.y = row.z = row.w = b->y; bh_point4f_madd(&a->y, &row, &tmp, &tmp);
row.x = row.y = row.z = row.w = b->z; bh_point4f_madd(&a->z, &row, &tmp, &tmp);
row.x = row.y = row.z = row.w = b->w; bh_point4f_madd(&a->w, &row, &tmp, &tmp);
*result = tmp;
return result;
}
bh_matrix3f_t *bh_matrix3f_identity(bh_matrix3f_t *result)
{
static const bh_matrix3f_t ident = {
{1.0f, 0.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, 0.0f, 1.0f}
};
*result = ident;
return result;
}
bh_matrix3f_t *bh_matrix3f_add(const bh_matrix3f_t *a,
const bh_matrix3f_t *b,
bh_matrix3f_t *result)
{
bh_point3f_add(&a->x, &b->x, &result->x);
bh_point3f_add(&a->y, &b->y, &result->y);
bh_point3f_add(&a->z, &b->z, &result->z);
return result;
}
bh_matrix3f_t *bh_matrix3f_sub(const bh_matrix3f_t *a,
const bh_matrix3f_t *b,
bh_matrix3f_t *result)
{
bh_point3f_sub(&a->x, &b->x, &result->x);
bh_point3f_sub(&a->y, &b->y, &result->y);
bh_point3f_sub(&a->z, &b->z, &result->z);
return result;
}
bh_matrix3f_t *bh_matrix3f_mul(const bh_matrix3f_t *a,
const bh_matrix3f_t *b,
bh_matrix3f_t *result)
{
bh_matrix3f_t tmp;
bh_point3f_t row;
row.x = row.y = row.z = b->x.x; bh_point3f_mul(&a->x, &row, &tmp.x);
row.x = row.y = row.z = b->x.y; bh_point3f_madd(&a->y, &row, &tmp.x, &tmp.x);
row.x = row.y = row.z = b->x.z; bh_point3f_madd(&a->z, &row, &tmp.x, &tmp.x);
row.x = row.y = row.z = b->y.x; bh_point3f_mul(&a->x, &row, &tmp.y);
row.x = row.y = row.z = b->y.y; bh_point3f_madd(&a->y, &row, &tmp.y, &tmp.y);
row.x = row.y = row.z = b->y.z; bh_point3f_madd(&a->z, &row, &tmp.y, &tmp.y);
row.x = row.y = row.z = b->z.x; bh_point3f_mul(&a->x, &row, &tmp.z);
row.x = row.y = row.z = b->z.y; bh_point3f_madd(&a->y, &row, &tmp.z, &tmp.z);
row.x = row.y = row.z = b->z.z; bh_point3f_madd(&a->z, &row, &tmp.z, &tmp.z);
*result = tmp;
return result;
}
bh_matrix3f_t *bh_matrix3f_scale(const bh_matrix3f_t *a,
float b,
bh_matrix3f_t *result)
{
bh_point3f_scale(&a->x, b, &result->x);
bh_point3f_scale(&a->y, b, &result->y);
bh_point3f_scale(&a->z, b, &result->z);
return result;
}
bh_matrix3f_t *bh_matrix3f_transpose(const bh_matrix3f_t *in,
bh_matrix3f_t *result)
{
bh_matrix3f_t tmp;
tmp.x.x = in->x.x;
tmp.x.y = in->y.x;
tmp.x.z = in->z.x;
tmp.y.x = in->x.y;
tmp.y.y = in->y.y;
tmp.y.z = in->z.y;
tmp.z.x = in->x.z;
tmp.z.y = in->y.z;
tmp.z.z = in->z.z;
*result = tmp;
return result;
}
float bh_matrix3f_trace(const bh_matrix3f_t *in)
{
return in->x.x + in->y.y + in->z.z;
}
float bh_matrix3f_determinant(const bh_matrix3f_t *in)
{
float a, b, c, result;
a = in->y.y * in->z.z - in->z.y * in->y.z;
b = in->x.y * in->z.z - in->z.y * in->x.z;
c = in->x.y * in->y.z - in->y.y * in->x.z;
result = 0.0f;
result += in->x.x * a;
result -= in->y.x * b;
result += in->z.x * c;
return result;
}
bh_matrix3f_t *bh_matrix3f_inverse(const bh_matrix3f_t *in,
bh_matrix3f_t *result)
{
float a, b, c, det;
bh_matrix3f_t tmp;
a = in->y.y * in->z.z - in->z.y * in->y.z;
b = in->x.y * in->z.z - in->z.y * in->x.z;
c = in->x.y * in->y.z - in->y.y * in->x.z;
tmp.x.x = a;
tmp.x.y = -b;
tmp.x.z = c;
det = 0.0f;
det += in->x.x * tmp.x.x;
det += in->y.x * tmp.x.y;
det += in->z.x * tmp.x.z;
if (det == 0.0f)
return bh_matrix3f_identity(result);
a = in->y.x * in->z.z - in->z.x * in->y.z;
b = in->x.x * in->z.z - in->z.x * in->x.z;
c = in->x.x * in->y.z - in->y.x * in->x.z;
tmp.y.x = -a;
tmp.y.y = b;
tmp.y.z = -c;
a = in->y.x * in->z.y - in->z.x * in->y.y;
b = in->x.x * in->z.y - in->z.x * in->x.y;
c = in->x.x * in->y.y - in->y.x * in->x.y;
tmp.z.x = a;
tmp.z.y = -b;
tmp.z.z = c;
return bh_matrix3f_scale(&tmp, 1.0f / det, result);
}
bh_matrix3f_t *bh_matrix3f_scaling(float x,
float y,
bh_matrix3f_t *result)
{
bh_matrix3f_identity(result);
result->x.x = x;
result->y.y = y;
return result;
}
bh_matrix3f_t *bh_matrix3f_translation(float x,
float y,
bh_matrix3f_t *result)
{
bh_matrix3f_identity(result);
result->z.x = x;
result->z.y = y;
return result;
}
bh_matrix3f_t *bh_matrix3f_rotation(float angle,
bh_matrix3f_t *result)
{
float c, s;
c = cosf(angle);
s = sinf(angle);
bh_matrix3f_identity(result);
result->x.x = c;
result->y.y = c;
result->y.x = -s;
result->x.y = s;
return result;
}
bh_point2f_t *bh_matrix3f_transform_point2f(const bh_matrix3f_t *a,
const bh_point2f_t *b,
bh_point2f_t *result)
{
bh_point3f_t tmp, row;
row.x = row.y = row.z = b->x; bh_point3f_mul(&a->x, &row, &tmp);
row.x = row.y = row.z = b->y; bh_point3f_madd(&a->y, &row, &tmp, &tmp);
row.x = row.y = row.z = 1.0f; bh_point3f_madd(&a->z, &row, &tmp, &tmp);
result->x = tmp.x;
result->y = tmp.y;
return result;
}
bh_point3f_t *bh_matrix3f_transform_point3f(const bh_matrix3f_t *a,
const bh_point3f_t *b,
bh_point3f_t *result)
{
bh_point3f_t tmp, row;
row.x = row.y = row.z = b->x; bh_point3f_mul(&a->x, &row, &tmp);
row.x = row.y = row.z = b->y; bh_point3f_madd(&a->y, &row, &tmp, &tmp);
row.x = row.y = row.z = b->z; bh_point3f_madd(&a->z, &row, &tmp, &tmp);
result->x = tmp.x;
result->y = tmp.y;
result->z = tmp.z;
return result;
}