From c40147753170cacf443208b58fbfffef17e8896f Mon Sep 17 00:00:00 2001 From: Ge Wang Date: Wed, 13 Nov 2024 17:52:19 -0800 Subject: [PATCH] add vec2/3/4 .dot() .cross() --- VERSIONS | 15 +++++- examples/vector/vec3.ck | 7 +++ examples/vector/vec4.ck | 8 +++- src/core/chuck_lang.cpp | 83 ++++++++++++++++++++++++++++++++++ src/core/chuck_lang.h | 5 ++ src/core/chuck_type.cpp | 2 +- src/test/01-Basic/257-vec3.ck | 51 +++++++++++++++++++++ src/test/01-Basic/257-vec3.txt | 9 ++++ src/test/01-Basic/258-vec4.ck | 31 +++++++++++++ src/test/01-Basic/258-vec4.txt | 6 +++ 10 files changed, 213 insertions(+), 4 deletions(-) create mode 100644 src/test/01-Basic/257-vec3.ck create mode 100644 src/test/01-Basic/257-vec3.txt create mode 100644 src/test/01-Basic/258-vec4.ck create mode 100644 src/test/01-Basic/258-vec4.txt diff --git a/VERSIONS b/VERSIONS index aa16f033a..dc86f8017 100644 --- a/VERSIONS +++ b/VERSIONS @@ -2,7 +2,7 @@ ChucK VERSIONS log ------------------ -1.5.4.2 +1.5.4.2 (November 2024) ======= (updated) --chugin-path: no longer auto-loads chugins found in the specified paths; instead the specified paths are added to the import @@ -18,6 +18,19 @@ ChucK VERSIONS log various scenarios. (fixed) long-standing SndBuf issue, especially prevalent on macOS: "System error : Too many open files." this was due a combination of +(fixed) vec2/vec3/vec4 implicit cast logic for +=> and -=> operations + (previously, this would cause a crash in some cases) +(added) vector dot product methods for vec2, vec3, and vec4 + float vec2.dot( vec2 rhs ) + float vec3.dot( vec3 rhs ) + float vec4.dot( vec4 rhs ) +(added) vector cross product method for vec3 and vec4 (as 3D shorthand) + NOTE: this is the same as vec3*vec3 or vec4*vec4 + NOTE: 4D cross product is mathematically undefined; vec4 cross product + ignores the `w` components and computes a 3D cross product; + `w` is also set to zero in the resulting vec4 + vec3 vec3.cross( vec3 rhs ) + vec4 vec4.cross( vec4 rhs ) (added) --auto-load-chugin-path: flag -- this behaves as --chugin-path previously did: chugins in the specified path(s) are auto-loaded; .ck files can be @imported diff --git a/examples/vector/vec3.ck b/examples/vector/vec3.ck index b7d28fa6a..27174ecf3 100644 --- a/examples/vector/vec3.ck +++ b/examples/vector/vec3.ck @@ -9,6 +9,10 @@ a + b => vec3 sum; a - b => vec3 diff; // cross product a * b => vec3 c; +// another way to do cross product (function) +a.cross(b) => vec3 cross; +// dot product (function) +a.dot(b) => float dot; // print sum! <<< "sum:", sum >>>; @@ -16,6 +20,8 @@ a * b => vec3 c; <<< "diff:", diff >>>; // print cross product <<< "cross product:", c >>>; +// print dot product +<<< "dot product:", dot >>>; // array [ a, b, @(-1,1,0) ] @=> vec3 group[]; @@ -37,3 +43,4 @@ v.normalize(); 5 * v => vec3 v2; // print result <<< "scalar multiply:", v2 >>>; + diff --git a/examples/vector/vec4.ck b/examples/vector/vec4.ck index a4a14c83f..b0aac3eb8 100644 --- a/examples/vector/vec4.ck +++ b/examples/vector/vec4.ck @@ -9,7 +9,10 @@ a + b => vec4 sum; a - b => vec4 diff; // cross product (ignores w component) a * b => vec4 c; - +// another way to do cross product (ignores w component) +a.cross(b) => vec4 cross; +// dot product (function) +a.dot(b) => float dot; // print sum! <<< "sum:", sum >>>; @@ -17,7 +20,8 @@ a * b => vec4 c; <<< "diff:", diff >>>; // print cross product <<< "cross product:", c >>>; - +// print dot product +<<< "dot product:", dot >>>; // array [ a, b, c ] @=> vec4 group[]; diff --git a/src/core/chuck_lang.cpp b/src/core/chuck_lang.cpp index f83943ba5..4356eb5c2 100644 --- a/src/core/chuck_lang.cpp +++ b/src/core/chuck_lang.cpp @@ -693,6 +693,11 @@ t_CKBOOL init_class_vec2( Chuck_Env * env, Chuck_Type * type ) func = make_new_mfun( "void", "normalize", vec2_normalize ); if( !type_engine_import_mfun( env, func ) ) goto error; + // add dot() product | 1.5.4.2 (ge & azaday) added + func = make_new_mfun( "float", "dot", vec2_dot ); + func->add_arg( "vec2", "rhs" ); + if( !type_engine_import_mfun( env, func ) ) goto error; + // end the class import type_engine_import_class_end( env ); @@ -747,6 +752,16 @@ t_CKBOOL init_class_vec3( Chuck_Env * env, Chuck_Type * type ) func = make_new_mfun( "void", "normalize", vec3_normalize ); if( !type_engine_import_mfun( env, func ) ) goto error; + // add dot() product | 1.5.4.2 (ge & azaday) added + func = make_new_mfun( "float", "dot", vec3_dot ); + func->add_arg( "vec3", "rhs" ); + if( !type_engine_import_mfun( env, func ) ) goto error; + + // add cross() product | same as vec3 * vec3 + func = make_new_mfun( "vec3", "cross", vec3_cross ); + func->add_arg( "vec3", "rhs" ); + if( !type_engine_import_mfun( env, func ) ) goto error; + // add interp() func = make_new_mfun( "float", "interp", vec3_interp ); if( !type_engine_import_mfun( env, func ) ) goto error; @@ -838,6 +853,17 @@ t_CKBOOL init_class_vec4( Chuck_Env * env, Chuck_Type * type ) func = make_new_mfun( "void", "normalize", vec4_normalize ); if( !type_engine_import_mfun( env, func ) ) goto error; + // add dot() product | 1.5.4.2 (ge & azaday) added + func = make_new_mfun( "float", "dot", vec4_dot ); + func->add_arg( "vec4", "rhs" ); + if( !type_engine_import_mfun( env, func ) ) goto error; + + // add cross() product | same as vec4 * vec4 + // (which ignores w and computes a 3d cross product) + func = make_new_mfun( "vec4", "cross", vec4_cross ); + func->add_arg( "vec4", "rhs" ); + if( !type_engine_import_mfun( env, func ) ) goto error; + // end the class import type_engine_import_class_end( env ); @@ -2222,6 +2248,16 @@ CK_DLL_MFUN( vec2_normalize ) } } +CK_DLL_MFUN( vec2_dot ) // 1.5.4.2 (ge & azaday) added +{ + // get lhs value + t_CKVEC2 lhs = *((t_CKVEC2 *)SELF); + // get rhs from argument + t_CKVEC2 rhs = GET_NEXT_VEC2(ARGS); + // compute dot product and set as return value + RETURN->v_float = lhs.x*rhs.x + lhs.y*rhs.y; +} + //----------------------------------------------------------------------------- // vec3 API @@ -2270,6 +2306,28 @@ CK_DLL_MFUN( vec3_normalize ) } } +CK_DLL_MFUN( vec3_dot ) // 1.5.4.2 (ge & azaday) added +{ + // get lhs value + t_CKVEC3 lhs = *((t_CKVEC3 *)SELF); + // get rhs from argument + t_CKVEC3 rhs = GET_NEXT_VEC3(ARGS); + // compute dot product and set as return value + RETURN->v_float = lhs.x*rhs.x + lhs.y*rhs.y + lhs.z*rhs.z; +} + +CK_DLL_MFUN( vec3_cross ) // 1.5.4.2 (ge & azaday) added +{ + // get lhs value + t_CKVEC3 lhs = *((t_CKVEC3 *)SELF); + // get rhs from argument + t_CKVEC3 rhs = GET_NEXT_VEC3(ARGS); + // compute cross product and set as return value + RETURN->v_vec3.x = lhs.y*rhs.z - lhs.z*rhs.y; + RETURN->v_vec3.y = lhs.z*rhs.x - lhs.x*rhs.z; + RETURN->v_vec3.z = lhs.x*rhs.y - lhs.y*rhs.x; +} + CK_DLL_MFUN( vec3_interp ) { // get data pointer @@ -2406,6 +2464,31 @@ CK_DLL_MFUN( vec4_normalize ) } } +CK_DLL_MFUN( vec4_dot ) // 1.5.4.2 (ge & azaday) added +{ + // get lhs value + t_CKVEC4 lhs = *((t_CKVEC4 *)SELF); + // get rhs from argument + t_CKVEC4 rhs = GET_NEXT_VEC4(ARGS); + // compute dot product and set as return value + RETURN->v_float = lhs.x*rhs.x + lhs.y*rhs.y + lhs.z*rhs.z + lhs.w*rhs.w; +} + +CK_DLL_MFUN( vec4_cross ) // 1.5.4.2 (ge & azaday) added +{ + // get lhs value + t_CKVEC3 lhs = *((t_CKVEC3 *)SELF); + // get rhs from argument + t_CKVEC3 rhs = GET_NEXT_VEC3(ARGS); + // compute cross product and set as return value + // 4D cross product is undefined; as a shorthand we do a 3D cross product + // w is ignored in the calcluation, and the resulting w component is set to 0 + RETURN->v_vec4.x = lhs.y*rhs.z - lhs.z*rhs.y; + RETURN->v_vec4.y = lhs.z*rhs.x - lhs.x*rhs.z; + RETURN->v_vec4.z = lhs.x*rhs.y - lhs.y*rhs.x; + RETURN->v_vec4.w = 0; +} + diff --git a/src/core/chuck_lang.h b/src/core/chuck_lang.h index c5fda87f8..83aaf5d96 100644 --- a/src/core/chuck_lang.h +++ b/src/core/chuck_lang.h @@ -263,10 +263,13 @@ CK_DLL_MFUN( vec2_set ); CK_DLL_MFUN( vec2_setAll ); CK_DLL_MFUN( vec2_magnitude ); CK_DLL_MFUN( vec2_normalize ); +CK_DLL_MFUN( vec2_dot ); CK_DLL_MFUN( vec3_set ); CK_DLL_MFUN( vec3_setAll ); CK_DLL_MFUN( vec3_magnitude ); CK_DLL_MFUN( vec3_normalize ); +CK_DLL_MFUN( vec3_dot ); +CK_DLL_MFUN( vec3_cross ); CK_DLL_MFUN( vec3_interp ); CK_DLL_MFUN( vec3_interp_delta_float ); CK_DLL_MFUN( vec3_interp_delta_dur ); @@ -278,6 +281,8 @@ CK_DLL_MFUN( vec4_set ); CK_DLL_MFUN( vec4_setAll ); CK_DLL_MFUN( vec4_magnitude ); CK_DLL_MFUN( vec4_normalize ); +CK_DLL_MFUN( vec4_dot ); +CK_DLL_MFUN( vec4_cross ); //----------------------------------------------------------------------------- diff --git a/src/core/chuck_type.cpp b/src/core/chuck_type.cpp index 63e6d3c47..bc24a0dc1 100644 --- a/src/core/chuck_type.cpp +++ b/src/core/chuck_type.cpp @@ -4669,7 +4669,7 @@ t_CKTYPE type_engine_check_exp_func_call( Chuck_Env * env, a_Exp exp_func, a_Exp } else if( exp_func->s_type == ae_exp_dot_member ) { - EM_error2( exp_func->where, + EM_error2( exp_func->dot_member.where, "argument type(s) do not match...\n...for function '%s(...)'...", type_engine_print_exp_dot_member( env, &exp_func->dot_member ).c_str() ); } diff --git a/src/test/01-Basic/257-vec3.ck b/src/test/01-Basic/257-vec3.ck new file mode 100644 index 000000000..cd08a992b --- /dev/null +++ b/src/test/01-Basic/257-vec3.ck @@ -0,0 +1,51 @@ +// test vec3 +// including .cross() and .dot(), which were added in 1.5.4.2 +// vec3 is a primitive type + +@(1,0,0) => vec3 a; +// declare another +@(0,1,0) => vec3 b; + +// add them +a + b => vec3 sum; +// difference +a - b => vec3 diff; +// cross product +a * b => vec3 c; +// another way to do cross product (function) +a.cross(b) => vec3 cross; +// dot product (function) +a.dot(b) => float dot; + +// print sum! +<<< "sum:", sum >>>; +// print difference +<<< "diff:", diff >>>; +// print cross product +<<< "cross product:", c >>>; +<<< "cross product (function):", cross >>>; +// print dot product +<<< "dot product:", dot >>>; + +// array +[ a, b, @(-1,1,0) ] @=> vec3 group[]; +// print them +<<< group[0], group[1], group[2] >>>; + +// another v +vec3 v; +// set value +v.set( 2,2,2 ); +// print magnitude +<<< "magnitude:", v.magnitude() >>>; +// normalize +v.normalize(); +// print vector +<<< "normalize:", v >>>; + +// multiply +5 * v => vec3 v2; +// print result +<<< "scalar multiply:", v2 >>>; + + diff --git a/src/test/01-Basic/257-vec3.txt b/src/test/01-Basic/257-vec3.txt new file mode 100644 index 000000000..5f15625d4 --- /dev/null +++ b/src/test/01-Basic/257-vec3.txt @@ -0,0 +1,9 @@ +sum: #(1.0000,1.0000,0.0000) +diff: #(1.0000,-1.0000,0.0000) +cross product: #(0.0000,0.0000,1.0000) +cross product (function): #(0.0000,0.0000,1.0000) +dot product: 0.000000 +#(1.0000,0.0000,0.0000) #(0.0000,1.0000,0.0000) #(-1.0000,1.0000,0.0000) +magnitude: 3.464102 +normalize: #(0.5774,0.5774,0.5774) +scalar multiply: #(2.8868,2.8868,2.8868) diff --git a/src/test/01-Basic/258-vec4.ck b/src/test/01-Basic/258-vec4.ck new file mode 100644 index 000000000..fc87fd93f --- /dev/null +++ b/src/test/01-Basic/258-vec4.ck @@ -0,0 +1,31 @@ +// vec4 is a primitive type +@(1,2,3,4) => vec4 a; +// declare another +@(5,6,7,8) => vec4 b; + +// add them +a + b => vec4 sum; +// difference +a - b => vec4 diff; +// cross product (ignores w component) +a * b => vec4 c; +// another way to do cross product (ignores w component) +a.cross(b) => vec4 cross; +// dot product (function) +a.dot(b) => float dot; + +// print sum! +<<< "sum:", sum >>>; +// print difference +<<< "diff:", diff >>>; +// print cross product +<<< "cross product:", c >>>; +<<< "cross product (function):", cross >>>; +// print dot product +<<< "dot product:", dot >>>; + +// array +[ a, b, c ] @=> vec4 group[]; + +// print them +<<< group[0], group[1], group[2] >>>; diff --git a/src/test/01-Basic/258-vec4.txt b/src/test/01-Basic/258-vec4.txt new file mode 100644 index 000000000..7c597ca90 --- /dev/null +++ b/src/test/01-Basic/258-vec4.txt @@ -0,0 +1,6 @@ +sum: #(6.0000,8.0000,10.0000,12.0000) +diff: #(-4.0000,-4.0000,-4.0000,-4.0000) +cross product: #(-4.0000,8.0000,-4.0000,0.0000) +cross product (function): #(-4.0000,8.0000,-4.0000,0.0000) +dot product: 70.000000 +#(1.0000,2.0000,3.0000,4.0000) #(5.0000,6.0000,7.0000,8.0000) #(-4.0000,8.0000,-4.0000,0.0000)