diff --git a/src/source/core/corelib/cseries/cseries_macros.h b/src/source/core/corelib/cseries/cseries_macros.h index 32be06c..5ae1e74 100644 --- a/src/source/core/corelib/cseries/cseries_macros.h +++ b/src/source/core/corelib/cseries/cseries_macros.h @@ -8,6 +8,10 @@ #define NUMBEROF(_array) (sizeof(_array) / sizeof(_array[0])) #define IN_RANGE_INCLUSIVE(value, begin, end) ((value) >= (begin) && (value) <= (end)) +#define VALID_INDEX(index, count) ((index) >= 0 && (index) < (count)) +#define FLAG(bit) (1 << (bit)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) /* ---------- definitions */ diff --git a/src/source/omaha/math/matrix_math.cpp b/src/source/omaha/math/matrix_math.cpp index 316eddc..c24cb71 100644 --- a/src/source/omaha/math/matrix_math.cpp +++ b/src/source/omaha/math/matrix_math.cpp @@ -16,6 +16,20 @@ /* ---------- public code */ +float magnitude_squared4d(union vector4d const * v) +{ + mangled_ppc("?magnitude_squared4d@@YAMPBTvector4d@@@Z"); + + return v->i * v->i + v->j * v->j + v->k * v->k + v->l * v->l; +}; + +float magnitude4d(union vector4d const * v) +{ + mangled_ppc("?magnitude4d@@YAMPBTvector4d@@@Z"); + + return square_root(magnitude_squared4d(v)); +}; + /* ---------- private code */ /* ---------- reverse engineering */ diff --git a/src/source/omaha/math/periodic_functions.cpp b/src/source/omaha/math/periodic_functions.cpp index 39828ec..b1e6d18 100644 --- a/src/source/omaha/math/periodic_functions.cpp +++ b/src/source/omaha/math/periodic_functions.cpp @@ -1,19 +1,187 @@ +#define __FILE_TAG_DEBUG_UNTRACKED_JUL_11_2011__ "C:\\SD\\Reach\\Publishing\\Main\\shared\\engine\\source\\omaha\\math\\periodic_functions.cpp" /* ---------- headers */ #include "omaha\math\periodic_functions.h" +#include "core\corelib\cseries\cseries_asserts.h" +#include "core\corelib\cseries\cseries_macros.h" + +#include + /* ---------- constants */ /* ---------- definitions */ /* ---------- prototypes */ +extern real fabs(real x); +extern real fmod(real x, real y); +extern real real_sgn(real x); + /* ---------- globals */ /* ---------- public code */ +void periodic_functions_initialize(void) +{ + mangled_ppc("?periodic_functions_initialize@@YAXXZ"); +}; + +void periodic_functions_dispose(void) +{ + mangled_ppc("?periodic_functions_dispose@@YAXXZ"); +}; + +real periodic_function_evaluate(short function_type, real time) +{ + mangled_ppc("?periodic_function_evaluate@@YAMFM@Z"); + + real value; + real next_value; + real one_over_255; + unsigned char const* table; + real time_scale; + real fractional_time; + long integer_time; + real result; + + if (function_type == _periodic_function_one) + { + result = 1.0f; + } + else + { + assert_tag_debug_untracked_jul_11_2011(216, function_type>=0 && function_type 0.75f && next_value < 0.25f) + next_value += 1.0f; + + result = value * (1.0f - fractional_time) + next_value * fractional_time; + + if (result > 1.0f) + result -= 1.0f; + } + else + { + result = value * (1.0f - fractional_time) + next_value * fractional_time; + } + } + + return result; +}; + +real transition_function_evaluate(short function_type, real time) +{ + mangled_ppc("?transition_function_evaluate@@YAMFM@Z"); + + real value; + real next_value; + real one_over_255; + unsigned char const* table; + real scaled_time; + short integer_time; + real fractional_time; + real result; + + if (time < 0.0f) + time = 0.0f; + else if (time > 1.0f) + time = 1.0f; + + if (function_type == _transition_function_linear) + { + result = time; + } + else + { + assert_tag_debug_untracked_jul_11_2011(275, function_type>=0 && function_type + /* ---------- constants */ /* ---------- definitions */ /* ---------- prototypes */ +extern bool valid_real(real const& value); +extern bool valid_real_vector2d(vector2d const* v); +extern real distance_squared3d(real_point3d const* a, real_point3d const* b); +extern vector3d* vector_from_points3d(real_point3d const* a, real_point3d const* b, vector3d* result); +extern real_point3d* point_from_line3d(real_point3d const* p, vector3d const* v, real t, real_point3d* result); + +extern void periodic_functions_initialize(void); +extern void periodic_functions_dispose(void); +extern real sine(real angle); +extern real cosine(real angle); +extern real reciprocal_square_root(real x); +extern real real_pin(real value, real minimum, real maximum); +extern vector3d* set_real_vector3d(vector3d* v, real i, real j, real k); +extern vector3d* scale_vector3d(vector3d const* v, real scale, vector3d* result); +extern real arccosine(real x); +extern real arctangent(real y, real x); +extern real ldexp(real value, int exponent); +extern real floor(real value); +extern real32_quaternion* set_real_quaternion(real32_quaternion* q, real i, real j, real k, real w); +extern real_point3d* set_real_point3d(real_point3d* p, real x, real y, real z); +extern vector3d* cross_product3d(vector3d const* a, vector3d const* b, vector3d* result); + +extern real real_min(real a, real b); +extern real real_max(real a, real b); +extern real fabs(real x); +extern real normalize3d(vector3d* v); + +real angle_between_normals3d(vector3d const* a, vector3d const* b); +real spring_system_calculate_acceleration(real position, real velocity, real target_position, real spring_constant, real damping_constant); +real calculate_new_position(real position, real velocity, real acceleration, real delta_time); +real calculate_new_velocity(real velocity, real acceleration, real delta_time); +bool point_in_triangle2d(real_point2d const* point, real_point2d const* a, real_point2d const* b, real_point2d const* c, real epsilon, real* out_u, real* out_v); + +void quaternion_normalize(real32_quaternion* q); +void approximate_quaternion_normalize(real32_quaternion* q); +void quaternions_interpolate(real32_quaternion const* a, real32_quaternion const* b, real fraction, real32_quaternion* result); +void quaternions_interpolate_long(real32_quaternion const* a, real32_quaternion const* b, real fraction, real32_quaternion* result); +void quaternions_slerp_interpolate(real32_quaternion const* a, real32_quaternion const* b, real fraction, real32_quaternion* result); + +void real_math_reset_precision(void); +void real_math_test_quantize_real(void); +void quaternion_to_euler_angles_internal(real32_quaternion const* q, euler_angles3d* angles, real epsilon); +real_point2d* project_point3d(real_point3d const* point, short projection, bool sign, real_point2d* result); +void closest_point_on_line2d(real_point2d const* point, real_point2d const* line_point, vector2d const* line_direction, real_point2d* closest_point, real* out_t); +void closest_point_on_line3d(real_point3d const* point, real_point3d const* line_point, vector3d const* line_direction, real_point3d* closest_point, real* out_t); +void component_vectors_from_normal3d(vector3d const* v, vector3d const* normal, vector3d* parallel, vector3d* perpendicular); + /* ---------- globals */ // short const const (*const global_projection3d_mappings)[2][3]; // "?global_projection3d_mappings@@3QAY112$$CBFA" @@ -261,15 +310,20 @@ // float dequantize_byte_to_real(float, float, unsigned char); // long quantize_real(float, float, float, long, bool, bool); -//void real_math_initialize(void) -//{ -// mangled_ppc("?real_math_initialize@@YAXXZ"); -//}; +void real_math_initialize(void) +{ + mangled_ppc("?real_math_initialize@@YAXXZ"); -//void real_math_dispose(void) -//{ -// mangled_ppc("?real_math_dispose@@YAXXZ"); -//}; + real_math_reset_precision(); + periodic_functions_initialize(); +}; + +void real_math_dispose(void) +{ + mangled_ppc("?real_math_dispose@@YAXXZ"); + + periodic_functions_dispose(); +}; //void real_math_enable_floating_point_exceptions(bool) //{ @@ -291,20 +345,37 @@ // mangled_ppc("?real_math_test_quantize_real@@YAXXZ"); //}; -//void real_math_test(void) -//{ -// mangled_ppc("?real_math_test@@YAXXZ"); -//}; +void real_math_test(void) +{ + mangled_ppc("?real_math_test@@YAXXZ"); -//float round_to_epsilon(float, long) -//{ -// mangled_ppc("?round_to_epsilon@@YAMMJ@Z"); -//}; + real_math_test_quantize_real(); +}; -//float signed_angle_between_vectors2d(union vector2d const *, union vector2d const *) -//{ -// mangled_ppc("?signed_angle_between_vectors2d@@YAMPBTvector2d@@0@Z"); -//}; +real round_to_epsilon(real value, long epsilon_exponent) +{ + mangled_ppc("?round_to_epsilon@@YAMMJ@Z"); + + value = ldexp(value, -epsilon_exponent); + value = value + 0.5f; + value = floor(value); + value = ldexp(value, epsilon_exponent); + + return value; +}; + +real signed_angle_between_vectors2d(vector2d const* a, vector2d const* b) +{ + mangled_ppc("?signed_angle_between_vectors2d@@YAMPBTvector2d@@0@Z"); + + real dot = dot_product2d(a, b); + real angle = arccosine(real_pin(dot, -1.0f, 1.0f)); + + if (cross_product2d(a, b) < 0.0f) + angle = -angle; + + return angle; +}; //float angle_between_vectors2d(union vector2d const *, union vector2d const *) //{ @@ -316,45 +387,91 @@ // mangled_ppc("?angle_between_vectors3d@@YAMPBTvector3d@@0@Z"); //}; -//float angle_between_normalized_vectors3d(union vector3d const *, union vector3d const *) -//{ -// mangled_ppc("?angle_between_normalized_vectors3d@@YAMPBTvector3d@@0@Z"); -//}; +real angle_between_normalized_vectors3d(vector3d const* a, vector3d const* b) +{ + mangled_ppc("?angle_between_normalized_vectors3d@@YAMPBTvector3d@@0@Z"); -//float angle_between_normals3d(union vector3d const *, union vector3d const *) -//{ -// mangled_ppc("?angle_between_normals3d@@YAMPBTvector3d@@0@Z"); -//}; + real dot; + real angle = 0.0f; + + dot = a->i * b->i + a->j * b->j + a->k * b->k; + angle = arccosine(real_pin(dot, -1.0f, 1.0f)); + + return angle; +}; + +real angle_between_normals3d(vector3d const* a, vector3d const* b) +{ + mangled_ppc("?angle_between_normals3d@@YAMPBTvector3d@@0@Z"); + + real angle; + + if (*(long const*)&a->i == *(long const*)&b->i + && *(long const*)&a->j == *(long const*)&b->j + && *(long const*)&a->k == *(long const*)&b->k) + { + angle = 0.0f; + } + else + { + angle = arccosine(real_pin(dot_product3d(a, b), -1.0f, 1.0f)); + } + + return angle; +}; //double angle_between_normals3d(union real64_vector3d const *, union real64_vector3d const *) //{ // mangled_ppc("?angle_between_normals3d@@YANPBTreal64_vector3d@@0@Z"); //}; -//float signed_angle_between_normals3d(union vector3d const *, union vector3d const *, union vector3d const *) -//{ -// mangled_ppc("?signed_angle_between_normals3d@@YAMPBTvector3d@@00@Z"); -//}; +real signed_angle_between_normals3d(vector3d const* a, vector3d const* b, vector3d const* reference) +{ + mangled_ppc("?signed_angle_between_normals3d@@YAMPBTvector3d@@00@Z"); + + real angle; + vector3d cross; + + angle = angle_between_normals3d(a, b); + cross_product3d(a, b, &cross); + if (dot_product3d(&cross, reference) < 0.0f) + angle = -angle; + + return angle; +}; //double signed_angle_between_normals3d(union real64_vector3d const *, union real64_vector3d const *, union real64_vector3d const *) //{ // mangled_ppc("?signed_angle_between_normals3d@@YANPBTreal64_vector3d@@00@Z"); //}; -//union vector2d * perpendicular2d(union vector2d const *, union vector2d *) -//{ -// mangled_ppc("?perpendicular2d@@YAPATvector2d@@PBT1@PAT1@@Z"); -//}; +vector2d* perpendicular2d(vector2d const* v, vector2d* result) +{ + mangled_ppc("?perpendicular2d@@YAPATvector2d@@PBT1@PAT1@@Z"); + + real i = v->i; + result->i = -v->j; + result->j = i; + + return result; +}; //union vector3d * perpendicular3d(union vector3d const *, union vector3d *) //{ // mangled_ppc("?perpendicular3d@@YAPATvector3d@@PBT1@PAT1@@Z"); //}; -//union vector4d * perpendicular4d(union vector4d const *, union vector4d *) -//{ -// mangled_ppc("?perpendicular4d@@YAPATvector4d@@PBT1@PAT1@@Z"); -//}; +vector4d* perpendicular4d(vector4d const* v, vector4d* result) +{ + mangled_ppc("?perpendicular4d@@YAPATvector4d@@PBT1@PAT1@@Z"); + + result->i = v->k; + result->j = v->l; + result->k = -v->i; + result->l = -v->j; + + return result; +}; //void yaw_vectors(union vector3d *, union vector3d const *, float, float) //{ @@ -366,10 +483,16 @@ // mangled_ppc("?pitch_vectors@@YAXPATvector3d@@0MM@Z"); //}; -//union vector3d * vector_from_yaw_and_pitch(float, float, union vector3d *) -//{ -// mangled_ppc("?vector_from_yaw_and_pitch@@YAPATvector3d@@MMPAT1@@Z"); -//}; +vector3d* vector_from_yaw_and_pitch(real yaw, real pitch, vector3d* v) +{ + mangled_ppc("?vector_from_yaw_and_pitch@@YAPATvector3d@@MMPAT1@@Z"); + + v->i = cosine(yaw) * cosine(pitch); + v->j = sine(yaw) * cosine(pitch); + v->k = sine(pitch); + + return v; +}; //union vector3d * rotate_vector_about_axis(union vector3d *, union vector3d const *, float, float) //{ @@ -416,35 +539,60 @@ // mangled_ppc("?normals_interpolate@@YAXPBTvector3d@@0MPAT1@@Z"); //}; -//void vectors_interpolate(union vector3d const *, union vector3d const *, float, union vector3d *) -//{ -// mangled_ppc("?vectors_interpolate@@YAXPBTvector3d@@0MPAT1@@Z"); -//}; +void vectors_interpolate(vector3d const* a, vector3d const* b, real fraction, vector3d* result) +{ + mangled_ppc("?vectors_interpolate@@YAXPBTvector3d@@0MPAT1@@Z"); -//void points_interpolate(union real_point3d const *, union real_point3d const *, float, union real_point3d *) -//{ -// mangled_ppc("?points_interpolate@@YAXPBTreal_point3d@@0MPAT1@@Z"); -//}; + real inverse_fraction = 1.0f - fraction; -//void scalars_interpolate(float, float, float, float *) -//{ -// mangled_ppc("?scalars_interpolate@@YAXMMMPAM@Z"); -//}; + result->i = inverse_fraction * a->i + fraction * b->i; + result->j = inverse_fraction * a->j + fraction * b->j; + result->k = inverse_fraction * a->k + fraction * b->k; +}; -//void scalars_interpolate_and_clamp_0_to_1(float, float, float, float *) -//{ -// mangled_ppc("?scalars_interpolate_and_clamp_0_to_1@@YAXMMMPAM@Z"); -//}; +void points_interpolate(real_point3d const* a, real_point3d const* b, real fraction, real_point3d* result) +{ + mangled_ppc("?points_interpolate@@YAXPBTreal_point3d@@0MPAT1@@Z"); + + real inverse_fraction = 1.0f - fraction; + + result->x = inverse_fraction * a->x + fraction * b->x; + result->y = inverse_fraction * a->y + fraction * b->y; + result->z = inverse_fraction * a->z + fraction * b->z; +}; + +void scalars_interpolate(real a, real b, real fraction, real* out) +{ + mangled_ppc("?scalars_interpolate@@YAXMMMPAM@Z"); + + *out = (1.0f - fraction) * a + fraction * b; +}; + +void scalars_interpolate_and_clamp_0_to_1(real a, real b, real fraction, real* out) +{ + mangled_ppc("?scalars_interpolate_and_clamp_0_to_1@@YAXMMMPAM@Z"); + + *out = real_pin((1.0f - fraction) * a + fraction * b, 0.0f, 1.0f); +}; //bool pin_normal_to_cone3d(union vector3d const *, union vector3d const *, float, float, union vector3d *) //{ // mangled_ppc("?pin_normal_to_cone3d@@YA_NPBTvector3d@@0MMPAT1@@Z"); //}; -//union vector3d * reflect_vector3d(union vector3d const *, union vector3d const *, union vector3d *) -//{ -// mangled_ppc("?reflect_vector3d@@YAPATvector3d@@PBT1@0PAT1@@Z"); -//}; +vector3d* reflect_vector3d(vector3d const* v, vector3d const* normal, vector3d* result) +{ + mangled_ppc("?reflect_vector3d@@YAPATvector3d@@PBT1@0PAT1@@Z"); + + real dot = dot_product3d(v, normal); + real double_dot = dot + dot; + + result->i = v->i - double_dot * normal->i; + result->j = v->j - double_dot * normal->j; + result->k = v->k - double_dot * normal->k; + + return result; +}; //union vector3d * refract_vector3d(union vector3d const *, union vector3d const *, float, union vector3d *) //{ @@ -456,25 +604,31 @@ // mangled_ppc("?component_vectors_from_normal3d@@YAXPBTvector3d@@0PAT1@1@Z"); //}; -//void component_vectors_from_plane3d(union vector3d const *, struct plane3d const *, union vector3d *, union vector3d *) -//{ -// mangled_ppc("?component_vectors_from_plane3d@@YAXPBTvector3d@@PBUplane3d@@PAT1@2@Z"); -//}; +void component_vectors_from_plane3d(vector3d const* v, plane3d const* plane, vector3d* parallel, vector3d* perpendicular) +{ + mangled_ppc("?component_vectors_from_plane3d@@YAXPBTvector3d@@PBUplane3d@@PAT1@2@Z"); + + component_vectors_from_normal3d(v, &plane->n, perpendicular, parallel); +}; //void component_vectors_from_direction3d(union vector3d const *, union vector3d const *, union vector3d *, union vector3d *) //{ // mangled_ppc("?component_vectors_from_direction3d@@YAXPBTvector3d@@0PAT1@1@Z"); //}; -//float quaternions_dot(struct real32_quaternion const *, struct real32_quaternion const *) -//{ -// mangled_ppc("?quaternions_dot@@YAMPBUreal32_quaternion@@0@Z"); -//}; +real quaternions_dot(real32_quaternion const* a, real32_quaternion const* b) +{ + mangled_ppc("?quaternions_dot@@YAMPBUreal32_quaternion@@0@Z"); -//void quaternion_inverse(struct real32_quaternion *) -//{ -// mangled_ppc("?quaternion_inverse@@YAXPAUreal32_quaternion@@@Z"); -//}; + return a->v.i * b->v.i + a->v.j * b->v.j + a->v.k * b->v.k + a->w * b->w; +}; + +void quaternion_inverse(real32_quaternion* q) +{ + mangled_ppc("?quaternion_inverse@@YAXPAUreal32_quaternion@@@Z"); + + q->w *= -1.0f; +}; //void quaternion_raise_to_power(struct real32_quaternion const *, float, struct real32_quaternion *) //{ @@ -496,10 +650,18 @@ // mangled_ppc("?approximate_quaternion_normalize@@YAXPAUreal32_quaternion@@@Z"); //}; -//void quaternion_from_angle_and_vector(struct real32_quaternion *, float, union vector3d const *) -//{ -// mangled_ppc("?quaternion_from_angle_and_vector@@YAXPAUreal32_quaternion@@MPBTvector3d@@@Z"); -//}; +void quaternion_from_angle_and_vector(real32_quaternion* q, real a, vector3d const* v) +{ + mangled_ppc("?quaternion_from_angle_and_vector@@YAXPAUreal32_quaternion@@MPBTvector3d@@@Z"); + + real half_angle = 0.5f * a; + real sine_of_half_angle = sine(half_angle); + + q->w = cosine(half_angle); + q->v.i = sine_of_half_angle * v->i; + q->v.j = sine_of_half_angle * v->j; + q->v.k = sine_of_half_angle * v->k; +}; //void quaternion_from_unit_vectors(struct real32_quaternion *, union vector3d const *, union vector3d const *) //{ @@ -526,30 +688,42 @@ // mangled_ppc("?quaternions_interpolate_long@@YAXPBUreal32_quaternion@@0MPAU1@@Z"); //}; -//void quaternions_interpolate_and_normalize(struct real32_quaternion const *, struct real32_quaternion const *, float, struct real32_quaternion *) -//{ -// mangled_ppc("?quaternions_interpolate_and_normalize@@YAXPBUreal32_quaternion@@0MPAU1@@Z"); -//}; +void quaternions_interpolate_and_normalize(real32_quaternion const* a, real32_quaternion const* b, real fraction, real32_quaternion* result) +{ + mangled_ppc("?quaternions_interpolate_and_normalize@@YAXPBUreal32_quaternion@@0MPAU1@@Z"); -//void quaternions_interpolate_long_and_normalize(struct real32_quaternion const *, struct real32_quaternion const *, float, struct real32_quaternion *) -//{ -// mangled_ppc("?quaternions_interpolate_long_and_normalize@@YAXPBUreal32_quaternion@@0MPAU1@@Z"); -//}; + quaternions_interpolate(a, b, fraction, result); + quaternion_normalize(result); +}; -//void approximate_quaternions_interpolate_and_normalize(struct real32_quaternion const *, struct real32_quaternion const *, float, struct real32_quaternion *) -//{ -// mangled_ppc("?approximate_quaternions_interpolate_and_normalize@@YAXPBUreal32_quaternion@@0MPAU1@@Z"); -//}; +void quaternions_interpolate_long_and_normalize(real32_quaternion const* a, real32_quaternion const* b, real fraction, real32_quaternion* result) +{ + mangled_ppc("?quaternions_interpolate_long_and_normalize@@YAXPBUreal32_quaternion@@0MPAU1@@Z"); + + quaternions_interpolate_long(a, b, fraction, result); + quaternion_normalize(result); +}; + +void approximate_quaternions_interpolate_and_normalize(real32_quaternion const* a, real32_quaternion const* b, real fraction, real32_quaternion* result) +{ + mangled_ppc("?approximate_quaternions_interpolate_and_normalize@@YAXPBUreal32_quaternion@@0MPAU1@@Z"); + + quaternions_interpolate(a, b, fraction, result); + approximate_quaternion_normalize(result); +}; //void quaternions_slerp_interpolate(struct real32_quaternion const *, struct real32_quaternion const *, float, struct real32_quaternion *) //{ // mangled_ppc("?quaternions_slerp_interpolate@@YAXPBUreal32_quaternion@@0MPAU1@@Z"); //}; -//void quaternions_slerp_interpolate_and_normalize(struct real32_quaternion const *, struct real32_quaternion const *, float, struct real32_quaternion *) -//{ -// mangled_ppc("?quaternions_slerp_interpolate_and_normalize@@YAXPBUreal32_quaternion@@0MPAU1@@Z"); -//}; +void quaternions_slerp_interpolate_and_normalize(real32_quaternion const* a, real32_quaternion const* b, real fraction, real32_quaternion* result) +{ + mangled_ppc("?quaternions_slerp_interpolate_and_normalize@@YAXPBUreal32_quaternion@@0MPAU1@@Z"); + + quaternions_slerp_interpolate(a, b, fraction, result); + quaternion_normalize(result); +}; //void quaternion_transform_point(struct real32_quaternion const *, union real_point3d const *, union real_point3d *) //{ @@ -576,20 +750,29 @@ // mangled_ppc("?orientations_multiply@@YAXPBUreal_orientation@@0PAU1@@Z"); //}; -//void orientation_identity(struct real_orientation *) -//{ -// mangled_ppc("?orientation_identity@@YAXPAUreal_orientation@@@Z"); -//}; +void orientation_identity(real_orientation* orientation) +{ + mangled_ppc("?orientation_identity@@YAXPAUreal_orientation@@@Z"); + + set_real_quaternion(&orientation->rotation, 0.0f, 0.0f, 0.0f, 1.0f); + set_real_point3d(&orientation->translation, 0.0f, 0.0f, 0.0f); + orientation->scale = 1.0f; +}; //void orientation_inverse(struct real_orientation const *, struct real_orientation *) //{ // mangled_ppc("?orientation_inverse@@YAXPBUreal_orientation@@PAU1@@Z"); //}; -//union euler_angles2d * euler_angles2d_from_vector3d(union euler_angles2d *, union vector3d const *) -//{ -// mangled_ppc("?euler_angles2d_from_vector3d@@YAPATeuler_angles2d@@PAT1@PBTvector3d@@@Z"); -//}; +euler_angles2d* euler_angles2d_from_vector3d(euler_angles2d* angles, vector3d const* v) +{ + mangled_ppc("?euler_angles2d_from_vector3d@@YAPATeuler_angles2d@@PAT1@PBTvector3d@@@Z"); + + angles->yaw = arctangent(v->j, v->i); + angles->pitch = arctangent(v->k, square_root(v->i * v->i + v->j * v->j)); + + return angles; +}; //union euler_angles3d * euler_angles3d_from_vectors3d(union euler_angles3d *, union vector3d const *, union vector3d const *) //{ @@ -606,30 +789,52 @@ // mangled_ppc("?vectors3d_from_euler_angles2d@@YAXPATvector3d@@0PBTeuler_angles2d@@@Z"); //}; -//union vector3d * vector3d_from_euler_angles2d(union vector3d *, union euler_angles2d const *) -//{ -// mangled_ppc("?vector3d_from_euler_angles2d@@YAPATvector3d@@PAT1@PBTeuler_angles2d@@@Z"); -//}; +vector3d* vector3d_from_euler_angles2d(vector3d* v, euler_angles2d const* angles) +{ + mangled_ppc("?vector3d_from_euler_angles2d@@YAPATvector3d@@PAT1@PBTeuler_angles2d@@@Z"); -//union vector3d * vector3d_from_angle(union vector3d *, float) -//{ -// mangled_ppc("?vector3d_from_angle@@YAPATvector3d@@PAT1@M@Z"); -//}; + real cosine_pitch = cosine(angles->pitch); + + v->i = cosine(angles->yaw) * cosine_pitch; + v->j = sine(angles->yaw) * cosine_pitch; + v->k = sine(angles->pitch); + + return v; +}; + +vector3d* vector3d_from_angle(vector3d* v, real angle) +{ + mangled_ppc("?vector3d_from_angle@@YAPATvector3d@@PAT1@M@Z"); + + set_real_vector3d(v, cosine(angle), sine(angle), 0.0f); + + return v; +}; //bool point_in_pill2d(union real_point2d const *, union real_point2d const *, union vector2d const *, float) //{ // mangled_ppc("?point_in_pill2d@@YA_NPBTreal_point2d@@0PBTvector2d@@M@Z"); //}; -//float point_to_line_distance_squared2d(union real_point2d const *, union real_point2d const *, union vector2d const *) -//{ -// mangled_ppc("?point_to_line_distance_squared2d@@YAMPBTreal_point2d@@0PBTvector2d@@@Z"); -//}; +real point_to_line_distance_squared2d(real_point2d const* point, real_point2d const* line_point, vector2d const* line_direction) +{ + mangled_ppc("?point_to_line_distance_squared2d@@YAMPBTreal_point2d@@0PBTvector2d@@@Z"); -//float point_to_line_distance_squared3d(union real_point3d const *, union real_point3d const *, union vector3d const *, float *) -//{ -// mangled_ppc("?point_to_line_distance_squared3d@@YAMPBTreal_point3d@@0PBTvector3d@@PAM@Z"); -//}; + real_point2d closest_point; + closest_point_on_line2d(point, line_point, line_direction, &closest_point, NULL); + + return distance_squared2d(point, &closest_point); +}; + +real point_to_line_distance_squared3d(real_point3d const* point, real_point3d const* line_point, vector3d const* line_direction, real* out_t) +{ + mangled_ppc("?point_to_line_distance_squared3d@@YAMPBTreal_point3d@@0PBTvector3d@@PAM@Z"); + + real_point3d closest_point; + closest_point_on_line3d(point, line_point, line_direction, &closest_point, out_t); + + return distance_squared3d(point, &closest_point); +}; //void closest_point_on_line2d(union real_point2d const *, union real_point2d const *, union vector2d const *, union real_point2d *, float *) //{ @@ -676,10 +881,12 @@ // mangled_ppc("?fast_vector_intersection_with_sphere@@YAMPBTreal_point3d@@PBTvector3d@@0M@Z"); //}; -//bool point_in_triangle2d(union real_point2d const *, union real_point2d const *, union real_point2d const *, union real_point2d const *, float *, float *) -//{ -// mangled_ppc("?point_in_triangle2d@@YA_NPBTreal_point2d@@000PAM1@Z"); -//}; +bool point_in_triangle2d(real_point2d const* point, real_point2d const* a, real_point2d const* b, real_point2d const* c, real* out_u, real* out_v) +{ + mangled_ppc("?point_in_triangle2d@@YA_NPBTreal_point2d@@000PAM1@Z"); + + return point_in_triangle2d(point, a, b, c, k_real_epsilon, out_u, out_v); +}; //bool point_in_triangle2d(union real_point2d const *, union real_point2d const *, union real_point2d const *, union real_point2d const *, float, float *, float *) //{ @@ -836,10 +1043,12 @@ // mangled_ppc("?pill_intersects_rectangle2d@@YA_NPBTreal_point2d@@PBTvector2d@@MPBTreal_rectangle2d@@@Z"); //}; -//bool pill_intersects_rectangle3d(union real_point3d const *, union vector3d const *, float, union real_rectangle3d const *) -//{ -// mangled_ppc("?pill_intersects_rectangle3d@@YA_NPBTreal_point3d@@PBTvector3d@@MPBTreal_rectangle3d@@@Z"); -//}; +bool pill_intersects_rectangle3d(real_point3d const* p, vector3d const* v, real radius, real_rectangle3d const* bounds) +{ + mangled_ppc("?pill_intersects_rectangle3d@@YA_NPBTreal_point3d@@PBTvector3d@@MPBTreal_rectangle3d@@@Z"); + + return false; +}; //bool pill_intersects_triangle2d(union real_point2d const *, union vector2d const *, float, union real_point2d const *, union real_point2d const *, union real_point2d const *) //{ @@ -891,25 +1100,36 @@ // mangled_ppc("?accelerate_to_position3d@@YA_NPATreal_point3d@@PATvector3d@@PBT1@MM@Z"); //}; -//void update_spring_system(float *, float *, float, float, float, float) -//{ -// mangled_ppc("?update_spring_system@@YAXPAM0MMMM@Z"); -//}; +void update_spring_system(real* position, real* velocity, real target_position, real spring_constant, real damping_constant, real delta_time) +{ + mangled_ppc("?update_spring_system@@YAXPAM0MMMM@Z"); -//float spring_system_calculate_acceleration(float, float, float, float, float) -//{ -// mangled_ppc("?spring_system_calculate_acceleration@@YAMMMMMM@Z"); -//}; + real acceleration = spring_system_calculate_acceleration(*position, *velocity, target_position, spring_constant, damping_constant); -//float calculate_new_position(float, float, float, float) -//{ -// mangled_ppc("?calculate_new_position@@YAMMMMM@Z"); -//}; + *position = calculate_new_position(*position, *velocity, acceleration, delta_time); + *velocity = calculate_new_velocity(*velocity, acceleration, delta_time); +}; -//float calculate_new_velocity(float, float, float) -//{ -// mangled_ppc("?calculate_new_velocity@@YAMMMM@Z"); -//}; +real spring_system_calculate_acceleration(real position, real velocity, real target_position, real spring_constant, real damping_constant) +{ + mangled_ppc("?spring_system_calculate_acceleration@@YAMMMMMM@Z"); + + return spring_constant * (target_position - position) - damping_constant * velocity; +}; + +real calculate_new_position(real position, real velocity, real acceleration, real delta_time) +{ + mangled_ppc("?calculate_new_position@@YAMMMMM@Z"); + + return position + velocity * delta_time + 0.5f * acceleration * (delta_time * delta_time); +}; + +real calculate_new_velocity(real velocity, real acceleration, real delta_time) +{ + mangled_ppc("?calculate_new_velocity@@YAMMMM@Z"); + + return velocity + acceleration * delta_time; +}; //void update_limited_spring_system(float *, float *, float, float, float, float, float, float) //{ @@ -971,15 +1191,19 @@ // mangled_ppc("?real_rectangle3d_compute_intersection@@YA_NPBTreal_rectangle3d@@0PAT1@@Z"); //}; -//float real_rectangle2d_area(union real_rectangle2d const *) -//{ -// mangled_ppc("?real_rectangle2d_area@@YAMPBTreal_rectangle2d@@@Z"); -//}; +real real_rectangle2d_area(real_rectangle2d const* bounds) +{ + mangled_ppc("?real_rectangle2d_area@@YAMPBTreal_rectangle2d@@@Z"); -//float real_rectangle3d_volume(union real_rectangle3d const *) -//{ -// mangled_ppc("?real_rectangle3d_volume@@YAMPBTreal_rectangle3d@@@Z"); -//}; + return (bounds->x1 - bounds->x0) * (bounds->y1 - bounds->y0); +}; + +real real_rectangle3d_volume(real_rectangle3d const* bounds) +{ + mangled_ppc("?real_rectangle3d_volume@@YAMPBTreal_rectangle3d@@@Z"); + + return (bounds->x1 - bounds->x0) * (bounds->y1 - bounds->y0) * (bounds->z1 - bounds->z0); +}; //void real_rectangle2d_clamp_bounds(union real_rectangle2d *, union real_rectangle2d const *) //{ @@ -996,10 +1220,18 @@ // mangled_ppc("?real_rectangle3d_enclose_points@@YAPATreal_rectangle3d@@PAT1@JQBTreal_point3d@@@Z"); //}; -//union real_rectangle2d * real_rectangle2d_enclose_rectangle(union real_rectangle2d *, union real_rectangle2d const *) -//{ -// mangled_ppc("?real_rectangle2d_enclose_rectangle@@YAPATreal_rectangle2d@@PAT1@PBT1@@Z"); -//}; +real_rectangle2d* real_rectangle2d_enclose_rectangle(real_rectangle2d* bounds, real_rectangle2d const* other) +{ + mangled_ppc("?real_rectangle2d_enclose_rectangle@@YAPATreal_rectangle2d@@PAT1@PBT1@@Z"); + + for (long axis_index = 0; axis_index < 2; axis_index++) + { + bounds->m[axis_index][0] = real_min(bounds->m[axis_index][0], other->m[axis_index][0]); + bounds->m[axis_index][1] = real_max(bounds->m[axis_index][1], other->m[axis_index][1]); + } + + return bounds; +}; //union real_rectangle3d * real_rectangle3d_enclose_rectangle(union real_rectangle3d *, union real_rectangle3d const *) //{ @@ -1081,20 +1313,32 @@ // mangled_ppc("?plane2d_clip_polygon@@YAJPBUplane2d@@_NMJQBTreal_point2d@@JQAT2@@Z"); //}; -//union real_point2d * intersection_point2d(union real_point2d const *, union real_point2d const *, float, float, union real_point2d *) -//{ -// mangled_ppc("?intersection_point2d@@YAPATreal_point2d@@PBT1@0MMPAT1@@Z"); -//}; +real_point2d* intersection_point2d(real_point2d const* p0, real_point2d const* p1, real d0, real d1, real_point2d* result) +{ + mangled_ppc("?intersection_point2d@@YAPATreal_point2d@@PBT1@0MMPAT1@@Z"); + + vector2d edge; + vector_from_points2d(p0, p1, &edge); + point_from_line2d(p0, &edge, d0 / (d0 - d1), result); + + return result; +}; //long plane3d_clip_polygon(struct plane3d const *, bool, float, long, union real_point3d const *const, long, union real_point3d *const) //{ // mangled_ppc("?plane3d_clip_polygon@@YAJPBUplane3d@@_NMJQBTreal_point3d@@JQAT2@@Z"); //}; -//union real_point3d * intersection_point3d(union real_point3d const *, union real_point3d const *, float, float, union real_point3d *) -//{ -// mangled_ppc("?intersection_point3d@@YAPATreal_point3d@@PBT1@0MMPAT1@@Z"); -//}; +real_point3d* intersection_point3d(real_point3d const* p0, real_point3d const* p1, real d0, real d1, real_point3d* result) +{ + mangled_ppc("?intersection_point3d@@YAPATreal_point3d@@PBT1@0MMPAT1@@Z"); + + vector3d edge; + vector_from_points3d(p0, p1, &edge); + point_from_line3d(p0, &edge, d0 / (d0 - d1), result); + + return result; +}; //void project_polygon2d(long, union real_point2d const *const, struct plane3d const *, long, bool, union real_point3d *const) //{ @@ -1121,25 +1365,43 @@ // mangled_ppc("?find_closest_point_on_3planes@@YA_NPBTreal_point3d@@PBUplane3d@@11PAM22PAT1@PAJ@Z"); //}; -//float normalize3d_with_default(union vector3d *, union vector3d const *) -//{ -// mangled_ppc("?normalize3d_with_default@@YAMPATvector3d@@PBT1@@Z"); -//}; +real normalize3d_with_default(vector3d* v, vector3d const* default_value) +{ + mangled_ppc("?normalize3d_with_default@@YAMPATvector3d@@PBT1@@Z"); -//void quaternion_to_euler_angles(struct real32_quaternion const *, union euler_angles3d *) -//{ -// mangled_ppc("?quaternion_to_euler_angles@@YAXPBUreal32_quaternion@@PATeuler_angles3d@@@Z"); -//}; + real magnitude = magnitude3d(v); + + if (fabs(magnitude - 0.0f) >= k_real_epsilon) + { + scale_vector3d(v, 1.0f / magnitude, v); + } + else + { + *v = *default_value; + magnitude = 0.0f; + } + + return magnitude; +}; + +void quaternion_to_euler_angles(real32_quaternion const* q, euler_angles3d* angles) +{ + mangled_ppc("?quaternion_to_euler_angles@@YAXPBUreal32_quaternion@@PATeuler_angles3d@@@Z"); + + quaternion_to_euler_angles_internal(q, angles, k_real_epsilon); +}; //void quaternion_to_euler_angles_internal(struct real32_quaternion const *, union euler_angles3d *, float) //{ // mangled_ppc("?quaternion_to_euler_angles_internal@@YAXPBUreal32_quaternion@@PATeuler_angles3d@@M@Z"); //}; -//void quaternion_to_euler_angles_unsafe(struct real32_quaternion const *, union euler_angles3d *) -//{ -// mangled_ppc("?quaternion_to_euler_angles_unsafe@@YAXPBUreal32_quaternion@@PATeuler_angles3d@@@Z"); -//}; +void quaternion_to_euler_angles_unsafe(real32_quaternion const* q, euler_angles3d* angles) +{ + mangled_ppc("?quaternion_to_euler_angles_unsafe@@YAXPBUreal32_quaternion@@PATeuler_angles3d@@@Z"); + + quaternion_to_euler_angles_internal(q, angles, 0.0f); +}; //void quaternion_from_euler_angles_OLD_AND_INCORRECT(struct real32_quaternion *, union euler_angles3d const *) //{ @@ -1181,30 +1443,53 @@ // mangled_ppc("?three_bone_ik_effector_distance_squared@@YAMMMMMMM@Z"); //}; -//float three_bone_ik_joint_angle_ratio(float, float, float) -//{ -// mangled_ppc("?three_bone_ik_joint_angle_ratio@@YAMMMM@Z"); -//}; +real three_bone_ik_joint_angle_ratio(real angle, real minimum_angle, real ratio) +{ + mangled_ppc("?three_bone_ik_joint_angle_ratio@@YAMMMM@Z"); -//void real_math_disable_fpu_exceptions(void) -//{ -// mangled_ppc("?real_math_disable_fpu_exceptions@@YAXXZ"); -//}; + real result = ratio; -//void real_math_recover_fpu_exceptions(void) -//{ -// mangled_ppc("?real_math_recover_fpu_exceptions@@YAXXZ"); -//}; + if (angle > minimum_angle) + result = 1.0f + (ratio - 1.0f) * (1.0f - (angle - minimum_angle) / (k_pi - minimum_angle)); -//union vector2d * fast_normalize2d(union vector2d *) -//{ -// mangled_ppc("?fast_normalize2d@@YAPATvector2d@@PAT1@@Z"); -//}; + return result; +}; -//void perpendicular_bisector2d(union real_point2d const *, union real_point2d const *, union real_point2d *, union vector2d *) -//{ -// mangled_ppc("?perpendicular_bisector2d@@YAXPBTreal_point2d@@0PAT1@PATvector2d@@@Z"); -//}; +void real_math_disable_fpu_exceptions(void) +{ + mangled_ppc("?real_math_disable_fpu_exceptions@@YAXXZ"); + + _controlfp(_CW_DEFAULT, _MCW_EM); +}; + +void real_math_recover_fpu_exceptions(void) +{ + mangled_ppc("?real_math_recover_fpu_exceptions@@YAXXZ"); + + _clearfp(); + real_math_reset_precision(); +}; + +vector2d* fast_normalize2d(vector2d* v) +{ + mangled_ppc("?fast_normalize2d@@YAPATvector2d@@PAT1@@Z"); + + real magnitude_squared = magnitude_squared2d(v); + if (magnitude_squared != 0.0f) + scale_vector2d(v, reciprocal_square_root(magnitude_squared), v); + + return v; +}; + +void perpendicular_bisector2d(real_point2d const* p0, real_point2d const* p1, real_point2d* midpoint, vector2d* normal) +{ + mangled_ppc("?perpendicular_bisector2d@@YAXPBTreal_point2d@@0PAT1@PATvector2d@@@Z"); + + midpoint2d(p0, p1, midpoint); + vector_from_points2d(p0, p1, normal); + normalize2d(normal); + perpendicular2d(normal, normal); +}; //short projection_from_vector3d(union vector3d const *) //{ @@ -1221,55 +1506,102 @@ // mangled_ppc("?project_point3d@@YAPATreal_point2d@@PBTreal_point3d@@F_NPAT1@@Z"); //}; -//union vector2d * project_vector3d(union vector3d const *, short, bool, union vector2d *) -//{ -// mangled_ppc("?project_vector3d@@YAPATvector2d@@PBTvector3d@@F_NPAT1@@Z"); -//}; +vector2d* project_vector3d(vector3d const* v, short projection, bool sign, vector2d* result) +{ + mangled_ppc("?project_vector3d@@YAPATvector2d@@PBTvector3d@@F_NPAT1@@Z"); -//union vector3d * fast_normalize3d(union vector3d *) -//{ -// mangled_ppc("?fast_normalize3d@@YAPATvector3d@@PAT1@@Z"); -//}; + return (vector2d*)project_point3d((real_point3d const*)v, projection, sign, (real_point2d*)result); +}; + +vector3d* fast_normalize3d(vector3d* v) +{ + mangled_ppc("?fast_normalize3d@@YAPATvector3d@@PAT1@@Z"); + + real magnitude_squared = magnitude_squared3d(v); + if (magnitude_squared != 0.0f) + scale_vector3d(v, reciprocal_square_root(magnitude_squared), v); + + return v; +}; //union real64_vector3d * cross_product3d(union real64_vector3d const *, union real64_vector3d const *, union real64_vector3d *) //{ // mangled_ppc("?cross_product3d@@YAPATreal64_vector3d@@PBT1@0PAT1@@Z"); //}; -//float plane2d_distance_to_point(struct plane2d const *, union real_point2d const *) -//{ -// mangled_ppc("?plane2d_distance_to_point@@YAMPBUplane2d@@PBTreal_point2d@@@Z"); -//}; +real plane2d_distance_to_point(plane2d const* plane, real_point2d const* point) +{ + mangled_ppc("?plane2d_distance_to_point@@YAMPBUplane2d@@PBTreal_point2d@@@Z"); -//struct plane3d * plane3d_from_points(struct plane3d *, union real_point3d const *, union real_point3d const *, union real_point3d const *) -//{ -// mangled_ppc("?plane3d_from_points@@YAPAUplane3d@@PAU1@PBTreal_point3d@@11@Z"); -//}; + return dot_product2d((vector2d const*)point, &plane->n) - plane->d; +}; -//bool valid_real_point2d(union real_point2d const *) -//{ -// mangled_ppc("?valid_real_point2d@@YA_NPBTreal_point2d@@@Z"); -//}; +plane3d* plane3d_from_points(plane3d* plane, real_point3d const* p0, real_point3d const* p1, real_point3d const* p2) +{ + mangled_ppc("?plane3d_from_points@@YAPAUplane3d@@PAU1@PBTreal_point3d@@11@Z"); -//bool valid_real_sine_cosine(float, float) -//{ -// mangled_ppc("?valid_real_sine_cosine@@YA_NMM@Z"); -//}; + vector3d v1; + vector3d v2; -//bool valid_real_plane2d(struct plane2d const *) -//{ -// mangled_ppc("?valid_real_plane2d@@YA_NPBUplane2d@@@Z"); -//}; + vector_from_points3d(p0, p1, &v1); + vector_from_points3d(p0, p2, &v2); + cross_product3d(&v1, &v2, &plane->n); -//bool valid_real_quaternion(struct real32_quaternion const *) -//{ -// mangled_ppc("?valid_real_quaternion@@YA_NPBUreal32_quaternion@@@Z"); -//}; + if (normalize3d(&plane->n) != 0.0f) + { + plane->d = dot_product3d((vector3d const*)p0, &plane->n); -//float dequantize_byte_to_real(float, float, unsigned char) -//{ -// mangled_ppc("?dequantize_byte_to_real@@YAMMME@Z"); -//}; + return plane; + } + else + { + plane->d = 0.0f; + + return NULL; + } +}; + +bool valid_real_point2d(real_point2d const* p) +{ + mangled_ppc("?valid_real_point2d@@YA_NPBTreal_point2d@@@Z"); + + return valid_real(p->x) && valid_real(p->y); +}; + +bool valid_real_sine_cosine(real sine, real cosine) +{ + mangled_ppc("?valid_real_sine_cosine@@YA_NMM@Z"); + + return valid_realcmp(sine * sine + cosine * cosine, 1.0f); +}; + +bool valid_real_plane2d(plane2d const* plane) +{ + mangled_ppc("?valid_real_plane2d@@YA_NPBUplane2d@@@Z"); + + return valid_real_vector2d(&plane->n) && valid_real(plane->d); +}; + +bool valid_real_quaternion(real32_quaternion const* q) +{ + mangled_ppc("?valid_real_quaternion@@YA_NPBUreal32_quaternion@@@Z"); + + return valid_realcmp(magnitude_squared3d(&q->v) + q->w * q->w, 1.0f); +}; + +real dequantize_byte_to_real(real minimum, real maximum, unsigned char value) +{ + mangled_ppc("?dequantize_byte_to_real@@YAMMME@Z"); + + real result; + + if (value == 0xff) + result = maximum; + else + result = minimum + (maximum - minimum) * ((real)value / 255.0f); + + return result; +}; //long quantize_real(float, float, float, long, bool, bool) //{ diff --git a/src/source/omaha/math/real_math.h b/src/source/omaha/math/real_math.h index f900c46..676e7f6 100644 --- a/src/source/omaha/math/real_math.h +++ b/src/source/omaha/math/real_math.h @@ -20,10 +20,10 @@ const float k_degrees_to_radians = 0.0174533f; const float k_radians_to_degrees = 57.2957802f; const float k_real_precision = __FLT_EPSILON__; const float k_pi = 3.1415927f; -const float k_2pi = k_pi * 2.0f; -const float k_3pi = k_pi * 3.0f; -const float k_half_pi = k_pi / 2.0f; -const float k_quarter_pi = k_pi / 4.0f; +const float k_2pi = 6.2831855f; +const float k_3pi = 9.424778f; +const float k_half_pi = 1.5707964f; +const float k_quarter_pi = 0.7853982f; const float k_one_over_root2 = 0.7071068f; const float k_cosine30 = 0.8660254f; const float k_sine30 = 0.5f; @@ -46,6 +46,8 @@ const float k_real_max = __FLT_MAX__; const float REAL_MIN = -__FLT_MAX__; const float REAL_MAX = __FLT_MAX__; +#define realcmp(a, b) (fabs((a) - (b)) < k_real_epsilon) + /* ---------- definitions */ typedef float real; @@ -416,26 +418,16 @@ extern inline bool valid_real_vector3d_axes3(vector3d const * f, vector3d const // mangled_ppc("?valid_real_vector3d_axes3@@YA_NPBTvector3d@@00@Z"); //}; -inline float cross_product2d(vector2d const * a, vector2d const * b) -{ - mangled_ppc("?cross_product2d@@YAMPBTvector2d@@0@Z"); - - return a->i * b->j - a->j * b->i; -}; - -float magnitude_squared4d(union vector4d const * v) -{ - mangled_ppc("?magnitude_squared4d@@YAMPBTvector4d@@@Z"); - - return v->i * v->i + v->j * v->j + v->k * v->k + v->l * v->l; -}; - -float magnitude4d(union vector4d const * v) -{ - mangled_ppc("?magnitude4d@@YAMPBTvector4d@@@Z"); +extern float cross_product2d(vector2d const * a, vector2d const * b); +//float cross_product2d(vector2d const * a, vector2d const * b) +//{ +// mangled_ppc("?cross_product2d@@YAMPBTvector2d@@0@Z"); +// +// return a->i * b->j - a->j * b->i; +//}; - return square_root(magnitude_squared4d(v)); -}; +extern float magnitude_squared4d(union vector4d const * v); +extern float magnitude4d(union vector4d const * v); extern double abs(double d); /*double abs(double d) diff --git a/tools/download_tool.py b/tools/download_tool.py index 7033929..e20aec8 100644 --- a/tools/download_tool.py +++ b/tools/download_tool.py @@ -11,6 +11,7 @@ ### import argparse +import hashlib import io import os import platform @@ -91,7 +92,71 @@ def wibo_url(tag: str) -> str: "wibo": wibo_url, } +def discard(path: Path) -> None: + try: + path.unlink() + except OSError: + pass # still in use, a later download will clean it up + + +def same_contents(a: Path, b: Path) -> bool: + try: + if a.stat().st_size != b.stat().st_size: + return False + with open(a, "rb") as f: + digest_a = hashlib.sha256(f.read()).digest() + with open(b, "rb") as f: + digest_b = hashlib.sha256(f.read()).digest() + except OSError: + return False + return digest_a == digest_b + + +def replace_locked(src: Path, dst: Path) -> None: + try: + os.replace(src, dst) + return + except PermissionError: + pass + + # The destination is in use -- a running dtk.exe, an antivirus scan, an + # editor holding it open. If it already holds exactly what we downloaded, + # keep it and just freshen its timestamp so the build system stops + # considering it out of date. + if same_contents(src, dst): + discard(src) + try: + dst.touch() + except OSError: + pass + print(f"{dst} is in use but already up to date, keeping it") + return + + # On Windows a running executable cannot be overwritten, but it can usually + # be renamed out of the way. Move the old file aside, put the new one in + # place, then delete the old one once nothing holds it open any more. + for index in range(16): + stale = dst.with_name(f"{dst.name}.old{index if index else ''}") + try: + if stale.exists(): + stale.unlink() + os.replace(dst, stale) + except OSError: + continue + try: + os.replace(src, dst) + except OSError: + os.replace(stale, dst) # put the original back + break + discard(stale) + return + + discard(src) + raise PermissionError(f"{dst} is in use and could not be replaced") + + def download(url, response, output) -> None: + output.parent.mkdir(parents=True, exist_ok=True) if url.endswith(".zip"): data = io.BytesIO(response.read()) with zipfile.ZipFile(data) as f: @@ -102,10 +167,23 @@ def download(url, response, output) -> None: os.chmod(os.path.join(root, name), 0o755) output.touch(mode=0o755) # Update dir modtime else: - with open(output, "wb") as f: + # The pid keeps concurrent builds from fighting over one scratch file. + temporary = output.with_name(f"{output.name}.{os.getpid()}.download") + with open(temporary, "wb") as f: shutil.copyfileobj(response, f) - st = os.stat(output) - os.chmod(output, st.st_mode | stat.S_IEXEC) + st = os.stat(temporary) + os.chmod(temporary, st.st_mode | stat.S_IEXEC) + try: + replace_locked(temporary, output) + except OSError as e: + discard(temporary) + if not output.exists(): + raise + try: + output.touch() + except OSError: + pass + print(f"WARNING: {e}, keeping the existing {output}") def main() -> None: parser = argparse.ArgumentParser()