feat: bench and test
This commit is contained in:
parent
0d985ae7e2
commit
75aa02b34c
|
@ -0,0 +1,40 @@
|
|||
cmake_minimum_required (VERSION 3.15)
|
||||
|
||||
project (benchtest)
|
||||
|
||||
# spdlog requires exception enable
|
||||
# or use the following option:
|
||||
# add_compile_definitions (SPDLOG_NO_EXCEPTIONS)
|
||||
set (ADMAKE_DISABLE_ADDRESS_SANITIZER ON)
|
||||
set (ADMAKE_ENABLE_WARNINGS ON)
|
||||
|
||||
include (CMakeListsPub)
|
||||
set (TARGET_NAME ${CMAKE_PROJECT_NAME})
|
||||
|
||||
append_3rd_modules (gtest benchmark)
|
||||
|
||||
########### Unit test ###########
|
||||
file (GLOB_RECURSE TEST_SRC_FILES
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/test/*.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/test/*.c")
|
||||
add_executable (${TARGET_NAME}_test ${TEST_SRC_FILES})
|
||||
target_include_directories (${TARGET_NAME}_test
|
||||
PRIVATE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/test")
|
||||
target_link_libraries (${TARGET_NAME}_test
|
||||
PRIVATE
|
||||
${GTEST_LIB})
|
||||
|
||||
########### Benchmark ###########
|
||||
file (GLOB_RECURSE BENCH_SRC_FILES
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/bench/*.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/bench/*.c")
|
||||
add_executable (${TARGET_NAME}_bench ${BENCH_SRC_FILES})
|
||||
target_include_directories (${TARGET_NAME}_bench
|
||||
PRIVATE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/test"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/bench")
|
||||
target_link_libraries (${TARGET_NAME}_bench
|
||||
PRIVATE
|
||||
${BENCHMARK_LIB})
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#include "benchmark/benchmark.h"
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
char arg0_default[] = "benchmark";
|
||||
char* args_default = arg0_default;
|
||||
|
||||
if (!argv) {
|
||||
argc = 1;
|
||||
argv = &args_default;
|
||||
}
|
||||
|
||||
::benchmark::Initialize(&argc, argv);
|
||||
if (::benchmark::ReportUnrecognizedArguments(argc, argv)) {
|
||||
return 1;
|
||||
}
|
||||
::benchmark::RunSpecifiedBenchmarks();
|
||||
::benchmark::Shutdown();
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,928 @@
|
|||
#include "vmath.h"
|
||||
|
||||
/* Vector Operations */
|
||||
/* Vector2f */
|
||||
void Vector2f_AddInPlace(Vector2f *o, Vector2f other) {
|
||||
o->x += other.x;
|
||||
o->y += other.y;
|
||||
}
|
||||
|
||||
Vector2f Vector2f_Add(Vector2f o, Vector2f other) {
|
||||
Vector2f r;
|
||||
r.x = o.x + other.x;
|
||||
r.y = o.y + other.y;
|
||||
return r;
|
||||
}
|
||||
|
||||
void Vector2f_SubInPlace(Vector2f *o, Vector2f s) {
|
||||
o->x = o->x - s.x;
|
||||
o->y = o->y - s.y;
|
||||
}
|
||||
|
||||
Vector2f Vector2f_Sub(Vector2f o, Vector2f s) {
|
||||
Vector2f r;
|
||||
r.x = o.x - s.x;
|
||||
r.y = o.y - s.y;
|
||||
return r;
|
||||
}
|
||||
|
||||
void Vector2f_MulInPlace(Vector2f *o, float s) {
|
||||
o->x *= s;
|
||||
o->y *= s;
|
||||
}
|
||||
|
||||
Vector2f Vector2f_Mul(Vector2f o, float s) {
|
||||
Vector2f r;
|
||||
r.x = o.x * s;
|
||||
r.y = o.y * s;
|
||||
return r;
|
||||
}
|
||||
|
||||
void Vector2f_DivInPlace(Vector2f *o, float s) {
|
||||
Vector2f_MulInPlace(o, 1.f / s);
|
||||
}
|
||||
|
||||
Vector2f Vector2f_Div(Vector2f o, float s) {
|
||||
return Vector2f_Mul(o, 1.f / s);
|
||||
}
|
||||
|
||||
float Vector2f_Dot(Vector2f u, Vector2f v) {
|
||||
return u.x * v.x + u.y * v.y;
|
||||
}
|
||||
|
||||
float Vector2f_Cross(Vector2f u, Vector2f v) {
|
||||
return u.x * v.y - u.y * v.x;
|
||||
}
|
||||
|
||||
float Vector2f_Length(Vector2f v) {
|
||||
return (float)sqrt(v.x * v.x + v.y * v.y);
|
||||
}
|
||||
|
||||
Vector2f Vector2f_Reflect(Vector2f o, Vector2f normal) {
|
||||
float idotn2 = (normal.x * o.x + normal.y * o.y) * -2.f;
|
||||
return (Vector2f){o.x + idotn2 * normal.x, o.y + idotn2 * normal.y};
|
||||
}
|
||||
|
||||
void Vector2f_NormalizeInPlace(Vector2f *o) {
|
||||
float length = Vector2f_Length(*o);
|
||||
if (length > 0.f) {
|
||||
float inv = 1.f / length;
|
||||
o->x *= inv;
|
||||
o->y *= inv;
|
||||
}
|
||||
}
|
||||
|
||||
Vector2f Vector2f_Normalize(Vector2f o) {
|
||||
float length = Vector2f_Length(o);
|
||||
if (length > 0) {
|
||||
float inv = 1.f / length;
|
||||
return (Vector2f){o.x * inv, o.y * inv};
|
||||
}
|
||||
return (Vector2f){0.f, 0.f};
|
||||
}
|
||||
|
||||
Vector2f Vector2f_Lerp(Vector2f a, Vector2f b, float t) {
|
||||
return (Vector2f){Lerpf(a.x, b.x, t), Lerpf(a.y, b.y, t)};
|
||||
}
|
||||
|
||||
Vector2f Vector2f_Saturate(Vector2f o) {
|
||||
return (Vector2f){Saturatef(o.x), Saturatef(o.y)};
|
||||
}
|
||||
|
||||
/* Vector3f */
|
||||
void Vector3f_AddInPlace(Vector3f *o, Vector3f other) {
|
||||
o->x += other.x;
|
||||
o->y += other.y;
|
||||
o->z += other.z;
|
||||
}
|
||||
|
||||
Vector3f Vector3f_Add(Vector3f o, Vector3f other) {
|
||||
Vector3f r;
|
||||
r.x = o.x + other.x;
|
||||
r.y = o.y + other.y;
|
||||
r.z = o.z + other.z;
|
||||
return r;
|
||||
}
|
||||
|
||||
void Vector3f_SubInPlace(Vector3f *o, Vector3f s) {
|
||||
o->x = o->x - s.x;
|
||||
o->y = o->y - s.y;
|
||||
o->z = o->z - s.z;
|
||||
}
|
||||
|
||||
Vector3f Vector3f_Sub(Vector3f o, Vector3f s) {
|
||||
Vector3f r;
|
||||
r.x = o.x - s.x;
|
||||
r.y = o.y - s.y;
|
||||
r.z = o.z - s.z;
|
||||
return r;
|
||||
}
|
||||
|
||||
void Vector3f_MulInPlace(Vector3f *o, float s) {
|
||||
o->x *= s;
|
||||
o->y *= s;
|
||||
o->z *= s;
|
||||
}
|
||||
|
||||
Vector3f Vector3f_Mul(Vector3f o, float s) {
|
||||
Vector3f r;
|
||||
r.x = o.x * s;
|
||||
r.y = o.y * s;
|
||||
r.z = o.z * s;
|
||||
return r;
|
||||
}
|
||||
|
||||
void Vector3f_DivInPlace(Vector3f *o, float s) {
|
||||
Vector3f_MulInPlace(o, 1.f / s);
|
||||
}
|
||||
|
||||
Vector3f Vector3f_Div(Vector3f o, float s) {
|
||||
return Vector3f_Mul(o, 1.f / s);
|
||||
}
|
||||
|
||||
float Vector3f_Dot(Vector3f u, Vector3f v) {
|
||||
return u.x * v.x + u.y * v.y + u.z * v.z;
|
||||
}
|
||||
|
||||
Vector3f Vector3f_Cross(Vector3f u, Vector3f v) {
|
||||
return (Vector3f){u.y * v.z - u.z * v.y, u.z * v.x - u.x * v.z,
|
||||
u.x * v.y - u.y * v.x};
|
||||
}
|
||||
|
||||
float Vector3f_Length(Vector3f v) {
|
||||
return (float)sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
|
||||
}
|
||||
|
||||
void Vector3f_NormalizeInPlace(Vector3f *o) {
|
||||
float length = Vector3f_Length(*o);
|
||||
if (length > 0.f) {
|
||||
float inv = 1.f / length;
|
||||
o->x *= inv;
|
||||
o->y *= inv;
|
||||
o->z *= inv;
|
||||
}
|
||||
}
|
||||
|
||||
Vector3f Vector3f_Normalize(Vector3f o) {
|
||||
float length = Vector3f_Length(o);
|
||||
if (length > 0.f) {
|
||||
float inv = 1.f / length;
|
||||
return (Vector3f){o.x * inv, o.y * inv, o.z * inv};
|
||||
}
|
||||
return (Vector3f){0.f, 0.f, 0.f};
|
||||
}
|
||||
|
||||
Vector3f Vector3f_Lerp(Vector3f a, Vector3f b, float t) {
|
||||
return (Vector3f){Lerpf(a.x, b.x, t), Lerpf(a.y, b.y, t), Lerpf(a.z, b.z, t)};
|
||||
}
|
||||
|
||||
Vector3f Vector3f_Saturate(Vector3f o) {
|
||||
return (Vector3f){Saturatef(o.x), Saturatef(o.y), Saturatef(o.z)};
|
||||
}
|
||||
|
||||
/* Ray */
|
||||
Point3f Rayf_At(Rayf *o, float t) {
|
||||
return Vector3f_Add(o->origin, Vector3f_Mul(o->direction, t));
|
||||
}
|
||||
|
||||
/* Matrix Operations */
|
||||
/* Matrix 3x3 */
|
||||
double Matrix3x3f_Det(const Matrix3x3f *o) {
|
||||
float ret = 0;
|
||||
float **m = (float **)o->m;
|
||||
|
||||
ret += m[0][0] * m[1][1] * m[2][2] + m[1][0] * m[2][1] * m[0][2] +
|
||||
m[2][0] * m[0][1] * m[1][2];
|
||||
ret -= m[2][0] * m[1][1] * m[0][2] + m[0][0] * m[2][1] * m[1][2] +
|
||||
m[1][0] * m[0][1] * m[2][2];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Matrix3x3f_ScaleInPlace(Matrix3x3f *o, float s) {
|
||||
o->m11 *= s;
|
||||
o->m12 *= s;
|
||||
o->m13 *= s;
|
||||
|
||||
o->m21 *= s;
|
||||
o->m22 *= s;
|
||||
o->m23 *= s;
|
||||
|
||||
o->m31 *= s;
|
||||
o->m32 *= s;
|
||||
o->m33 *= s;
|
||||
}
|
||||
|
||||
Matrix3x3f Matrix3x3f_Scale(const Matrix3x3f *o, float s) {
|
||||
Matrix3x3f r;
|
||||
r.m11 = o->m11 * s;
|
||||
r.m12 = o->m12 * s;
|
||||
r.m13 = o->m13 * s;
|
||||
|
||||
r.m21 = o->m21 * s;
|
||||
r.m22 = o->m22 * s;
|
||||
r.m23 = o->m23 * s;
|
||||
|
||||
r.m31 = o->m31 * s;
|
||||
r.m32 = o->m32 * s;
|
||||
r.m33 = o->m33 * s;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void Matrix3x3f_Invert(const Matrix3x3f *o, Matrix3x3f *dest) {
|
||||
float det;
|
||||
float **m = (float **)o->m;
|
||||
float a = m[0][0], b = m[0][1], c = m[0][2], d = m[1][0], e = m[1][1],
|
||||
f = m[1][2], g = m[2][0], h = m[2][1], i = m[2][2];
|
||||
|
||||
float **dm = (float **)dest->m;
|
||||
|
||||
dm[0][0] = e * i - f * h;
|
||||
dm[0][1] = -(b * i - h * c);
|
||||
dm[0][2] = b * f - e * c;
|
||||
dm[1][0] = -(d * i - g * f);
|
||||
dm[1][1] = a * i - c * g;
|
||||
dm[1][2] = -(a * f - d * c);
|
||||
dm[2][0] = d * h - g * e;
|
||||
dm[2][1] = -(a * h - g * b);
|
||||
dm[2][2] = a * e - b * d;
|
||||
|
||||
det = 1.0f / (a * dm[0][0] + b * dm[1][0] + c * dm[2][0]);
|
||||
|
||||
Matrix3x3f_Scale(dest, det);
|
||||
}
|
||||
|
||||
void Matrix3x3f_TransposeInPlace(Matrix3x3f *o) {
|
||||
#define _SWAP(a, b) (((a) ^ (b)) && ((b) ^= (a) ^= (b), (a) ^= (b)))
|
||||
union {
|
||||
float f;
|
||||
int i;
|
||||
} x, y;
|
||||
|
||||
x.f = o->m12, y.f = o->m21;
|
||||
_SWAP(x.i, y.i);
|
||||
x.f = o->m13, y.f = o->m31;
|
||||
_SWAP(x.i, y.i);
|
||||
x.f = o->m21, y.f = o->m12;
|
||||
_SWAP(x.i, y.i);
|
||||
x.f = o->m23, y.f = o->m32;
|
||||
_SWAP(x.i, y.i);
|
||||
x.f = o->m31, y.f = o->m13;
|
||||
_SWAP(x.i, y.i);
|
||||
x.f = o->m32, y.f = o->m23;
|
||||
_SWAP(x.i, y.i);
|
||||
#undef _SWAP
|
||||
}
|
||||
|
||||
Vector3f Matrix3x3f_MulVector3f(const Matrix3x3f *o, Vector3f v) {
|
||||
Vector3f dest;
|
||||
|
||||
dest.x = o->m11 * v.x + o->m21 * v.y + o->m31 * v.z;
|
||||
dest.y = o->m12 * v.x + o->m22 * v.y + o->m32 * v.z;
|
||||
dest.x = o->m13 * v.x + o->m23 * v.y + o->m33 * v.z;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
Matrix3x3f Matrix3x3f_InvertTranspose(const Matrix3x3f *o) {
|
||||
Matrix3x3f dest;
|
||||
Matrix3x3f_Invert(o, &dest);
|
||||
Matrix3x3f_TransposeInPlace(&dest);
|
||||
return dest;
|
||||
}
|
||||
|
||||
Vector3f Vector3f_Barycentric(const Vector2i tri[3], Vector2i p) {
|
||||
Matrix3x3f a = {(float)tri[0].x, (float)tri[0].y, 1.0f,
|
||||
(float)tri[1].x, (float)tri[1].y, 1.0f,
|
||||
(float)tri[2].x, (float)tri[2].y, 1.0f};
|
||||
if (Matrix3x3f_Det(&a) < 1e-3) {
|
||||
return (Vector3f){
|
||||
-1, 1, 1}; // for a degenerate triangle generate negative coordinates,
|
||||
// it will be thrown away by the rasterizator
|
||||
}
|
||||
Matrix3x3f dest = Matrix3x3f_InvertTranspose(&a);
|
||||
return Matrix3x3f_MulVector3f(&dest,
|
||||
(Vector3f){(float)p.x, (float)p.y, 1.0f});
|
||||
}
|
||||
|
||||
Vector3f Vector2i_Barycentric(const Vector2i tri[3], const Vector2i p) {
|
||||
Vector3f r;
|
||||
float det = (tri[1].y - tri[2].y) * (tri[0].x - tri[2].x) +
|
||||
(tri[2].x - tri[1].x) * (tri[0].y - tri[2].y);
|
||||
r.x = ((tri[1].y - tri[2].y) * (p.x - tri[2].x) +
|
||||
(tri[2].x - tri[1].x) * (p.y - tri[2].y)) /
|
||||
det;
|
||||
r.y = ((tri[2].y - tri[0].y) * (p.x - tri[2].x) +
|
||||
(tri[0].x - tri[2].x) * (p.y - tri[2].y)) /
|
||||
det;
|
||||
r.z = 1.f - r.v[0] - r.v[1];
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
float Vector4f_Length(Vector4f v) { return Vector3f_Length(v.xyz); }
|
||||
|
||||
Vector4f Vector4f_Add(Vector4f x, Vector4f y) {
|
||||
Vector4f z;
|
||||
z.xyz = Vector3f_Add(x.xyz, y.xyz);
|
||||
z.w = 1.f;
|
||||
return z;
|
||||
}
|
||||
|
||||
Vector4f Vector4f_Sub(Vector4f x, Vector4f y) {
|
||||
Vector4f z;
|
||||
z.xyz = Vector3f_Sub(x.xyz, y.xyz);
|
||||
z.w = 1.f;
|
||||
return z;
|
||||
}
|
||||
|
||||
float Vector4f_Dot(Vector4f x, Vector4f y) {
|
||||
return Vector3f_Dot(x.xyz, y.xyz);
|
||||
}
|
||||
|
||||
Vector4f Vector4f_Cross(Vector4f x, Vector4f y) {
|
||||
Vector4f z;
|
||||
z.xyz = Vector3f_Cross(x.xyz, y.xyz);
|
||||
z.w = 1.f;
|
||||
return z;
|
||||
}
|
||||
|
||||
Vector4f Vector4f_Lerp(Vector4f x1, Vector4f x2, float t) {
|
||||
Vector4f z;
|
||||
z.xyz = Vector3f_Lerp(x1.xyz, x2.xyz, t);
|
||||
z.w = 1.0f;
|
||||
return z;
|
||||
}
|
||||
|
||||
void Vector4f_NormalizeInPlace(Vector4f *v) {
|
||||
Vector3f_NormalizeInPlace(&v->xyz);
|
||||
}
|
||||
|
||||
Vector4f Vector4f_Normalize(Vector4f v) {
|
||||
Vector4f r = {0.f, 0.f, 0.f, 1.f};
|
||||
r.xyz = Vector3f_Normalize(v.xyz);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Quaternion Operations */
|
||||
float Quaternionf_Dot(Quaternionf a, Quaternionf b) {
|
||||
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
|
||||
}
|
||||
|
||||
float Quaternionf_Length(Quaternionf q) {
|
||||
return (float)sqrt(Quaternionf_Dot(q, q));
|
||||
}
|
||||
|
||||
Quaternionf Quaternionf_Normalize(Quaternionf q) {
|
||||
float factor = 1 / Quaternionf_Length(q);
|
||||
return (Quaternionf){q.x * factor, q.y * factor, q.z * factor, q.w * factor};
|
||||
}
|
||||
|
||||
void Quaternionf_SetIdentity(Quaternionf *q) {
|
||||
q->x = 0.f;
|
||||
q->y = 0.f;
|
||||
q->z = 0.f;
|
||||
q->w = 1.f;
|
||||
}
|
||||
|
||||
// From D3DXMath
|
||||
//
|
||||
// Reference:
|
||||
// https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles#Source_code
|
||||
Quaternionf
|
||||
Quaternionf_RotationRollPitchYaw(float pitch, float yaw, float roll) {
|
||||
Quaternionf q;
|
||||
|
||||
// The math format: // roll (x), pitch (y), yaw (z), angles are in radians
|
||||
// double cr = cos(roll * 0.5);
|
||||
// double sr = sin(roll * 0.5);
|
||||
// double cp = cos(pitch * 0.5);
|
||||
// double sp = sin(pitch * 0.5);
|
||||
// double cy = cos(yaw * 0.5);
|
||||
// double sy = sin(yaw * 0.5);
|
||||
//
|
||||
// q.w = cr * cp * cy + sr * sp * sy;
|
||||
// q.x = sr * cp * cy - cr * sp * sy;
|
||||
// q.y = cr * sp * cy + sr * cp * sy;
|
||||
// q.z = cr * cp * sy - sr * sp * cy;
|
||||
|
||||
// The D3DXMath format(game format): pitch (x), yaw (y), roll (z)
|
||||
double cp = cos(pitch * 0.5);
|
||||
double sp = sin(pitch * 0.5);
|
||||
double cy = cos(yaw * 0.5);
|
||||
double sy = sin(yaw * 0.5);
|
||||
double cr = cos(roll * 0.5);
|
||||
double sr = sin(roll * 0.5);
|
||||
|
||||
q.w = cr * cp * cy + sr * sp * sy;
|
||||
q.x = cr * sp * cy + sr * cp * sy;
|
||||
q.y = cr * cp * sy - sr * sp * cy;
|
||||
q.z = sr * cp * cy - cr * sp * sy;
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
/*
|
||||
* For spherical linear interpolation, see
|
||||
* 3D Math Primer for Graphics and Game Development, 2nd Edition, Chapter 8
|
||||
*/
|
||||
Quaternionf Quaternionf_Slerp(Quaternionf a, Quaternionf b,
|
||||
float t) {
|
||||
float cos_angle = Quaternionf_Dot(a, b);
|
||||
if (cos_angle < 0) {
|
||||
b = (Quaternionf){-b.x, -b.y, -b.z, -b.w};
|
||||
cos_angle = -cos_angle;
|
||||
}
|
||||
if (cos_angle > 1 - EPSILON) {
|
||||
float x = Lerpf(a.x, b.x, t);
|
||||
float y = Lerpf(a.y, b.y, t);
|
||||
float z = Lerpf(a.z, b.z, t);
|
||||
float w = Lerpf(a.w, b.w, t);
|
||||
return (Quaternionf){x, y, z, w};
|
||||
} else {
|
||||
float angle = (float)acos(cos_angle);
|
||||
float sin_angle_inv = 1.f / (float)sin(angle);
|
||||
float angle_a = (1 - t) * angle;
|
||||
float angle_b = t * angle;
|
||||
float factor_a = (float)sin(angle_a) * sin_angle_inv;
|
||||
float factor_b = (float)sin(angle_b) * sin_angle_inv;
|
||||
float x = factor_a * a.x + factor_b * b.x;
|
||||
float y = factor_a * a.y + factor_b * b.y;
|
||||
float z = factor_a * a.z + factor_b * b.z;
|
||||
float w = factor_a * a.w + factor_b * b.w;
|
||||
return (Quaternionf){x, y, z, w};
|
||||
}
|
||||
}
|
||||
|
||||
Matrix4x4f Matrix4x4f_Add(Matrix4x4f a, Matrix4x4f b) {
|
||||
Matrix4x4f r;
|
||||
int i, j;
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
r.m[i][j] = a.m[i][j] + b.m[i][j];
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
Matrix4x4f Matrix4x4f_Sub(Matrix4x4f a, Matrix4x4f b) {
|
||||
Matrix4x4f r;
|
||||
int i, j;
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
r.m[i][j] = a.m[i][j] - b.m[i][j];
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
Matrix4x4f Matrix4x4f_MulMatrix4x4(Matrix4x4f o,
|
||||
Matrix4x4f other) {
|
||||
Matrix4x4f r;
|
||||
int i, j;
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
r.m[j][i] = (o.m[j][0] * other.m[0][i]) + (o.m[j][1] * other.m[1][i]) +
|
||||
(o.m[j][2] * other.m[2][i]) + (o.m[j][3] * other.m[3][i]);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void Matrix4x4f_ScaleInPlace(Matrix4x4f *o, float f) {
|
||||
int i, j;
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
o->m[i][j] *= f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Matrix4x4f Matrix4x4f_Scale(Matrix4x4f o, float f) {
|
||||
Matrix4x4f r;
|
||||
int i, j;
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
r.m[i][j] = o.m[i][j] * f;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int Matrix4x4f_Invert(Matrix4x4f o, Matrix4x4f *inv_out) {
|
||||
Matrix4x4f inv;
|
||||
float det;
|
||||
|
||||
inv.m11 = o.m22 * o.m33 * o.m44 - o.m22 * o.m34 * o.m43 -
|
||||
o.m32 * o.m23 * o.m44 + o.m32 * o.m24 * o.m43 +
|
||||
o.m42 * o.m23 * o.m34 - o.m43 * o.m24 * o.m33;
|
||||
|
||||
inv.m21 = -o.m21 * o.m33 * o.m44 + o.m21 * o.m34 * o.m43 + o.m31 * o.m23 * o.m44 -
|
||||
o.m31 * o.m24 * o.m43 - o.m41 * o.m23 * o.m34 + o.m41 * o.m24 * o.m33;
|
||||
|
||||
inv.m31 = o.m21 * o.m32 * o.m44 - o.m21 * o.m34 * o.m43 - o.m31 * o.m22 * o.m44 +
|
||||
o.m31 * o.m24 * o.m43 + o.m41 * o.m22 * o.m34 - o.m41 * o.m24 * o.m32;
|
||||
|
||||
inv.m41 = -o.m21 * o.m32 * o.m43 + o.m21 * o.m33 * o.m43 + o.m31 * o.m22 * o.m43 -
|
||||
o.m31 * o.m23 * o.m43 - o.m41 * o.m22 * o.m33 + o.m41 * o.m23 * o.m32;
|
||||
|
||||
inv.m12 = -o.m12 * o.m33 * o.m44 + o.m12 * o.m34 * o.m43 + o.m32 * o.m13 * o.m44 -
|
||||
o.m32 * o.m14 * o.m43 - o.m43 * o.m13 * o.m34 + o.m43 * o.m14 * o.m33;
|
||||
|
||||
inv.m22 = o.m11 * o.m33 * o.m44 - o.m11 * o.m34 * o.m43 - o.m31 * o.m13 * o.m44 +
|
||||
o.m31 * o.m14 * o.m43 + o.m41 * o.m13 * o.m34 - o.m41 * o.m14 * o.m33;
|
||||
|
||||
inv.m32 = -o.m11 * o.m32 * o.m44 + o.m11 * o.m34 * o.m43 + o.m31 * o.m12 * o.m44 -
|
||||
o.m31 * o.m14 * o.m43 - o.m41 * o.m12 * o.m34 + o.m41 * o.m14 * o.m32;
|
||||
|
||||
inv.m42 = o.m11 * o.m32 * o.m43 - o.m11 * o.m33 * o.m43 - o.m31 * o.m12 * o.m43 +
|
||||
o.m31 * o.m13 * o.m43 + o.m41 * o.m12 * o.m33 - o.m41 * o.m13 * o.m32;
|
||||
|
||||
inv.m13 = o.m12 * o.m23 * o.m44 - o.m12 * o.m24 * o.m43 - o.m22 * o.m13 * o.m44 +
|
||||
o.m22 * o.m14 * o.m43 + o.m43 * o.m13 * o.m24 - o.m43 * o.m14 * o.m23;
|
||||
|
||||
inv.m23 = -o.m11 * o.m23 * o.m44 + o.m11 * o.m24 * o.m43 + o.m21 * o.m13 * o.m44 -
|
||||
o.m21 * o.m14 * o.m43 - o.m41 * o.m13 * o.m24 + o.m41 * o.m14 * o.m23;
|
||||
|
||||
inv.m33 = o.m11 * o.m22 * o.m44 - o.m11 * o.m24 * o.m43 - o.m21 * o.m12 * o.m44 +
|
||||
o.m21 * o.m14 * o.m43 + o.m41 * o.m12 * o.m24 - o.m41 * o.m14 * o.m22;
|
||||
|
||||
inv.m43 = -o.m11 * o.m22 * o.m43 + o.m11 * o.m23 * o.m43 + o.m21 * o.m12 * o.m43 -
|
||||
o.m21 * o.m13 * o.m43 - o.m41 * o.m12 * o.m23 + o.m41 * o.m13 * o.m22;
|
||||
|
||||
inv.m14 = -o.m12 * o.m23 * o.m34 + o.m12 * o.m24 * o.m33 + o.m22 * o.m13 * o.m34 -
|
||||
o.m22 * o.m14 * o.m33 - o.m32 * o.m13 * o.m24 + o.m32 * o.m14 * o.m23;
|
||||
|
||||
inv.m24 = o.m11 * o.m23 * o.m34 - o.m11 * o.m24 * o.m33 - o.m21 * o.m13 * o.m34 +
|
||||
o.m21 * o.m14 * o.m33 + o.m31 * o.m13 * o.m24 - o.m31 * o.m14 * o.m23;
|
||||
|
||||
inv.m34 = -o.m11 * o.m22 * o.m34 + o.m11 * o.m24 * o.m32 + o.m21 * o.m12 * o.m34 -
|
||||
o.m21 * o.m14 * o.m32 - o.m31 * o.m12 * o.m24 + o.m31 * o.m14 * o.m22;
|
||||
|
||||
inv.m44 = o.m11 * o.m22 * o.m33 - o.m11 * o.m23 * o.m32 - o.m21 * o.m12 * o.m33 +
|
||||
o.m21 * o.m13 * o.m32 + o.m31 * o.m12 * o.m23 - o.m31 * o.m13 * o.m22;
|
||||
|
||||
det = o.m11 * inv.m11 + o.m12 * inv.m21 + o.m13 * inv.m31 + o.m14 * inv.m41;
|
||||
|
||||
if (det == 0.f) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*inv_out = Matrix4x4f_Scale(inv, 1.f / det);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// y = x * m
|
||||
void Matrix4x4f_Apply(Vector4f *y, const Vector4f *x,
|
||||
const Matrix4x4f *m) {
|
||||
float X = x->x, Y = x->y, Z = x->z, W = x->w;
|
||||
y->x = X * m->m[0][0] + Y * m->m[1][0] + Z * m->m[2][0] + W * m->m[3][0];
|
||||
y->y = X * m->m[0][1] + Y * m->m[1][1] + Z * m->m[2][1] + W * m->m[3][1];
|
||||
y->z = X * m->m[0][2] + Y * m->m[1][2] + Z * m->m[2][2] + W * m->m[3][2];
|
||||
y->w = X * m->m[0][3] + Y * m->m[1][3] + Z * m->m[2][3] + W * m->m[3][3];
|
||||
}
|
||||
|
||||
void Matrix4x4f_SetZero(Matrix4x4f *m) {
|
||||
memset(m->m, 0, sizeof(float) * 16);
|
||||
}
|
||||
|
||||
void Matrix4x4f_SetIdentity(Matrix4x4f *m) {
|
||||
Matrix4x4f_SetZero(m);
|
||||
m->m11 = m->m22 = m->m33 = m->m44 = 1.0f;
|
||||
}
|
||||
|
||||
void Matrix4x4f_SetTranslate(Matrix4x4f *m, float x, float y,
|
||||
float z) {
|
||||
Matrix4x4f_SetIdentity(m);
|
||||
m->m41 = x;
|
||||
m->m42 = y;
|
||||
m->m43 = z;
|
||||
}
|
||||
|
||||
void Matrix4x4f_SetScale(Matrix4x4f *m, float x, float y,
|
||||
float z) {
|
||||
Matrix4x4f_SetIdentity(m);
|
||||
m->m11 = x;
|
||||
m->m22 = y;
|
||||
m->m33 = z;
|
||||
}
|
||||
|
||||
void Matrix4x4f_SetRotate(Matrix4x4f *m, float x, float y,
|
||||
float z, float theta) {
|
||||
float qsin = (float)sin(theta * 0.5f);
|
||||
float qcos = (float)cos(theta * 0.5f);
|
||||
Vector4f vec = {x, y, z, 1.0f};
|
||||
float w = qcos;
|
||||
Vector4f_NormalizeInPlace(&vec);
|
||||
x = vec.x * qsin;
|
||||
y = vec.y * qsin;
|
||||
z = vec.z * qsin;
|
||||
m->m11 = 1 - 2 * y * y - 2 * z * z;
|
||||
m->m21 = 2 * x * y - 2 * w * z;
|
||||
m->m31 = 2 * x * z + 2 * w * y;
|
||||
m->m12 = 2 * x * y + 2 * w * z;
|
||||
m->m22 = 1 - 2 * x * x - 2 * z * z;
|
||||
m->m32 = 2 * y * z - 2 * w * x;
|
||||
m->m13 = 2 * x * z - 2 * w * y;
|
||||
m->m23 = 2 * y * z + 2 * w * x;
|
||||
m->m33 = 1 - 2 * x * x - 2 * y * y;
|
||||
m->m14 = m->m24 = m->m34 = 0.f;
|
||||
m->m41 = m->m42 = m->m43 = 0.f;
|
||||
m->m44 = 1.f;
|
||||
}
|
||||
|
||||
void Matrix4x4f_SetLookAt(Matrix4x4f *m, Vector4f eye, Vector4f at,
|
||||
Vector4f up) {
|
||||
Vector4f xaxis, yaxis, zaxis;
|
||||
|
||||
zaxis = Vector4f_Sub(at, eye);
|
||||
Vector4f_NormalizeInPlace(&zaxis);
|
||||
xaxis = Vector4f_Cross(up, zaxis);
|
||||
Vector4f_NormalizeInPlace(&xaxis);
|
||||
yaxis = Vector4f_Cross(zaxis, xaxis);
|
||||
|
||||
m->m11 = xaxis.x;
|
||||
m->m21 = xaxis.y;
|
||||
m->m31 = xaxis.z;
|
||||
m->m41 = -Vector4f_Dot(xaxis, eye);
|
||||
|
||||
m->m12 = yaxis.x;
|
||||
m->m22 = yaxis.y;
|
||||
m->m32 = yaxis.z;
|
||||
m->m42 = -Vector4f_Dot(yaxis, eye);
|
||||
|
||||
m->m13 = zaxis.x;
|
||||
m->m23 = zaxis.y;
|
||||
m->m33 = zaxis.z;
|
||||
m->m43 = -Vector4f_Dot(zaxis, eye);
|
||||
|
||||
m->m14 = m->m24 = m->m34 = 0.f;
|
||||
m->m44 = 1.f;
|
||||
}
|
||||
|
||||
// D3DXMatrixPerspectiveFovLH
|
||||
void Matrix4x4f_SetPerspective(Matrix4x4f *m, float fovy, float aspect,
|
||||
float zn, float zf) {
|
||||
float fax = 1.0f / (float)tan(fovy * 0.5f);
|
||||
Matrix4x4f_SetZero(m);
|
||||
m->m11 = (float)(fax / aspect);
|
||||
m->m22 = (float)(fax);
|
||||
m->m33 = zf / (zf - zn);
|
||||
m->m43 = -zn * zf / (zf - zn);
|
||||
m->m34 = 1;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
Matrix4x4f world; // 世界坐标变换
|
||||
Matrix4x4f view; // 摄影机坐标变换
|
||||
Matrix4x4f projection; // 投影变换
|
||||
Matrix4x4f transform; // transform = world * view * projection
|
||||
float w, h; // 屏幕大小
|
||||
} Transform;
|
||||
|
||||
// 矩阵更新,计算 transform = world * view * projection
|
||||
void Transform_Update(Transform *ts) {
|
||||
ts->transform = Matrix4x4f_MulMatrix4x4(
|
||||
Matrix4x4f_MulMatrix4x4(ts->world, ts->view), ts->projection);
|
||||
}
|
||||
|
||||
// 初始化,设置屏幕长宽
|
||||
void Transform_Init(Transform *ts, int width, int height) {
|
||||
float aspect = (float)width / ((float)height);
|
||||
Matrix4x4f_SetIdentity(&ts->world);
|
||||
Matrix4x4f_SetIdentity(&ts->view);
|
||||
Matrix4x4f_SetPerspective(&ts->projection, 3.1415926f * 0.5f, aspect, 1.0f,
|
||||
500.0f);
|
||||
ts->w = (float)width;
|
||||
ts->h = (float)height;
|
||||
Transform_Update(ts);
|
||||
}
|
||||
|
||||
// 将矢量 x 进行 project
|
||||
void Transform_Apply(const Transform *ts, Vector4f *y,
|
||||
const Vector4f *x) {
|
||||
Matrix4x4f_Apply(y, x, &ts->transform);
|
||||
}
|
||||
|
||||
// 检查齐次坐标同 cvv 的边界用于视锥裁剪
|
||||
int Transform_CheckCvv(const Vector4f *v) {
|
||||
float w = v->w;
|
||||
int check = 0;
|
||||
if (v->z < 0.0f)
|
||||
check |= 1;
|
||||
if (v->z > w)
|
||||
check |= 2;
|
||||
if (v->x < -w)
|
||||
check |= 4;
|
||||
if (v->x > w)
|
||||
check |= 8;
|
||||
if (v->y < -w)
|
||||
check |= 16;
|
||||
if (v->y > w)
|
||||
check |= 32;
|
||||
|
||||
return check;
|
||||
}
|
||||
|
||||
// 归一化,得到屏幕坐标
|
||||
void Transform_Homogenize(const Transform *ts, Vector4f *y,
|
||||
const Vector4f *x) {
|
||||
float rhw = 1.0f / x->w;
|
||||
y->x = (x->x * rhw + 1.0f) * ts->w * 0.5f;
|
||||
y->y = (1.0f - x->y * rhw) * ts->h * 0.5f;
|
||||
y->z = x->z * rhw;
|
||||
y->w = 1.0f;
|
||||
}
|
||||
|
||||
//=====================================================================
|
||||
// 几何计算:顶点、扫描线、边缘、矩形、步长计算
|
||||
//=====================================================================
|
||||
typedef struct {
|
||||
float r, g, b;
|
||||
} Color3f;
|
||||
|
||||
typedef struct {
|
||||
float u, v;
|
||||
} Texcoord2f;
|
||||
|
||||
typedef struct {
|
||||
Point4f pos;
|
||||
Texcoord2f tc;
|
||||
Color3f color;
|
||||
float rhw;
|
||||
} Vertexf;
|
||||
|
||||
typedef struct {
|
||||
Vertexf v, v1, v2;
|
||||
} Edgef;
|
||||
|
||||
typedef struct {
|
||||
float top, bottom;
|
||||
Edgef left, right;
|
||||
} Trapezoidf;
|
||||
|
||||
typedef struct {
|
||||
Vertexf v, step;
|
||||
int x, y, w;
|
||||
} Scanlinef;
|
||||
|
||||
void Vertexf_RhwInit(Vertexf *v) {
|
||||
float rhw = 1.0f / v->pos.w;
|
||||
v->rhw = rhw;
|
||||
v->tc.u *= rhw;
|
||||
v->tc.v *= rhw;
|
||||
v->color.r *= rhw;
|
||||
v->color.g *= rhw;
|
||||
v->color.b *= rhw;
|
||||
}
|
||||
|
||||
void Vertexf_Interpolate(Vertexf *y, const Vertexf *x1,
|
||||
const Vertexf *x2, float t) {
|
||||
y->pos = Vector4f_Lerp(x1->pos, x2->pos, t);
|
||||
y->tc.u = Interpolatef(x1->tc.u, x2->tc.u, t);
|
||||
y->tc.v = Interpolatef(x1->tc.v, x2->tc.v, t);
|
||||
y->color.r = Interpolatef(x1->color.r, x2->color.r, t);
|
||||
y->color.g = Interpolatef(x1->color.g, x2->color.g, t);
|
||||
y->color.b = Interpolatef(x1->color.b, x2->color.b, t);
|
||||
y->rhw = Interpolatef(x1->rhw, x2->rhw, t);
|
||||
}
|
||||
|
||||
void Vertexf_Division(Vertexf *y, const Vertexf *x1, const Vertexf *x2,
|
||||
float w) {
|
||||
float inv = 1.0f / w;
|
||||
y->pos.x = (x2->pos.x - x1->pos.x) * inv;
|
||||
y->pos.y = (x2->pos.y - x1->pos.y) * inv;
|
||||
y->pos.z = (x2->pos.z - x1->pos.z) * inv;
|
||||
y->pos.w = (x2->pos.w - x1->pos.w) * inv;
|
||||
y->tc.u = (x2->tc.u - x1->tc.u) * inv;
|
||||
y->tc.v = (x2->tc.v - x1->tc.v) * inv;
|
||||
y->color.r = (x2->color.r - x1->color.r) * inv;
|
||||
y->color.g = (x2->color.g - x1->color.g) * inv;
|
||||
y->color.b = (x2->color.b - x1->color.b) * inv;
|
||||
y->rhw = (x2->rhw - x1->rhw) * inv;
|
||||
}
|
||||
|
||||
void Vertexf_Add(Vertexf *y, const Vertexf *x) {
|
||||
y->pos.x += x->pos.x;
|
||||
y->pos.y += x->pos.y;
|
||||
y->pos.z += x->pos.z;
|
||||
y->pos.w += x->pos.w;
|
||||
y->rhw += x->rhw;
|
||||
y->tc.u += x->tc.u;
|
||||
y->tc.v += x->tc.v;
|
||||
y->color.r += x->color.r;
|
||||
y->color.g += x->color.g;
|
||||
y->color.b += x->color.b;
|
||||
}
|
||||
|
||||
// 根据三角形生成 0-2 个梯形,并且返回合法梯形的数量
|
||||
int Trapezoidf_InitTriangle(Trapezoidf *trap, const Vertexf *p1,
|
||||
const Vertexf *p2, const Vertexf *p3) {
|
||||
const Vertexf *p;
|
||||
float k, x;
|
||||
|
||||
if (p1->pos.y > p2->pos.y) {
|
||||
p = p1, p1 = p2, p2 = p;
|
||||
}
|
||||
|
||||
if (p1->pos.y > p3->pos.y) {
|
||||
p = p1, p1 = p3, p3 = p;
|
||||
}
|
||||
|
||||
if (p2->pos.y > p3->pos.y) {
|
||||
p = p2, p2 = p3, p3 = p;
|
||||
}
|
||||
|
||||
if (p1->pos.y == p2->pos.y && p1->pos.y == p3->pos.y) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (p1->pos.x == p2->pos.x && p1->pos.x == p3->pos.x) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (p1->pos.y == p2->pos.y) { // triangle down
|
||||
if (p1->pos.x > p2->pos.x) {
|
||||
p = p1, p1 = p2, p2 = p;
|
||||
}
|
||||
trap[0].top = p1->pos.y;
|
||||
trap[0].bottom = p3->pos.y;
|
||||
trap[0].left.v1 = *p1;
|
||||
trap[0].left.v2 = *p3;
|
||||
trap[0].right.v1 = *p2;
|
||||
trap[0].right.v2 = *p3;
|
||||
|
||||
return (trap[0].top < trap[0].bottom) ? 1 : 0;
|
||||
}
|
||||
|
||||
if (p2->pos.y == p3->pos.y) { // triangle up
|
||||
if (p2->pos.x > p3->pos.x) {
|
||||
p = p2, p2 = p3, p3 = p;
|
||||
}
|
||||
trap[0].top = p1->pos.y;
|
||||
trap[0].bottom = p3->pos.y;
|
||||
trap[0].left.v1 = *p1;
|
||||
trap[0].left.v2 = *p2;
|
||||
trap[0].right.v1 = *p1;
|
||||
trap[0].right.v2 = *p3;
|
||||
|
||||
return (trap[0].top < trap[0].bottom) ? 1 : 0;
|
||||
}
|
||||
|
||||
trap[0].top = p1->pos.y;
|
||||
trap[0].bottom = p2->pos.y;
|
||||
trap[1].top = p2->pos.y;
|
||||
trap[1].bottom = p3->pos.y;
|
||||
|
||||
k = (p3->pos.y - p1->pos.y) / (p2->pos.y - p1->pos.y);
|
||||
x = p1->pos.x + (p2->pos.x - p1->pos.x) * k;
|
||||
|
||||
if (x <= p3->pos.x) { // triangle left
|
||||
trap[0].left.v1 = *p1;
|
||||
trap[0].left.v2 = *p2;
|
||||
trap[0].right.v1 = *p1;
|
||||
trap[0].right.v2 = *p3;
|
||||
trap[1].left.v1 = *p2;
|
||||
trap[1].left.v2 = *p3;
|
||||
trap[1].right.v1 = *p1;
|
||||
trap[1].right.v2 = *p3;
|
||||
} else { // triangle right
|
||||
trap[0].left.v1 = *p1;
|
||||
trap[0].left.v2 = *p3;
|
||||
trap[0].right.v1 = *p1;
|
||||
trap[0].right.v2 = *p2;
|
||||
trap[1].left.v1 = *p1;
|
||||
trap[1].left.v2 = *p3;
|
||||
trap[1].right.v1 = *p2;
|
||||
trap[1].right.v2 = *p3;
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
// 按照 Y 坐标计算出左右两条边纵坐标等于 Y 的顶点
|
||||
void Trapezoidf_EdgeInterpolate(Trapezoidf *trap, float y) {
|
||||
float s1 = trap->left.v2.pos.y - trap->left.v1.pos.y;
|
||||
float s2 = trap->right.v2.pos.y - trap->right.v1.pos.y;
|
||||
float t1 = (y - trap->left.v1.pos.y) / s1;
|
||||
float t2 = (y - trap->right.v1.pos.y) / s2;
|
||||
Vertexf_Interpolate(&trap->left.v, &trap->left.v1, &trap->left.v2, t1);
|
||||
Vertexf_Interpolate(&trap->right.v, &trap->right.v1, &trap->right.v2, t2);
|
||||
}
|
||||
|
||||
// 根据左右两边的端点,初始化计算出扫描线的起点和步长
|
||||
void Trapezoidf_InitScanline(const Trapezoidf *trap, Scanlinef *scanline,
|
||||
int y) {
|
||||
float width = trap->right.v.pos.x - trap->left.v.pos.x;
|
||||
scanline->x = (int)(trap->left.v.pos.x + 0.5f);
|
||||
scanline->w = (int)(trap->right.v.pos.x + 0.5f) - scanline->x;
|
||||
scanline->y = y;
|
||||
scanline->v = trap->left.v;
|
||||
if (trap->left.v.pos.x >= trap->right.v.pos.x) {
|
||||
scanline->w = 0;
|
||||
}
|
||||
Vertexf_Division(&scanline->step, &trap->left.v, &trap->right.v, width);
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h> /**< rand */
|
||||
#include <math.h> /**< abs */
|
||||
#include <string.h> /**< memset */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#define EPSILON 1e-5f
|
||||
|
||||
#define INTERPOLATE(a, b, t) ((a) + (((b) - (a)) * (t)))
|
||||
#define CLAMP(x, min, max) ((x) < (min)) ? (min) : (((x) > (max)) ? (max) : (x))
|
||||
#define SATURATE(f) ((f) < 0 ? 0 : ((f) > 1 ? 1 : (f)))
|
||||
|
||||
/* Vector Definitions */
|
||||
typedef union {
|
||||
struct {
|
||||
float x, y;
|
||||
};
|
||||
float v[2];
|
||||
} Vector2f;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
int x, y;
|
||||
};
|
||||
int v[2];
|
||||
} Vector2i;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
float x, y, z;
|
||||
};
|
||||
float v[3];
|
||||
Vector2f xy;
|
||||
} Vector3f;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
float x, y, z, w;
|
||||
};
|
||||
float v[4];
|
||||
Vector3f xyz;
|
||||
Vector2f xy;
|
||||
} Vector4f;
|
||||
|
||||
/* Matrix Definitions, D3D math */
|
||||
typedef union {
|
||||
struct {
|
||||
float m11, m12, m13, m14;
|
||||
float m21, m22, m23, m24;
|
||||
float m31, m32, m33, m34;
|
||||
float m41, m42, m43, m44;
|
||||
};
|
||||
struct {
|
||||
Vector4f row1;
|
||||
Vector4f row2;
|
||||
Vector4f row3;
|
||||
Vector4f row4;
|
||||
};
|
||||
float m[4][4];
|
||||
} Matrix4x4f;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
float m11, m12, m13;
|
||||
float m21, m22, m23;
|
||||
float m31, m32, m33;
|
||||
};
|
||||
struct {
|
||||
Vector3f row1;
|
||||
Vector3f row2;
|
||||
Vector3f row3;
|
||||
};
|
||||
float m[3][3];
|
||||
} Matrix3x3f;
|
||||
|
||||
typedef Vector3f Point3f;
|
||||
typedef Vector4f Point4f;
|
||||
typedef Vector4f Quaternionf;
|
||||
|
||||
typedef struct {
|
||||
Point3f origin;
|
||||
Vector3f direction;
|
||||
} Rayf;
|
||||
|
||||
/* Common Math Functions */
|
||||
/* interpolation:t [0, 1] */
|
||||
static inline float Interpolatef(float x1, float x2, float t) {
|
||||
return INTERPOLATE(x1, x2, t);
|
||||
}
|
||||
|
||||
#define Lerpf Interpolatef
|
||||
|
||||
static inline float Clampf(float f, float min, float max) {
|
||||
return CLAMP(f, min, max);
|
||||
}
|
||||
|
||||
static inline float Saturatef(float f) { return SATURATE(f); }
|
||||
|
||||
static inline float Randomf() { return rand() / ((float)RAND_MAX + 1.f); }
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#include "benchmark/benchmark.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "vmath.h"
|
||||
|
||||
static void BM_ValuePass(::benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
// Generate a huge ini file in CWD
|
||||
state.PauseTiming();
|
||||
// Prepare
|
||||
state.ResumeTiming();
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_ValuePass)->Unit(::benchmark::kMillisecond);
|
||||
|
||||
static void BM_PointerPass(::benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
// Generate a huge ini file in CWD
|
||||
state.PauseTiming();
|
||||
// Prepare
|
||||
state.ResumeTiming();
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_PointerPass)->Unit(::benchmark::kMillisecond);
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
#include "gtest/gtest.h"
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#include "gtest/gtest.h"
|
||||
|
||||
TEST(Basic, Basic)
|
||||
{
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -309,7 +309,7 @@ swwModel *swwModel_CreateFromFile(const char *filepath) {
|
|||
token = strtok_r(NULL, delimiters, &last);
|
||||
i++;
|
||||
}
|
||||
VertexVector_PushBack(&o->norms, Vector3f_Normalize(&v));
|
||||
VertexVector_PushBack(&o->norms, Vector3f_Normalize(v));
|
||||
} else if (len >= 3 && line[0] == 'v' && line[1] == 't' && line[2] == ' ') {
|
||||
// vt 0 1
|
||||
Vector2f uv;
|
||||
|
|
|
@ -351,7 +351,7 @@ void DrawBox(Device *device, float theta) {
|
|||
|
||||
void Camera_AtZero(Device *device, float x, float y, float z) {
|
||||
Point4f eye = {x, y, z, 1}, at = {0, 0, 0, 1}, up = {0, 0, 1, 1};
|
||||
Matrix4x4f_SetLookAt(&device->transform.view, &eye, &at, &up);
|
||||
Matrix4x4f_SetLookAt(&device->transform.view, eye, at, up);
|
||||
Transform_Update(&device->transform);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,57 @@ typedef struct {
|
|||
SceneFunc fs[MAX_SCENE];
|
||||
} UserData;
|
||||
|
||||
static inline Vector3f RandomInUnitDisk() {
|
||||
static const Vector3f kPv = {1, 1, 0};
|
||||
Vector3f p;
|
||||
do {
|
||||
Vector3f rp = {Randomf(), Randomf(), 0};
|
||||
p = Vector3f_Sub(rp, kPv);
|
||||
Vector3f_MulInPlace(&p, 2.0);
|
||||
} while (Vector3f_Dot(p, p) >= 1.0);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
Vector3f origin;
|
||||
Vector3f lower_left_corner;
|
||||
Vector3f horizontal;
|
||||
Vector3f vertical;
|
||||
Vector3f u;
|
||||
Vector3f v;
|
||||
Vector3f w;
|
||||
float lens_radius;
|
||||
} Camera;
|
||||
|
||||
void Camera_Construct(Camera *o, Vector3f lookfrom, Vector3f lookat, Vector3f vup, float vfov, float aspect, float aperture, float focus_dist) {
|
||||
// vfov is top to bottom in degrees
|
||||
o->lens_radius = aperture / 2;
|
||||
float theta = vfov * M_PI / 180.f;
|
||||
float half_height = tan(theta / 2);
|
||||
float half_width = aspect * half_height;
|
||||
o->origin = lookfrom;
|
||||
o->w = Vector3f_Normalize(Vector3f_Sub(lookfrom, lookat));
|
||||
o->u = Vector3f_Normalize(Vector3f_Cross(vup, o->w));
|
||||
o->v = Vector3f_Cross(o->w, o->u);
|
||||
// o->lower_left_corner = o->origin - half_width * focus_dist * o->u - half_height * focus_dist * o->v - focus_dist * o->w;
|
||||
o->lower_left_corner = Vector3f_Sub(o->origin, Vector3f_Mul(o->u, half_width * focus_dist));
|
||||
Vector3f_SubInPlace(&o->lower_left_corner, Vector3f_Mul(o->v, half_height * focus_dist));
|
||||
Vector3f_SubInPlace(&o->lower_left_corner, Vector3f_Mul(o->w, focus_dist));
|
||||
o->horizontal = Vector3f_Mul(o->u, 2 * half_width * focus_dist);
|
||||
o->vertical = Vector3f_Mul(o->v, 2 * half_height * focus_dist);
|
||||
}
|
||||
|
||||
Rayf Camera_GetRay(Camera *o, float s, float t) {
|
||||
Vector3f rd = Vector3f_Mul(RandomInUnitDisk(), o->lens_radius);
|
||||
Vector3f offset = Vector3f_Add(Vector3f_Mul(o->u, rd.x), Vector3f_Mul(o->v, rd.y));
|
||||
Vector3f direction = Vector3f_Add(o->lower_left_corner, Vector3f_Mul(o->horizontal, s));
|
||||
Vector3f_AddInPlace(&direction, Vector3f_Mul(o->vertical, t));
|
||||
Vector3f_SubInPlace(&direction, Vector3f_Add(o->origin, offset));
|
||||
|
||||
return (Rayf){Vector3f_Add(o->origin, offset), direction};
|
||||
}
|
||||
|
||||
void OnKey(swwWindow *o, swwKeycode key, int pressed) {
|
||||
UserData *ud = swwWindow_GetUserData(o);
|
||||
if (key == swwKeycode_ESCAPE && pressed) {
|
||||
|
@ -80,8 +131,8 @@ void Scene1(swwWindow *o) {
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t RayColor(Ray *ray) {
|
||||
Vector3f unit_direction = Vector3f_Normalize(&ray->direction);
|
||||
uint32_t RayColor(Rayf *ray) {
|
||||
Vector3f unit_direction = Vector3f_Normalize(ray->direction);
|
||||
float t = 0.5f * (unit_direction.y + 1.f);
|
||||
return Color_Lerp(kWhite, Color_RGB(128, 179, 255), t);
|
||||
}
|
||||
|
@ -104,35 +155,35 @@ void Scene2(swwWindow *o) {
|
|||
Vector3f viewport_v = {0, -vh, 0};
|
||||
|
||||
// Calculate the horizontal and vertical delta vectors from pixel to pixel.
|
||||
Vector3f pixel_delta_u = Vector3f_Div(&viewport_u, w);
|
||||
Vector3f pixel_delta_v = Vector3f_Div(&viewport_v, h);
|
||||
Vector3f pixel_delta_u = Vector3f_Div(viewport_u, w);
|
||||
Vector3f pixel_delta_v = Vector3f_Div(viewport_v, h);
|
||||
|
||||
// Calculate the location of the upper left pixel.
|
||||
// auto viewport_upper_left = camera_center - vec3(0, 0, focal_length) -
|
||||
// viewport_u/2 - viewport_v/2;
|
||||
Vector3f focal_length_v = {0, 0, -focal_length};
|
||||
Vector3f vpu2 = Vector3f_Div(&viewport_u, 2);
|
||||
Vector3f vpv2 = Vector3f_Div(&viewport_v, 2);
|
||||
Vector3f_SubInPlace(&focal_length_v, &vpu2);
|
||||
Vector3f_SubInPlace(&focal_length_v, &vpv2);
|
||||
Point3f viewport_upper_left = Vector3f_Add(&camera_center, &focal_length_v);
|
||||
Vector3f vpu2 = Vector3f_Div(viewport_u, 2);
|
||||
Vector3f vpv2 = Vector3f_Div(viewport_v, 2);
|
||||
Vector3f_SubInPlace(&focal_length_v, vpu2);
|
||||
Vector3f_SubInPlace(&focal_length_v, vpv2);
|
||||
Point3f viewport_upper_left = Vector3f_Add(camera_center, focal_length_v);
|
||||
// auto pixel00_loc = viewport_upper_left + 0.5 * (pixel_delta_u +
|
||||
// pixel_delta_v);
|
||||
Vector3f pds = Vector3f_Add(&pixel_delta_u, &pixel_delta_v);
|
||||
Vector3f pds = Vector3f_Add(pixel_delta_u, pixel_delta_v);
|
||||
Vector3f_MulInPlace(&pds, 0.5);
|
||||
Point3f pixel00_loc = Vector3f_Add(&viewport_upper_left, &pds);
|
||||
Point3f pixel00_loc = Vector3f_Add(viewport_upper_left, pds);
|
||||
|
||||
Ray r = {{0, 0, 0}, {0, 0, 0}};
|
||||
Rayf r = {{0, 0, 0}, {0, 0, 0}};
|
||||
// Render
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; ++x) {
|
||||
// auto pixel_center = pixel00_loc + (x * pixel_delta_u) + (y *
|
||||
// pixel_delta_v);
|
||||
Vector3f pixel_u = Vector3f_Mul(&pixel_delta_u, x);
|
||||
Vector3f pixel_v = Vector3f_Mul(&pixel_delta_v, y);
|
||||
Vector3f pixel_uv = Vector3f_Add(&pixel_u, &pixel_v);
|
||||
Vector3f pixel_center = Vector3f_Add(&pixel00_loc, &pixel_uv);
|
||||
Vector3f ray_direction = Vector3f_Sub(&pixel_center, &camera_center);
|
||||
Vector3f pixel_u = Vector3f_Mul(pixel_delta_u, x);
|
||||
Vector3f pixel_v = Vector3f_Mul(pixel_delta_v, y);
|
||||
Vector3f pixel_uv = Vector3f_Add(pixel_u, pixel_v);
|
||||
Vector3f pixel_center = Vector3f_Add(pixel00_loc, pixel_uv);
|
||||
Vector3f ray_direction = Vector3f_Sub(pixel_center, camera_center);
|
||||
|
||||
r.origin = camera_center;
|
||||
r.direction = ray_direction;
|
||||
|
|
Loading…
Reference in New Issue