Improving math functions (#813)
* Improving math functions * Isaac review
This commit is contained in:
parent
0087bfbda0
commit
8db6356754
2
Makefile
2
Makefile
@ -264,7 +264,7 @@ endif
|
||||
# Including an option to disable it.
|
||||
|
||||
# Level 0 produces no debug information at all. Thus, -g0 negates -g.
|
||||
# Level 1 produces minimal information, enough for making backtraces in parts of the program that you don’t plan to debug. This includes descriptions of functions and external variables, and line number tables, but no information about local variables.
|
||||
# Level 1 produces minimal information, enough for making backtraces in parts of the program that you don't plan to debug. This includes descriptions of functions and external variables, and line number tables, but no information about local variables.
|
||||
# Level 3 includes extra information, such as all the macro definitions present in the program. Some debuggers support macro expansion when you use -g3.
|
||||
# From https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html
|
||||
ifeq ($(DEBUG_INFO_LEVEL),3)
|
||||
|
@ -1,4 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
python3 ./autogen/gen_math.py $1
|
||||
python3 ./autogen/convert_structs.py $1
|
||||
python3 ./autogen/convert_functions.py $1
|
||||
python3 ./autogen/convert_constants.py $1
|
||||
|
@ -523,15 +523,15 @@ def main():
|
||||
|
||||
built_c = build_to_c(built_files)
|
||||
|
||||
with open(get_path(out_filename), 'w') as out:
|
||||
with open(get_path(out_filename), 'w', encoding='utf-8', newline='\n') as out:
|
||||
out.write(built_c)
|
||||
|
||||
doc = doc_files(processed_files)
|
||||
with open(get_path(out_filename_docs), 'w') as out:
|
||||
with open(get_path(out_filename_docs), 'w', encoding='utf-8', newline='\n') as out:
|
||||
out.write(doc)
|
||||
|
||||
defs = build_to_def(processed_files)
|
||||
with open(get_path(out_filename_defs), 'w') as out:
|
||||
with open(get_path(out_filename_defs), 'w', encoding='utf-8', newline='\n') as out:
|
||||
out.write(defs)
|
||||
|
||||
global totalConstants
|
||||
|
@ -16,6 +16,11 @@ out_filename_defs = 'autogen/lua_definitions/functions.lua'
|
||||
in_files = [
|
||||
"src/audio/external.h",
|
||||
"src/engine/math_util.h",
|
||||
"src/engine/math_util.inl",
|
||||
"src/engine/math_util_vec3f.inl",
|
||||
"src/engine/math_util_vec3i.inl",
|
||||
"src/engine/math_util_vec3s.inl",
|
||||
"src/engine/math_util_mat4.inl",
|
||||
"src/engine/surface_collision.h",
|
||||
"src/engine/surface_load.h",
|
||||
"src/game/camera.h",
|
||||
@ -49,7 +54,6 @@ in_files = [
|
||||
"src/pc/lua/utils/smlua_camera_utils.h",
|
||||
"src/pc/lua/utils/smlua_gfx_utils.h",
|
||||
"src/pc/lua/utils/smlua_collision_utils.h",
|
||||
"src/pc/lua/utils/smlua_math_utils.h",
|
||||
"src/pc/lua/utils/smlua_model_utils.h",
|
||||
"src/pc/lua/utils/smlua_text_utils.h",
|
||||
"src/pc/lua/utils/smlua_audio_utils.h",
|
||||
@ -96,7 +100,6 @@ override_allowed_functions = {
|
||||
|
||||
override_disallowed_functions = {
|
||||
"src/audio/external.h": [ " func_" ],
|
||||
"src/engine/math_util.h": [ "atan2f", "vec3s_sub" ],
|
||||
"src/engine/surface_load.h": [ "load_area_terrain", "alloc_surface_pools", "clear_dynamic_surfaces", "get_area_terrain_size" ],
|
||||
"src/engine/surface_collision.h": [ " debug_", "f32_find_wall_collision" ],
|
||||
"src/game/mario_actions_airborne.c": [ "^[us]32 act_.*" ],
|
||||
@ -1190,7 +1193,7 @@ def output_fuzz_file():
|
||||
global fuzz_functions
|
||||
with open(fuzz_from) as f:
|
||||
file_str = f.read()
|
||||
with open(fuzz_to, 'w') as f:
|
||||
with open(fuzz_to, 'w', encoding='utf-8', newline='\n') as f:
|
||||
f.write(file_str.replace('-- $[FUNCS]', fuzz_functions))
|
||||
|
||||
############################################################################
|
||||
@ -1379,7 +1382,7 @@ def doc_files(processed_files):
|
||||
|
||||
buffer = buffer.replace('$[FUNCTION_NAV_HERE', function_nav)
|
||||
|
||||
with open(get_path(out_filename_docs % page_name), 'w', newline='\n') as out:
|
||||
with open(get_path(out_filename_docs % page_name), 'w', encoding='utf-8', newline='\n') as out:
|
||||
out.write(buffer)
|
||||
|
||||
############################################################################
|
||||
@ -1437,7 +1440,7 @@ def def_files(processed_files):
|
||||
for def_pointer in def_pointers:
|
||||
s += '--- @alias %s %s\n' % (def_pointer, def_pointer[8:])
|
||||
|
||||
with open(get_path(out_filename_defs), 'w', newline='\n') as out:
|
||||
with open(get_path(out_filename_defs), 'w', encoding='utf-8', newline='\n') as out:
|
||||
out.write(s)
|
||||
|
||||
############################################################################
|
||||
@ -1458,7 +1461,7 @@ def main():
|
||||
.replace("$[BINDS]", built_binds) \
|
||||
.replace("$[INCLUDES]", built_includes)
|
||||
|
||||
with open(filename, 'w', newline='\n') as out:
|
||||
with open(filename, 'w', encoding='utf-8', newline='\n') as out:
|
||||
out.write(gen)
|
||||
|
||||
if rejects != "":
|
||||
|
@ -70,9 +70,6 @@ struct LuaObjectField* smlua_get_object_field_autogen(u16 lot, const char* key);
|
||||
#endif
|
||||
"""
|
||||
|
||||
override_field_names = {
|
||||
}
|
||||
|
||||
override_field_types = {
|
||||
"Surface": { "normal": "Vec3f" },
|
||||
"Object": { "oAnimations": "ObjectAnimPointer*" },
|
||||
@ -415,7 +412,7 @@ def output_fuzz_file():
|
||||
global fuzz_structs_calls
|
||||
with open(fuzz_from) as f:
|
||||
file_str = f.read()
|
||||
with open(fuzz_to, 'w') as f:
|
||||
with open(fuzz_to, 'w', encoding='utf-8', newline='\n') as f:
|
||||
f.write(file_str.replace('-- $[STRUCTS]', fuzz_structs).replace('-- $[FUZZ-STRUCTS]', fuzz_structs_calls))
|
||||
|
||||
############################################################################
|
||||
@ -463,9 +460,6 @@ def get_struct_field_info(struct, field):
|
||||
ftype = field['type']
|
||||
size = 1
|
||||
|
||||
if sid in override_field_names and fid in override_field_names[sid]:
|
||||
fid = override_field_names[sid][fid]
|
||||
|
||||
if sid in override_field_types and fid in override_field_types[sid]:
|
||||
ftype = override_field_types[sid][fid]
|
||||
|
||||
@ -729,7 +723,7 @@ def doc_structs(structs):
|
||||
continue
|
||||
s += doc_struct(struct) + '\n'
|
||||
|
||||
with open(get_path(out_filename_docs), 'w', newline='\n') as out:
|
||||
with open(get_path(out_filename_docs), 'w', encoding='utf-8', newline='\n') as out:
|
||||
out.write(s)
|
||||
|
||||
############################################################################
|
||||
@ -777,7 +771,7 @@ def def_structs(structs):
|
||||
for def_pointer in def_pointers:
|
||||
s += '--- @alias %s %s\n' % (def_pointer, def_pointer[8:])
|
||||
|
||||
with open(get_path(out_filename_defs), 'w', newline='\n') as out:
|
||||
with open(get_path(out_filename_defs), 'w', encoding='utf-8', newline='\n') as out:
|
||||
out.write(s)
|
||||
|
||||
############################################################################
|
||||
@ -799,11 +793,11 @@ def build_files():
|
||||
built_include = build_includes()
|
||||
|
||||
out_c_filename = get_path(out_filename_c)
|
||||
with open(out_c_filename, 'w', newline='\n') as out:
|
||||
with open(out_c_filename, 'w', encoding='utf-8', newline='\n') as out:
|
||||
out.write(c_template.replace("$[BODY]", built_body).replace('$[INCLUDES]', built_include))
|
||||
|
||||
out_h_filename = get_path(out_filename_h)
|
||||
with open(out_h_filename, 'w', newline='\n') as out:
|
||||
with open(out_h_filename, 'w', encoding='utf-8', newline='\n') as out:
|
||||
out.write(h_template.replace("$[BODY]", built_enum))
|
||||
|
||||
doc_structs(parsed)
|
||||
|
103
autogen/gen_math.py
Normal file
103
autogen/gen_math.py
Normal file
@ -0,0 +1,103 @@
|
||||
import sys
|
||||
|
||||
|
||||
VEC3X_TO_VEC3Y = """
|
||||
/* |description|
|
||||
Converts a 3D {{desc}} vector `a` into a 3D {{desc_2}} vector and stores the result in `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 {{type_2}} *vec3{{suffix}}_to_vec3{{suffix_2}}(Vec3{{suffix_2}} dest, Vec3{{suffix}} a) {
|
||||
dest[0] = a[0]{{rounding_0}};
|
||||
dest[1] = a[1]{{rounding_1}};
|
||||
dest[2] = a[2]{{rounding_2}};
|
||||
return dest;
|
||||
}
|
||||
"""
|
||||
|
||||
ROUNDING_FORMULA = " + ((a[%d] > 0) ? 0.5f : -0.5f)"
|
||||
|
||||
def vec3_write_conversion_functions(generated: str, curr_template: dict, templates: list, size: int) -> str:
|
||||
for template in templates:
|
||||
if template["suffix"] == curr_template["suffix"]:
|
||||
continue
|
||||
|
||||
generated += VEC3X_TO_VEC3Y \
|
||||
.replace("{{desc}}", curr_template["desc"]) \
|
||||
.replace("{{suffix}}", curr_template["suffix"]) \
|
||||
.replace("{{desc_2}}", template["desc"]) \
|
||||
.replace("{{type_2}}", template["type"]) \
|
||||
.replace("{{suffix_2}}", template["suffix"])
|
||||
|
||||
for i in range(size):
|
||||
rounding_i = "{{rounding_%d}}" % (i)
|
||||
generated = generated.replace(rounding_i, ROUNDING_FORMULA % (i) if curr_template["rounding"] else "")
|
||||
|
||||
return generated
|
||||
|
||||
|
||||
TEMPLATES = {
|
||||
"src/engine/math_util_vec3.tmpl": {
|
||||
"size": 3,
|
||||
"templates": [
|
||||
{
|
||||
"desc": "floating-point",
|
||||
"type": "f32",
|
||||
"suffix": "f",
|
||||
"rounding": True
|
||||
},
|
||||
{
|
||||
"desc": "integer",
|
||||
"type": "s32",
|
||||
"suffix": "i",
|
||||
"rounding": False
|
||||
},
|
||||
{
|
||||
"desc": "short integer",
|
||||
"type": "s16",
|
||||
"suffix": "s",
|
||||
"rounding": False
|
||||
}
|
||||
],
|
||||
"post-template": {
|
||||
"function": vec3_write_conversion_functions,
|
||||
"args": {
|
||||
"size": 3
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
verbose = len(sys.argv) > 1 and (sys.argv[1] == "-v" or sys.argv[1] == "--verbose")
|
||||
for template_file, x in TEMPLATES.items():
|
||||
with open(template_file) as f:
|
||||
tmpl = f.read()
|
||||
templates = x["templates"]
|
||||
post_template = x.get("post-template", None)
|
||||
|
||||
if verbose:
|
||||
print("Generating the following files from template: %s" % (template_file))
|
||||
|
||||
for template in templates:
|
||||
generated = (
|
||||
"/* THIS FILE IS AUTO-GENERATED */\n" +
|
||||
"/* DO NOT EDIT IT MANUALLY */\n\n" +
|
||||
tmpl
|
||||
)
|
||||
|
||||
for template_field, template_replacement in template.items():
|
||||
generated = generated.replace("{{" + template_field + "}}", str(template_replacement))
|
||||
|
||||
if post_template:
|
||||
generated = post_template["function"](generated, template, templates, **post_template["args"])
|
||||
|
||||
generated_filename = template_file[:template_file.rfind(".")] + template["suffix"] + ".inl"
|
||||
with open(generated_filename, 'w', encoding='utf-8', newline='\n') as f:
|
||||
f.write(generated)
|
||||
|
||||
if verbose:
|
||||
print(">>> %s" % (generated_filename))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -135,6 +135,39 @@ function network_player_get_override_palette_color(np, part)
|
||||
end
|
||||
|
||||
|
||||
--------------------
|
||||
-- math functions --
|
||||
--------------------
|
||||
--- Note: These functions don't exist in the Lua math library,
|
||||
--- and are useful enough to not have to redefine them in every mod
|
||||
|
||||
local __math_min, __math_max, __math_sqrt = math.min, math.max, math.sqrt
|
||||
|
||||
--- @param x number
|
||||
--- @return number
|
||||
--- Computes the square of the number `x`
|
||||
function math.sqr(x)
|
||||
return x * x
|
||||
end
|
||||
|
||||
--- @param x number
|
||||
--- @param a number
|
||||
--- @param b number
|
||||
--- @return number
|
||||
--- Clamps the number `x` between bounds `a` (minimum) and `b` (maximum)
|
||||
function math.clamp(x, a, b)
|
||||
return __math_min(__math_max(x, a), b)
|
||||
end
|
||||
|
||||
--- @param a number
|
||||
--- @param b number
|
||||
--- @return number
|
||||
--- Computes the hypotenuse of a right-angled triangle given sides `a` and `b` using the Pythagorean theorem
|
||||
function math.hypot(a, b)
|
||||
return __math_sqrt(a * a + b * b)
|
||||
end
|
||||
|
||||
|
||||
-----------------
|
||||
-- legacy font --
|
||||
-----------------
|
||||
|
@ -1,2 +1,19 @@
|
||||
--- @type integer
|
||||
ANIM_FLAG_FORWARD = (1 << 1)
|
||||
|
||||
|
||||
--------------------
|
||||
-- Math functions --
|
||||
--------------------
|
||||
--- Note: These functions were originally in smlua_math_utils.h,
|
||||
--- but performed worse (~2x slower) than built-in Lua math functions
|
||||
|
||||
min = math.min
|
||||
minf = math.min
|
||||
max = math.max
|
||||
maxf = math.max
|
||||
sqr = math.sqr
|
||||
sqrf = math.sqr
|
||||
clamp = math.clamp
|
||||
clampf = math.clamp
|
||||
hypotf = math.hypot
|
||||
|
@ -137,6 +137,39 @@ function network_player_get_override_palette_color(np, part)
|
||||
end
|
||||
|
||||
|
||||
--------------------
|
||||
-- math functions --
|
||||
--------------------
|
||||
--- Note: These functions don't exist in the Lua math library,
|
||||
--- and are useful enough to not have to redefine them in every mod
|
||||
|
||||
local __math_min, __math_max, __math_sqrt = math.min, math.max, math.sqrt
|
||||
|
||||
--- @param x number
|
||||
--- @return number
|
||||
--- Computes the square of the number `x`
|
||||
function math.sqr(x)
|
||||
return x * x
|
||||
end
|
||||
|
||||
--- @param x number
|
||||
--- @param a number
|
||||
--- @param b number
|
||||
--- @return number
|
||||
--- Clamps the number `x` between bounds `a` (minimum) and `b` (maximum)
|
||||
function math.clamp(x, a, b)
|
||||
return __math_min(__math_max(x, a), b)
|
||||
end
|
||||
|
||||
--- @param a number
|
||||
--- @param b number
|
||||
--- @return number
|
||||
--- Computes the hypotenuse of a right-angled triangle given sides `a` and `b` using the Pythagorean theorem
|
||||
function math.hypot(a, b)
|
||||
return __math_sqrt(a * a + b * b)
|
||||
end
|
||||
|
||||
|
||||
-----------------
|
||||
-- legacy font --
|
||||
-----------------
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2432,6 +2432,25 @@
|
||||
--- @field public z number
|
||||
--- @field public w number
|
||||
|
||||
--- @class Vec2i
|
||||
--- @field public x integer
|
||||
--- @field public y integer
|
||||
|
||||
--- @class Vec3i
|
||||
--- @field public x integer
|
||||
--- @field public y integer
|
||||
--- @field public z integer
|
||||
|
||||
--- @class Vec4i
|
||||
--- @field public x integer
|
||||
--- @field public y integer
|
||||
--- @field public z integer
|
||||
--- @field public w integer
|
||||
|
||||
--- @class Vec2s
|
||||
--- @field public x integer
|
||||
--- @field public y integer
|
||||
|
||||
--- @class Vec3s
|
||||
--- @field public x integer
|
||||
--- @field public y integer
|
||||
|
@ -26,6 +26,41 @@ VEC_TYPES = {
|
||||
"w": "[3]",
|
||||
},
|
||||
},
|
||||
"Vec2i": {
|
||||
"field_c_type": "s32",
|
||||
"field_lua_type": "integer",
|
||||
"fields_mapping": {
|
||||
"x": "[0]",
|
||||
"y": "[1]",
|
||||
},
|
||||
},
|
||||
"Vec3i": {
|
||||
"field_c_type": "s32",
|
||||
"field_lua_type": "integer",
|
||||
"fields_mapping": {
|
||||
"x": "[0]",
|
||||
"y": "[1]",
|
||||
"z": "[2]",
|
||||
},
|
||||
},
|
||||
"Vec4i": {
|
||||
"field_c_type": "s32",
|
||||
"field_lua_type": "integer",
|
||||
"fields_mapping": {
|
||||
"x": "[0]",
|
||||
"y": "[1]",
|
||||
"z": "[2]",
|
||||
"w": "[3]",
|
||||
},
|
||||
},
|
||||
"Vec2s": {
|
||||
"field_c_type": "s16",
|
||||
"field_lua_type": "integer",
|
||||
"fields_mapping": {
|
||||
"x": "[0]",
|
||||
"y": "[1]",
|
||||
},
|
||||
},
|
||||
"Vec3s": {
|
||||
"field_c_type": "s16",
|
||||
"field_lua_type": "integer",
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -5,6 +5,483 @@
|
||||
[< prev](functions-5.md) | [1](functions.md) | [2](functions-2.md) | [3](functions-3.md) | [4](functions-4.md) | [5](functions-5.md) | 6]
|
||||
|
||||
|
||||
---
|
||||
# functions from smlua_audio_utils.h
|
||||
|
||||
<br />
|
||||
|
||||
|
||||
## [smlua_audio_utils_reset_all](#smlua_audio_utils_reset_all)
|
||||
|
||||
### Description
|
||||
Resets all custom sequences back to vanilla
|
||||
|
||||
### Lua Example
|
||||
`smlua_audio_utils_reset_all()`
|
||||
|
||||
### Parameters
|
||||
- None
|
||||
|
||||
### Returns
|
||||
- None
|
||||
|
||||
### C Prototype
|
||||
`void smlua_audio_utils_reset_all(void);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [smlua_audio_utils_replace_sequence](#smlua_audio_utils_replace_sequence)
|
||||
|
||||
### Description
|
||||
Replaces the sequence corresponding to `sequenceId` with one called `m64Name`.m64 with `bankId` and `defaultVolume`
|
||||
|
||||
### Lua Example
|
||||
`smlua_audio_utils_replace_sequence(sequenceId, bankId, defaultVolume, m64Name)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| sequenceId | `integer` |
|
||||
| bankId | `integer` |
|
||||
| defaultVolume | `integer` |
|
||||
| m64Name | `string` |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
|
||||
### C Prototype
|
||||
`void smlua_audio_utils_replace_sequence(u8 sequenceId, u8 bankId, u8 defaultVolume, const char* m64Name);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [audio_stream_load](#audio_stream_load)
|
||||
|
||||
### Description
|
||||
Loads an `audio` stream by `filename` (with extension)
|
||||
|
||||
### Lua Example
|
||||
`local ModAudioValue = audio_stream_load(filename)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| filename | `string` |
|
||||
|
||||
### Returns
|
||||
[ModAudio](structs.md#ModAudio)
|
||||
|
||||
### C Prototype
|
||||
`struct ModAudio* audio_stream_load(const char* filename);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [audio_stream_destroy](#audio_stream_destroy)
|
||||
|
||||
### Description
|
||||
Destroys an `audio` stream
|
||||
|
||||
### Lua Example
|
||||
`audio_stream_destroy(audio)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| audio | [ModAudio](structs.md#ModAudio) |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
|
||||
### C Prototype
|
||||
`void audio_stream_destroy(struct ModAudio* audio);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [audio_stream_play](#audio_stream_play)
|
||||
|
||||
### Description
|
||||
Plays an `audio` stream with `volume`. `restart` sets the elapsed time back to 0.
|
||||
|
||||
### Lua Example
|
||||
`audio_stream_play(audio, restart, volume)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| audio | [ModAudio](structs.md#ModAudio) |
|
||||
| restart | `boolean` |
|
||||
| volume | `number` |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
|
||||
### C Prototype
|
||||
`void audio_stream_play(struct ModAudio* audio, bool restart, f32 volume);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [audio_stream_pause](#audio_stream_pause)
|
||||
|
||||
### Description
|
||||
Pauses an `audio` stream
|
||||
|
||||
### Lua Example
|
||||
`audio_stream_pause(audio)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| audio | [ModAudio](structs.md#ModAudio) |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
|
||||
### C Prototype
|
||||
`void audio_stream_pause(struct ModAudio* audio);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [audio_stream_stop](#audio_stream_stop)
|
||||
|
||||
### Description
|
||||
Stops an `audio` stream
|
||||
|
||||
### Lua Example
|
||||
`audio_stream_stop(audio)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| audio | [ModAudio](structs.md#ModAudio) |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
|
||||
### C Prototype
|
||||
`void audio_stream_stop(struct ModAudio* audio);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [audio_stream_get_position](#audio_stream_get_position)
|
||||
|
||||
### Description
|
||||
Gets the position of an `audio` stream in seconds
|
||||
|
||||
### Lua Example
|
||||
`local numberValue = audio_stream_get_position(audio)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| audio | [ModAudio](structs.md#ModAudio) |
|
||||
|
||||
### Returns
|
||||
- `number`
|
||||
|
||||
### C Prototype
|
||||
`f32 audio_stream_get_position(struct ModAudio* audio);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [audio_stream_set_position](#audio_stream_set_position)
|
||||
|
||||
### Description
|
||||
Sets the position of an `audio` stream in seconds
|
||||
|
||||
### Lua Example
|
||||
`audio_stream_set_position(audio, pos)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| audio | [ModAudio](structs.md#ModAudio) |
|
||||
| pos | `number` |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
|
||||
### C Prototype
|
||||
`void audio_stream_set_position(struct ModAudio* audio, f32 pos);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [audio_stream_get_looping](#audio_stream_get_looping)
|
||||
|
||||
### Description
|
||||
Gets if an `audio` stream is looping or not
|
||||
|
||||
### Lua Example
|
||||
`local booleanValue = audio_stream_get_looping(audio)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| audio | [ModAudio](structs.md#ModAudio) |
|
||||
|
||||
### Returns
|
||||
- `boolean`
|
||||
|
||||
### C Prototype
|
||||
`bool audio_stream_get_looping(struct ModAudio* audio);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [audio_stream_set_looping](#audio_stream_set_looping)
|
||||
|
||||
### Description
|
||||
Sets if an `audio` stream is looping or not
|
||||
|
||||
### Lua Example
|
||||
`audio_stream_set_looping(audio, looping)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| audio | [ModAudio](structs.md#ModAudio) |
|
||||
| looping | `boolean` |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
|
||||
### C Prototype
|
||||
`void audio_stream_set_looping(struct ModAudio* audio, bool looping);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [audio_stream_set_loop_points](#audio_stream_set_loop_points)
|
||||
|
||||
### Description
|
||||
Sets an `audio` stream's loop points in samples
|
||||
|
||||
### Lua Example
|
||||
`audio_stream_set_loop_points(audio, loopStart, loopEnd)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| audio | [ModAudio](structs.md#ModAudio) |
|
||||
| loopStart | `integer` |
|
||||
| loopEnd | `integer` |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
|
||||
### C Prototype
|
||||
`void audio_stream_set_loop_points(struct ModAudio* audio, s64 loopStart, s64 loopEnd);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [audio_stream_get_frequency](#audio_stream_get_frequency)
|
||||
|
||||
### Description
|
||||
Gets the frequency of an `audio` stream
|
||||
|
||||
### Lua Example
|
||||
`local numberValue = audio_stream_get_frequency(audio)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| audio | [ModAudio](structs.md#ModAudio) |
|
||||
|
||||
### Returns
|
||||
- `number`
|
||||
|
||||
### C Prototype
|
||||
`f32 audio_stream_get_frequency(struct ModAudio* audio);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [audio_stream_set_frequency](#audio_stream_set_frequency)
|
||||
|
||||
### Description
|
||||
Sets the frequency of an `audio` stream
|
||||
|
||||
### Lua Example
|
||||
`audio_stream_set_frequency(audio, freq)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| audio | [ModAudio](structs.md#ModAudio) |
|
||||
| freq | `number` |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
|
||||
### C Prototype
|
||||
`void audio_stream_set_frequency(struct ModAudio* audio, f32 freq);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [audio_stream_get_volume](#audio_stream_get_volume)
|
||||
|
||||
### Description
|
||||
Gets the volume of an `audio` stream
|
||||
|
||||
### Lua Example
|
||||
`local numberValue = audio_stream_get_volume(audio)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| audio | [ModAudio](structs.md#ModAudio) |
|
||||
|
||||
### Returns
|
||||
- `number`
|
||||
|
||||
### C Prototype
|
||||
`f32 audio_stream_get_volume(struct ModAudio* audio);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [audio_stream_set_volume](#audio_stream_set_volume)
|
||||
|
||||
### Description
|
||||
Sets the volume of an `audio` stream
|
||||
|
||||
### Lua Example
|
||||
`audio_stream_set_volume(audio, volume)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| audio | [ModAudio](structs.md#ModAudio) |
|
||||
| volume | `number` |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
|
||||
### C Prototype
|
||||
`void audio_stream_set_volume(struct ModAudio* audio, f32 volume);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [audio_sample_load](#audio_sample_load)
|
||||
|
||||
### Description
|
||||
Loads an `audio` sample
|
||||
|
||||
### Lua Example
|
||||
`local ModAudioValue = audio_sample_load(filename)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| filename | `string` |
|
||||
|
||||
### Returns
|
||||
[ModAudio](structs.md#ModAudio)
|
||||
|
||||
### C Prototype
|
||||
`struct ModAudio* audio_sample_load(const char* filename);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [audio_sample_destroy](#audio_sample_destroy)
|
||||
|
||||
### Description
|
||||
Destroys an `audio` sample
|
||||
|
||||
### Lua Example
|
||||
`audio_sample_destroy(audio)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| audio | [ModAudio](structs.md#ModAudio) |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
|
||||
### C Prototype
|
||||
`void audio_sample_destroy(struct ModAudio* audio);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [audio_sample_stop](#audio_sample_stop)
|
||||
|
||||
### Description
|
||||
Stops an `audio` sample
|
||||
|
||||
### Lua Example
|
||||
`audio_sample_stop(audio)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| audio | [ModAudio](structs.md#ModAudio) |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
|
||||
### C Prototype
|
||||
`void audio_sample_stop(struct ModAudio* audio);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [audio_sample_play](#audio_sample_play)
|
||||
|
||||
### Description
|
||||
Plays an `audio` sample at `position` with `volume`
|
||||
|
||||
### Lua Example
|
||||
`audio_sample_play(audio, position, volume)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| audio | [ModAudio](structs.md#ModAudio) |
|
||||
| position | [Vec3f](structs.md#Vec3f) |
|
||||
| volume | `number` |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
|
||||
### C Prototype
|
||||
`void audio_sample_play(struct ModAudio* audio, Vec3f position, f32 volume);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
---
|
||||
# functions from smlua_camera_utils.h
|
||||
|
||||
@ -2574,320 +3051,6 @@ Warps back to the castle from `aLevel`
|
||||
|
||||
<br />
|
||||
|
||||
---
|
||||
# functions from smlua_math_utils.h
|
||||
|
||||
<br />
|
||||
|
||||
|
||||
## [min](#min)
|
||||
|
||||
### Description
|
||||
Finds the minimum of two signed 32-bit integers
|
||||
|
||||
### Lua Example
|
||||
`local integerValue = min(a, b)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| a | `integer` |
|
||||
| b | `integer` |
|
||||
|
||||
### Returns
|
||||
- `integer`
|
||||
|
||||
### C Prototype
|
||||
`s32 min(s32 a, s32 b);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [max](#max)
|
||||
|
||||
### Description
|
||||
Finds the maximum of two signed 32-bit integers
|
||||
|
||||
### Lua Example
|
||||
`local integerValue = max(a, b)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| a | `integer` |
|
||||
| b | `integer` |
|
||||
|
||||
### Returns
|
||||
- `integer`
|
||||
|
||||
### C Prototype
|
||||
`s32 max(s32 a, s32 b);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [sqr](#sqr)
|
||||
|
||||
### Description
|
||||
Computes the square of a signed 32-bit integer
|
||||
|
||||
### Lua Example
|
||||
`local integerValue = sqr(x)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| x | `integer` |
|
||||
|
||||
### Returns
|
||||
- `integer`
|
||||
|
||||
### C Prototype
|
||||
`s32 sqr(s32 x);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [minf](#minf)
|
||||
|
||||
### Description
|
||||
Finds the minimum of two floating-point numbers
|
||||
|
||||
### Lua Example
|
||||
`local numberValue = minf(a, b)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| a | `number` |
|
||||
| b | `number` |
|
||||
|
||||
### Returns
|
||||
- `number`
|
||||
|
||||
### C Prototype
|
||||
`f32 minf(f32 a, f32 b);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [maxf](#maxf)
|
||||
|
||||
### Description
|
||||
Finds the maximum of two floating-point numbers
|
||||
|
||||
### Lua Example
|
||||
`local numberValue = maxf(a, b)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| a | `number` |
|
||||
| b | `number` |
|
||||
|
||||
### Returns
|
||||
- `number`
|
||||
|
||||
### C Prototype
|
||||
`f32 maxf(f32 a, f32 b);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [sqrf](#sqrf)
|
||||
|
||||
### Description
|
||||
Computes the square of a floating-point number
|
||||
|
||||
### Lua Example
|
||||
`local numberValue = sqrf(x)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| x | `number` |
|
||||
|
||||
### Returns
|
||||
- `number`
|
||||
|
||||
### C Prototype
|
||||
`f32 sqrf(f32 x);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [sm64_to_radians](#sm64_to_radians)
|
||||
|
||||
### Description
|
||||
Converts an angle from SM64 format to radians
|
||||
|
||||
### Lua Example
|
||||
`local numberValue = sm64_to_radians(sm64Angle)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| sm64Angle | `integer` |
|
||||
|
||||
### Returns
|
||||
- `number`
|
||||
|
||||
### C Prototype
|
||||
`f32 sm64_to_radians(s16 sm64Angle);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [radians_to_sm64](#radians_to_sm64)
|
||||
|
||||
### Description
|
||||
Converts an angle from radians to SM64 format
|
||||
|
||||
### Lua Example
|
||||
`local integerValue = radians_to_sm64(radiansAngle)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| radiansAngle | `number` |
|
||||
|
||||
### Returns
|
||||
- `integer`
|
||||
|
||||
### C Prototype
|
||||
`s16 radians_to_sm64(f32 radiansAngle);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [sm64_to_degrees](#sm64_to_degrees)
|
||||
|
||||
### Description
|
||||
Converts an angle from SM64 format to degrees
|
||||
|
||||
### Lua Example
|
||||
`local numberValue = sm64_to_degrees(sm64Angle)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| sm64Angle | `integer` |
|
||||
|
||||
### Returns
|
||||
- `number`
|
||||
|
||||
### C Prototype
|
||||
`f32 sm64_to_degrees(s16 sm64Angle);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [degrees_to_sm64](#degrees_to_sm64)
|
||||
|
||||
### Description
|
||||
Converts an angle from degrees to SM64 format
|
||||
|
||||
### Lua Example
|
||||
`local integerValue = degrees_to_sm64(degreesAngle)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| degreesAngle | `number` |
|
||||
|
||||
### Returns
|
||||
- `integer`
|
||||
|
||||
### C Prototype
|
||||
`s16 degrees_to_sm64(f32 degreesAngle);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [hypotf](#hypotf)
|
||||
|
||||
### Description
|
||||
Computes the hypotenuse of a right triangle given sides `a` and `b` using the Pythagorean theorem
|
||||
|
||||
### Lua Example
|
||||
`local numberValue = hypotf(a, b)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| a | `number` |
|
||||
| b | `number` |
|
||||
|
||||
### Returns
|
||||
- `number`
|
||||
|
||||
### C Prototype
|
||||
`f32 hypotf(f32 a, f32 b);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [clamp](#clamp)
|
||||
|
||||
### Description
|
||||
Clamps a signed 32-bit integer `a` between bounds `b` (minimum) and `c` (maximum)
|
||||
|
||||
### Lua Example
|
||||
`local integerValue = clamp(a, b, c)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| a | `integer` |
|
||||
| b | `integer` |
|
||||
| c | `integer` |
|
||||
|
||||
### Returns
|
||||
- `integer`
|
||||
|
||||
### C Prototype
|
||||
`s32 clamp(s32 a, s32 b, s32 c);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [clampf](#clampf)
|
||||
|
||||
### Description
|
||||
Clamps a floating-point number `a` between bounds `b` (minimum) and `c` (maximum)
|
||||
|
||||
### Lua Example
|
||||
`local numberValue = clampf(a, b, c)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| a | `number` |
|
||||
| b | `number` |
|
||||
| c | `number` |
|
||||
|
||||
### Returns
|
||||
- `number`
|
||||
|
||||
### C Prototype
|
||||
`f32 clampf(f32 a, f32 b, f32 c);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
---
|
||||
# functions from smlua_misc_utils.h
|
||||
|
||||
|
@ -1190,42 +1190,19 @@
|
||||
- [sins](functions-4.md#sins)
|
||||
- [coss](functions-4.md#coss)
|
||||
- [atan2s](functions-4.md#atan2s)
|
||||
- [vec3f_copy](functions-4.md#vec3f_copy)
|
||||
- [vec3f_set](functions-4.md#vec3f_set)
|
||||
- [vec3f_add](functions-4.md#vec3f_add)
|
||||
- [vec3f_sum](functions-4.md#vec3f_sum)
|
||||
- [vec3f_sub](functions-4.md#vec3f_sub)
|
||||
- [vec3f_dif](functions-4.md#vec3f_dif)
|
||||
- [vec3f_mul](functions-4.md#vec3f_mul)
|
||||
- [vec3f_div](functions-4.md#vec3f_div)
|
||||
- [vec3f_cross](functions-4.md#vec3f_cross)
|
||||
- [vec3f_normalize](functions-4.md#vec3f_normalize)
|
||||
- [vec3f_normalize2](functions-4.md#vec3f_normalize2)
|
||||
- [vec3f_length](functions-4.md#vec3f_length)
|
||||
- [vec3f_dot](functions-4.md#vec3f_dot)
|
||||
- [vec3f_combine](functions-4.md#vec3f_combine)
|
||||
- [atan2f](functions-4.md#atan2f)
|
||||
- [approach_s32](functions-4.md#approach_s32)
|
||||
- [approach_f32](functions-4.md#approach_f32)
|
||||
- [spline_get_weights](functions-4.md#spline_get_weights)
|
||||
- [anim_spline_init](functions-4.md#anim_spline_init)
|
||||
- [anim_spline_poll](functions-4.md#anim_spline_poll)
|
||||
- [vec3f_rotate_zxy](functions-4.md#vec3f_rotate_zxy)
|
||||
- [vec3f_rotate_around_n](functions-4.md#vec3f_rotate_around_n)
|
||||
- [vec3f_project](functions-4.md#vec3f_project)
|
||||
- [vec3f_dist](functions-4.md#vec3f_dist)
|
||||
- [vec3f_transform](functions-4.md#vec3f_transform)
|
||||
- [vec3f_get_dist_and_angle](functions-4.md#vec3f_get_dist_and_angle)
|
||||
- [vec3f_set_dist_and_angle](functions-4.md#vec3f_set_dist_and_angle)
|
||||
- [vec3f_zero](functions-4.md#vec3f_zero)
|
||||
- [vec3f_to_vec3s](functions-4.md#vec3f_to_vec3s)
|
||||
- [vec3s_copy](functions-4.md#vec3s_copy)
|
||||
- [vec3s_set](functions-4.md#vec3s_set)
|
||||
- [vec3s_add](functions-4.md#vec3s_add)
|
||||
- [vec3s_sum](functions-4.md#vec3s_sum)
|
||||
- [vec3s_dif](functions-4.md#vec3s_dif)
|
||||
- [vec3s_mul](functions-4.md#vec3s_mul)
|
||||
- [vec3s_div](functions-4.md#vec3s_div)
|
||||
- [vec3s_length](functions-4.md#vec3s_length)
|
||||
- [vec3s_dist](functions-4.md#vec3s_dist)
|
||||
- [vec3s_zero](functions-4.md#vec3s_zero)
|
||||
- [vec3s_to_vec3f](functions-4.md#vec3s_to_vec3f)
|
||||
- [find_vector_perpendicular_to_plane](functions-4.md#find_vector_perpendicular_to_plane)
|
||||
- [mtxf_copy](functions-4.md#mtxf_copy)
|
||||
- [mtxf_identity](functions-4.md#mtxf_identity)
|
||||
- [mtxf_translate](functions-4.md#mtxf_translate)
|
||||
- [mtxf_lookat](functions-4.md#mtxf_lookat)
|
||||
- [mtxf_rotate_zxy_and_translate](functions-4.md#mtxf_rotate_zxy_and_translate)
|
||||
- [mtxf_rotate_xyz_and_translate](functions-4.md#mtxf_rotate_xyz_and_translate)
|
||||
@ -1234,17 +1211,100 @@
|
||||
- [mtxf_align_terrain_normal](functions-4.md#mtxf_align_terrain_normal)
|
||||
- [mtxf_align_terrain_triangle](functions-4.md#mtxf_align_terrain_triangle)
|
||||
- [mtxf_mul](functions-4.md#mtxf_mul)
|
||||
- [mtxf_scale_vec3f](functions-4.md#mtxf_scale_vec3f)
|
||||
- [mtxf_mul_vec3s](functions-4.md#mtxf_mul_vec3s)
|
||||
- [mtxf_rotate_xy](functions-4.md#mtxf_rotate_xy)
|
||||
- [mtxf_inverse](functions-4.md#mtxf_inverse)
|
||||
- [mtxf_zero](functions-4.md#mtxf_zero)
|
||||
- [get_pos_from_transform_mtx](functions-4.md#get_pos_from_transform_mtx)
|
||||
- [approach_s32](functions-4.md#approach_s32)
|
||||
- [approach_f32](functions-4.md#approach_f32)
|
||||
- [spline_get_weights](functions-4.md#spline_get_weights)
|
||||
- [anim_spline_init](functions-4.md#anim_spline_init)
|
||||
- [anim_spline_poll](functions-4.md#anim_spline_poll)
|
||||
- [not_zero](functions-4.md#not_zero)
|
||||
|
||||
<br />
|
||||
|
||||
- math_util.inl
|
||||
- [replace_value_if_not_zero](functions-4.md#replace_value_if_not_zero)
|
||||
- [sm64_to_radians](functions-4.md#sm64_to_radians)
|
||||
- [radians_to_sm64](functions-4.md#radians_to_sm64)
|
||||
- [sm64_to_degrees](functions-4.md#sm64_to_degrees)
|
||||
- [degrees_to_sm64](functions-4.md#degrees_to_sm64)
|
||||
|
||||
<br />
|
||||
|
||||
- math_util_mat4.inl
|
||||
- [mtxf_zero](functions-4.md#mtxf_zero)
|
||||
- [mtxf_copy](functions-4.md#mtxf_copy)
|
||||
- [mtxf_identity](functions-4.md#mtxf_identity)
|
||||
- [mtxf_translate](functions-4.md#mtxf_translate)
|
||||
- [mtxf_scale_vec3f](functions-4.md#mtxf_scale_vec3f)
|
||||
|
||||
<br />
|
||||
|
||||
- math_util_vec3f.inl
|
||||
- [vec3f_zero](functions-4.md#vec3f_zero)
|
||||
- [vec3f_copy](functions-4.md#vec3f_copy)
|
||||
- [vec3f_set](functions-4.md#vec3f_set)
|
||||
- [vec3f_add](functions-4.md#vec3f_add)
|
||||
- [vec3f_sum](functions-4.md#vec3f_sum)
|
||||
- [vec3f_sub](functions-4.md#vec3f_sub)
|
||||
- [vec3f_dif](functions-4.md#vec3f_dif)
|
||||
- [vec3f_mul](functions-4.md#vec3f_mul)
|
||||
- [vec3f_div](functions-4.md#vec3f_div)
|
||||
- [vec3f_length](functions-4.md#vec3f_length)
|
||||
- [vec3f_normalize](functions-4.md#vec3f_normalize)
|
||||
- [vec3f_set_magnitude](functions-4.md#vec3f_set_magnitude)
|
||||
- [vec3f_dot](functions-4.md#vec3f_dot)
|
||||
- [vec3f_cross](functions-4.md#vec3f_cross)
|
||||
- [vec3f_combine](functions-4.md#vec3f_combine)
|
||||
- [vec3f_dist](functions-4.md#vec3f_dist)
|
||||
- [vec3f_hdist](functions-4.md#vec3f_hdist)
|
||||
- [vec3f_is_zero](functions-4.md#vec3f_is_zero)
|
||||
- [vec3f_to_vec3i](functions-4.md#vec3f_to_vec3i)
|
||||
- [vec3f_to_vec3s](functions-4.md#vec3f_to_vec3s)
|
||||
|
||||
<br />
|
||||
|
||||
- math_util_vec3i.inl
|
||||
- [vec3i_zero](functions-4.md#vec3i_zero)
|
||||
- [vec3i_copy](functions-4.md#vec3i_copy)
|
||||
- [vec3i_set](functions-4.md#vec3i_set)
|
||||
- [vec3i_add](functions-4.md#vec3i_add)
|
||||
- [vec3i_sum](functions-4.md#vec3i_sum)
|
||||
- [vec3i_sub](functions-4.md#vec3i_sub)
|
||||
- [vec3i_dif](functions-4.md#vec3i_dif)
|
||||
- [vec3i_mul](functions-4.md#vec3i_mul)
|
||||
- [vec3i_div](functions-4.md#vec3i_div)
|
||||
- [vec3i_length](functions-4.md#vec3i_length)
|
||||
- [vec3i_normalize](functions-4.md#vec3i_normalize)
|
||||
- [vec3i_set_magnitude](functions-4.md#vec3i_set_magnitude)
|
||||
- [vec3i_dot](functions-4.md#vec3i_dot)
|
||||
- [vec3i_cross](functions-4.md#vec3i_cross)
|
||||
- [vec3i_combine](functions-4.md#vec3i_combine)
|
||||
- [vec3i_dist](functions-4.md#vec3i_dist)
|
||||
- [vec3i_hdist](functions-4.md#vec3i_hdist)
|
||||
- [vec3i_is_zero](functions-4.md#vec3i_is_zero)
|
||||
- [vec3i_to_vec3f](functions-4.md#vec3i_to_vec3f)
|
||||
- [vec3i_to_vec3s](functions-4.md#vec3i_to_vec3s)
|
||||
|
||||
<br />
|
||||
|
||||
- math_util_vec3s.inl
|
||||
- [vec3s_zero](functions-4.md#vec3s_zero)
|
||||
- [vec3s_copy](functions-4.md#vec3s_copy)
|
||||
- [vec3s_set](functions-4.md#vec3s_set)
|
||||
- [vec3s_add](functions-4.md#vec3s_add)
|
||||
- [vec3s_sum](functions-4.md#vec3s_sum)
|
||||
- [vec3s_sub](functions-4.md#vec3s_sub)
|
||||
- [vec3s_dif](functions-4.md#vec3s_dif)
|
||||
- [vec3s_mul](functions-4.md#vec3s_mul)
|
||||
- [vec3s_div](functions-4.md#vec3s_div)
|
||||
- [vec3s_length](functions-4.md#vec3s_length)
|
||||
- [vec3s_normalize](functions-4.md#vec3s_normalize)
|
||||
- [vec3s_set_magnitude](functions-4.md#vec3s_set_magnitude)
|
||||
- [vec3s_dot](functions-4.md#vec3s_dot)
|
||||
- [vec3s_cross](functions-4.md#vec3s_cross)
|
||||
- [vec3s_combine](functions-4.md#vec3s_combine)
|
||||
- [vec3s_dist](functions-4.md#vec3s_dist)
|
||||
- [vec3s_hdist](functions-4.md#vec3s_hdist)
|
||||
- [vec3s_is_zero](functions-4.md#vec3s_is_zero)
|
||||
- [vec3s_to_vec3f](functions-4.md#vec3s_to_vec3f)
|
||||
- [vec3s_to_vec3i](functions-4.md#vec3s_to_vec3i)
|
||||
|
||||
<br />
|
||||
|
||||
@ -1263,40 +1323,40 @@
|
||||
<br />
|
||||
|
||||
- mod_storage.h
|
||||
- [mod_storage_save](functions-4.md#mod_storage_save)
|
||||
- [mod_storage_save_number](functions-4.md#mod_storage_save_number)
|
||||
- [mod_storage_save_bool](functions-4.md#mod_storage_save_bool)
|
||||
- [mod_storage_load](functions-4.md#mod_storage_load)
|
||||
- [mod_storage_load_number](functions-4.md#mod_storage_load_number)
|
||||
- [mod_storage_load_bool](functions-4.md#mod_storage_load_bool)
|
||||
- [mod_storage_exists](functions-4.md#mod_storage_exists)
|
||||
- [mod_storage_remove](functions-4.md#mod_storage_remove)
|
||||
- [mod_storage_clear](functions-4.md#mod_storage_clear)
|
||||
- [mod_storage_save](functions-5.md#mod_storage_save)
|
||||
- [mod_storage_save_number](functions-5.md#mod_storage_save_number)
|
||||
- [mod_storage_save_bool](functions-5.md#mod_storage_save_bool)
|
||||
- [mod_storage_load](functions-5.md#mod_storage_load)
|
||||
- [mod_storage_load_number](functions-5.md#mod_storage_load_number)
|
||||
- [mod_storage_load_bool](functions-5.md#mod_storage_load_bool)
|
||||
- [mod_storage_exists](functions-5.md#mod_storage_exists)
|
||||
- [mod_storage_remove](functions-5.md#mod_storage_remove)
|
||||
- [mod_storage_clear](functions-5.md#mod_storage_clear)
|
||||
|
||||
<br />
|
||||
|
||||
- network_player.h
|
||||
- [network_player_connected_count](functions-4.md#network_player_connected_count)
|
||||
- [network_player_set_description](functions-4.md#network_player_set_description)
|
||||
- [network_player_set_override_location](functions-4.md#network_player_set_override_location)
|
||||
- [network_player_from_global_index](functions-4.md#network_player_from_global_index)
|
||||
- [get_network_player_from_level](functions-4.md#get_network_player_from_level)
|
||||
- [get_network_player_from_area](functions-4.md#get_network_player_from_area)
|
||||
- [get_network_player_smallest_global](functions-4.md#get_network_player_smallest_global)
|
||||
- [network_player_set_override_palette_color](functions-4.md#network_player_set_override_palette_color)
|
||||
- [network_player_reset_override_palette](functions-4.md#network_player_reset_override_palette)
|
||||
- [network_player_is_override_palette_same](functions-4.md#network_player_is_override_palette_same)
|
||||
- [network_player_connected_count](functions-5.md#network_player_connected_count)
|
||||
- [network_player_set_description](functions-5.md#network_player_set_description)
|
||||
- [network_player_set_override_location](functions-5.md#network_player_set_override_location)
|
||||
- [network_player_from_global_index](functions-5.md#network_player_from_global_index)
|
||||
- [get_network_player_from_level](functions-5.md#get_network_player_from_level)
|
||||
- [get_network_player_from_area](functions-5.md#get_network_player_from_area)
|
||||
- [get_network_player_smallest_global](functions-5.md#get_network_player_smallest_global)
|
||||
- [network_player_set_override_palette_color](functions-5.md#network_player_set_override_palette_color)
|
||||
- [network_player_reset_override_palette](functions-5.md#network_player_reset_override_palette)
|
||||
- [network_player_is_override_palette_same](functions-5.md#network_player_is_override_palette_same)
|
||||
|
||||
<br />
|
||||
|
||||
- network_utils.h
|
||||
- [network_global_index_from_local](functions-4.md#network_global_index_from_local)
|
||||
- [network_local_index_from_global](functions-4.md#network_local_index_from_global)
|
||||
- [network_is_server](functions-4.md#network_is_server)
|
||||
- [network_is_moderator](functions-4.md#network_is_moderator)
|
||||
- [network_get_player_text_color_string](functions-4.md#network_get_player_text_color_string)
|
||||
- [network_check_singleplayer_pause](functions-4.md#network_check_singleplayer_pause)
|
||||
- [network_discord_id_from_local_index](functions-4.md#network_discord_id_from_local_index)
|
||||
- [network_global_index_from_local](functions-5.md#network_global_index_from_local)
|
||||
- [network_local_index_from_global](functions-5.md#network_local_index_from_global)
|
||||
- [network_is_server](functions-5.md#network_is_server)
|
||||
- [network_is_moderator](functions-5.md#network_is_moderator)
|
||||
- [network_get_player_text_color_string](functions-5.md#network_get_player_text_color_string)
|
||||
- [network_check_singleplayer_pause](functions-5.md#network_check_singleplayer_pause)
|
||||
- [network_discord_id_from_local_index](functions-5.md#network_discord_id_from_local_index)
|
||||
|
||||
<br />
|
||||
|
||||
@ -1686,26 +1746,26 @@
|
||||
<br />
|
||||
|
||||
- smlua_audio_utils.h
|
||||
- [smlua_audio_utils_reset_all](functions-5.md#smlua_audio_utils_reset_all)
|
||||
- [smlua_audio_utils_replace_sequence](functions-5.md#smlua_audio_utils_replace_sequence)
|
||||
- [audio_stream_load](functions-5.md#audio_stream_load)
|
||||
- [audio_stream_destroy](functions-5.md#audio_stream_destroy)
|
||||
- [audio_stream_play](functions-5.md#audio_stream_play)
|
||||
- [audio_stream_pause](functions-5.md#audio_stream_pause)
|
||||
- [audio_stream_stop](functions-5.md#audio_stream_stop)
|
||||
- [audio_stream_get_position](functions-5.md#audio_stream_get_position)
|
||||
- [audio_stream_set_position](functions-5.md#audio_stream_set_position)
|
||||
- [audio_stream_get_looping](functions-5.md#audio_stream_get_looping)
|
||||
- [audio_stream_set_looping](functions-5.md#audio_stream_set_looping)
|
||||
- [audio_stream_set_loop_points](functions-5.md#audio_stream_set_loop_points)
|
||||
- [audio_stream_get_frequency](functions-5.md#audio_stream_get_frequency)
|
||||
- [audio_stream_set_frequency](functions-5.md#audio_stream_set_frequency)
|
||||
- [audio_stream_get_volume](functions-5.md#audio_stream_get_volume)
|
||||
- [audio_stream_set_volume](functions-5.md#audio_stream_set_volume)
|
||||
- [audio_sample_load](functions-5.md#audio_sample_load)
|
||||
- [audio_sample_destroy](functions-5.md#audio_sample_destroy)
|
||||
- [audio_sample_stop](functions-5.md#audio_sample_stop)
|
||||
- [audio_sample_play](functions-5.md#audio_sample_play)
|
||||
- [smlua_audio_utils_reset_all](functions-6.md#smlua_audio_utils_reset_all)
|
||||
- [smlua_audio_utils_replace_sequence](functions-6.md#smlua_audio_utils_replace_sequence)
|
||||
- [audio_stream_load](functions-6.md#audio_stream_load)
|
||||
- [audio_stream_destroy](functions-6.md#audio_stream_destroy)
|
||||
- [audio_stream_play](functions-6.md#audio_stream_play)
|
||||
- [audio_stream_pause](functions-6.md#audio_stream_pause)
|
||||
- [audio_stream_stop](functions-6.md#audio_stream_stop)
|
||||
- [audio_stream_get_position](functions-6.md#audio_stream_get_position)
|
||||
- [audio_stream_set_position](functions-6.md#audio_stream_set_position)
|
||||
- [audio_stream_get_looping](functions-6.md#audio_stream_get_looping)
|
||||
- [audio_stream_set_looping](functions-6.md#audio_stream_set_looping)
|
||||
- [audio_stream_set_loop_points](functions-6.md#audio_stream_set_loop_points)
|
||||
- [audio_stream_get_frequency](functions-6.md#audio_stream_get_frequency)
|
||||
- [audio_stream_set_frequency](functions-6.md#audio_stream_set_frequency)
|
||||
- [audio_stream_get_volume](functions-6.md#audio_stream_get_volume)
|
||||
- [audio_stream_set_volume](functions-6.md#audio_stream_set_volume)
|
||||
- [audio_sample_load](functions-6.md#audio_sample_load)
|
||||
- [audio_sample_destroy](functions-6.md#audio_sample_destroy)
|
||||
- [audio_sample_stop](functions-6.md#audio_sample_stop)
|
||||
- [audio_sample_play](functions-6.md#audio_sample_play)
|
||||
|
||||
<br />
|
||||
|
||||
@ -1841,23 +1901,6 @@
|
||||
|
||||
<br />
|
||||
|
||||
- smlua_math_utils.h
|
||||
- [min](functions-6.md#min)
|
||||
- [max](functions-6.md#max)
|
||||
- [sqr](functions-6.md#sqr)
|
||||
- [minf](functions-6.md#minf)
|
||||
- [maxf](functions-6.md#maxf)
|
||||
- [sqrf](functions-6.md#sqrf)
|
||||
- [sm64_to_radians](functions-6.md#sm64_to_radians)
|
||||
- [radians_to_sm64](functions-6.md#radians_to_sm64)
|
||||
- [sm64_to_degrees](functions-6.md#sm64_to_degrees)
|
||||
- [degrees_to_sm64](functions-6.md#degrees_to_sm64)
|
||||
- [hypotf](functions-6.md#hypotf)
|
||||
- [clamp](functions-6.md#clamp)
|
||||
- [clampf](functions-6.md#clampf)
|
||||
|
||||
<br />
|
||||
|
||||
- smlua_misc_utils.h
|
||||
- [get_network_area_timer](functions-6.md#get_network_area_timer)
|
||||
- [get_area_update_counter](functions-6.md#get_area_update_counter)
|
||||
|
@ -106,9 +106,13 @@
|
||||
- [UnusedArea28](#UnusedArea28)
|
||||
- [VblankHandler](#VblankHandler)
|
||||
- [Vec2f](#Vec2f)
|
||||
- [Vec2i](#Vec2i)
|
||||
- [Vec2s](#Vec2s)
|
||||
- [Vec3f](#Vec3f)
|
||||
- [Vec3i](#Vec3i)
|
||||
- [Vec3s](#Vec3s)
|
||||
- [Vec4f](#Vec4f)
|
||||
- [Vec4i](#Vec4i)
|
||||
- [Vec4s](#Vec4s)
|
||||
- [Vtx](#Vtx)
|
||||
- [Vtx_Interp](#Vtx_Interp)
|
||||
@ -3201,6 +3205,28 @@
|
||||
|
||||
<br />
|
||||
|
||||
## [Vec2i](#Vec2i)
|
||||
|
||||
| Field | Type | Access |
|
||||
| ----- | ---- | ------ |
|
||||
| x | `integer` | |
|
||||
| y | `integer` | |
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [Vec2s](#Vec2s)
|
||||
|
||||
| Field | Type | Access |
|
||||
| ----- | ---- | ------ |
|
||||
| x | `integer` | |
|
||||
| y | `integer` | |
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [Vec3f](#Vec3f)
|
||||
|
||||
| Field | Type | Access |
|
||||
@ -3213,6 +3239,18 @@
|
||||
|
||||
<br />
|
||||
|
||||
## [Vec3i](#Vec3i)
|
||||
|
||||
| Field | Type | Access |
|
||||
| ----- | ---- | ------ |
|
||||
| x | `integer` | |
|
||||
| y | `integer` | |
|
||||
| z | `integer` | |
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [Vec3s](#Vec3s)
|
||||
|
||||
| Field | Type | Access |
|
||||
@ -3238,6 +3276,19 @@
|
||||
|
||||
<br />
|
||||
|
||||
## [Vec4i](#Vec4i)
|
||||
|
||||
| Field | Type | Access |
|
||||
| ----- | ---- | ------ |
|
||||
| x | `integer` | |
|
||||
| y | `integer` | |
|
||||
| z | `integer` | |
|
||||
| w | `integer` | |
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [Vec4s](#Vec4s)
|
||||
|
||||
| Field | Type | Access |
|
||||
|
@ -7,8 +7,8 @@
|
||||
*/
|
||||
|
||||
#ifdef OBJECT_FIELDS_INDEX_DIRECTLY
|
||||
#define OBJECT_FIELD_U16(index, subIndex) index + subIndex
|
||||
#define OBJECT_FIELD_S16(index, subIndex) index + subIndex
|
||||
#define OBJECT_FIELD_U16(index, subIndex) index // Warning: UB! Do not use these in behavior scripts
|
||||
#define OBJECT_FIELD_S16(index, subIndex) index // Warning: UB! Do not use these in behavior scripts
|
||||
#define OBJECT_FIELD_U32(index) index
|
||||
#define OBJECT_FIELD_S32(index) index
|
||||
#define OBJECT_FIELD_F32(index) index
|
||||
|
@ -11,15 +11,6 @@
|
||||
#include "include/geo_commands.h"
|
||||
#include "pc/debuglog.h"
|
||||
|
||||
// unused Mtx(s)
|
||||
s16 identityMtx[4][4] = { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } };
|
||||
s16 zeroMtx[4][4] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } };
|
||||
|
||||
Vec3f gVec3fZero = { 0.0f, 0.0f, 0.0f };
|
||||
Vec3s gVec3sZero = { 0, 0, 0 };
|
||||
Vec3f gVec3fOne = { 1.0f, 1.0f, 1.0f };
|
||||
UNUSED Vec3s gVec3sOne = { 1, 1, 1 };
|
||||
|
||||
/**
|
||||
* Initialize a geo node with a given type. Sets all links such that there
|
||||
* are no siblings, parent or children for this node.
|
||||
|
@ -380,11 +380,6 @@ extern struct GraphNode *gCurGraphNodeList[];
|
||||
|
||||
extern s16 gCurGraphNodeIndex;
|
||||
|
||||
extern Vec3f gVec3fZero;
|
||||
extern Vec3s gVec3sZero;
|
||||
extern Vec3f gVec3fOne;
|
||||
extern Vec3s gVec3sOne;
|
||||
|
||||
void init_scene_graph_node_links(struct GraphNode *graphNode, s32 type);
|
||||
|
||||
struct GraphNodeRoot *init_graph_node_root(struct DynamicPool *pool, struct GraphNodeRoot *graphNode,
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include "lighting_engine.h"
|
||||
#include "math_util.h"
|
||||
#include "surface_collision.h"
|
||||
#include "pc/lua/utils/smlua_math_utils.h"
|
||||
#include "pc/debuglog.h"
|
||||
#include "data/dynos_cmap.cpp.h"
|
||||
|
||||
|
@ -7,25 +7,6 @@
|
||||
|
||||
#include "trig_tables.inc.c"
|
||||
|
||||
Mat4 gMat4Identity = {
|
||||
{ 1, 0, 0, 0 },
|
||||
{ 0, 1, 0, 0 },
|
||||
{ 0, 0, 1, 0 },
|
||||
{ 0, 0, 0, 1 },
|
||||
};
|
||||
|
||||
Mat4 gMat4Zero = {
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
// These functions have bogus return values.
|
||||
// Disable the compiler warning.
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wreturn-local-addr"
|
||||
|
||||
inline f32 sins(s16 sm64Angle) {
|
||||
return gSineTable[(u16) (sm64Angle) >> 4];
|
||||
}
|
||||
@ -35,44 +16,231 @@ inline f32 coss(s16 sm64Angle) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set 'dest' the normal vector of a triangle with vertices a, b and c.
|
||||
* It is similar to vec3f_cross, but it calculates the vectors (c-b) and (b-a)
|
||||
* at the same time.
|
||||
* Helper function for atan2s. Does a look up of the arctangent of y/x assuming
|
||||
* the resulting angle is in range [0, 0x2000] (1/8 of a circle).
|
||||
*/
|
||||
OPTIMIZE_O3 f32 *find_vector_perpendicular_to_plane(Vec3f dest, Vec3f a, Vec3f b, Vec3f c) {
|
||||
dest[0] = (b[1] - a[1]) * (c[2] - b[2]) - (c[1] - b[1]) * (b[2] - a[2]);
|
||||
dest[1] = (b[2] - a[2]) * (c[0] - b[0]) - (c[2] - b[2]) * (b[0] - a[0]);
|
||||
dest[2] = (b[0] - a[0]) * (c[1] - b[1]) - (c[0] - b[0]) * (b[1] - a[1]);
|
||||
return dest;
|
||||
static OPTIMIZE_O3 u16 atan2_lookup(f32 y, f32 x) {
|
||||
s16 idx = (s16)(y / x * 1024.0f + 0.5f);
|
||||
idx = (idx >= 0 && idx < 0x401) ? idx : 0;
|
||||
return gArctanTable[idx];
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
/**
|
||||
* Compute the angle from (0, 0) to (x, y) as a s16. Given that terrain is in
|
||||
* the xz-plane, this is commonly called with (z, x) to get a yaw angle.
|
||||
*/
|
||||
inline s16 atan2s(f32 y, f32 x) {
|
||||
// Extract sign bits: 1 if negative, 0 otherwise
|
||||
u8 signx = (x < 0.0f);
|
||||
u8 signy = (y < 0.0f);
|
||||
|
||||
OPTIMIZE_O3 f32 *vec3f_project(Vec3f vec, Vec3f onto, Vec3f out) {
|
||||
f32 numerator = vec3f_dot(vec, onto);
|
||||
f32 denominator = vec3f_dot(onto, onto);
|
||||
if (denominator == 0) {
|
||||
return vec3f_zero(out);
|
||||
// Take absolute values
|
||||
f32 absx = absx(x);
|
||||
f32 absy = absx(y);
|
||||
|
||||
// Compute the angle in the first octant
|
||||
u16 angle = atan2_lookup(min(absx, absy), max(absy, absx));
|
||||
|
||||
// Create an index based on the signs and swap status
|
||||
u8 idx = ((absy > absx) << 2) | (signx << 1) | signy;
|
||||
|
||||
// Combined lookup tables for offsets and sign multipliers
|
||||
static const s16 offsets[] = {0x4000, 0x4000, 0xC000, 0xC000, 0x0000, 0x8000, 0x0000, 0x8000};
|
||||
static const s8 signs[] = {-1, 1, 1, -1, 1, -1, -1, 1};
|
||||
|
||||
// Adjust output for (0, 0) edge case
|
||||
s16 zeroAdj = (x == 0.0f && y == 0.0f) * -0x4000;
|
||||
|
||||
// Ensure the result fits into 16 bits via an explicit cast on angle
|
||||
return ((offsets[idx] + (signs[idx] * (s16)angle)) + zeroAdj) & 0xFFFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the atan2 in radians by calling atan2s and converting the result.
|
||||
*/
|
||||
f32 atan2f(f32 y, f32 x) {
|
||||
return (f32) atan2s(y, x) * M_PI / 0x8000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value 'current' after it tries to approach target, going up at
|
||||
* most 'inc' and going down at most 'dec'.
|
||||
*/
|
||||
OPTIMIZE_O3 s32 approach_s32(s32 current, s32 target, s32 inc, s32 dec) {
|
||||
//! If target is close to the max or min s32, then it's possible to overflow
|
||||
// past it without stopping.
|
||||
|
||||
if (current < target) {
|
||||
current += inc;
|
||||
if (current > target) {
|
||||
current = target;
|
||||
}
|
||||
} else {
|
||||
current -= dec;
|
||||
if (current < target) {
|
||||
current = target;
|
||||
}
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value 'current' after it tries to approach target, going up at
|
||||
* most 'inc' and going down at most 'dec'.
|
||||
*/
|
||||
OPTIMIZE_O3 f32 approach_f32(f32 current, f32 target, f32 inc, f32 dec) {
|
||||
if (current < target) {
|
||||
current += inc;
|
||||
if (current > target) {
|
||||
current = target;
|
||||
}
|
||||
} else {
|
||||
current -= dec;
|
||||
if (current < target) {
|
||||
current = target;
|
||||
}
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
#define CURVE_BEGIN_1 1
|
||||
#define CURVE_BEGIN_2 2
|
||||
#define CURVE_MIDDLE 3
|
||||
#define CURVE_END_1 4
|
||||
#define CURVE_END_2 5
|
||||
|
||||
/**
|
||||
* Set 'result' to a 4-vector with weights corresponding to interpolation
|
||||
* value t in [0, 1] and gSplineState. Given the current control point P, these
|
||||
* weights are for P[0], P[1], P[2] and P[3] to obtain an interpolated point.
|
||||
* The weights naturally sum to 1, and they are also always in range [0, 1] so
|
||||
* the interpolated point will never overshoot. The curve is guaranteed to go
|
||||
* through the first and last point, but not through intermediate points.
|
||||
*
|
||||
* gSplineState ensures that the curve is clamped: the first two points
|
||||
* and last two points have different weight formulas. These are the weights
|
||||
* just before gSplineState transitions:
|
||||
* 1: [1, 0, 0, 0]
|
||||
* 1->2: [0, 3/12, 7/12, 2/12]
|
||||
* 2->3: [0, 1/6, 4/6, 1/6]
|
||||
* 3->3: [0, 1/6, 4/6, 1/6] (repeats)
|
||||
* 3->4: [0, 1/6, 4/6, 1/6]
|
||||
* 4->5: [0, 2/12, 7/12, 3/12]
|
||||
* 5: [0, 0, 0, 1]
|
||||
*
|
||||
* I suspect that the weight formulas will give a 3rd degree B-spline with the
|
||||
* common uniform clamped knot vector, e.g. for n points:
|
||||
* [0, 0, 0, 0, 1, 2, ... n-1, n, n, n, n]
|
||||
* TODO: verify the classification of the spline / figure out how polynomials were computed
|
||||
*/
|
||||
OPTIMIZE_O3 void spline_get_weights(struct MarioState* m, Vec4f result, f32 t, UNUSED s32 c) {
|
||||
if (!m) { return; }
|
||||
f32 tinv = 1 - t;
|
||||
f32 tinv2 = tinv * tinv;
|
||||
f32 tinv3 = tinv2 * tinv;
|
||||
f32 t2 = t * t;
|
||||
f32 t3 = t2 * t;
|
||||
|
||||
switch (m->splineState) {
|
||||
case CURVE_BEGIN_1:
|
||||
result[0] = tinv3;
|
||||
result[1] = t3 * 1.75f - t2 * 4.5f + t * 3.0f;
|
||||
result[2] = -t3 * (11 / 12.0f) + t2 * 1.5f;
|
||||
result[3] = t3 * (1 / 6.0f);
|
||||
break;
|
||||
case CURVE_BEGIN_2:
|
||||
result[0] = tinv3 * 0.25f;
|
||||
result[1] = t3 * (7 / 12.0f) - t2 * 1.25f + t * 0.25f + (7 / 12.0f);
|
||||
result[2] = -t3 * 0.5f + t2 * 0.5f + t * 0.5f + (1 / 6.0f);
|
||||
result[3] = t3 * (1 / 6.0f);
|
||||
break;
|
||||
case CURVE_MIDDLE:
|
||||
result[0] = tinv3 * (1 / 6.0f);
|
||||
result[1] = t3 * 0.5f - t2 + (4 / 6.0f);
|
||||
result[2] = -t3 * 0.5f + t2 * 0.5f + t * 0.5f + (1 / 6.0f);
|
||||
result[3] = t3 * (1 / 6.0f);
|
||||
break;
|
||||
case CURVE_END_1:
|
||||
result[0] = tinv3 * (1 / 6.0f);
|
||||
result[1] = -tinv3 * 0.5f + tinv2 * 0.5f + tinv * 0.5f + (1 / 6.0f);
|
||||
result[2] = tinv3 * (7 / 12.0f) - tinv2 * 1.25f + tinv * 0.25f + (7 / 12.0f);
|
||||
result[3] = t3 * 0.25f;
|
||||
break;
|
||||
case CURVE_END_2:
|
||||
result[0] = tinv3 * (1 / 6.0f);
|
||||
result[1] = -tinv3 * (11 / 12.0f) + tinv2 * 1.5f;
|
||||
result[2] = tinv3 * 1.75f - tinv2 * 4.5f + tinv * 3.0f;
|
||||
result[3] = t3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a spline animation.
|
||||
* 'keyFrames' should be an array of (s, x, y, z) vectors
|
||||
* s: the speed of the keyframe in 1000/frames, e.g. s=100 means the keyframe lasts 10 frames
|
||||
* (x, y, z): point in 3D space on the curve
|
||||
* The array should end with three entries with s=0 (infinite keyframe duration).
|
||||
* That's because the spline has a 3rd degree polynomial, so it looks 3 points ahead.
|
||||
*/
|
||||
OPTIMIZE_O3 void anim_spline_init(struct MarioState* m, Vec4s *keyFrames) {
|
||||
if (!m) { return; }
|
||||
m->splineKeyframe = keyFrames;
|
||||
m->splineKeyframeFraction = 0;
|
||||
m->splineState = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Poll the next point from a spline animation.
|
||||
* anim_spline_init should be called before polling for vectors.
|
||||
* Returns TRUE when the last point is reached, FALSE otherwise.
|
||||
*/
|
||||
OPTIMIZE_O3 s32 anim_spline_poll(struct MarioState* m, Vec3f result) {
|
||||
if (!m) { return 0; }
|
||||
Vec4f weights = { 0 };
|
||||
s32 i;
|
||||
s32 hasEnded = FALSE;
|
||||
|
||||
vec3f_copy(result, gVec3fZero);
|
||||
spline_get_weights(m, weights, m->splineKeyframeFraction, m->splineState);
|
||||
|
||||
if (m->splineKeyframe == NULL) { return FALSE; }
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
result[0] += weights[i] * m->splineKeyframe[i][1];
|
||||
result[1] += weights[i] * m->splineKeyframe[i][2];
|
||||
result[2] += weights[i] * m->splineKeyframe[i][3];
|
||||
}
|
||||
|
||||
vec3f_copy(out, onto);
|
||||
vec3f_mul(out, numerator / denominator);
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Scale vector 'dest' so it has length 1
|
||||
OPTIMIZE_O3 f32 *vec3f_normalize(Vec3f dest) {
|
||||
f32 div = vec3f_length(dest);
|
||||
if (div == 0) {
|
||||
vec3f_set(dest, 0, 0, 0);
|
||||
return dest;
|
||||
if ((m->splineKeyframeFraction += m->splineKeyframe[0][0] / 1000.0f) >= 1) {
|
||||
m->splineKeyframe++;
|
||||
m->splineKeyframeFraction--;
|
||||
switch (m->splineState) {
|
||||
case CURVE_END_2:
|
||||
hasEnded = TRUE;
|
||||
break;
|
||||
case CURVE_MIDDLE:
|
||||
if (m->splineKeyframe[2][0] == 0) {
|
||||
m->splineState = CURVE_END_1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
m->splineState++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
f32 invsqrt = 1.0f / div;
|
||||
vec3f_mul(dest, invsqrt);
|
||||
return dest;
|
||||
return hasEnded;
|
||||
}
|
||||
|
||||
///////////
|
||||
// Vec3f //
|
||||
///////////
|
||||
|
||||
Vec3f gVec3fZero = { 0.0f, 0.0f, 0.0f };
|
||||
|
||||
Vec3f gVec3fOne = { 1.0f, 1.0f, 1.0f };
|
||||
|
||||
/**
|
||||
* Returns a vector rotated around the z axis, then the x axis, then the y
|
||||
* axis.
|
||||
@ -100,6 +268,49 @@ OPTIMIZE_O3 f32 *vec3f_rotate_zxy(Vec3f dest, Vec3s rotate) {
|
||||
return dest;
|
||||
}
|
||||
|
||||
// Rodrigues' formula
|
||||
// dest = v * cos(r) + (n x v) * sin(r) + n * (n . v) * (1 - cos(r))
|
||||
OPTIMIZE_O3 f32 *vec3f_rotate_around_n(Vec3f dest, Vec3f v, Vec3f n, s16 r) {
|
||||
Vec3f nvCross;
|
||||
vec3f_cross(nvCross, n, v);
|
||||
f32 nvDot = vec3f_dot(n, v);
|
||||
f32 cosr = coss(r);
|
||||
f32 sinr = sins(r);
|
||||
dest[0] = v[0] * cosr + nvCross[0] * sinr + n[0] * nvDot * (1.f - cosr);
|
||||
dest[1] = v[1] * cosr + nvCross[1] * sinr + n[1] * nvDot * (1.f - cosr);
|
||||
dest[2] = v[2] * cosr + nvCross[2] * sinr + n[2] * nvDot * (1.f - cosr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
OPTIMIZE_O3 f32 *vec3f_project(Vec3f dest, Vec3f v, Vec3f onto) {
|
||||
f32 numerator = vec3f_dot(v, onto);
|
||||
f32 denominator = vec3f_dot(onto, onto);
|
||||
if (denominator == 0) {
|
||||
return vec3f_zero(dest);
|
||||
}
|
||||
|
||||
vec3f_copy(dest, onto);
|
||||
vec3f_mul(dest, numerator / denominator);
|
||||
return dest;
|
||||
}
|
||||
|
||||
OPTIMIZE_O3 f32 *vec3f_transform(Vec3f dest, Vec3f v, Vec3f translation, Vec3s rotation, Vec3f scale) {
|
||||
vec3f_copy(dest, v);
|
||||
|
||||
// scale
|
||||
dest[0] *= scale[0];
|
||||
dest[1] *= scale[1];
|
||||
dest[2] *= scale[2];
|
||||
|
||||
// rotation
|
||||
vec3f_rotate_zxy(dest, rotation);
|
||||
|
||||
// translation
|
||||
vec3f_add(dest, translation);
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take the vector starting at 'from' pointed at 'to' an retrieve the length
|
||||
* of that vector, as well as the yaw and pitch angles.
|
||||
@ -125,6 +336,52 @@ OPTIMIZE_O3 void vec3f_set_dist_and_angle(Vec3f from, Vec3f to, f32 dist, s16 pi
|
||||
to[2] = from[2] + dist * coss(pitch) * coss(yaw);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set 'dest' the normal vector of a triangle with vertices a, b and c.
|
||||
* It is similar to vec3f_cross, but it calculates the vectors (c-b) and (b-a)
|
||||
* at the same time.
|
||||
*/
|
||||
OPTIMIZE_O3 f32 *find_vector_perpendicular_to_plane(Vec3f dest, Vec3f a, Vec3f b, Vec3f c) {
|
||||
dest[0] = (b[1] - a[1]) * (c[2] - b[2]) - (c[1] - b[1]) * (b[2] - a[2]);
|
||||
dest[1] = (b[2] - a[2]) * (c[0] - b[0]) - (c[2] - b[2]) * (b[0] - a[0]);
|
||||
dest[2] = (b[0] - a[0]) * (c[1] - b[1]) - (c[0] - b[0]) * (b[1] - a[1]);
|
||||
return dest;
|
||||
}
|
||||
|
||||
///////////
|
||||
// Vec3i //
|
||||
///////////
|
||||
|
||||
Vec3i gVec3iZero = { 0, 0, 0 };
|
||||
|
||||
Vec3i gVec3iOne = { 1, 1, 1 };
|
||||
|
||||
///////////
|
||||
// Vec3s //
|
||||
///////////
|
||||
|
||||
Vec3s gVec3sZero = { 0, 0, 0 };
|
||||
|
||||
Vec3s gVec3sOne = { 1, 1, 1 };
|
||||
|
||||
//////////
|
||||
// Mat4 //
|
||||
//////////
|
||||
|
||||
Mat4 gMat4Identity = {
|
||||
{ 1, 0, 0, 0 },
|
||||
{ 0, 1, 0, 0 },
|
||||
{ 0, 0, 1, 0 },
|
||||
{ 0, 0, 0, 1 },
|
||||
};
|
||||
|
||||
Mat4 gMat4Zero = {
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
/**
|
||||
* Set mtx to a look-at matrix for the camera. The resulting transformation
|
||||
* transforms the world as if there exists a camera at position 'from' pointed
|
||||
@ -285,12 +542,9 @@ OPTIMIZE_O3 void mtxf_billboard(Mat4 dest, Mat4 mtx, Vec3f position, s16 angle)
|
||||
dest[2][2] = 1;
|
||||
dest[2][3] = 0;
|
||||
|
||||
dest[3][0] =
|
||||
mtx[0][0] * position[0] + mtx[1][0] * position[1] + mtx[2][0] * position[2] + mtx[3][0];
|
||||
dest[3][1] =
|
||||
mtx[0][1] * position[0] + mtx[1][1] * position[1] + mtx[2][1] * position[2] + mtx[3][1];
|
||||
dest[3][2] =
|
||||
mtx[0][2] * position[0] + mtx[1][2] * position[1] + mtx[2][2] * position[2] + mtx[3][2];
|
||||
dest[3][0] = mtx[0][0] * position[0] + mtx[1][0] * position[1] + mtx[2][0] * position[2] + mtx[3][0];
|
||||
dest[3][1] = mtx[0][1] * position[0] + mtx[1][1] * position[1] + mtx[2][1] * position[2] + mtx[3][1];
|
||||
dest[3][2] = mtx[0][2] * position[0] + mtx[1][2] * position[1] + mtx[2][2] * position[2] + mtx[3][2];
|
||||
dest[3][3] = 1;
|
||||
}
|
||||
|
||||
@ -311,12 +565,9 @@ OPTIMIZE_O3 void mtxf_cylboard(Mat4 dest, Mat4 mtx, Vec3f position, s16 angle) {
|
||||
dest[2][2] = 1;
|
||||
dest[2][3] = 0;
|
||||
|
||||
dest[3][0] =
|
||||
mtx[0][0] * position[0] + mtx[1][0] * position[1] + mtx[2][0] * position[2] + mtx[3][0];
|
||||
dest[3][1] =
|
||||
mtx[0][1] * position[0] + mtx[1][1] * position[1] + mtx[2][1] * position[2] + mtx[3][1];
|
||||
dest[3][2] =
|
||||
mtx[0][2] * position[0] + mtx[1][2] * position[1] + mtx[2][2] * position[2] + mtx[3][2];
|
||||
dest[3][0] = mtx[0][0] * position[0] + mtx[1][0] * position[1] + mtx[2][0] * position[2] + mtx[3][0];
|
||||
dest[3][1] = mtx[0][1] * position[0] + mtx[1][1] * position[1] + mtx[2][1] * position[2] + mtx[3][1];
|
||||
dest[3][2] = mtx[0][2] * position[0] + mtx[1][2] * position[1] + mtx[2][2] * position[2] + mtx[3][2];
|
||||
dest[3][3] = 1;
|
||||
}
|
||||
|
||||
@ -471,47 +722,15 @@ OPTIMIZE_O3 s16 *mtxf_mul_vec3s(Mat4 mtx, Vec3s b) {
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert float matrix 'src' to fixed point matrix 'dest'.
|
||||
* The float matrix may not contain entries larger than 65536 or the console
|
||||
* crashes. The fixed point matrix has entries with a 16-bit integer part, so
|
||||
* the floating point numbers are multiplied by 2^16 before being cast to a s32
|
||||
* integer. If this doesn't fit, the N64 and iQue consoles will throw an
|
||||
* exception. On Wii and Wii U Virtual Console the value will simply be clamped
|
||||
* and no crashes occur.
|
||||
*/
|
||||
OPTIMIZE_O3 void mtxf_to_mtx(Mtx *dest, Mat4 src) {
|
||||
#ifdef AVOID_UB
|
||||
// Avoid type-casting which is technically UB by calling the equivalent
|
||||
// guMtxF2L function. This helps little-endian systems, as well.
|
||||
guMtxF2L(src, dest);
|
||||
#else
|
||||
s32 asFixedPoint;
|
||||
register s32 i;
|
||||
register s16 *a3 = (s16 *) dest; // all integer parts stored in first 16 bytes
|
||||
register s16 *t0 = (s16 *) dest + 16; // all fraction parts stored in last 16 bytes
|
||||
register f32 *t1 = (f32 *) src;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
asFixedPoint = *t1++ * (1 << 16); //! float-to-integer conversion responsible for PU crashes
|
||||
*a3++ = GET_HIGH_S16_OF_32(asFixedPoint); // integer part
|
||||
*t0++ = GET_LOW_S16_OF_32(asFixedPoint); // fraction part
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Set 'mtx' to a transformation matrix that rotates around the z axis.
|
||||
*/
|
||||
OPTIMIZE_O3 void mtxf_rotate_xy(Mtx *mtx, s16 angle) {
|
||||
Mat4 temp;
|
||||
|
||||
mtxf_identity(temp);
|
||||
temp[0][0] = coss(angle);
|
||||
temp[0][1] = sins(angle);
|
||||
temp[1][0] = -temp[0][1];
|
||||
temp[1][1] = temp[0][0];
|
||||
mtxf_to_mtx(mtx, temp);
|
||||
OPTIMIZE_O3 void mtxf_rotate_xy(Mat4 mtx, s16 angle) {
|
||||
mtxf_identity(mtx);
|
||||
mtx[0][0] = coss(angle);
|
||||
mtx[0][1] = sins(angle);
|
||||
mtx[1][0] = -mtx[0][1];
|
||||
mtx[1][1] = mtx[0][0];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -575,240 +794,9 @@ OPTIMIZE_O3 f32 *get_pos_from_transform_mtx(Vec3f dest, Mat4 objMtx, Mat4 camMtx
|
||||
f32 camY = camMtx[3][0] * camMtx[1][0] + camMtx[3][1] * camMtx[1][1] + camMtx[3][2] * camMtx[1][2];
|
||||
f32 camZ = camMtx[3][0] * camMtx[2][0] + camMtx[3][1] * camMtx[2][1] + camMtx[3][2] * camMtx[2][2];
|
||||
|
||||
dest[0] =
|
||||
objMtx[3][0] * camMtx[0][0] + objMtx[3][1] * camMtx[0][1] + objMtx[3][2] * camMtx[0][2] - camX;
|
||||
dest[1] =
|
||||
objMtx[3][0] * camMtx[1][0] + objMtx[3][1] * camMtx[1][1] + objMtx[3][2] * camMtx[1][2] - camY;
|
||||
dest[2] =
|
||||
objMtx[3][0] * camMtx[2][0] + objMtx[3][1] * camMtx[2][1] + objMtx[3][2] * camMtx[2][2] - camZ;
|
||||
dest[0] = objMtx[3][0] * camMtx[0][0] + objMtx[3][1] * camMtx[0][1] + objMtx[3][2] * camMtx[0][2] - camX;
|
||||
dest[1] = objMtx[3][0] * camMtx[1][0] + objMtx[3][1] * camMtx[1][1] + objMtx[3][2] * camMtx[1][2] - camY;
|
||||
dest[2] = objMtx[3][0] * camMtx[2][0] + objMtx[3][1] * camMtx[2][1] + objMtx[3][2] * camMtx[2][2] - camZ;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value 'current' after it tries to approach target, going up at
|
||||
* most 'inc' and going down at most 'dec'.
|
||||
*/
|
||||
OPTIMIZE_O3 s32 approach_s32(s32 current, s32 target, s32 inc, s32 dec) {
|
||||
//! If target is close to the max or min s32, then it's possible to overflow
|
||||
// past it without stopping.
|
||||
|
||||
if (current < target) {
|
||||
current += inc;
|
||||
if (current > target) {
|
||||
current = target;
|
||||
}
|
||||
} else {
|
||||
current -= dec;
|
||||
if (current < target) {
|
||||
current = target;
|
||||
}
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value 'current' after it tries to approach target, going up at
|
||||
* most 'inc' and going down at most 'dec'.
|
||||
*/
|
||||
OPTIMIZE_O3 f32 approach_f32(f32 current, f32 target, f32 inc, f32 dec) {
|
||||
if (current < target) {
|
||||
current += inc;
|
||||
if (current > target) {
|
||||
current = target;
|
||||
}
|
||||
} else {
|
||||
current -= dec;
|
||||
if (current < target) {
|
||||
current = target;
|
||||
}
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for atan2s. Does a look up of the arctangent of y/x assuming
|
||||
* the resulting angle is in range [0, 0x2000] (1/8 of a circle).
|
||||
*/
|
||||
static OPTIMIZE_O3 u16 atan2_lookup(f32 y, f32 x) {
|
||||
s16 idx = (s16)(y / x * 1024.0f + 0.5f);
|
||||
idx = (idx >= 0 && idx < 0x401) ? idx : 0;
|
||||
return gArctanTable[idx];
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the angle from (0, 0) to (x, y) as a s16. Given that terrain is in
|
||||
* the xz-plane, this is commonly called with (z, x) to get a yaw angle.
|
||||
*/
|
||||
inline s16 atan2s(f32 y, f32 x) {
|
||||
// Extract sign bits: 1 if negative, 0 otherwise
|
||||
u8 signx = (x < 0.0f);
|
||||
u8 signy = (y < 0.0f);
|
||||
|
||||
// Take absolute values
|
||||
f32 absx = absx(x);
|
||||
f32 absy = absx(y);
|
||||
|
||||
// Compute the angle in the first octant
|
||||
u16 angle = atan2_lookup(min(absx, absy), max(absy, absx));
|
||||
|
||||
// Create an index based on the signs and swap status
|
||||
u8 idx = ((absy > absx) << 2) | (signx << 1) | signy;
|
||||
|
||||
// Combined lookup tables for offsets and sign multipliers
|
||||
static const s16 offsets[] = {0x4000, 0x4000, 0xC000, 0xC000, 0x0000, 0x8000, 0x0000, 0x8000};
|
||||
static const s8 signs[] = {-1, 1, 1, -1, 1, -1, -1, 1};
|
||||
|
||||
// Adjust output for (0, 0) edge case
|
||||
s16 zeroAdj = (x == 0.0f && y == 0.0f) * -0x4000;
|
||||
|
||||
// Ensure the result fits into 16 bits via an explicit cast on angle
|
||||
return ((offsets[idx] + (signs[idx] * (s16)angle)) + zeroAdj) & 0xFFFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the atan2 in radians by calling atan2s and converting the result.
|
||||
*/
|
||||
f32 atan2f(f32 y, f32 x) {
|
||||
return (f32) atan2s(y, x) * M_PI / 0x8000;
|
||||
}
|
||||
|
||||
#define CURVE_BEGIN_1 1
|
||||
#define CURVE_BEGIN_2 2
|
||||
#define CURVE_MIDDLE 3
|
||||
#define CURVE_END_1 4
|
||||
#define CURVE_END_2 5
|
||||
|
||||
/**
|
||||
* Set 'result' to a 4-vector with weights corresponding to interpolation
|
||||
* value t in [0, 1] and gSplineState. Given the current control point P, these
|
||||
* weights are for P[0], P[1], P[2] and P[3] to obtain an interpolated point.
|
||||
* The weights naturally sum to 1, and they are also always in range [0, 1] so
|
||||
* the interpolated point will never overshoot. The curve is guaranteed to go
|
||||
* through the first and last point, but not through intermediate points.
|
||||
*
|
||||
* gSplineState ensures that the curve is clamped: the first two points
|
||||
* and last two points have different weight formulas. These are the weights
|
||||
* just before gSplineState transitions:
|
||||
* 1: [1, 0, 0, 0]
|
||||
* 1->2: [0, 3/12, 7/12, 2/12]
|
||||
* 2->3: [0, 1/6, 4/6, 1/6]
|
||||
* 3->3: [0, 1/6, 4/6, 1/6] (repeats)
|
||||
* 3->4: [0, 1/6, 4/6, 1/6]
|
||||
* 4->5: [0, 2/12, 7/12, 3/12]
|
||||
* 5: [0, 0, 0, 1]
|
||||
*
|
||||
* I suspect that the weight formulas will give a 3rd degree B-spline with the
|
||||
* common uniform clamped knot vector, e.g. for n points:
|
||||
* [0, 0, 0, 0, 1, 2, ... n-1, n, n, n, n]
|
||||
* TODO: verify the classification of the spline / figure out how polynomials were computed
|
||||
*/
|
||||
OPTIMIZE_O3 void spline_get_weights(struct MarioState* m, Vec4f result, f32 t, UNUSED s32 c) {
|
||||
if (!m) { return; }
|
||||
f32 tinv = 1 - t;
|
||||
f32 tinv2 = tinv * tinv;
|
||||
f32 tinv3 = tinv2 * tinv;
|
||||
f32 t2 = t * t;
|
||||
f32 t3 = t2 * t;
|
||||
|
||||
switch (m->splineState) {
|
||||
case CURVE_BEGIN_1:
|
||||
result[0] = tinv3;
|
||||
result[1] = t3 * 1.75f - t2 * 4.5f + t * 3.0f;
|
||||
result[2] = -t3 * (11 / 12.0f) + t2 * 1.5f;
|
||||
result[3] = t3 * (1 / 6.0f);
|
||||
break;
|
||||
case CURVE_BEGIN_2:
|
||||
result[0] = tinv3 * 0.25f;
|
||||
result[1] = t3 * (7 / 12.0f) - t2 * 1.25f + t * 0.25f + (7 / 12.0f);
|
||||
result[2] = -t3 * 0.5f + t2 * 0.5f + t * 0.5f + (1 / 6.0f);
|
||||
result[3] = t3 * (1 / 6.0f);
|
||||
break;
|
||||
case CURVE_MIDDLE:
|
||||
result[0] = tinv3 * (1 / 6.0f);
|
||||
result[1] = t3 * 0.5f - t2 + (4 / 6.0f);
|
||||
result[2] = -t3 * 0.5f + t2 * 0.5f + t * 0.5f + (1 / 6.0f);
|
||||
result[3] = t3 * (1 / 6.0f);
|
||||
break;
|
||||
case CURVE_END_1:
|
||||
result[0] = tinv3 * (1 / 6.0f);
|
||||
result[1] = -tinv3 * 0.5f + tinv2 * 0.5f + tinv * 0.5f + (1 / 6.0f);
|
||||
result[2] = tinv3 * (7 / 12.0f) - tinv2 * 1.25f + tinv * 0.25f + (7 / 12.0f);
|
||||
result[3] = t3 * 0.25f;
|
||||
break;
|
||||
case CURVE_END_2:
|
||||
result[0] = tinv3 * (1 / 6.0f);
|
||||
result[1] = -tinv3 * (11 / 12.0f) + tinv2 * 1.5f;
|
||||
result[2] = tinv3 * 1.75f - tinv2 * 4.5f + tinv * 3.0f;
|
||||
result[3] = t3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a spline animation.
|
||||
* 'keyFrames' should be an array of (s, x, y, z) vectors
|
||||
* s: the speed of the keyframe in 1000/frames, e.g. s=100 means the keyframe lasts 10 frames
|
||||
* (x, y, z): point in 3D space on the curve
|
||||
* The array should end with three entries with s=0 (infinite keyframe duration).
|
||||
* That's because the spline has a 3rd degree polynomial, so it looks 3 points ahead.
|
||||
*/
|
||||
OPTIMIZE_O3 void anim_spline_init(struct MarioState* m, Vec4s *keyFrames) {
|
||||
if (!m) { return; }
|
||||
m->splineKeyframe = keyFrames;
|
||||
m->splineKeyframeFraction = 0;
|
||||
m->splineState = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Poll the next point from a spline animation.
|
||||
* anim_spline_init should be called before polling for vectors.
|
||||
* Returns TRUE when the last point is reached, FALSE otherwise.
|
||||
*/
|
||||
OPTIMIZE_O3 s32 anim_spline_poll(struct MarioState* m, Vec3f result) {
|
||||
if (!m) { return 0; }
|
||||
Vec4f weights = { 0 };
|
||||
s32 i;
|
||||
s32 hasEnded = FALSE;
|
||||
|
||||
vec3f_copy(result, gVec3fZero);
|
||||
spline_get_weights(m, weights, m->splineKeyframeFraction, m->splineState);
|
||||
|
||||
if (m->splineKeyframe == NULL) { return FALSE; }
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
result[0] += weights[i] * m->splineKeyframe[i][1];
|
||||
result[1] += weights[i] * m->splineKeyframe[i][2];
|
||||
result[2] += weights[i] * m->splineKeyframe[i][3];
|
||||
}
|
||||
|
||||
if ((m->splineKeyframeFraction += m->splineKeyframe[0][0] / 1000.0f) >= 1) {
|
||||
m->splineKeyframe++;
|
||||
m->splineKeyframeFraction--;
|
||||
switch (m->splineState) {
|
||||
case CURVE_END_2:
|
||||
hasEnded = TRUE;
|
||||
break;
|
||||
case CURVE_MIDDLE:
|
||||
if (m->splineKeyframe[2][0] == 0) {
|
||||
m->splineState = CURVE_END_1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
m->splineState++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return hasEnded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the second value if it does not equal zero.
|
||||
*/
|
||||
OPTIMIZE_O3 f32 not_zero(f32 value, f32 replacement) {
|
||||
if (replacement != 0) {
|
||||
return replacement;
|
||||
}
|
||||
return value;
|
||||
}
|
@ -72,6 +72,10 @@ extern f32 gCosineTable[];
|
||||
default: __builtin_abs \
|
||||
)(x)
|
||||
|
||||
#define clamp(x, a, b) ( \
|
||||
min(max(x, a), b) \
|
||||
)
|
||||
|
||||
#else
|
||||
|
||||
// Fallback to the original implementation for iDO
|
||||
@ -79,12 +83,21 @@ extern f32 gCosineTable[];
|
||||
#define max(a,b) (a > b ? a : b)
|
||||
#define sqr(x) (x * x)
|
||||
#define absx(x) ((x) < 0 ? -(x) : (x))
|
||||
#define clamp(x, a, b) (min(max(x, a), b))
|
||||
|
||||
#endif
|
||||
|
||||
extern Vec3f gVec3fZero;
|
||||
extern Vec3i gVec3iZero;
|
||||
extern Vec3s gVec3sZero;
|
||||
extern Vec3f gVec3fOne;
|
||||
extern Vec3i gVec3iOne;
|
||||
extern Vec3s gVec3sOne;
|
||||
extern Mat4 gMat4Identity;
|
||||
extern Mat4 gMat4Zero;
|
||||
|
||||
#include "math_util.inl"
|
||||
|
||||
/* |description|
|
||||
Calculates the sine of the given angle, where the angle is specified as a signed 16-bit integer representing a fixed-point "SM64 angle". This function returns a floating-point result corresponding to sin(angle)
|
||||
|descriptionEnd| */
|
||||
@ -105,78 +118,36 @@ Computes the arctangent of a/b and returns it as a floating-point angle in radia
|
||||
|descriptionEnd| */
|
||||
f32 atan2f(f32 a, f32 b);
|
||||
|
||||
#include "../../include/libc/stdlib.h"
|
||||
/* |description|
|
||||
Gradually moves an integer `current` value toward a `target` value, increasing it by `inc` if it is too low, or decreasing it by `dec` if it is too high. This is often used for smooth transitions or animations
|
||||
|descriptionEnd| */
|
||||
OPTIMIZE_O3 s32 approach_s32(s32 current, s32 target, s32 inc, s32 dec);
|
||||
|
||||
/* |description|
|
||||
Copies the contents of a 3D floating-point vector (`src`) into another 3D floating-point vector (`dest`). After this operation, `dest` will have the same x, y, and z values as `src`
|
||||
Similar to `approach_s32`, but operates on floating-point numbers. It moves `current` toward `target` by increasing it by `inc` if below target, or decreasing it by `dec` if above target, creating a smooth interpolation
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_copy(Vec3f dest, Vec3f src);
|
||||
OPTIMIZE_O3 f32 approach_f32(f32 current, f32 target, f32 inc, f32 dec);
|
||||
|
||||
/* |description|
|
||||
Sets the values of the 3D floating-point vector `dest` to the given x, y, and z values. After this function, `dest` will have values (x, y, z)
|
||||
Computes spline interpolation weights for a given parameter `t` and stores these weights in `result`. This is used in spline-based animations to find intermediate positions between keyframes
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_set(Vec3f dest, f32 x, f32 y, f32 z);
|
||||
OPTIMIZE_O3 void spline_get_weights(struct MarioState* m, Vec4f result, f32 t, UNUSED s32 c);
|
||||
|
||||
/* |description|
|
||||
Adds the components of the 3D floating-point vector `a` to `dest`. After this operation, `dest.x` will be `dest.x + a.x`, and similarly for the y and z components
|
||||
Initializes a spline-based animation for the `MarioState` structure `m` using the provided array of 3D signed-integer vectors `keyFrames`. This sets up the animation so that it can be advanced by polling
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_add(Vec3f dest, Vec3f a);
|
||||
OPTIMIZE_O3 void anim_spline_init(struct MarioState* m, Vec4s *keyFrames);
|
||||
|
||||
/* |description|
|
||||
Adds the corresponding components of two 3D floating-point vectors `a` and `b`, and stores the result in `dest`. For example, `dest.x = a.x + b.x`, `dest.y = a.y + b.y`, and `dest.z = a.z + b.z`
|
||||
Advances the spline-based animation associated with `m` and stores the current interpolated position in `result`. It returns the animation's status, allowing the caller to determine if the animation is ongoing or has completed
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_sum(Vec3f dest, Vec3f a, Vec3f b);
|
||||
OPTIMIZE_O3 s32 anim_spline_poll(struct MarioState* m, Vec3f result);
|
||||
|
||||
/* |description|
|
||||
Subtracts the components of the 3D floating-point vector `a` from `dest`. After this operation, `dest.x` will be `dest.x - a.x`, and similarly for the y and z components
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_sub(Vec3f dest, Vec3f a);
|
||||
///////////
|
||||
// Vec3f //
|
||||
///////////
|
||||
|
||||
/* |description|
|
||||
Subtracts the components of the 3D floating-point vector `b` from the components of `a` and stores the result in `dest`. For example, `dest.x = a.x - b.x`
|
||||
This results in a vector that represents the difference between `a` and `b`.
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_dif(Vec3f dest, Vec3f a, Vec3f b);
|
||||
|
||||
/* |description|
|
||||
Multiplies each component of the 3D floating-point vector `dest` by the scalar value `a`. For instance, `dest.x = dest.x * a`, and similarly for y and z. This scales the vector `dest` by `a`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_mul(Vec3f dest, f32 a);
|
||||
|
||||
/* |description|
|
||||
Divides each component of the 3D floating-point vector `dest` by the scalar value `a`. For instance, `dest.x = dest.x / a`, and similarly for y and z. This scales the vector `dest` by `a`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_div(Vec3f dest, f32 a);
|
||||
|
||||
/* |description|
|
||||
Computes the cross product of two 3D floating-point vectors `a` and `b`. The cross product is a vector perpendicular to both `a` and `b`. The result is stored in `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_cross(Vec3f dest, Vec3f a, Vec3f b);
|
||||
|
||||
/* |description|
|
||||
Normalizes the 3D floating-point vector `dest` so that its length (magnitude) becomes 1, while retaining its direction. This effectively scales `dest` so that it lies on the unit sphere
|
||||
|descriptionEnd| */
|
||||
OPTIMIZE_O3 f32 *vec3f_normalize(Vec3f dest);
|
||||
|
||||
/* |description|
|
||||
Normalizes each component of the 3D floating-point vector 'v'.
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_normalize2(Vec3f v);
|
||||
|
||||
/* |description|
|
||||
Calculates the length (magnitude) of the 3D floating-point vector `a`. The length is defined as sqrt(x² + y² + z²) for the vector components (x, y, z)
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 vec3f_length(Vec3f a);
|
||||
|
||||
/* |description|
|
||||
Computes the dot product of the two 3D floating-point vectors `a` and `b`. The dot product is a scalar value defined by (a.x * b.x + a.y * b.y + a.z * b.z), representing how aligned the two vectors are
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 vec3f_dot(Vec3f a, Vec3f b);
|
||||
|
||||
/* |description|
|
||||
Takes two 3D floating-point vectors `vecA` and `vecB`, multiplies them by `sclA` and `sclB` respectively, and then adds the scaled vectors together. The final combined vector is stored in `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_combine(Vec3f dest, Vec3f vecA, Vec3f vecB, f32 sclA, f32 sclB);
|
||||
#include "math_util_vec3f.inl"
|
||||
|
||||
/* |description|
|
||||
Rotates the 3D floating-point vector `v` by the angles specified in the 3D signed-integer vector `rotate`, applying the rotations in the order Z, then X, then Y. The rotated vector replaces `v`
|
||||
@ -184,14 +155,19 @@ Rotates the 3D floating-point vector `v` by the angles specified in the 3D signe
|
||||
OPTIMIZE_O3 f32 *vec3f_rotate_zxy(Vec3f v, Vec3s rotate);
|
||||
|
||||
/* |description|
|
||||
Projects the 3D floating-point vector `vec` onto another 3D floating-point vector `onto`. The resulting projection, stored in `out`, represents how much of `vec` lies along the direction of `onto`
|
||||
Rotates the 3D floating-point vector `v` around the vector `n`, given a rotation `r` (in sm64 angle units), and stores the result in `dest`
|
||||
|descriptionEnd| */
|
||||
OPTIMIZE_O3 f32 *vec3f_project(Vec3f vec, Vec3f onto, Vec3f out);
|
||||
OPTIMIZE_O3 f32 *vec3f_rotate_around_n(Vec3f dest, Vec3f v, Vec3f n, s16 r);
|
||||
|
||||
/* |description|
|
||||
Calculates the distance between two 3D floating-point points `v1` and `v2`. The distance is the length of the vector `v2 - v1`, i.e., sqrt((v2.x - v1.x)² + (v2.y - v1.y)² + (v2.z - v1.z)²)
|
||||
Projects the 3D floating-point vector `v` onto another 3D floating-point vector `onto`. The resulting projection, stored in `dest`, represents how much of `v` lies along the direction of `onto`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 vec3f_dist(Vec3f v1, Vec3f v2);
|
||||
OPTIMIZE_O3 f32 *vec3f_project(Vec3f dest, Vec3f v, Vec3f onto);
|
||||
|
||||
/* |description|
|
||||
Scales the 3D floating-point vector `v` by the vector `scale`, then rotates it by the rotation vector `rotation`, and finally translates it by the vector `translation`. The resulting vector is stored in `dest`
|
||||
|descriptionEnd| */
|
||||
OPTIMIZE_O3 f32 *vec3f_transform(Vec3f dest, Vec3f v, Vec3f translation, Vec3s rotation, Vec3f scale);
|
||||
|
||||
/* |description|
|
||||
Calculates the distance between two points in 3D space (`from` and `to`), as well as the pitch and yaw angles that describe the direction from `from` to `to`. The results are stored in `dist`, `pitch`, and `yaw`
|
||||
@ -203,96 +179,28 @@ Positions the point `to` at a given `dist`, `pitch`, and `yaw` relative to the p
|
||||
|descriptionEnd| */
|
||||
OPTIMIZE_O3 void vec3f_set_dist_and_angle(Vec3f from, Vec3f to, f32 dist, s16 pitch, s16 yaw);
|
||||
|
||||
/* |description|
|
||||
Sets the values of the 3D floating-point vector `v` to 0. After this function, `v` will have values of 0.
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_zero(Vec3f v);
|
||||
|
||||
/* |description|
|
||||
Converts a 3D floating-point vector `a` (Vec3f) into a 3D signed-integer vector and stores it in `dest`. After this operation, `dest` will contain the integer versions of `a`'s floating-point components
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s16 *vec3f_to_vec3s(Vec3s dest, Vec3f a);
|
||||
|
||||
/* |description|
|
||||
Copies the components of one 3D signed-integer vector (`src`) to another (`dest`). After this function, `dest` will have the same x, y, and z integer values as `src`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_copy(Vec3s dest, Vec3s src);
|
||||
|
||||
/* |description|
|
||||
Sets the 3D signed-integer vector `dest` to the specified integer values (x, y, z), so that `dest` becomes (x, y, z).
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_set(Vec3s dest, s16 x, s16 y, s16 z);
|
||||
|
||||
/* |description|
|
||||
Adds the components of a 3D signed-integer vector `a` to the corresponding components of `dest`. After this operation, each component of `dest` is increased by the corresponding component in `a`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_add(Vec3s dest, Vec3s a);
|
||||
|
||||
/* |description|
|
||||
Adds the components of two 3D signed-integer vectors `a` and `b` together and stores the resulting vector in `dest`. For example, `dest.x = a.x + b.x`, and similarly for y and z
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_sum(Vec3s dest, Vec3s a, Vec3s b);
|
||||
|
||||
/* |description|
|
||||
Subtracts the components of a 3D signed-integer vector `b` from the components of `a` and stores the result in `dest`. This gives a vector representing the difference `a - b`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_sub(Vec3s dest, Vec3s a);
|
||||
|
||||
/* |description|
|
||||
Subtracts the components of the 3D signed-integer vector `b` from the components of `a` and stores the result in `dest`. For example, `dest.x = a.x - b.x`
|
||||
This results in a vector that represents the difference between `a` and `b`.
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_dif(Vec3s dest, Vec3s a, Vec3s b);
|
||||
|
||||
/* |description|
|
||||
Multiplies each component of the 3D signed-integer vector `dest` by the scalar value `a`. For instance, `dest.x = dest.x * a`, and similarly for y and z. This scales the vector `dest` by `a`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_mul(Vec3s dest, s16 a);
|
||||
|
||||
/* |description|
|
||||
Divides each component of the 3D signed-integer vector `dest` by the scalar value `a`. For instance, `dest.x = dest.x / a`, and similarly for y and z. This scales the vector `dest` by `a`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_div(Vec3s dest, s16 a);
|
||||
|
||||
/* |description|
|
||||
Calculates the length (magnitude) of the 3D signed-integer vector `a`. The length is defined as sqrt(x² + y² + z²) for the vector components (x, y, z)
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 vec3s_length(Vec3s a);
|
||||
|
||||
/* |description|
|
||||
Calculates the distance between two 3D signed-integer points `v1` and `v2`. The distance is the length of the vector `v2 - v1`, i.e., sqrt((v2.x - v1.x)² + (v2.y - v1.y)² + (v2.z - v1.z)²)
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 vec3s_dist(Vec3s v1, Vec3s v2);
|
||||
|
||||
/* |description|
|
||||
Sets the values of the 3D signed-integer vector `v` to 0. After this function, `v` will have values of 0.
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_zero(Vec3s v);
|
||||
|
||||
/* |description|
|
||||
Converts a 3D signed-integer vector `a` (vec3s) into a 3D floating-point vector and stores it in `dest`. After this operation, `dest` will contain the floating-point equivalents of `a`'s integer components
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3s_to_vec3f(Vec3f dest, Vec3s a);
|
||||
|
||||
/* |description|
|
||||
Determines a vector that is perpendicular (normal) to the plane defined by three given 3D floating-point points `a`, `b`, and `c`. The resulting perpendicular vector is stored in `dest`
|
||||
|descriptionEnd| */
|
||||
OPTIMIZE_O3 f32 *find_vector_perpendicular_to_plane(Vec3f dest, Vec3f a, Vec3f b, Vec3f c);
|
||||
|
||||
/* |description|
|
||||
Copies the 4x4 floating-point matrix `src` into `dest`. After this operation, `dest` contains the same matrix values as `src`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 void mtxf_copy(Mat4 dest, Mat4 src);
|
||||
///////////
|
||||
// Vec3i //
|
||||
///////////
|
||||
|
||||
/* |description|
|
||||
Sets the 4x4 floating-point matrix `mtx` to the identity matrix. The identity matrix leaves points unchanged when they are transformed by it which is useful for matrix math
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 void mtxf_identity(Mat4 mtx);
|
||||
#include "math_util_vec3i.inl"
|
||||
|
||||
/* |description|
|
||||
Applies a translation to the 4x4 floating-point matrix `dest` by adding the coordinates in the 3D floating-point vector `b`. This shifts any transformed point by `b`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 void mtxf_translate(Mat4 dest, Vec3f b);
|
||||
///////////
|
||||
// Vec3s //
|
||||
///////////
|
||||
|
||||
#include "math_util_vec3s.inl"
|
||||
|
||||
//////////
|
||||
// Mat4 //
|
||||
//////////
|
||||
|
||||
#include "math_util_mat4.inl"
|
||||
|
||||
/* |description|
|
||||
Adjusts the 4x4 floating-point matrix `mtx` so that it represents a viewing transformation looking from the point `from` toward the point `to`, with a given roll angle. This creates a view matrix oriented toward `to`
|
||||
@ -334,73 +242,25 @@ Multiplies two 4x4 floating-point matrices `a` and `b` (in that order), storing
|
||||
|descriptionEnd| */
|
||||
OPTIMIZE_O3 void mtxf_mul(Mat4 dest, Mat4 a, Mat4 b);
|
||||
|
||||
/* |description|
|
||||
Scales the 4x4 floating-point matrix `mtx` by the scaling factors found in the 3D floating-point vector `s`, and stores the result in `dest`. This enlarges or shrinks objects in 3D space
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 void mtxf_scale_vec3f(Mat4 dest, Mat4 mtx, Vec3f s);
|
||||
|
||||
/* |description|
|
||||
Multiplies the 4x4 floating-point matrix `mtx` by a 3D signed-integer vector `b`, potentially interpreting `b` as angles or translations depending on usage, and modifies `mtx` accordingly
|
||||
|descriptionEnd| */
|
||||
OPTIMIZE_O3 s16 *mtxf_mul_vec3s(Mat4 mtx, Vec3s b);
|
||||
|
||||
/* |description|
|
||||
Converts the floating-point matrix `src` into a fixed-point (integer-based) matrix suitable for the `Mtx` format, and stores the result in `dest`
|
||||
|descriptionEnd| */
|
||||
OPTIMIZE_O3 void mtxf_to_mtx(Mtx *dest, Mat4 src);
|
||||
|
||||
/* |description|
|
||||
Rotates the matrix `mtx` in the XY plane by the given `angle`. Rotating in the XY plane typically means pivoting around the Z axis
|
||||
|descriptionEnd| */
|
||||
OPTIMIZE_O3 void mtxf_rotate_xy(Mtx *mtx, s16 angle);
|
||||
OPTIMIZE_O3 void mtxf_rotate_xy(Mat4 mtx, s16 angle);
|
||||
|
||||
/* |description|
|
||||
Inverts the 4x4 floating-point matrix `src` and stores the inverse in `dest`. Applying the inverse transformation undoes whatever `src` did, returning points back to their original coordinate space
|
||||
|descriptionEnd| */
|
||||
OPTIMIZE_O3 void mtxf_inverse(Mat4 dest, Mat4 src);
|
||||
|
||||
/* |description|
|
||||
Sets the 4x4 floating-point matrix `mtx` to all zeros.
|
||||
Unless you really need this-It's reccomended to use mtxf_identity instead.
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 void mtxf_zero(Mat4 mtx);
|
||||
|
||||
/* |description|
|
||||
Extracts the position (translation component) from the transformation matrix `objMtx` relative to the coordinate system defined by `camMtx` and stores that 3D position in `dest`. This can be used to get the object's coordinates in camera space
|
||||
|descriptionEnd| */
|
||||
OPTIMIZE_O3 f32 *get_pos_from_transform_mtx(Vec3f dest, Mat4 objMtx, Mat4 camMtx);
|
||||
|
||||
/* |description|
|
||||
Gradually moves an integer `current` value toward a `target` value, increasing it by `inc` if it is too low, or decreasing it by `dec` if it is too high. This is often used for smooth transitions or animations
|
||||
|descriptionEnd| */
|
||||
OPTIMIZE_O3 s32 approach_s32(s32 current, s32 target, s32 inc, s32 dec);
|
||||
|
||||
/* |description|
|
||||
Similar to `approach_s32`, but operates on floating-point numbers. It moves `current` toward `target` by increasing it by `inc` if below target, or decreasing it by `dec` if above target, creating a smooth interpolation
|
||||
|descriptionEnd| */
|
||||
OPTIMIZE_O3 f32 approach_f32(f32 current, f32 target, f32 inc, f32 dec);
|
||||
|
||||
/* |description|
|
||||
Computes spline interpolation weights for a given parameter `t` and stores these weights in `result`. This is used in spline-based animations to find intermediate positions between keyframes
|
||||
|descriptionEnd| */
|
||||
OPTIMIZE_O3 void spline_get_weights(struct MarioState* m, Vec4f result, f32 t, UNUSED s32 c);
|
||||
|
||||
/* |description|
|
||||
Initializes a spline-based animation for the `MarioState` structure `m` using the provided array of 3D signed-integer vectors `keyFrames`. This sets up the animation so that it can be advanced by polling
|
||||
|descriptionEnd| */
|
||||
OPTIMIZE_O3 void anim_spline_init(struct MarioState* m, Vec4s *keyFrames);
|
||||
|
||||
/* |description|
|
||||
Advances the spline-based animation associated with `m` and stores the current interpolated position in `result`. It returns the animation's status, allowing the caller to determine if the animation is ongoing or has completed
|
||||
|descriptionEnd| */
|
||||
OPTIMIZE_O3 s32 anim_spline_poll(struct MarioState* m, Vec3f result);
|
||||
|
||||
/* |description|
|
||||
Checks if `value` is zero. If not, it returns `value`. If it is zero, it returns the `replacement` value. This function ensures that a zero value can be substituted with a fallback value if needed
|
||||
|descriptionEnd| */
|
||||
OPTIMIZE_O3 f32 not_zero(f32 value, f32 replacement);
|
||||
|
||||
#include "math_util.inl"
|
||||
|
||||
#endif // MATH_UTIL_H
|
||||
|
||||
|
@ -10,314 +10,42 @@ optimizations and bug reports.
|
||||
#ifndef MATH_UTIL_INL
|
||||
#define MATH_UTIL_INL
|
||||
|
||||
/*
|
||||
Vec3f Functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copy vector 'src' to 'dest'.
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_copy(Vec3f dest, Vec3f src) {
|
||||
dest[0] = src[0];
|
||||
dest[1] = src[1];
|
||||
dest[2] = src[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set vector 'dest' to (x, y, z).
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_set(Vec3f dest, f32 x, f32 y, f32 z) {
|
||||
dest[0] = x;
|
||||
dest[1] = y;
|
||||
dest[2] = z;
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add vector 'a' to 'dest'.
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_add(Vec3f dest, Vec3f a) {
|
||||
dest[0] += a[0];
|
||||
dest[1] += a[1];
|
||||
dest[2] += a[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make 'dest' the sum of vectors a and b.
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_sum(Vec3f dest, Vec3f a, Vec3f b) {
|
||||
dest[0] = a[0] + b[0];
|
||||
dest[1] = a[1] + b[1];
|
||||
dest[2] = a[2] + b[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtracts vector a from 'dest'.
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_sub(Vec3f dest, Vec3f a) {
|
||||
if (!dest || !a) { return NULL; }
|
||||
dest[0] -= a[0];
|
||||
dest[1] -= a[1];
|
||||
dest[2] -= a[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make 'dest' the difference of vectors a and b.
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_dif(Vec3f dest, Vec3f a, Vec3f b) {
|
||||
dest[0] = a[0] - b[0];
|
||||
dest[1] = a[1] - b[1];
|
||||
dest[2] = a[2] - b[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply vector 'dest' by a.
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_mul(Vec3f dest, f32 a) {
|
||||
dest[0] *= a;
|
||||
dest[1] *= a;
|
||||
dest[2] *= a;
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides vector 'dest' by a.
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_div(Vec3f dest, f32 a) {
|
||||
dest[0] /= a;
|
||||
dest[1] /= a;
|
||||
dest[2] /= a;
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make vector 'dest' the cross product of vectors a and b.
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_cross(Vec3f dest, Vec3f a, Vec3f b) {
|
||||
dest[0] = a[1] * b[2] - b[1] * a[2];
|
||||
dest[1] = a[2] * b[0] - b[2] * a[0];
|
||||
dest[2] = a[0] * b[1] - b[0] * a[1];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes each component of the 3D floating-point vector 'v'.
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_normalize2(Vec3f v) {
|
||||
float s = vec3f_length(v);
|
||||
vec3f_div(v, s);
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get length of vector 'a'.
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 f32 vec3f_length(Vec3f a) {
|
||||
return sqrtf(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get dot product of vectors 'a' and 'b'.
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 f32 vec3f_dot(Vec3f a, Vec3f b) {
|
||||
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes respective scales of vecA and vecB, and sums them.
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_combine(Vec3f dest, Vec3f vecA, Vec3f vecB, f32 sclA, f32 sclB) {
|
||||
for (s32 i = 0; i < 3; ++i) {
|
||||
dest[i] = vecA[i] * sclA + vecB[i] * sclB;
|
||||
/* |description|
|
||||
Returns `replacement` if `replacement` is not zero. Otherwise, returns `value`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 replace_value_if_not_zero(f32 value, f32 replacement) {
|
||||
if (replacement != 0) {
|
||||
return replacement;
|
||||
}
|
||||
return dest;
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the distance between point 'v1' and 'v2'.
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 f32 vec3f_dist(Vec3f v1, Vec3f v2) {
|
||||
Vec3f diff;
|
||||
vec3f_dif(diff, v1, v2);
|
||||
return vec3f_length(diff);
|
||||
/* |description|
|
||||
Converts an angle from SM64 format to radians
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 sm64_to_radians(s16 sm64Angle) {
|
||||
return sm64Angle * M_PI / 0x8000;
|
||||
}
|
||||
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_zero(Vec3f v) {
|
||||
return vec3f_set(v, 0, 0, 0);
|
||||
/* |description|
|
||||
Converts an angle from radians to SM64 format
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s16 radians_to_sm64(f32 radiansAngle) {
|
||||
return radiansAngle * 0x8000 / M_PI;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert float vector a to a short vector 'dest' by rounding the components
|
||||
* to the nearest integer.
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 s16 *vec3f_to_vec3s(Vec3s dest, Vec3f a) {
|
||||
// add/subtract 0.5 in order to round to the nearest s32 instead of truncating
|
||||
dest[0] = a[0] + ((a[0] > 0) ? 0.5f : -0.5f);
|
||||
dest[1] = a[1] + ((a[1] > 0) ? 0.5f : -0.5f);
|
||||
dest[2] = a[2] + ((a[2] > 0) ? 0.5f : -0.5f);
|
||||
return dest;
|
||||
/* |description|
|
||||
Converts an angle from SM64 format to degrees
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 sm64_to_degrees(s16 sm64Angle) {
|
||||
return sm64Angle * 180.0f / 0x8000;
|
||||
}
|
||||
|
||||
/*
|
||||
Vec3s Functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copy vector src to dest.
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_copy(Vec3s dest, Vec3s src) {
|
||||
dest[0] = src[0];
|
||||
dest[1] = src[1];
|
||||
dest[2] = src[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set vector 'dest' to (x, y, z).
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_set(Vec3s dest, s16 x, s16 y, s16 z) {
|
||||
dest[0] = x;
|
||||
dest[1] = y;
|
||||
dest[2] = z;
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add vector a to 'dest'.
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_add(Vec3s dest, Vec3s a) {
|
||||
dest[0] += a[0];
|
||||
dest[1] += a[1];
|
||||
dest[2] += a[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make 'dest' the sum of vectors a and b.
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_sum(Vec3s dest, Vec3s a, Vec3s b) {
|
||||
dest[0] = a[0] + b[0];
|
||||
dest[1] = a[1] + b[1];
|
||||
dest[2] = a[2] + b[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtracts vector a from 'dest'.
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_sub(Vec3s dest, Vec3s a) {
|
||||
dest[0] -= a[0];
|
||||
dest[1] -= a[1];
|
||||
dest[2] -= a[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make 'dest' the difference of vectors a and b.
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_dif(Vec3s dest, Vec3s a, Vec3s b) {
|
||||
dest[0] = a[0] - b[0];
|
||||
dest[1] = a[1] - b[1];
|
||||
dest[2] = a[2] - b[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply vector 'dest' by a.
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_mul(Vec3s dest, s16 a) {
|
||||
dest[0] *= a;
|
||||
dest[1] *= a;
|
||||
dest[2] *= a;
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides vector 'dest' by a.
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_div(Vec3s dest, s16 a) {
|
||||
dest[0] /= a;
|
||||
dest[1] /= a;
|
||||
dest[2] /= a;
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get length of vector 'a'.
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 f32 vec3s_length(Vec3s a) {
|
||||
return sqrtf(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the distance between point 'v1' and 'v2'.
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 f32 vec3s_dist(Vec3s v1, Vec3s v2) {
|
||||
Vec3s diff;
|
||||
vec3s_dif(diff, v1, v2);
|
||||
return vec3s_length(diff);
|
||||
}
|
||||
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_zero(Vec3s v) {
|
||||
return vec3s_set(v, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert short vector a to float vector 'dest'.
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 f32 *vec3s_to_vec3f(Vec3f dest, Vec3s a) {
|
||||
dest[0] = a[0];
|
||||
dest[1] = a[1];
|
||||
dest[2] = a[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/*
|
||||
Mat4 Functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copy matrix 'src' to 'dest'.
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 void mtxf_copy(Mat4 dest, Mat4 src) {
|
||||
memcpy(dest, src, sizeof(Mat4));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set mtx to the identity matrix
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 void mtxf_identity(Mat4 mtx) {
|
||||
mtxf_copy(mtx, gMat4Identity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set dest to a translation matrix of vector b
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 void mtxf_translate(Mat4 dest, Vec3f b) {
|
||||
mtxf_identity(dest);
|
||||
vec3f_copy(dest[3], b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set matrix 'dest' to 'mtx' scaled by vector s
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 void mtxf_scale_vec3f(Mat4 dest, Mat4 mtx, Vec3f s) {
|
||||
mtxf_copy(dest, mtx);
|
||||
vec3f_mul(dest[0], s[0]);
|
||||
vec3f_mul(dest[1], s[1]);
|
||||
vec3f_mul(dest[2], s[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set mtx to all zeros.
|
||||
*/
|
||||
INLINE OPTIMIZE_O3 void mtxf_zero(Mat4 mtx) {
|
||||
mtxf_copy(mtx, gMat4Zero);
|
||||
/* |description|
|
||||
Converts an angle from degrees to SM64 format
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s16 degrees_to_sm64(f32 degreesAngle) {
|
||||
return degreesAngle * 0x8000 / 180.0f;
|
||||
}
|
||||
|
||||
#endif // MATH_UTIL_INL
|
60
src/engine/math_util_mat4.inl
Normal file
60
src/engine/math_util_mat4.inl
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
.inl files are for inlined functions and function templates.
|
||||
|
||||
It's best to put them in this file so they can be recompiled if needed.
|
||||
|
||||
Credit to PeachyPeach, Isaac0, Blockyyy, and others for suggestions
|
||||
optimizations and bug reports.
|
||||
*/
|
||||
|
||||
#ifndef MATH_UTIL_MAT4_INL
|
||||
#define MATH_UTIL_MAT4_INL
|
||||
|
||||
/* |description|
|
||||
Sets the 4x4 floating-point matrix `mtx` to all zeros.
|
||||
Unless you really need this-It's reccomended to use mtxf_identity instead.
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 void mtxf_zero(Mat4 mtx) {
|
||||
memset(mtx, 0, sizeof(Mat4));
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Copies the 4x4 floating-point matrix `src` into `dest`. After this operation, `dest` contains the same matrix values as `src`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 void mtxf_copy(Mat4 dest, Mat4 src) {
|
||||
memcpy(dest, src, sizeof(Mat4));
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Sets the 4x4 floating-point matrix `mtx` to the identity matrix. The identity matrix leaves points unchanged when they are transformed by it which is useful for matrix math
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 void mtxf_identity(Mat4 mtx) {
|
||||
mtxf_copy(mtx, gMat4Identity);
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Applies a translation to the 4x4 floating-point matrix `dest` by adding the coordinates in the 3D floating-point vector `b`. This shifts any transformed point by `b`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 void mtxf_translate(Mat4 dest, Vec3f b) {
|
||||
mtxf_identity(dest);
|
||||
vec3f_copy(dest[3], b);
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Scales the 4x4 floating-point matrix `mtx` by the scaling factors found in the 3D floating-point vector `s`, and stores the result in `dest`. This enlarges or shrinks objects in 3D space
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 void mtxf_scale_vec3f(Mat4 dest, Mat4 mtx, Vec3f s) {
|
||||
mtxf_copy(dest, mtx);
|
||||
vec3f_mul(dest[0], s[0]);
|
||||
vec3f_mul(dest[1], s[1]);
|
||||
vec3f_mul(dest[2], s[2]);
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Converts the floating-point matrix `src` into a fixed-point (integer-based) matrix suitable for the `Mtx` format, and stores the result in `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 void mtxf_to_mtx(Mtx *dest, Mat4 src) {
|
||||
mtxf_copy(dest->m, src);
|
||||
}
|
||||
|
||||
#endif // MATH_UTIL_MAT4_INL
|
166
src/engine/math_util_vec3.tmpl
Normal file
166
src/engine/math_util_vec3.tmpl
Normal file
@ -0,0 +1,166 @@
|
||||
#pragma once
|
||||
|
||||
/* |description|
|
||||
Sets the components of the 3D {{desc}} vector `v` to 0
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 {{type}} *vec3{{suffix}}_zero(Vec3{{suffix}} v) {
|
||||
memset(v, 0, sizeof(Vec3{{suffix}}));
|
||||
return v;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Copies the contents of a 3D {{desc}} vector (`src`) into another 3D {{desc}} vector (`dest`)
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 {{type}} *vec3{{suffix}}_copy(Vec3{{suffix}} dest, Vec3{{suffix}} src) {
|
||||
dest[0] = src[0];
|
||||
dest[1] = src[1];
|
||||
dest[2] = src[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Sets the values of the 3D {{desc}} vector `dest` to the given x, y, and z values
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 {{type}} *vec3{{suffix}}_set(Vec3{{suffix}} dest, {{type}} x, {{type}} y, {{type}} z) {
|
||||
dest[0] = x;
|
||||
dest[1] = y;
|
||||
dest[2] = z;
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Adds the components of the 3D {{desc}} vector `a` to `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 {{type}} *vec3{{suffix}}_add(Vec3{{suffix}} dest, Vec3{{suffix}} a) {
|
||||
dest[0] += a[0];
|
||||
dest[1] += a[1];
|
||||
dest[2] += a[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Adds the components of two 3D {{desc}} vectors `a` and `b` and stores the result in `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 {{type}} *vec3{{suffix}}_sum(Vec3{{suffix}} dest, Vec3{{suffix}} a, Vec3{{suffix}} b) {
|
||||
dest[0] = a[0] + b[0];
|
||||
dest[1] = a[1] + b[1];
|
||||
dest[2] = a[2] + b[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Subtracts the components of the 3D {{desc}} vector `a` from `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 {{type}} *vec3{{suffix}}_sub(Vec3{{suffix}} dest, Vec3{{suffix}} a) {
|
||||
dest[0] -= a[0];
|
||||
dest[1] -= a[1];
|
||||
dest[2] -= a[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Subtracts the components of the 3D {{desc}} vector `b` from the components of `a` and stores the result in `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 {{type}} *vec3{{suffix}}_dif(Vec3{{suffix}} dest, Vec3{{suffix}} a, Vec3{{suffix}} b) {
|
||||
dest[0] = a[0] - b[0];
|
||||
dest[1] = a[1] - b[1];
|
||||
dest[2] = a[2] - b[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Multiplies each component of the 3D {{desc}} vector `dest` by the scalar value `a`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 {{type}} *vec3{{suffix}}_mul(Vec3{{suffix}} dest, f32 a) {
|
||||
dest[0] *= a;
|
||||
dest[1] *= a;
|
||||
dest[2] *= a;
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Divides each component of the 3D {{desc}} vector `dest` by the scalar value `a`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 {{type}} *vec3{{suffix}}_div(Vec3{{suffix}} dest, f32 a) {
|
||||
if (a == 0) { return dest; }
|
||||
dest[0] /= a;
|
||||
dest[1] /= a;
|
||||
dest[2] /= a;
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Calculates the length (magnitude) of the 3D {{desc}} vector `a`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 vec3{{suffix}}_length(Vec3{{suffix}} a) {
|
||||
return sqrtf(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Normalizes the 3D {{desc}} vector `v` so that its length (magnitude) becomes 1, while retaining its direction
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 {{type}} *vec3{{suffix}}_normalize(Vec3{{suffix}} v) {
|
||||
f32 mag = vec3{{suffix}}_length(v);
|
||||
vec3{{suffix}}_div(v, mag);
|
||||
return v;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Sets the length (magnitude) of 3D {{desc}} vector `v`, while retaining its direction
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 {{type}} *vec3{{suffix}}_set_magnitude(Vec3{{suffix}} v, f32 mag) {
|
||||
vec3{{suffix}}_normalize(v);
|
||||
vec3{{suffix}}_mul(v, mag);
|
||||
return v;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Computes the dot product of the two 3D {{desc}} vectors `a` and `b`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 vec3{{suffix}}_dot(Vec3{{suffix}} a, Vec3{{suffix}} b) {
|
||||
return (f32) (a[0] * b[0] + a[1] * b[1] + a[2] * b[2]);
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Computes the cross product of two 3D {{desc}} vectors `a` and `b` and stores the result in `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 {{type}} *vec3{{suffix}}_cross(Vec3{{suffix}} dest, Vec3{{suffix}} a, Vec3{{suffix}} b) {
|
||||
dest[0] = a[1] * b[2] - b[1] * a[2];
|
||||
dest[1] = a[2] * b[0] - b[2] * a[0];
|
||||
dest[2] = a[0] * b[1] - b[0] * a[1];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Takes two 3D {{desc}} vectors `vecA` and `vecB`, multiplies them by `sclA` and `sclB` respectively, adds the scaled vectors together and stores the result in `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 {{type}} *vec3{{suffix}}_combine(Vec3{{suffix}} dest, Vec3{{suffix}} vecA, Vec3{{suffix}} vecB, f32 sclA, f32 sclB) {
|
||||
dest[0] = vecA[0] * sclA + vecB[0] * sclB;
|
||||
dest[1] = vecA[1] * sclA + vecB[1] * sclB;
|
||||
dest[2] = vecA[2] * sclA + vecB[2] * sclB;
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Calculates the distance between two 3D {{desc}} vectors `v1` and `v2`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 vec3{{suffix}}_dist(Vec3{{suffix}} v1, Vec3{{suffix}} v2) {
|
||||
Vec3{{suffix}} diff;
|
||||
vec3{{suffix}}_dif(diff, v1, v2);
|
||||
return vec3{{suffix}}_length(diff);
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Calculates the horizontal distance between two 3D {{desc}} vectors `v1` and `v2`, as if their y component was 0
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 vec3{{suffix}}_hdist(Vec3{{suffix}} v1, Vec3{{suffix}} v2) {
|
||||
Vec3{{suffix}} hdiff = { ({{type}}) (v2[0] - v1[0]), 0, ({{type}}) (v2[2] - v1[2]) };
|
||||
return vec3{{suffix}}_length(hdiff);
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Returns `true` if all components of the 3D {{desc}} vector `v` are zero
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 bool vec3{{suffix}}_is_zero(Vec3{{suffix}} v) {
|
||||
return memcmp(v, gVec3{{suffix}}Zero, sizeof(Vec3{{suffix}})) == 0;
|
||||
}
|
189
src/engine/math_util_vec3f.inl
Normal file
189
src/engine/math_util_vec3f.inl
Normal file
@ -0,0 +1,189 @@
|
||||
/* THIS FILE IS AUTO-GENERATED */
|
||||
/* DO NOT EDIT IT MANUALLY */
|
||||
|
||||
#pragma once
|
||||
|
||||
/* |description|
|
||||
Sets the components of the 3D floating-point vector `v` to 0
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_zero(Vec3f v) {
|
||||
memset(v, 0, sizeof(Vec3f));
|
||||
return v;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Copies the contents of a 3D floating-point vector (`src`) into another 3D floating-point vector (`dest`)
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_copy(Vec3f dest, Vec3f src) {
|
||||
dest[0] = src[0];
|
||||
dest[1] = src[1];
|
||||
dest[2] = src[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Sets the values of the 3D floating-point vector `dest` to the given x, y, and z values
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_set(Vec3f dest, f32 x, f32 y, f32 z) {
|
||||
dest[0] = x;
|
||||
dest[1] = y;
|
||||
dest[2] = z;
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Adds the components of the 3D floating-point vector `a` to `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_add(Vec3f dest, Vec3f a) {
|
||||
dest[0] += a[0];
|
||||
dest[1] += a[1];
|
||||
dest[2] += a[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Adds the components of two 3D floating-point vectors `a` and `b` and stores the result in `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_sum(Vec3f dest, Vec3f a, Vec3f b) {
|
||||
dest[0] = a[0] + b[0];
|
||||
dest[1] = a[1] + b[1];
|
||||
dest[2] = a[2] + b[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Subtracts the components of the 3D floating-point vector `a` from `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_sub(Vec3f dest, Vec3f a) {
|
||||
dest[0] -= a[0];
|
||||
dest[1] -= a[1];
|
||||
dest[2] -= a[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Subtracts the components of the 3D floating-point vector `b` from the components of `a` and stores the result in `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_dif(Vec3f dest, Vec3f a, Vec3f b) {
|
||||
dest[0] = a[0] - b[0];
|
||||
dest[1] = a[1] - b[1];
|
||||
dest[2] = a[2] - b[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Multiplies each component of the 3D floating-point vector `dest` by the scalar value `a`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_mul(Vec3f dest, f32 a) {
|
||||
dest[0] *= a;
|
||||
dest[1] *= a;
|
||||
dest[2] *= a;
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Divides each component of the 3D floating-point vector `dest` by the scalar value `a`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_div(Vec3f dest, f32 a) {
|
||||
if (a == 0) { return dest; }
|
||||
dest[0] /= a;
|
||||
dest[1] /= a;
|
||||
dest[2] /= a;
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Calculates the length (magnitude) of the 3D floating-point vector `a`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 vec3f_length(Vec3f a) {
|
||||
return sqrtf(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Normalizes the 3D floating-point vector `v` so that its length (magnitude) becomes 1, while retaining its direction
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_normalize(Vec3f v) {
|
||||
f32 mag = vec3f_length(v);
|
||||
vec3f_div(v, mag);
|
||||
return v;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Sets the length (magnitude) of 3D floating-point vector `v`, while retaining its direction
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_set_magnitude(Vec3f v, f32 mag) {
|
||||
vec3f_normalize(v);
|
||||
vec3f_mul(v, mag);
|
||||
return v;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Computes the dot product of the two 3D floating-point vectors `a` and `b`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 vec3f_dot(Vec3f a, Vec3f b) {
|
||||
return (f32) (a[0] * b[0] + a[1] * b[1] + a[2] * b[2]);
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Computes the cross product of two 3D floating-point vectors `a` and `b` and stores the result in `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_cross(Vec3f dest, Vec3f a, Vec3f b) {
|
||||
dest[0] = a[1] * b[2] - b[1] * a[2];
|
||||
dest[1] = a[2] * b[0] - b[2] * a[0];
|
||||
dest[2] = a[0] * b[1] - b[0] * a[1];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Takes two 3D floating-point vectors `vecA` and `vecB`, multiplies them by `sclA` and `sclB` respectively, adds the scaled vectors together and stores the result in `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3f_combine(Vec3f dest, Vec3f vecA, Vec3f vecB, f32 sclA, f32 sclB) {
|
||||
dest[0] = vecA[0] * sclA + vecB[0] * sclB;
|
||||
dest[1] = vecA[1] * sclA + vecB[1] * sclB;
|
||||
dest[2] = vecA[2] * sclA + vecB[2] * sclB;
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Calculates the distance between two 3D floating-point vectors `v1` and `v2`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 vec3f_dist(Vec3f v1, Vec3f v2) {
|
||||
Vec3f diff;
|
||||
vec3f_dif(diff, v1, v2);
|
||||
return vec3f_length(diff);
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Calculates the horizontal distance between two 3D floating-point vectors `v1` and `v2`, as if their y component was 0
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 vec3f_hdist(Vec3f v1, Vec3f v2) {
|
||||
Vec3f hdiff = { (f32) (v2[0] - v1[0]), 0, (f32) (v2[2] - v1[2]) };
|
||||
return vec3f_length(hdiff);
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Returns `true` if all components of the 3D floating-point vector `v` are zero
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 bool vec3f_is_zero(Vec3f v) {
|
||||
return memcmp(v, gVec3fZero, sizeof(Vec3f)) == 0;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Converts a 3D floating-point vector `a` into a 3D integer vector and stores the result in `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s32 *vec3f_to_vec3i(Vec3i dest, Vec3f a) {
|
||||
dest[0] = a[0] + ((a[0] > 0) ? 0.5f : -0.5f);
|
||||
dest[1] = a[1] + ((a[1] > 0) ? 0.5f : -0.5f);
|
||||
dest[2] = a[2] + ((a[2] > 0) ? 0.5f : -0.5f);
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Converts a 3D floating-point vector `a` into a 3D short integer vector and stores the result in `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s16 *vec3f_to_vec3s(Vec3s dest, Vec3f a) {
|
||||
dest[0] = a[0] + ((a[0] > 0) ? 0.5f : -0.5f);
|
||||
dest[1] = a[1] + ((a[1] > 0) ? 0.5f : -0.5f);
|
||||
dest[2] = a[2] + ((a[2] > 0) ? 0.5f : -0.5f);
|
||||
return dest;
|
||||
}
|
189
src/engine/math_util_vec3i.inl
Normal file
189
src/engine/math_util_vec3i.inl
Normal file
@ -0,0 +1,189 @@
|
||||
/* THIS FILE IS AUTO-GENERATED */
|
||||
/* DO NOT EDIT IT MANUALLY */
|
||||
|
||||
#pragma once
|
||||
|
||||
/* |description|
|
||||
Sets the components of the 3D integer vector `v` to 0
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s32 *vec3i_zero(Vec3i v) {
|
||||
memset(v, 0, sizeof(Vec3i));
|
||||
return v;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Copies the contents of a 3D integer vector (`src`) into another 3D integer vector (`dest`)
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s32 *vec3i_copy(Vec3i dest, Vec3i src) {
|
||||
dest[0] = src[0];
|
||||
dest[1] = src[1];
|
||||
dest[2] = src[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Sets the values of the 3D integer vector `dest` to the given x, y, and z values
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s32 *vec3i_set(Vec3i dest, s32 x, s32 y, s32 z) {
|
||||
dest[0] = x;
|
||||
dest[1] = y;
|
||||
dest[2] = z;
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Adds the components of the 3D integer vector `a` to `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s32 *vec3i_add(Vec3i dest, Vec3i a) {
|
||||
dest[0] += a[0];
|
||||
dest[1] += a[1];
|
||||
dest[2] += a[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Adds the components of two 3D integer vectors `a` and `b` and stores the result in `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s32 *vec3i_sum(Vec3i dest, Vec3i a, Vec3i b) {
|
||||
dest[0] = a[0] + b[0];
|
||||
dest[1] = a[1] + b[1];
|
||||
dest[2] = a[2] + b[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Subtracts the components of the 3D integer vector `a` from `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s32 *vec3i_sub(Vec3i dest, Vec3i a) {
|
||||
dest[0] -= a[0];
|
||||
dest[1] -= a[1];
|
||||
dest[2] -= a[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Subtracts the components of the 3D integer vector `b` from the components of `a` and stores the result in `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s32 *vec3i_dif(Vec3i dest, Vec3i a, Vec3i b) {
|
||||
dest[0] = a[0] - b[0];
|
||||
dest[1] = a[1] - b[1];
|
||||
dest[2] = a[2] - b[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Multiplies each component of the 3D integer vector `dest` by the scalar value `a`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s32 *vec3i_mul(Vec3i dest, f32 a) {
|
||||
dest[0] *= a;
|
||||
dest[1] *= a;
|
||||
dest[2] *= a;
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Divides each component of the 3D integer vector `dest` by the scalar value `a`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s32 *vec3i_div(Vec3i dest, f32 a) {
|
||||
if (a == 0) { return dest; }
|
||||
dest[0] /= a;
|
||||
dest[1] /= a;
|
||||
dest[2] /= a;
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Calculates the length (magnitude) of the 3D integer vector `a`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 vec3i_length(Vec3i a) {
|
||||
return sqrtf(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Normalizes the 3D integer vector `v` so that its length (magnitude) becomes 1, while retaining its direction
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s32 *vec3i_normalize(Vec3i v) {
|
||||
f32 mag = vec3i_length(v);
|
||||
vec3i_div(v, mag);
|
||||
return v;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Sets the length (magnitude) of 3D integer vector `v`, while retaining its direction
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s32 *vec3i_set_magnitude(Vec3i v, f32 mag) {
|
||||
vec3i_normalize(v);
|
||||
vec3i_mul(v, mag);
|
||||
return v;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Computes the dot product of the two 3D integer vectors `a` and `b`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 vec3i_dot(Vec3i a, Vec3i b) {
|
||||
return (f32) (a[0] * b[0] + a[1] * b[1] + a[2] * b[2]);
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Computes the cross product of two 3D integer vectors `a` and `b` and stores the result in `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s32 *vec3i_cross(Vec3i dest, Vec3i a, Vec3i b) {
|
||||
dest[0] = a[1] * b[2] - b[1] * a[2];
|
||||
dest[1] = a[2] * b[0] - b[2] * a[0];
|
||||
dest[2] = a[0] * b[1] - b[0] * a[1];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Takes two 3D integer vectors `vecA` and `vecB`, multiplies them by `sclA` and `sclB` respectively, adds the scaled vectors together and stores the result in `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s32 *vec3i_combine(Vec3i dest, Vec3i vecA, Vec3i vecB, f32 sclA, f32 sclB) {
|
||||
dest[0] = vecA[0] * sclA + vecB[0] * sclB;
|
||||
dest[1] = vecA[1] * sclA + vecB[1] * sclB;
|
||||
dest[2] = vecA[2] * sclA + vecB[2] * sclB;
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Calculates the distance between two 3D integer vectors `v1` and `v2`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 vec3i_dist(Vec3i v1, Vec3i v2) {
|
||||
Vec3i diff;
|
||||
vec3i_dif(diff, v1, v2);
|
||||
return vec3i_length(diff);
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Calculates the horizontal distance between two 3D integer vectors `v1` and `v2`, as if their y component was 0
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 vec3i_hdist(Vec3i v1, Vec3i v2) {
|
||||
Vec3i hdiff = { (s32) (v2[0] - v1[0]), 0, (s32) (v2[2] - v1[2]) };
|
||||
return vec3i_length(hdiff);
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Returns `true` if all components of the 3D integer vector `v` are zero
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 bool vec3i_is_zero(Vec3i v) {
|
||||
return memcmp(v, gVec3iZero, sizeof(Vec3i)) == 0;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Converts a 3D integer vector `a` into a 3D floating-point vector and stores the result in `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3i_to_vec3f(Vec3f dest, Vec3i a) {
|
||||
dest[0] = a[0];
|
||||
dest[1] = a[1];
|
||||
dest[2] = a[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Converts a 3D integer vector `a` into a 3D short integer vector and stores the result in `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s16 *vec3i_to_vec3s(Vec3s dest, Vec3i a) {
|
||||
dest[0] = a[0];
|
||||
dest[1] = a[1];
|
||||
dest[2] = a[2];
|
||||
return dest;
|
||||
}
|
189
src/engine/math_util_vec3s.inl
Normal file
189
src/engine/math_util_vec3s.inl
Normal file
@ -0,0 +1,189 @@
|
||||
/* THIS FILE IS AUTO-GENERATED */
|
||||
/* DO NOT EDIT IT MANUALLY */
|
||||
|
||||
#pragma once
|
||||
|
||||
/* |description|
|
||||
Sets the components of the 3D short integer vector `v` to 0
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_zero(Vec3s v) {
|
||||
memset(v, 0, sizeof(Vec3s));
|
||||
return v;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Copies the contents of a 3D short integer vector (`src`) into another 3D short integer vector (`dest`)
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_copy(Vec3s dest, Vec3s src) {
|
||||
dest[0] = src[0];
|
||||
dest[1] = src[1];
|
||||
dest[2] = src[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Sets the values of the 3D short integer vector `dest` to the given x, y, and z values
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_set(Vec3s dest, s16 x, s16 y, s16 z) {
|
||||
dest[0] = x;
|
||||
dest[1] = y;
|
||||
dest[2] = z;
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Adds the components of the 3D short integer vector `a` to `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_add(Vec3s dest, Vec3s a) {
|
||||
dest[0] += a[0];
|
||||
dest[1] += a[1];
|
||||
dest[2] += a[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Adds the components of two 3D short integer vectors `a` and `b` and stores the result in `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_sum(Vec3s dest, Vec3s a, Vec3s b) {
|
||||
dest[0] = a[0] + b[0];
|
||||
dest[1] = a[1] + b[1];
|
||||
dest[2] = a[2] + b[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Subtracts the components of the 3D short integer vector `a` from `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_sub(Vec3s dest, Vec3s a) {
|
||||
dest[0] -= a[0];
|
||||
dest[1] -= a[1];
|
||||
dest[2] -= a[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Subtracts the components of the 3D short integer vector `b` from the components of `a` and stores the result in `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_dif(Vec3s dest, Vec3s a, Vec3s b) {
|
||||
dest[0] = a[0] - b[0];
|
||||
dest[1] = a[1] - b[1];
|
||||
dest[2] = a[2] - b[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Multiplies each component of the 3D short integer vector `dest` by the scalar value `a`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_mul(Vec3s dest, f32 a) {
|
||||
dest[0] *= a;
|
||||
dest[1] *= a;
|
||||
dest[2] *= a;
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Divides each component of the 3D short integer vector `dest` by the scalar value `a`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_div(Vec3s dest, f32 a) {
|
||||
if (a == 0) { return dest; }
|
||||
dest[0] /= a;
|
||||
dest[1] /= a;
|
||||
dest[2] /= a;
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Calculates the length (magnitude) of the 3D short integer vector `a`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 vec3s_length(Vec3s a) {
|
||||
return sqrtf(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Normalizes the 3D short integer vector `v` so that its length (magnitude) becomes 1, while retaining its direction
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_normalize(Vec3s v) {
|
||||
f32 mag = vec3s_length(v);
|
||||
vec3s_div(v, mag);
|
||||
return v;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Sets the length (magnitude) of 3D short integer vector `v`, while retaining its direction
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_set_magnitude(Vec3s v, f32 mag) {
|
||||
vec3s_normalize(v);
|
||||
vec3s_mul(v, mag);
|
||||
return v;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Computes the dot product of the two 3D short integer vectors `a` and `b`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 vec3s_dot(Vec3s a, Vec3s b) {
|
||||
return (f32) (a[0] * b[0] + a[1] * b[1] + a[2] * b[2]);
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Computes the cross product of two 3D short integer vectors `a` and `b` and stores the result in `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_cross(Vec3s dest, Vec3s a, Vec3s b) {
|
||||
dest[0] = a[1] * b[2] - b[1] * a[2];
|
||||
dest[1] = a[2] * b[0] - b[2] * a[0];
|
||||
dest[2] = a[0] * b[1] - b[0] * a[1];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Takes two 3D short integer vectors `vecA` and `vecB`, multiplies them by `sclA` and `sclB` respectively, adds the scaled vectors together and stores the result in `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s16 *vec3s_combine(Vec3s dest, Vec3s vecA, Vec3s vecB, f32 sclA, f32 sclB) {
|
||||
dest[0] = vecA[0] * sclA + vecB[0] * sclB;
|
||||
dest[1] = vecA[1] * sclA + vecB[1] * sclB;
|
||||
dest[2] = vecA[2] * sclA + vecB[2] * sclB;
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Calculates the distance between two 3D short integer vectors `v1` and `v2`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 vec3s_dist(Vec3s v1, Vec3s v2) {
|
||||
Vec3s diff;
|
||||
vec3s_dif(diff, v1, v2);
|
||||
return vec3s_length(diff);
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Calculates the horizontal distance between two 3D short integer vectors `v1` and `v2`, as if their y component was 0
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 vec3s_hdist(Vec3s v1, Vec3s v2) {
|
||||
Vec3s hdiff = { (s16) (v2[0] - v1[0]), 0, (s16) (v2[2] - v1[2]) };
|
||||
return vec3s_length(hdiff);
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Returns `true` if all components of the 3D short integer vector `v` are zero
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 bool vec3s_is_zero(Vec3s v) {
|
||||
return memcmp(v, gVec3sZero, sizeof(Vec3s)) == 0;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Converts a 3D short integer vector `a` into a 3D floating-point vector and stores the result in `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 f32 *vec3s_to_vec3f(Vec3f dest, Vec3s a) {
|
||||
dest[0] = a[0];
|
||||
dest[1] = a[1];
|
||||
dest[2] = a[2];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* |description|
|
||||
Converts a 3D short integer vector `a` into a 3D integer vector and stores the result in `dest`
|
||||
|descriptionEnd| */
|
||||
INLINE OPTIMIZE_O3 s32 *vec3s_to_vec3i(Vec3i dest, Vec3s a) {
|
||||
dest[0] = a[0];
|
||||
dest[1] = a[1];
|
||||
dest[2] = a[2];
|
||||
return dest;
|
||||
}
|
@ -17,8 +17,6 @@ Vec3f gFindWallDirection = { 0 };
|
||||
u8 gFindWallDirectionActive = false;
|
||||
u8 gFindWallDirectionAirborne = false;
|
||||
|
||||
#define CLAMP(_val, _min, _max) MAX(MIN((_val), _max), _min)
|
||||
|
||||
void set_find_wall_direction(Vec3f dir, bool active, bool airborne) {
|
||||
if (active) {
|
||||
vec3f_copy(gFindWallDirection, dir);
|
||||
@ -50,18 +48,18 @@ void closest_point_to_triangle(struct Surface* surf, Vec3f src, Vec3f out) {
|
||||
if (s < 0) {
|
||||
if (t < 0) {
|
||||
if (d < 0) {
|
||||
s = CLAMP(-d/a, 0, 1);
|
||||
s = clamp(-d/a, 0, 1);
|
||||
t = 0;
|
||||
} else {
|
||||
s = 0;
|
||||
t = CLAMP(-e/c, 0, 1);
|
||||
t = clamp(-e/c, 0, 1);
|
||||
}
|
||||
} else {
|
||||
s = 0;
|
||||
t = CLAMP(-e/c, 0, 1);
|
||||
t = clamp(-e/c, 0, 1);
|
||||
}
|
||||
} else if (t < 0) {
|
||||
s = CLAMP(-d/a, 0, 1);
|
||||
s = clamp(-d/a, 0, 1);
|
||||
t = 0;
|
||||
} else {
|
||||
f32 invDet = 1 / det;
|
||||
@ -75,26 +73,26 @@ void closest_point_to_triangle(struct Surface* surf, Vec3f src, Vec3f out) {
|
||||
if (tmp1 > tmp0) {
|
||||
f32 numer = tmp1 - tmp0;
|
||||
f32 denom = a-2*b+c;
|
||||
s = CLAMP(numer/denom, 0, 1);
|
||||
s = clamp(numer/denom, 0, 1);
|
||||
t = (1 - s);
|
||||
} else {
|
||||
t = CLAMP(-e/c, 0, 1);
|
||||
t = clamp(-e/c, 0, 1);
|
||||
s = 0;
|
||||
}
|
||||
} else if (t < 0.f) {
|
||||
if ((a + d) > (b + e)) {
|
||||
f32 numer = c+e-b-d;
|
||||
f32 denom = a-2*b+c;
|
||||
s = CLAMP(numer/denom, 0, 1);
|
||||
s = clamp(numer/denom, 0, 1);
|
||||
t = (1 - s);
|
||||
} else {
|
||||
s = CLAMP(-e/c, 0, 1);
|
||||
s = clamp(-e/c, 0, 1);
|
||||
t = 0;
|
||||
}
|
||||
} else {
|
||||
f32 numer = c+e-b-d;
|
||||
f32 denom = a-2*b+c;
|
||||
s = CLAMP(numer/denom, 0, 1);
|
||||
s = clamp(numer/denom, 0, 1);
|
||||
t = 1 - s;
|
||||
}
|
||||
}
|
||||
|
@ -12073,7 +12073,7 @@ Gfx *geo_camera_fov(s32 callContext, struct GraphNode *g, UNUSED void *context)
|
||||
}
|
||||
}
|
||||
|
||||
perspective->fov = get_first_person_enabled() ? gFirstPersonCamera.fov : not_zero(gFOVState.fov, gOverrideFOV);
|
||||
perspective->fov = get_first_person_enabled() ? gFirstPersonCamera.fov : replace_value_if_not_zero(gFOVState.fov, gOverrideFOV);
|
||||
shake_camera_fov(perspective);
|
||||
return NULL;
|
||||
}
|
||||
@ -12296,7 +12296,7 @@ void rom_hack_cam_walk(Vec3f pos, Vec3f dir, f32 dist) {
|
||||
surf->normal.y,
|
||||
surf->normal.z,
|
||||
};
|
||||
vec3f_project(dirNorm, normal, dir);
|
||||
vec3f_project(dir, dirNorm, normal);
|
||||
dir[0] = dirNorm[0] - dir[0];
|
||||
dir[1] = dirNorm[1] - dir[1];
|
||||
dir[2] = dirNorm[2] - dir[2];
|
||||
|
@ -18,8 +18,6 @@
|
||||
#include "pc/lua/utils/smlua_camera_utils.h"
|
||||
#include "pc/lua/smlua_hooks.h"
|
||||
|
||||
#define CLAMP(_val, _min, _max) MAX(MIN((_val), _max), _min)
|
||||
|
||||
struct FirstPersonCamera gFirstPersonCamera = {
|
||||
.enabled = false,
|
||||
.forcePitch = false,
|
||||
@ -73,16 +71,16 @@ static void first_person_camera_update(void) {
|
||||
s16 extStickX = m->controller->extStickX;
|
||||
s16 extStickY = m->controller->extStickY;
|
||||
if (extStickX == 0) {
|
||||
extStickX = (CLAMP(m->controller->buttonDown & R_CBUTTONS, 0, 1) - CLAMP(m->controller->buttonDown & L_CBUTTONS, 0, 1)) * 32;
|
||||
extStickX = (clamp(m->controller->buttonDown & R_CBUTTONS, 0, 1) - clamp(m->controller->buttonDown & L_CBUTTONS, 0, 1)) * 32;
|
||||
}
|
||||
if (extStickY == 0) {
|
||||
extStickY = (CLAMP(m->controller->buttonDown & U_CBUTTONS, 0, 1) - CLAMP(m->controller->buttonDown & D_CBUTTONS, 0, 1)) * 24;
|
||||
extStickY = (clamp(m->controller->buttonDown & U_CBUTTONS, 0, 1) - clamp(m->controller->buttonDown & D_CBUTTONS, 0, 1)) * 24;
|
||||
}
|
||||
|
||||
// update pitch
|
||||
if (!gFirstPersonCamera.forcePitch) {
|
||||
gFirstPersonCamera.pitch -= sensY * (invY * extStickY - 1.5f * mouse_y);
|
||||
gFirstPersonCamera.pitch = CLAMP(gFirstPersonCamera.pitch, -0x3F00, 0x3F00);
|
||||
gFirstPersonCamera.pitch = clamp(gFirstPersonCamera.pitch, -0x3F00, 0x3F00);
|
||||
}
|
||||
|
||||
// update yaw
|
||||
@ -121,9 +119,9 @@ static void first_person_camera_update(void) {
|
||||
if (mario_is_crouching(m) || m->action == ACT_LEDGE_GRAB) {
|
||||
bool up = (m->controller->buttonDown & Z_TRIG) != 0 || m->action == ACT_CROUCH_SLIDE || m->action == ACT_LEDGE_GRAB;
|
||||
f32 inc = 10 * (up ? 1 : -1);
|
||||
gFirstPersonCamera.crouch = CLAMP(gFirstPersonCamera.crouch + inc, 0, FIRST_PERSON_MARIO_HEAD_POS - FIRST_PERSON_MARIO_HEAD_POS_SHORT);
|
||||
gFirstPersonCamera.crouch = clamp(gFirstPersonCamera.crouch + inc, 0, FIRST_PERSON_MARIO_HEAD_POS - FIRST_PERSON_MARIO_HEAD_POS_SHORT);
|
||||
} else {
|
||||
gFirstPersonCamera.crouch = CLAMP(gFirstPersonCamera.crouch - 10, 0, FIRST_PERSON_MARIO_HEAD_POS - FIRST_PERSON_MARIO_HEAD_POS_SHORT);
|
||||
gFirstPersonCamera.crouch = clamp(gFirstPersonCamera.crouch - 10, 0, FIRST_PERSON_MARIO_HEAD_POS - FIRST_PERSON_MARIO_HEAD_POS_SHORT);
|
||||
}
|
||||
|
||||
if (m->action == ACT_LEDGE_GRAB) {
|
||||
|
@ -37,7 +37,6 @@
|
||||
#include "game/camera.h"
|
||||
#include "level_info.h"
|
||||
#include "pc/lua/utils/smlua_text_utils.h"
|
||||
#include "pc/lua/utils/smlua_math_utils.h"
|
||||
#include "menu/ingame_text.h"
|
||||
|
||||
u16 gDialogColorFadeTimer;
|
||||
|
@ -31,7 +31,7 @@
|
||||
#endif
|
||||
#include "level_table.h"
|
||||
#include "course_table.h"
|
||||
#include "../../include/libc/stdlib.h"
|
||||
#include "libc/stdlib.h"
|
||||
#include "rumble_init.h"
|
||||
#include "game/interaction.h"
|
||||
#include "menu/intro_geo.h"
|
||||
|
@ -77,7 +77,7 @@ Plays a sound if Mario does not currently have a specific flag set. Once played,
|
||||
void play_sound_if_no_flag(struct MarioState *m, u32 soundBits, u32 flags);
|
||||
|
||||
/* |description|
|
||||
Plays Mario’s jump sound if it hasn't been played yet since the last action change. This helps avoid overlapping jump voice lines on repeated jumps
|
||||
Plays Mario's jump sound if it hasn't been played yet since the last action change. This helps avoid overlapping jump voice lines on repeated jumps
|
||||
|descriptionEnd| */
|
||||
void play_mario_jump_sound(struct MarioState *m);
|
||||
|
||||
@ -157,14 +157,14 @@ Useful for controlling friction, movement speed adjustments, and whether Mario s
|
||||
s32 mario_get_floor_class(struct MarioState *m);
|
||||
|
||||
/* |description|
|
||||
Computes a value added to terrain sounds, depending on the floor’s type (sand, snow, water, etc.) and slipperiness. This returns a sound 'addend' used with sound effects.
|
||||
Computes a value added to terrain sounds, depending on the floor's type (sand, snow, water, etc.) and slipperiness. This returns a sound 'addend' used with sound effects.
|
||||
Useful for playing context-specific footstep or movement sounds
|
||||
|descriptionEnd| */
|
||||
u32 mario_get_terrain_sound_addend(struct MarioState *m);
|
||||
|
||||
/* |description|
|
||||
Checks for and resolves wall collisions at a given position `pos`, returning the last wall encountered. Primarily used to prevent Mario from going through walls.
|
||||
Useful for collision detection when updating Mario’s movement or adjusting his position
|
||||
Useful for collision detection when updating Mario's movement or adjusting his position
|
||||
|descriptionEnd| */
|
||||
struct Surface *resolve_and_return_wall_collisions(Vec3f pos, f32 offset, f32 radius);
|
||||
|
||||
@ -301,7 +301,7 @@ Sets Mario's particle flags to spawn various visual effects (dust, water splashe
|
||||
void set_mario_particle_flags(struct MarioState* m, u32 flags, u8 clear);
|
||||
|
||||
/* |description|
|
||||
Updates Mario's wall information based on wall collisions (`WallCollisionData`). Chooses the most relevant wall depending on the level’s collision fix settings
|
||||
Updates Mario's wall information based on wall collisions (`WallCollisionData`). Chooses the most relevant wall depending on the level's collision fix settings
|
||||
|descriptionEnd| */
|
||||
void mario_update_wall(struct MarioState* m, struct WallCollisionData* wcd);
|
||||
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "rumble_init.h"
|
||||
#include "obj_behaviors.h"
|
||||
#include "hardcoded.h"
|
||||
#include "../../include/libc/stdlib.h"
|
||||
#include "libc/stdlib.h"
|
||||
#include "pc/debuglog.h"
|
||||
#include "pc/pc_main.h"
|
||||
#include "pc/configfile.h"
|
||||
|
@ -11,8 +11,6 @@
|
||||
#include "pc/lua/smlua.h"
|
||||
#include "game/hardcoded.h"
|
||||
|
||||
#define CLAMP(_val, _min, _max) MAX(MIN((_val), _max), _min)
|
||||
|
||||
static s16 sMovingSandSpeeds[] = { 12, 8, 4, 0 };
|
||||
|
||||
struct Surface gWaterSurfacePseudoFloor = {
|
||||
@ -316,7 +314,7 @@ static s32 perform_ground_quarter_step(struct MarioState *m, Vec3f nextPos) {
|
||||
if (floor == NULL) {
|
||||
if (gServerSettings.bouncyLevelBounds != BOUNCY_LEVEL_BOUNDS_OFF) {
|
||||
m->faceAngle[1] += 0x8000;
|
||||
mario_set_forward_vel(m, gServerSettings.bouncyLevelBounds == BOUNCY_LEVEL_BOUNDS_ON_CAP ? CLAMP(1.5f * m->forwardVel, -500, 500) : 1.5f * m->forwardVel);
|
||||
mario_set_forward_vel(m, gServerSettings.bouncyLevelBounds == BOUNCY_LEVEL_BOUNDS_ON_CAP ? clamp(1.5f * m->forwardVel, -500, 500) : 1.5f * m->forwardVel);
|
||||
}
|
||||
smlua_call_event_hooks_mario_param(HOOK_ON_COLLIDE_LEVEL_BOUNDS, m);
|
||||
return GROUND_STEP_HIT_WALL_STOP_QSTEPS;
|
||||
@ -505,7 +503,7 @@ s32 perform_air_quarter_step(struct MarioState *m, Vec3f intendedPos, u32 stepAr
|
||||
m->pos[1] = nextPos[1];
|
||||
if (gServerSettings.bouncyLevelBounds != BOUNCY_LEVEL_BOUNDS_OFF) {
|
||||
m->faceAngle[1] += 0x8000;
|
||||
mario_set_forward_vel(m, gServerSettings.bouncyLevelBounds == BOUNCY_LEVEL_BOUNDS_ON_CAP ? CLAMP(1.5f * m->forwardVel, -500, 500) : 1.5f * m->forwardVel);
|
||||
mario_set_forward_vel(m, gServerSettings.bouncyLevelBounds == BOUNCY_LEVEL_BOUNDS_ON_CAP ? clamp(1.5f * m->forwardVel, -500, 500) : 1.5f * m->forwardVel);
|
||||
}
|
||||
smlua_call_event_hooks_mario_param(HOOK_ON_COLLIDE_LEVEL_BOUNDS, m);
|
||||
return AIR_STEP_HIT_WALL;
|
||||
|
@ -246,7 +246,7 @@ void patch_mtx_interpolated(f32 delta) {
|
||||
u16 perspNorm;
|
||||
f32 fovInterpolated = delta_interpolate_f32(sPerspectiveNode->prevFov, sPerspectiveNode->fov, delta);
|
||||
f32 near = MIN(sPerspectiveNode->near, gProjectionMaxNearValue);
|
||||
guPerspective(sPerspectiveMtx, &perspNorm, fovInterpolated, sPerspectiveAspect, get_first_person_enabled() ? 1 : not_zero(near, gOverrideNear), not_zero(sPerspectiveNode->far, gOverrideFar), 1.0f);
|
||||
guPerspective(sPerspectiveMtx, &perspNorm, fovInterpolated, sPerspectiveAspect, get_first_person_enabled() ? 1 : replace_value_if_not_zero(near, gOverrideNear), replace_value_if_not_zero(sPerspectiveNode->far, gOverrideFar), 1.0f);
|
||||
gSPMatrix(sPerspectivePos, VIRTUAL_TO_PHYSICAL(sPerspectiveNode), G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH);
|
||||
}
|
||||
|
||||
@ -497,7 +497,7 @@ static void geo_process_perspective(struct GraphNodePerspective *node) {
|
||||
gProjectionVanillaNearValue = node->near;
|
||||
gProjectionVanillaFarValue = node->far;
|
||||
f32 near = MIN(node->near, gProjectionMaxNearValue);
|
||||
guPerspective(mtx, &perspNorm, node->prevFov, aspect, get_first_person_enabled() ? 1 : not_zero(near, gOverrideNear), not_zero(node->far, gOverrideFar), 1.0f);
|
||||
guPerspective(mtx, &perspNorm, node->prevFov, aspect, get_first_person_enabled() ? 1 : replace_value_if_not_zero(near, gOverrideNear), replace_value_if_not_zero(node->far, gOverrideFar), 1.0f);
|
||||
|
||||
sPerspectiveNode = node;
|
||||
sPerspectiveMtx = mtx;
|
||||
@ -566,7 +566,7 @@ static void geo_process_camera(struct GraphNodeCamera *node) {
|
||||
if (node->fnNode.func != NULL) {
|
||||
node->fnNode.func(GEO_CONTEXT_RENDER, &node->fnNode.node, gMatStack[gMatStackIndex]);
|
||||
}
|
||||
mtxf_rotate_xy(rollMtx, node->rollScreen);
|
||||
mtxf_rotate_xy(rollMtx->m, node->rollScreen);
|
||||
|
||||
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(rollMtx), G_MTX_PROJECTION | G_MTX_MUL | G_MTX_NOPUSH);
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include "scroll_targets.h"
|
||||
#include "pc/lua/utils/smlua_math_utils.h"
|
||||
#include "data/dynos_cmap.cpp.h"
|
||||
|
||||
static void *sScrollTargets = NULL;
|
||||
|
@ -634,7 +634,7 @@ static void hud_rotate_and_translate_vec3f(Vec3f vec, Mat4* mtx, Vec3f out) {
|
||||
}
|
||||
|
||||
f32 get_current_fov() {
|
||||
return get_first_person_enabled() ? gFirstPersonCamera.fov : not_zero(gFOVState.fov, gOverrideFOV) + gFOVState.fovOffset;
|
||||
return get_first_person_enabled() ? gFirstPersonCamera.fov : replace_value_if_not_zero(gFOVState.fov, gOverrideFOV) + gFOVState.fovOffset;
|
||||
}
|
||||
|
||||
f32 djui_hud_get_fov_coeff() {
|
||||
|
@ -623,7 +623,7 @@ static void calculate_normal_dir(const Light_t *light, Vec3f coeffs, bool applyL
|
||||
}
|
||||
|
||||
gfx_transposed_matrix_mul(coeffs, light_dir, rsp.modelview_matrix_stack[rsp.modelview_matrix_stack_size - 1]);
|
||||
vec3f_normalize2(coeffs);
|
||||
vec3f_normalize(coeffs);
|
||||
}
|
||||
|
||||
static void OPTIMIZE_O3 gfx_sp_matrix(uint8_t parameters, const int32_t *addr) {
|
||||
|
@ -55,6 +55,33 @@ static struct LuaObjectField sVec4fFields[LUA_VEC4F_FIELD_COUNT] = {
|
||||
{ "z", LVT_F32, sizeof(f32) * 2, false, LOT_NONE, 1, sizeof(f32) },
|
||||
};
|
||||
|
||||
#define LUA_VEC2I_FIELD_COUNT 2
|
||||
static struct LuaObjectField sVec2iFields[LUA_VEC2I_FIELD_COUNT] = {
|
||||
{ "x", LVT_S32, sizeof(s32) * 0, false, LOT_NONE, 1, sizeof(s32) },
|
||||
{ "y", LVT_S32, sizeof(s32) * 1, false, LOT_NONE, 1, sizeof(s32) },
|
||||
};
|
||||
|
||||
#define LUA_VEC3I_FIELD_COUNT 3
|
||||
static struct LuaObjectField sVec3iFields[LUA_VEC3I_FIELD_COUNT] = {
|
||||
{ "x", LVT_S32, sizeof(s32) * 0, false, LOT_NONE, 1, sizeof(s32) },
|
||||
{ "y", LVT_S32, sizeof(s32) * 1, false, LOT_NONE, 1, sizeof(s32) },
|
||||
{ "z", LVT_S32, sizeof(s32) * 2, false, LOT_NONE, 1, sizeof(s32) },
|
||||
};
|
||||
|
||||
#define LUA_VEC4I_FIELD_COUNT 4
|
||||
static struct LuaObjectField sVec4iFields[LUA_VEC4I_FIELD_COUNT] = {
|
||||
{ "w", LVT_S32, sizeof(s32) * 3, false, LOT_NONE, 1, sizeof(s32) },
|
||||
{ "x", LVT_S32, sizeof(s32) * 0, false, LOT_NONE, 1, sizeof(s32) },
|
||||
{ "y", LVT_S32, sizeof(s32) * 1, false, LOT_NONE, 1, sizeof(s32) },
|
||||
{ "z", LVT_S32, sizeof(s32) * 2, false, LOT_NONE, 1, sizeof(s32) },
|
||||
};
|
||||
|
||||
#define LUA_VEC2S_FIELD_COUNT 2
|
||||
static struct LuaObjectField sVec2sFields[LUA_VEC2S_FIELD_COUNT] = {
|
||||
{ "x", LVT_S16, sizeof(s16) * 0, false, LOT_NONE, 1, sizeof(s16) },
|
||||
{ "y", LVT_S16, sizeof(s16) * 1, false, LOT_NONE, 1, sizeof(s16) },
|
||||
};
|
||||
|
||||
#define LUA_VEC3S_FIELD_COUNT 3
|
||||
static struct LuaObjectField sVec3sFields[LUA_VEC3S_FIELD_COUNT] = {
|
||||
{ "x", LVT_S16, sizeof(s16) * 0, false, LOT_NONE, 1, sizeof(s16) },
|
||||
@ -118,6 +145,10 @@ struct LuaObjectTable sLuaObjectTable[LOT_MAX] = {
|
||||
[LOT_VEC2F] = { LOT_VEC2F, sVec2fFields, LUA_VEC2F_FIELD_COUNT },
|
||||
[LOT_VEC3F] = { LOT_VEC3F, sVec3fFields, LUA_VEC3F_FIELD_COUNT },
|
||||
[LOT_VEC4F] = { LOT_VEC4F, sVec4fFields, LUA_VEC4F_FIELD_COUNT },
|
||||
[LOT_VEC2I] = { LOT_VEC2I, sVec2iFields, LUA_VEC2I_FIELD_COUNT },
|
||||
[LOT_VEC3I] = { LOT_VEC3I, sVec3iFields, LUA_VEC3I_FIELD_COUNT },
|
||||
[LOT_VEC4I] = { LOT_VEC4I, sVec4iFields, LUA_VEC4I_FIELD_COUNT },
|
||||
[LOT_VEC2S] = { LOT_VEC2S, sVec2sFields, LUA_VEC2S_FIELD_COUNT },
|
||||
[LOT_VEC3S] = { LOT_VEC3S, sVec3sFields, LUA_VEC3S_FIELD_COUNT },
|
||||
[LOT_VEC4S] = { LOT_VEC4S, sVec4sFields, LUA_VEC4S_FIELD_COUNT },
|
||||
[LOT_MAT4] = { LOT_MAT4, sMat4Fields, LUA_MAT4_FIELD_COUNT },
|
||||
@ -2919,6 +2950,10 @@ const char *sLuaLotNames[] = {
|
||||
[LOT_VEC2F] = "Vec2f",
|
||||
[LOT_VEC3F] = "Vec3f",
|
||||
[LOT_VEC4F] = "Vec4f",
|
||||
[LOT_VEC2I] = "Vec2i",
|
||||
[LOT_VEC3I] = "Vec3i",
|
||||
[LOT_VEC4I] = "Vec4i",
|
||||
[LOT_VEC2S] = "Vec2s",
|
||||
[LOT_VEC3S] = "Vec3s",
|
||||
[LOT_VEC4S] = "Vec4s",
|
||||
[LOT_MAT4] = "Mat4",
|
||||
|
@ -8,6 +8,10 @@ enum LuaObjectType {
|
||||
LOT_VEC2F,
|
||||
LOT_VEC3F,
|
||||
LOT_VEC4F,
|
||||
LOT_VEC2I,
|
||||
LOT_VEC3I,
|
||||
LOT_VEC4I,
|
||||
LOT_VEC2S,
|
||||
LOT_VEC3S,
|
||||
LOT_VEC4S,
|
||||
LOT_MAT4,
|
||||
|
@ -123,6 +123,33 @@ char gSmluaConstants[] = ""
|
||||
"}\n"
|
||||
"return color\n"
|
||||
"end\n"
|
||||
"--------------------\n"
|
||||
"-- math functions --\n"
|
||||
"--------------------\n"
|
||||
"--- Note: These functions don't exist in the Lua math library,\n"
|
||||
"--- and are useful enough to not have to redefine them in every mod\n"
|
||||
"local __math_min, __math_max, __math_sqrt = math.min, math.max, math.sqrt\n"
|
||||
"--- @param x number\n"
|
||||
"--- @return number\n"
|
||||
"--- Computes the square of the number `x`\n"
|
||||
"function math.sqr(x)\n"
|
||||
"return x * x\n"
|
||||
"end\n"
|
||||
"--- @param x number\n"
|
||||
"--- @param a number\n"
|
||||
"--- @param b number\n"
|
||||
"--- @return number\n"
|
||||
"--- Clamps the number `x` between bounds `a` (minimum) and `b` (maximum)\n"
|
||||
"function math.clamp(x, a, b)\n"
|
||||
"return __math_min(__math_max(x, a), b)\n"
|
||||
"end\n"
|
||||
"--- @param a number\n"
|
||||
"--- @param b number\n"
|
||||
"--- @return number\n"
|
||||
"--- Computes the hypotenuse of a right-angled triangle given sides `a` and `b` using the Pythagorean theorem\n"
|
||||
"function math.hypot(a, b)\n"
|
||||
"return __math_sqrt(a * a + b * b)\n"
|
||||
"end\n"
|
||||
"-----------------\n"
|
||||
"-- legacy font --\n"
|
||||
"-----------------\n"
|
||||
@ -130,6 +157,20 @@ char gSmluaConstants[] = ""
|
||||
"FONT_TINY = -1\n"
|
||||
"--- @type integer\n"
|
||||
"ANIM_FLAG_FORWARD = (1 << 1)\n"
|
||||
"--------------------\n"
|
||||
"-- Math functions --\n"
|
||||
"--------------------\n"
|
||||
"--- Note: These functions were originally in smlua_math_utils.h,\n"
|
||||
"--- but performed worse (~2x slower) than built-in Lua math functions\n"
|
||||
"min = math.min\n"
|
||||
"minf = math.min\n"
|
||||
"max = math.max\n"
|
||||
"maxf = math.max\n"
|
||||
"sqr = math.sqr\n"
|
||||
"sqrf = math.sqr\n"
|
||||
"clamp = math.clamp\n"
|
||||
"clampf = math.clamp\n"
|
||||
"hypotf = math.hypot\n"
|
||||
"INSTANT_WARP_INDEX_START=0x00\n"
|
||||
"INSTANT_WARP_INDEX_STOP=0x04\n"
|
||||
"MAX_AREAS=16\n"
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,58 +0,0 @@
|
||||
#include "sm64.h"
|
||||
#include "types.h"
|
||||
|
||||
f32 sm64_to_radians(s16 sm64Angle) {
|
||||
return sm64Angle * M_PI / 0x8000;
|
||||
}
|
||||
|
||||
s16 radians_to_sm64(f32 radiansAngle) {
|
||||
return radiansAngle * 0x8000 / M_PI;
|
||||
}
|
||||
|
||||
f32 sm64_to_degrees(s16 sm64Angle) {
|
||||
return sm64Angle * 180.0f / 0x8000;
|
||||
}
|
||||
|
||||
s16 degrees_to_sm64(f32 degreesAngle) {
|
||||
return degreesAngle * 0x8000 / 180.0f;
|
||||
}
|
||||
|
||||
f32 hypotf(f32 a, f32 b) {
|
||||
return __builtin_sqrtf(a * a + b * b);
|
||||
}
|
||||
|
||||
f32 minf(f32 a, f32 b) {
|
||||
return __builtin_fminf(a, b);
|
||||
}
|
||||
|
||||
f32 maxf(f32 a, f32 b) {
|
||||
return __builtin_fmaxf(a, b);
|
||||
}
|
||||
|
||||
s32 min(s32 a, s32 b){
|
||||
return ((a) <= (b) ? (a) : (b));
|
||||
}
|
||||
|
||||
s32 max(s32 a, s32 b){
|
||||
return ((a) >= (b) ? (a) : (b));
|
||||
}
|
||||
|
||||
s32 sqr(s32 x) {
|
||||
return x * x;
|
||||
}
|
||||
|
||||
f32 sqrf(f32 x) {
|
||||
return x * x;
|
||||
}
|
||||
|
||||
s32 clamp(s32 a, s32 b, s32 c) {
|
||||
if (a < b) { return b; }
|
||||
if (a > c) { return c; }
|
||||
return a;
|
||||
}
|
||||
|
||||
f32 clampf(f32 a, f32 b, f32 c) {
|
||||
if (a < b) { return b; }
|
||||
if (a > c) { return c; }
|
||||
return a;
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
#ifndef SMLUA_MATH_UTILS_H
|
||||
#define SMLUA_MATH_UTILS_H
|
||||
|
||||
#if defined(min)
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
#if defined(max)
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
#if defined(sqr)
|
||||
#undef sqr
|
||||
#endif
|
||||
|
||||
// these are also defined in math_util.h as macros
|
||||
|
||||
/* |description|Finds the minimum of two signed 32-bit integers|descriptionEnd| */
|
||||
s32 min(s32 a, s32 b);
|
||||
|
||||
/* |description|Finds the maximum of two signed 32-bit integers|descriptionEnd| */
|
||||
s32 max(s32 a, s32 b);
|
||||
|
||||
/* |description|Computes the square of a signed 32-bit integer|descriptionEnd| */
|
||||
s32 sqr(s32 x);
|
||||
|
||||
/* |description|Finds the minimum of two floating-point numbers|descriptionEnd| */
|
||||
f32 minf(f32 a, f32 b);
|
||||
|
||||
/* |description|Finds the maximum of two floating-point numbers|descriptionEnd| */
|
||||
f32 maxf(f32 a, f32 b);
|
||||
|
||||
/* |description|Computes the square of a floating-point number|descriptionEnd| */
|
||||
f32 sqrf(f32 x);
|
||||
|
||||
/* |description|Converts an angle from SM64 format to radians|descriptionEnd| */
|
||||
f32 sm64_to_radians(s16 sm64Angle);
|
||||
|
||||
/* |description|Converts an angle from radians to SM64 format|descriptionEnd| */
|
||||
s16 radians_to_sm64(f32 radiansAngle);
|
||||
|
||||
/* |description|Converts an angle from SM64 format to degrees|descriptionEnd| */
|
||||
f32 sm64_to_degrees(s16 sm64Angle);
|
||||
|
||||
/* |description|Converts an angle from degrees to SM64 format|descriptionEnd| */
|
||||
s16 degrees_to_sm64(f32 degreesAngle);
|
||||
|
||||
/* |description|Computes the hypotenuse of a right triangle given sides `a` and `b` using the Pythagorean theorem|descriptionEnd| */
|
||||
f32 hypotf(f32 a, f32 b);
|
||||
|
||||
/* |description|Clamps a signed 32-bit integer `a` between bounds `b` (minimum) and `c` (maximum)|descriptionEnd| */
|
||||
s32 clamp(s32 a, s32 b, s32 c);
|
||||
|
||||
/* |description|Clamps a floating-point number `a` between bounds `b` (minimum) and `c` (maximum)|descriptionEnd| */
|
||||
f32 clampf(f32 a, f32 b, f32 c);
|
||||
|
||||
#endif // SMLUA_MATH_UTILS_H
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include "include/course_table.h"
|
||||
#include "game/level_geo.h"
|
||||
#include "game/first_person_cam.h"
|
||||
#include "pc/lua/utils/smlua_math_utils.h"
|
||||
#include "pc/lua/utils/smlua_audio_utils.h"
|
||||
|
||||
#ifdef DISCORD_SDK
|
||||
|
@ -6,12 +6,9 @@
|
||||
#include "engine/math_util.h"
|
||||
#include "game/obj_behaviors.h"
|
||||
#include "game/camera.h"
|
||||
#include "pc/lua/utils/smlua_math_utils.h"
|
||||
#include "pc/lua/utils/smlua_misc_utils.h"
|
||||
#include "pc/lua/smlua_hooks.h"
|
||||
|
||||
#define CLAMP(_val, _min, _max) MAX(MIN((_val), _max), _min)
|
||||
|
||||
#define FADE_SCALE 4.f
|
||||
|
||||
struct StateExtras {
|
||||
@ -105,7 +102,7 @@ void nametags_render(void) {
|
||||
f32 measure = djui_hud_measure_text(name) * scale * 0.5f;
|
||||
out[1] -= 16 * scale;
|
||||
|
||||
u8 alpha = (i == 0 ? 255 : MIN(np->fadeOpacity << 3, 255)) * CLAMP(FADE_SCALE - scale, 0.f, 1.f);
|
||||
u8 alpha = (i == 0 ? 255 : MIN(np->fadeOpacity << 3, 255)) * clamp(FADE_SCALE - scale, 0.f, 1.f);
|
||||
|
||||
struct StateExtras* e = &sStateExtras[i];
|
||||
if (!e->inited) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user