Added new function signatures in `assimp-vc143-mt.lib` for improved logging, parsing, and vector operations. Added new metadata and configuration information in `assimp-vc143-mt.dll` for versioning and licensing compliance. Added Sobol sequence generation in `Sobol.c` for quasi-random sampling. Added window message handling in `Window.c` for rendering graphics. Added ray-triangle intersection tests in `RayIntersection.c` for collision detection. Added functions for loading mesh data in `Mesh.c` to support 3D model import. Added functions for managing triangle collections in `Triangle.c` to enhance geometric data handling. Added light evaluation functions in `LightEvaluation.c` and `SkyLight.c` for realistic rendering. Added sampling and evaluation functions for simple lit materials in `SimpleLit.c`. Changed various header files to include copyright and licensing information. Changed existing functions in multiple files to improve performance and clarity. Removed unused code in several files to streamline the library.
128 lines
4.4 KiB
C
128 lines
4.4 KiB
C
#ifndef COMMON_H
|
|
#define COMMON_H
|
|
|
|
#include "Algorithm/Sobol.h"
|
|
#include "cglm/struct/vec4.h"
|
|
#include "cglm/struct/vec3.h"
|
|
#include <math.h>
|
|
|
|
#define COLOR_CLAMP(color) (unsigned char)fminf(fmaxf(color, 0.0f), 255.0f)
|
|
|
|
inline float random_float()
|
|
{
|
|
return (float)rand() / (float)RAND_MAX;
|
|
}
|
|
|
|
inline vec3s sample_cosine_weighted_hemisphere_z_angular(sobol_state_t* sobol_state, float angular)
|
|
{
|
|
float r1 = sobol_next(sobol_state);
|
|
float r2 = sobol_next(sobol_state);
|
|
|
|
float phi = 2.0f * (float)M_PI * r1;
|
|
float cos_theta = 1.0f - r2 * (1.0f - cosf(angular));
|
|
float sin_theta = sqrtf(1.0f - cos_theta * cos_theta);
|
|
|
|
// Convert spherical to Cartesian coordinates (relative to +Z axis)
|
|
float x = cosf(phi) * sin_theta;
|
|
float y = sinf(phi) * sin_theta;
|
|
float z = cos_theta;
|
|
|
|
// Create the vector in local coordinates (Z is up)
|
|
vec3s local_dir = {{x, y, z}};
|
|
return local_dir;
|
|
}
|
|
|
|
// Function to generate a direction with cosine weighting around (0, 0, 1)
|
|
// This is the local coordinate sample.
|
|
inline vec3s sample_cosine_weighted_hemisphere_z(sobol_state_t* sobol_state)
|
|
{
|
|
// float r1 = random_float();
|
|
// float r2 = random_float();
|
|
float r1 = sobol_next(sobol_state);
|
|
float r2 = sobol_next(sobol_state);
|
|
|
|
// Convert uniform random numbers to spherical coordinates for cosine weighting
|
|
// phi = angle around Z-axis (azimuthal)
|
|
// theta = angle from Z-axis (polar)
|
|
float phi = 2.0f * (float)M_PI * r1;
|
|
// cos(theta) = sqrt(r2), so z = sqrt(r2)
|
|
// sin(theta) = sqrt(1 - cos^2(theta)) = sqrt(1 - r2)
|
|
float sqrt_r2 = sqrtf(r2); // This is z
|
|
float sqrt_1_minus_r2 = sqrtf(1.0f - r2); // This is sin(theta)
|
|
|
|
// Convert spherical to Cartesian coordinates (relative to +Z axis)
|
|
float x = cosf(phi) * sqrt_1_minus_r2;
|
|
float y = sinf(phi) * sqrt_1_minus_r2;
|
|
float z = sqrt_r2; // Direct mapping for cosine weighting
|
|
|
|
// Create the vector in local coordinates (Z is up)
|
|
vec3s local_dir = {{x, y, z}};
|
|
return local_dir; // Already normalized by construction
|
|
}
|
|
|
|
// Function to create an orthonormal basis (coordinate system) from a single vector (normal)
|
|
// w will be aligned with normal, u and v will be perpendicular.
|
|
inline void create_orthonormal_basis(const vec3s normal, vec3s* u, vec3s* v)
|
|
{
|
|
// Choose a vector 'a' that is not parallel to 'normal'
|
|
vec3s a;
|
|
if (fabsf(normal.x) > 0.9f)
|
|
{ // If w is close to x-axis
|
|
a = (vec3s){{0.0f, 1.0f, 0.0f}}; // Use y-axis
|
|
}
|
|
else
|
|
{
|
|
a = (vec3s){{1.0f, 0.0f, 0.0f}}; // Use x-axis
|
|
}
|
|
|
|
// Calculate u = normalize(cross(a, w)) - this is the new 'x-axis'
|
|
*u = glms_vec3_normalize(glms_vec3_cross(a, normal));
|
|
|
|
// Calculate v = cross(w, u) - this is the new 'y-axis'
|
|
// Since w and u are orthonormal, v will also be normalized.
|
|
*v = glms_vec3_cross(normal, *u);
|
|
}
|
|
|
|
inline vec3s random_cosine_direction_angular(const vec3s normal, float angular, sobol_state_t* sobol_state)
|
|
{
|
|
vec3s local_dir = sample_cosine_weighted_hemisphere_z_angular(sobol_state, angular);
|
|
|
|
vec3s u, v;
|
|
create_orthonormal_basis(normal, &u, &v);
|
|
|
|
vec3s term_u = glms_vec3_scale(u, local_dir.x);
|
|
vec3s term_v = glms_vec3_scale(v, local_dir.y);
|
|
vec3s term_w = glms_vec3_scale(normal, local_dir.z);
|
|
|
|
vec3s world_dir = glms_vec3_add(glms_vec3_add(term_u, term_v), term_w);
|
|
|
|
return world_dir;
|
|
}
|
|
|
|
// Samples a direction from the hemisphere oriented along 'normal'
|
|
// with a cosine-weighted distribution.
|
|
inline vec3s random_cosine_direction(const vec3s normal, sobol_state_t* sobol_state)
|
|
{
|
|
// 1. Sample a direction in local coordinates (hemisphere oriented along +Z)
|
|
vec3s local_dir = sample_cosine_weighted_hemisphere_z(sobol_state);
|
|
|
|
// 2. Create an orthonormal basis aligned with the surface normal
|
|
vec3s u, v;
|
|
create_orthonormal_basis(normal, &u, &v);
|
|
|
|
// 3. Transform the local direction to world coordinates using the basis
|
|
// world_dir = u * local_dir.x + v * local_dir.y + w * local_dir.z
|
|
vec3s term_u = glms_vec3_scale(u, local_dir.x);
|
|
vec3s term_v = glms_vec3_scale(v, local_dir.y);
|
|
vec3s term_w = glms_vec3_scale(normal, local_dir.z);
|
|
|
|
vec3s world_dir = glms_vec3_add(glms_vec3_add(term_u, term_v), term_w);
|
|
|
|
// The result should be normalized due to the sampling method and basis transform.
|
|
// Is it necessary to be that safe?
|
|
// return glms_vec3_normalize(world_dir);
|
|
return world_dir;
|
|
}
|
|
|
|
#endif // COMMON_H
|