diff --git a/CodeGen/VectorGen/.gitignore b/CodeGen/VectorGen/.gitignore index 5f0e724..5b7e8f0 100644 --- a/CodeGen/VectorGen/.gitignore +++ b/CodeGen/VectorGen/.gitignore @@ -1,2 +1,3 @@ # Result -*.hpp +VxTypes.hpp +VxTypes.cpp diff --git a/CodeGen/VectorGen/VxTypes.cpp.jinja b/CodeGen/VectorGen/VxTypes.cpp.jinja new file mode 100644 index 0000000..3e3b63e --- /dev/null +++ b/CodeGen/VectorGen/VxTypes.cpp.jinja @@ -0,0 +1,178 @@ +{% import 'VxTypes.shared.jinja' as shared %} +{# +For friend operator overload, we do not need add CLASSNAME:: prefix for it. +Because they are not a part of that class. +#} + +#pragma region {{ sname }} + +{# Ctor type 1 - Default ctor -#} +{{ sname }}::{{ sname }}() : {{- shared.initialize_list_builder(svars, False) -}} {} {% if not is_vector %}// SET YOUR CUSTOM INIT{% endif %} +{#- Ctor type 2 - User specified ctor #} +{{ sname }}::{{ sname }}({{- shared.argument_list_builder(svars) -}}) : {{- shared.initialize_list_builder(svars, True) -}} {} + +{#- Offset operator #} +CKFLOAT& {{ sname }}::operator[](size_t i) { + switch (i) { + {%- for item in svars %} + case {{ loop.index0 }}: return {{ item }}; + {%- endfor %} + default: throw LogicException("Invalid index for {{ sname }}::operator[]."); + } +} +const CKFLOAT& {{ sname }}::operator[](size_t i) const { + switch (i) { + {%- for item in svars %} + case {{ loop.index0 }}: return {{ item }}; + {%- endfor %} + default: throw LogicException("Invalid index for {{ sname }}::operator[]."); + } +} + +{#- Equal operator #} +bool {{ sname }}::operator==(const {{ sname }}& rhs) const { + return ( + {%- for item in svars -%} + {{ item }} == rhs.{{ item }} {%- if not loop.last %} && {% endif %} + {%- endfor -%} + ); +} + +{#- Spaceship operator #} +auto {{ sname }}::operator<=>(const {{ sname }}& rhs) const { + {%- for item in svars[:-1] %} + if (auto cmp = {{ item }} <=> rhs.{{ item }}; cmp != 0) return cmp; + {%- endfor %} + return {{ svars[-1] }} <=> rhs.{{ svars[-1] }}; +} + + +{#- BEGIN VECTOR SPECIFIC #} +{%- if is_vector %} + +{#- Add, minus operators #} +{#- Unary operators #} +{{ sname }} {{ sname }}::operator+() const { + return *this; +} +{{ sname }} {{ sname }}::operator-() const { + return {{ sname }}( + {%- for item in svars -%} + -{{ item }} {%- if not loop.last %}, {% endif %} + {%- endfor -%} + ); +} +{#- Additive operators #} +{{ sname }}& {{ sname }}::operator+=(const {{ sname }}& rhs) { + {%- for item in svars %} + {{ item }} += rhs.{{ item }}; + {%- endfor %} + return *this; +} +{{ sname }} operator+(const {{ sname }}& lhs, const {{ sname }}& rhs) { + return {{ sname }}( + {%- for item in svars -%} + lhs.{{ item }} + rhs.{{ item }} {%- if not loop.last %}, {% endif %} + {%- endfor -%} + ); +} +{{ sname }}& {{ sname }}::operator-=(const {{ sname }}& rhs) { + {%- for item in svars %} + {{ item }} -= rhs.{{ item }}; + {%- endfor %} + return *this; +} +{{ sname }} operator-(const {{ sname }}& lhs, const {{ sname }}& rhs) { + return {{ sname }}( + {%- for item in svars -%} + lhs.{{ item }} - rhs.{{ item }} {%- if not loop.last %}, {% endif %} + {%- endfor -%} + ); +} + +{#- Mul operator #} +{{ sname }}& {{ sname }}::operator*=(CKFLOAT rhs) { + {%- for item in svars %} + {{ item }} *= rhs; + {%- endfor %} + return *this; +} +{{ sname }} operator*(const {{ sname }}& lhs, CKFLOAT rhs) { + return {{ sname }}( + {%- for item in svars -%} + lhs.{{ item }} * rhs {%- if not loop.last %}, {% endif %} + {%- endfor -%} + ); +} +{{ sname }} operator*(CKFLOAT lhs, const {{ sname }}& rhs) { + return {{ sname }}( + {%- for item in svars -%} + lhs * rhs.{{ item }} {%- if not loop.last %}, {% endif %} + {%- endfor -%} + ); +} +CKFLOAT operator*(const {{ sname }}& lhs, const {{ sname }}& rhs) { + return ( + {%- for item in svars -%} + lhs.{{ item }} * rhs.{{ item }} {%- if not loop.last %} + {% endif %} + {%- endfor -%} + ); +} + +{#- Div operator #} +{{ sname }}& {{ sname }}::operator/=(CKFLOAT rhs) { + if (rhs == 0.0f) return *this; + {%- for item in svars %} + {{ item }} /= rhs; + {%- endfor %} + return *this; +} +{{ sname }} operator/(const {{ sname }}& lhs, CKFLOAT rhs) { + if (rhs == 0.0f) return {{ sname }}(); + else return {{ sname }}( + {%- for item in svars -%} + lhs.{{ item }} / rhs {%- if not loop.last %}, {% endif %} + {%- endfor -%} + ); +} + +{#- Length functions #} +CKFLOAT {{ sname }}::SquaredLength() const { + return ( + {%- for item in svars -%} + {{ item }} * {{ item }} {%- if not loop.last %} + {% endif %} + {%- endfor -%} + ); +} +CKFLOAT {{ sname }}::Length() const { + return std::sqrt(SquaredLength()); +} + +{#- Normalize functions #} +void {{ sname }}::Normalized() { + CKFLOAT len = Length(); + if (len == 0.0f) return; + {%- for item in svars %} + {{ item }} /= len; + {%- endfor %} +} +{{ sname }} {{ sname }}::Normalize() const { + CKFLOAT len = Length(); + if (len == 0.0f) return {{ sname }}(); + else return {{ sname }}( + {%- for item in svars -%} + {{ item }} / len {%- if not loop.last %}, {% endif %} + {%- endfor -%} + ); +} + +{%- endif %} +{#- END VECTOR SPECIFIC #} + + +{#- User custom region #} + +/* ===== BEGIN USER CUSTOM ===== */ +/* ===== END USER CUSTOM ===== */ + +#pragma endregion diff --git a/CodeGen/VectorGen/VxTypes.hpp.jinja b/CodeGen/VectorGen/VxTypes.hpp.jinja new file mode 100644 index 0000000..f3a7631 --- /dev/null +++ b/CodeGen/VectorGen/VxTypes.hpp.jinja @@ -0,0 +1,65 @@ +{% import 'VxTypes.shared.jinja' as shared %} + +struct {{ sname }} { + {#- Variable declaration #} + CKFLOAT {{ ", ".join(svars) }}; + + {#- Ctor type 1 - Default ctor #} + {{ sname }}(); + {#- Ctor type 2 - User specified ctor #} + {{ sname }}({{- shared.argument_list_builder(svars) -}}); + + {#- Default copy ctor, move ctor, copy assigner, move assigner #} + YYCC_DEF_CLS_COPY_MOVE({{ sname }}); + + {#- Offset operator #} + CKFLOAT& operator[](size_t i); + const CKFLOAT& operator[](size_t i) const; + + {#- Equal operator #} + bool operator==(const {{ sname }}& rhs) const; + + {#- Spaceship operator #} + auto operator<=>(const {{ sname }}& rhs) const; + + + {#- BEGIN VECTOR SPECIFIC #} + {%- if is_vector %} + + {#- Add, minus operators #} + {#- Unary operators #} + {{ sname }} operator+() const; + {{ sname }} operator-() const; + {#- Additive operators #} + {{ sname }}& operator+=(const {{ sname }}& rhs); + friend {{ sname }} operator+(const {{ sname }}& lhs, const {{ sname }}& rhs); + {{ sname }}& operator-=(const {{ sname }}& rhs); + friend {{ sname }} operator-(const {{ sname }}& lhs, const {{ sname }}& rhs); + + {#- Mul operator #} + {{ sname }}& operator*=(CKFLOAT rhs); + friend {{ sname }} operator*(const {{ sname }}& lhs, CKFLOAT rhs); + friend {{ sname }} operator*(CKFLOAT lhs, const {{ sname }}& rhs); + friend CKFLOAT operator*(const {{ sname }}& lhs, const {{ sname }}& rhs); + + {#- Div operator #} + {{ sname }}& operator/=(CKFLOAT rhs); + friend {{ sname }} operator/(const {{ sname }}& lhs, CKFLOAT rhs); + + {#- Length functions #} + CKFLOAT SquaredLength() const; + CKFLOAT Length() const; + + {#- Normalize functions #} + void Normalized(); + {{ sname }} Normalize() const; + + {%- endif %} + {#- END VECTOR SPECIFIC #} + + + {#- User custom region #} + + /* ===== BEGIN USER CUSTOM ===== */ + /* ===== END USER CUSTOM ===== */ +}; diff --git a/CodeGen/VectorGen/VxTypes.shared.jinja b/CodeGen/VectorGen/VxTypes.shared.jinja new file mode 100644 index 0000000..555a9aa --- /dev/null +++ b/CodeGen/VectorGen/VxTypes.shared.jinja @@ -0,0 +1,21 @@ +{# +The macro to generate C++ ctor argument list +It produce like this: `CKFLOAT _x, CKFLOAT _y, CKFLOAT _z, CKFLOAT _w` +#} +{% macro argument_list_builder(svars) %} +{%- for item in svars -%} +CKFLOAT _{{- item -}}{%- if not loop.last %}, {% endif -%} +{%- endfor -%} +{% endmacro %} + +{# +The macro to generate C++ ctor initialize list +It produce like this: `x(0.0f), y(0.0f), z(0.0f), w(0.0f)` +or this: `x(_x), y(_y), z(_z), w(_w)` +according to user request. +#} +{% macro initialize_list_builder(svars, is_user) %} +{%- for item in svars -%} +{{- item -}}({%- if is_user -%}_{{- item -}}{%- else -%}0.0f{%- endif -%}){%- if not loop.last %}, {% endif -%} +{%- endfor -%} +{% endmacro %} diff --git a/CodeGen/VectorGen/VxVectorGen.py b/CodeGen/VectorGen/VxVectorGen.py new file mode 100644 index 0000000..3c2abc7 --- /dev/null +++ b/CodeGen/VectorGen/VxVectorGen.py @@ -0,0 +1,63 @@ +import os +import io +import typing +import jinja2 + +g_HppTemplateFile: str = 'VxTypes.hpp.jinja' +g_CppTemplateFile: str = 'VxTypes.cpp.jinja' + +g_ResultHppFile: str = 'VxTypes.hpp' +g_ResultCppFile: str = 'VxTypes.cpp' + +def get_root_directory() -> str: + return os.path.dirname(__file__) + +class TemplateRender: + m_Loader: jinja2.BaseLoader + m_Environment: jinja2.Environment + + m_HppTemplate: jinja2.Template + m_CppTemplate: jinja2.Template + + m_OutputHpp: io.TextIOWrapper + m_OutputCpp: io.TextIOWrapper + + def __init__(self, output_hpp_path: str, output_cpp_path: str) -> None: + self.m_Loader = jinja2.FileSystemLoader(get_root_directory()) + self.m_Environment = jinja2.Environment(loader=self.m_Loader) + + self.m_HppTemplate = self.m_Environment.get_template(g_HppTemplateFile) + self.m_CppTemplate = self.m_Environment.get_template(g_CppTemplateFile) + + self.m_OutputHpp = open(os.path.join(get_root_directory(), output_hpp_path), 'w', encoding='utf-8') + self.m_OutputCpp = open(os.path.join(get_root_directory(), output_cpp_path), 'w', encoding='utf-8') + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, traceback): + self.m_OutputHpp.close() + self.m_OutputCpp.close() + + def __render(self, sname: str, is_vector: bool, svars: tuple[str]) -> None: + template_argument: dict[str, typing.Any] = { + 'sname': sname, + 'is_vector': is_vector, + 'svars': svars + } + self.m_OutputHpp.write(self.m_HppTemplate.render(**template_argument)) + self.m_OutputCpp.write(self.m_CppTemplate.render(**template_argument)) + + def render_vector(self, sname: str, svars: tuple[str]) -> None: + self.__render(sname, True, svars) + + def render_others(self, sname: str, svars: tuple[str]) -> None: + self.__render(sname, False, svars) + +if __name__ == '__main__': + with TemplateRender(g_ResultHppFile, g_ResultCppFile) as render: + render.render_vector('VxVector2', ('x', 'y', )) + render.render_vector('VxVector3', ('x', 'y', 'z', )) + render.render_vector('VxVector4', ('x', 'y', 'z', 'w', )) + render.render_others('VxQuaternion', ('x', 'y', 'z', 'w', )) + render.render_others('VxColor', ('r', 'g', 'b', 'a', )) diff --git a/CodeGen/VectorGen/VxVectors.py b/CodeGen/VectorGen/VxVectors.py deleted file mode 100644 index 77c6a0c..0000000 --- a/CodeGen/VectorGen/VxVectors.py +++ /dev/null @@ -1,166 +0,0 @@ -import os - -def GetTmplDecl(svars: tuple[str]) -> str: - return f'CKFLOAT {", ".join(svars)};' - -def GetTmplCtor1(sname: str, svars: tuple[str]) -> str: - return f'{sname}() : {", ".join(map(lambda x: f"{x}(0.0f)", svars))} {{}}' - -def GetTmplCtor2(sname: str, svars: tuple[str]) -> str: - return f'{sname}({", ".join(map(lambda x: f"CKFLOAT _{x}", svars))}) : {", ".join(map(lambda x: f"{x}(_{x})", svars))} {{}}' - -def GetTmplCopyCtor(sname: str, svars: tuple[str]) -> str: - return f'{sname}(const {sname}& rhs) : {", ".join(map(lambda x: f"{x}(rhs.{x})", svars))} {{}}' - -def GetTmplMoveCtor(sname: str, svars: tuple[str]) -> str: - return f'{sname}({sname}&& rhs) : {", ".join(map(lambda x: f"{x}(rhs.{x})", svars))} {{}}' - -def GetTmplOperAssignCopy(sname: str, svars: tuple[str]) -> str: - sp: str = '\n\t\t' - return f"""\t{sname}& operator=(const {sname}& rhs) {{ -\t\t{sp.join(map(lambda x: f'{x} = rhs.{x};', svars))} -\t\treturn *this; -\t}}""" - -def GetTmplOperAssignMove(sname: str, svars: tuple[str]) -> str: - sp: str = '\n\t\t' - return f"""\t{sname}& operator=({sname}&& rhs) {{ -\t\t{sp.join(map(lambda x: f'{x} = rhs.{x};', svars))} -\t\treturn *this; -\t}}""" - -def GetTmplOperOffset(sname: str, svars: tuple[str]) -> str: - sp: str = '\n\t\t\t' - return f"""\tCKFLOAT& operator[](size_t i) {{ -\t\tswitch (i) {{ -\t\t\t{sp.join(map(lambda x: f'case {x}: return {svars[x]};', range(len(svars))))} -\t\t\tdefault: throw LogicException("Invalid index for {sname}::operator[]."); -\t\t}} -\t}} -\tconst CKFLOAT& operator[](size_t i) const {{ -\t\tswitch (i) {{ -\t\t\t{sp.join(map(lambda x: f'case {x}: return {svars[x]};', range(len(svars))))} -\t\t\tdefault: throw LogicException("Invalid index for {sname}::operator[]."); -\t\t}} -\t}}""" - -def GetTmplOperAddMinus(sname: str, svars: tuple[str], oper: str) -> str: - sp: str = '\n\t\t' - return f"""\t{sname}& operator{oper}=(const {sname}& rhs) {{ -\t\t{sp.join(map(lambda x: f'{x} {oper}= rhs.{x};', svars))} -\t\treturn *this; -\t}} -\tfriend {sname} operator{oper}(const {sname}& lhs, const {sname}& rhs) {{ -\t\treturn {sname}({', '.join(map(lambda x: f'lhs.{x} {oper} rhs.{x}', svars))}); -\t}}""" - -def GetTmplOperMul(sname: str, svars: tuple[str]) -> str: - sp: str = '\n\t\t' - return f"""\t{sname}& operator*=(CKFLOAT rhs) {{ -\t\t{sp.join(map(lambda x: f'{x} *= rhs;', svars))} -\t\treturn *this; -\t}} -\tfriend {sname} operator*(const {sname}& lhs, CKFLOAT rhs) {{ -\t\treturn {sname}({', '.join(map(lambda x: f'lhs.{x} * rhs', svars))}); -\t}} -\tfriend {sname} operator*(CKFLOAT lhs, const {sname}& rhs) {{ -\t\treturn {sname}({', '.join(map(lambda x: f'lhs * rhs.{x}', svars))}); -\t}} -\tfriend CKFLOAT operator*(const {sname}& lhs, const {sname}& rhs) {{ -\t\treturn ({' + '.join(map(lambda x: f'lhs.{x} * rhs.{x}', svars))}); -\t}}""" - -def GetTmplOperDiv(sname: str, svars: tuple[str]) -> str: - sp: str = '\n\t\t' - return f"""\t{sname}& operator/=(CKFLOAT rhs) {{ -\t\tif (rhs == 0.0f) return *this; -\t\t{sp.join(map(lambda x: f'{x} /= rhs;', svars))} -\t\treturn *this; -\t}} -\tfriend {sname} operator/(const {sname}& lhs, CKFLOAT rhs) {{ -\t\tif (rhs == 0.0f) return {sname}({', '.join(map(lambda x: '0.0f', range(len(svars))))}); -\t\treturn {sname}({', '.join(map(lambda x: f'lhs.{x} / rhs', svars))}); -\t}}""" - -def GetTmplOperEqual(sname: str, svars: tuple[str]) -> str: - return f"""\tbool operator==(const {sname}& rhs) const {{ -\t\treturn ({' && '.join(map(lambda x: f'{x} == rhs.{x}', svars))}); -\t}}""" - -def GetTmplOperSpaceship(sname: str, svars: tuple[str]) -> str: - sp: str = '\n\t\t' - return f"""\tauto operator<=>(const {sname}& rhs) const {{ -\t\t{sp.join(map(lambda x: f'if (auto cmp = {x} <=> rhs.{x}; cmp != 0) return cmp;', svars[:-1]))} -\t\treturn {svars[-1]} <=> rhs.{svars[-1]}; -\t}}""" - -def GetTmplLength(sname: str, svars: tuple[str]) -> str: - return f"""\tCKFLOAT SquaredLength() const {{ -\t\treturn ({' + '.join(map(lambda x: f'{x} * {x}', svars))}); -\t}} -\tCKFLOAT Length() const {{ -\t\treturn std::sqrt(SquaredLength()); -\t}}""" - -def GetTmplNormalize(sname: str, svars: tuple[str]) -> str: - sp: str = '\n\t\t' - return f"""\tvoid Normalized() {{ -\t\tCKFLOAT len = Length(); -\t\tif (len == 0.0f) return; -\t\t{sp.join(map(lambda x: f'{x} /= len;', svars))} -\t}} -\t{sname} Normalize() const {{ -\t\tCKFLOAT len = Length(); -\t\tif (len == 0.0f) return {sname}(); -\t\treturn {sname}({', '.join(map(lambda x: f'{x} / len', svars))}); -\t}}""" - -def GetTmplVector(sname: str, svars: tuple[str]) -> str: - return f""" -struct {sname} {{ -\t{GetTmplDecl(svars)} -\t{GetTmplCtor1(sname, svars)} -\t{GetTmplCtor2(sname, svars)} -\tYYCC_DEF_CLS_COPY_MOVE({sname}); -{GetTmplOperOffset(sname, svars)} -{GetTmplOperAddMinus(sname, svars, '+')} -{GetTmplOperAddMinus(sname, svars, '-')} -{GetTmplOperMul(sname, svars)} -{GetTmplOperDiv(sname, svars)} -{GetTmplOperEqual(sname, svars)} -{GetTmplOperSpaceship(sname, svars)} -{GetTmplLength(sname, svars)} -{GetTmplNormalize(sname, svars)} -}}; -""" - -def GetTmplOthers(sname: str, svars: tuple[str]) -> str: - return f""" -struct {sname} {{ -\t{GetTmplDecl(svars)} -\t{GetTmplCtor1(sname, svars)} // set your custom init. -\t{GetTmplCtor2(sname, svars)} -\tYYCC_DEF_CLS_COPY_MOVE({sname}); -{GetTmplOperOffset(sname, svars)} -{GetTmplOperEqual(sname, svars)} -{GetTmplOperSpaceship(sname, svars)} -}}; -""" - -# use YYCC_DEF_CLS_COPY_MOVE instead of these outputs. -#\t{GetTmplCopyCtor(sname, svars)} -#\t{GetTmplMoveCtor(sname, svars)} -#{GetTmplOperAssignCopy(sname, svars)} -#{GetTmplOperAssignMove(sname, svars)} - -if __name__ == '__main__': - # get file path - self_path: str = os.path.dirname(__file__) - cpp_file: str = os.path.join(self_path, 'VxTypes.hpp') - # generate files - with open(cpp_file, 'w', encoding='utf-8') as fs: - fs.write(GetTmplVector('VxVector2', ('x', 'y', ))) - fs.write(GetTmplVector('VxVector3', ('x', 'y', 'z', ))) - fs.write(GetTmplVector('VxVector4', ('x', 'y', 'z', 'w', ))) - fs.write(GetTmplOthers('VxQuaternion', ('x', 'y', 'z', 'w', ))) - fs.write(GetTmplOthers('VxColor', ('r', 'g', 'b', 'a', ))) diff --git a/LibCmo/CK2/ObjImpls/CK3dEntity.cpp b/LibCmo/CK2/ObjImpls/CK3dEntity.cpp index f34960c..46de068 100644 --- a/LibCmo/CK2/ObjImpls/CK3dEntity.cpp +++ b/LibCmo/CK2/ObjImpls/CK3dEntity.cpp @@ -157,7 +157,7 @@ namespace LibCmo::CK2::ObjImpls { // read matrix // reset - m_WorldMatrix.ResetToIdentity(); + m_WorldMatrix.SetIdentity(); // force read as vector3 chunk->ReadStruct(reinterpret_cast(&m_WorldMatrix[0])); chunk->ReadStruct(reinterpret_cast(&m_WorldMatrix[1])); diff --git a/LibCmo/CK2/ObjImpls/CKCamera.cpp b/LibCmo/CK2/ObjImpls/CKCamera.cpp index 02bb0cd..c5d2272 100644 --- a/LibCmo/CK2/ObjImpls/CKCamera.cpp +++ b/LibCmo/CK2/ObjImpls/CKCamera.cpp @@ -3,4 +3,45 @@ namespace LibCmo::CK2::ObjImpls { +#pragma region Class Operations + + CK_CAMERA_PROJECTION CKCamera::GetProjectionType() const { + return CK_CAMERA_PROJECTION(); + } + void CKCamera::SetProjectionType(CK_CAMERA_PROJECTION proj) {} + + CKFLOAT CKCamera::GetOrthographicZoom() const { + return CKFLOAT(); + } + void CKCamera::SetOrthographicZoom(CKFLOAT zoom) {} + + CKFLOAT CKCamera::GetFrontPlane() const { + return CKFLOAT(); + } + CKFLOAT CKCamera::GetBackPlane() const { + return CKFLOAT(); + } + CKFLOAT CKCamera::GetFov() const { + return CKFLOAT(); + } + void CKCamera::SetFrontPlane(CKFLOAT front) {} + void CKCamera::SetBackPlane(CKFLOAT back) {} + void CKCamera::SetFov(CKFLOAT fov) {} + + void CKCamera::GetAspectRatio(int& width, int& height) const {} + void CKCamera::SetAspectRatio(int width, int height) {} + + void CKCamera::ComputeProjectionMatrix(VxMath::VxMatrix& mat) const {} + + void CKCamera::ResetRoll() {} + void CKCamera::Roll(CKFLOAT angle) {} + + CK3dEntity* CKCamera::GetTarget() const { + return nullptr; + } + void CKCamera::SetTarget(CK3dEntity* target) {} + +#pragma endregion + + } diff --git a/LibCmo/CK2/ObjImpls/CKLight.cpp b/LibCmo/CK2/ObjImpls/CKLight.cpp index 5054138..7dd3e83 100644 --- a/LibCmo/CK2/ObjImpls/CKLight.cpp +++ b/LibCmo/CK2/ObjImpls/CKLight.cpp @@ -131,7 +131,6 @@ namespace LibCmo::CK2::ObjImpls { VxMath::VXLIGHT_TYPE CKLight::GetType() const { return m_LightData.m_Type; } - void CKLight::SetType(VxMath::VXLIGHT_TYPE light_type) { m_LightData.m_Type = light_type; } @@ -139,7 +138,6 @@ namespace LibCmo::CK2::ObjImpls { const VxMath::VxColor& CKLight::GetColor() const { return m_LightData.m_Diffuse; } - void CKLight::SetColor(const VxMath::VxColor& c) { m_LightData.m_Diffuse = c; } @@ -147,23 +145,18 @@ namespace LibCmo::CK2::ObjImpls { CKFLOAT CKLight::GetConstantAttenuation() const { return m_LightData.m_Attenuation0; } - CKFLOAT CKLight::GetLinearAttenuation() const { return m_LightData.m_Attenuation1; } - CKFLOAT CKLight::GetQuadraticAttenuation() const { return m_LightData.m_Attenuation2; } - void CKLight::SetConstantAttenuation(CKFLOAT value) { m_LightData.m_Attenuation0 = value; } - void CKLight::SetLinearAttenuation(CKFLOAT value) { m_LightData.m_Attenuation1 = value; } - void CKLight::SetQuadraticAttenuation(CKFLOAT value) { m_LightData.m_Attenuation2 = value; } @@ -171,7 +164,6 @@ namespace LibCmo::CK2::ObjImpls { CKFLOAT CKLight::GetRange() const { return m_LightData.m_Range; } - void CKLight::SetRange(CKFLOAT value) { m_LightData.m_Range = value; } @@ -179,23 +171,18 @@ namespace LibCmo::CK2::ObjImpls { CKFLOAT CKLight::GetHotSpot() const { return m_LightData.m_InnerSpotCone; } - CKFLOAT CKLight::GetFalloff() const { return m_LightData.m_OuterSpotCone; } - CKFLOAT CKLight::GetFalloffShape() const { return m_LightData.m_Falloff; } - void CKLight::SetHotSpot(CKFLOAT value) { m_LightData.m_InnerSpotCone = value; } - void CKLight::SetFalloff(CKFLOAT value) { m_LightData.m_OuterSpotCone = value; } - void CKLight::SetFalloffShape(CKFLOAT value) { m_LightData.m_Falloff = value; } @@ -203,7 +190,6 @@ namespace LibCmo::CK2::ObjImpls { bool CKLight::GetActivity() const { return YYCC::EnumHelper::Has(m_LightFlags, LightFlags::Active); } - void CKLight::Active(bool active) { if (active) { YYCC::EnumHelper::Add(m_LightFlags, LightFlags::Active); @@ -215,7 +201,6 @@ namespace LibCmo::CK2::ObjImpls { bool CKLight::GetSpecularFlag() const { return YYCC::EnumHelper::Has(m_LightFlags, LightFlags::Specular); } - void CKLight::SetSpecularFlag(bool specular) { if (specular) { YYCC::EnumHelper::Add(m_LightFlags, LightFlags::Specular); @@ -229,7 +214,6 @@ namespace LibCmo::CK2::ObjImpls { // So it always return nullptr. return nullptr; } - void CKLight::SetTarget(CK3dEntity* target) { // Normal light do not support target. // So, do nothing. @@ -238,7 +222,6 @@ namespace LibCmo::CK2::ObjImpls { CKFLOAT CKLight::GetLightPower() const { return m_LightPower; } - void CKLight::SetLightPower(CKFLOAT power) { m_LightPower = power; } diff --git a/LibCmo/CK2/ObjImpls/CKMesh.cpp b/LibCmo/CK2/ObjImpls/CKMesh.cpp index 08481be..f589608 100644 --- a/LibCmo/CK2/ObjImpls/CKMesh.cpp +++ b/LibCmo/CK2/ObjImpls/CKMesh.cpp @@ -573,7 +573,7 @@ namespace LibCmo::CK2::ObjImpls { // get diff by distance VxMath::VxVector3 diff = m_VertexNormal[vid] - generated[vid]; // abs the diff and add into accumulated diff - VxMath::NSVxVector::Abs(diff); + VxMath::NSVxVector::Absolute(diff); accnml += diff; } diff --git a/LibCmo/CMakeLists.txt b/LibCmo/CMakeLists.txt index 9d32080..7a65020 100644 --- a/LibCmo/CMakeLists.txt +++ b/LibCmo/CMakeLists.txt @@ -36,6 +36,7 @@ PRIVATE CK2/ObjImpls/CKTargetCamera.cpp # VxMath VxMath/VxMemoryMappedFile.cpp + VxMath/VxTypes.cpp VxMath/VxMath.cpp # X Container XContainer/XTypes.cpp diff --git a/LibCmo/VxMath/VxMath.cpp b/LibCmo/VxMath/VxMath.cpp index c822e80..00f71b2 100644 --- a/LibCmo/VxMath/VxMath.cpp +++ b/LibCmo/VxMath/VxMath.cpp @@ -134,39 +134,4 @@ namespace LibCmo::VxMath { #pragma endregion -#pragma region Patched - - namespace NSVxVector { - - float DotProduct(const VxVector2& lhs, const VxVector2& rhs) { - return lhs * rhs; - } - - float DotProduct(const VxVector3& lhs, const VxVector3& rhs) { - return lhs * rhs; - } - - float DotProduct(const VxVector4& lhs, const VxVector4& rhs) { - return lhs * rhs; - } - - VxVector3 CrossProduct(const VxVector3& lhs, const VxVector3& rhs) { - return VxVector3( - lhs.y * rhs.z - lhs.z * rhs.y, - lhs.z * rhs.x - lhs.x * rhs.z, - lhs.x * rhs.y - lhs.y * rhs.x - ); - } - - void Abs(VxVector3& lhs) { - lhs.x = std::fabs(lhs.x); - lhs.y = std::fabs(lhs.y); - lhs.z = std::fabs(lhs.z); - } - - } - -#pragma endregion - - } diff --git a/LibCmo/VxMath/VxMath.hpp b/LibCmo/VxMath/VxMath.hpp index 5a3de26..75d90cb 100644 --- a/LibCmo/VxMath/VxMath.hpp +++ b/LibCmo/VxMath/VxMath.hpp @@ -95,56 +95,5 @@ namespace LibCmo::VxMath { */ void VxDoAlphaBlit(VxImageDescEx* dst_desc, const CKBYTE* AlphaValues); - - // ========== Patch Section ========== - - /** - * @brief The patch namespace for VxVector-like classes - * @details This namespace provides VxVector-like classes member functions which presented in original Virtools SDK. - * These functions are put in public namespace in original Virtools SDK. - * We just organise them into an unique namespace. - */ - namespace NSVxVector { - - /** - * @brief Dot product 2 2d vectors. - * @param[in] lhs The left side vector of dot product symbol. - * @param[in] rhs The right side vector of dot product symbol. - * @return The float pointing result of dot product. - */ - CKFLOAT DotProduct(const VxVector2& lhs, const VxVector2& rhs); - /** - * @brief Dot product 2 3d vectors. - * @param[in] lhs The left side vector of dot product symbol. - * @param[in] rhs The right side vector of dot product symbol. - * @return The float pointing result of dot product. - */ - CKFLOAT DotProduct(const VxVector3& lhs, const VxVector3& rhs); - /** - * @brief Dot product 2 4d vectors. - * @param[in] lhs The left side vector of dot product symbol. - * @param[in] rhs The right side vector of dot product symbol. - * @return The float pointing result of dot product. - */ - CKFLOAT DotProduct(const VxVector4& lhs, const VxVector4& rhs); - - /** - * @brief Cross product 2 3d vectors. - * @param[in] lhs The left side vector of cross product symbol. - * @param[in] rhs The right side vector of cross product symbol. - * @return The 3d vector result of cross product. - */ - VxVector3 CrossProduct(const VxVector3& lhs, const VxVector3& rhs); - - /** - * @brief Set all factor in vector to its absolute value. - * @param[in,out] lhs The vector for processing. - * @remarks This function is rarely used. - * Please note this function is not calculate the absolute value of vector. - */ - void Abs(VxVector3& lhs); - - } - } diff --git a/LibCmo/VxMath/VxTypes.cpp b/LibCmo/VxMath/VxTypes.cpp new file mode 100644 index 0000000..38a487a --- /dev/null +++ b/LibCmo/VxMath/VxTypes.cpp @@ -0,0 +1,529 @@ +#include "VxTypes.hpp" +#include + +namespace LibCmo::VxMath { + +#pragma region VxVector2 + + VxVector2::VxVector2() :x(0.0f), y(0.0f) {} + VxVector2::VxVector2(CKFLOAT _x, CKFLOAT _y) : x(_x), y(_y) {} + CKFLOAT& VxVector2::operator[](size_t i) { + switch (i) { + case 0: return x; + case 1: return y; + default: throw LogicException("Invalid index for VxVector2::operator[]."); + } + } + const CKFLOAT& VxVector2::operator[](size_t i) const { + switch (i) { + case 0: return x; + case 1: return y; + default: throw LogicException("Invalid index for VxVector2::operator[]."); + } + } + bool VxVector2::operator==(const VxVector2& rhs) const { + return (x == rhs.x && y == rhs.y); + } + auto VxVector2::operator<=>(const VxVector2& rhs) const { + if (auto cmp = x <=> rhs.x; cmp != 0) return cmp; + return y <=> rhs.y; + } + VxVector2 VxVector2::operator+() const { + return *this; + } + VxVector2 VxVector2::operator-() const { + return VxVector2(-x, -y); + } + VxVector2& VxVector2::operator+=(const VxVector2& rhs) { + x += rhs.x; + y += rhs.y; + return *this; + } + VxVector2 operator+(const VxVector2& lhs, const VxVector2& rhs) { + return VxVector2(lhs.x + rhs.x, lhs.y + rhs.y); + } + VxVector2& VxVector2::operator-=(const VxVector2& rhs) { + x -= rhs.x; + y -= rhs.y; + return *this; + } + VxVector2 operator-(const VxVector2& lhs, const VxVector2& rhs) { + return VxVector2(lhs.x - rhs.x, lhs.y - rhs.y); + } + VxVector2& VxVector2::operator*=(CKFLOAT rhs) { + x *= rhs; + y *= rhs; + return *this; + } + VxVector2 operator*(const VxVector2& lhs, CKFLOAT rhs) { + return VxVector2(lhs.x * rhs, lhs.y * rhs); + } + VxVector2 operator*(CKFLOAT lhs, const VxVector2& rhs) { + return VxVector2(lhs * rhs.x, lhs * rhs.y); + } + CKFLOAT operator*(const VxVector2& lhs, const VxVector2& rhs) { + return (lhs.x * rhs.x + lhs.y * rhs.y); + } + VxVector2& VxVector2::operator/=(CKFLOAT rhs) { + if (rhs == 0.0f) return *this; + x /= rhs; + y /= rhs; + return *this; + } + VxVector2 operator/(const VxVector2& lhs, CKFLOAT rhs) { + if (rhs == 0.0f) return VxVector2(); + else return VxVector2(lhs.x / rhs, lhs.y / rhs); + } + CKFLOAT VxVector2::SquaredLength() const { + return (x * x + y * y); + } + CKFLOAT VxVector2::Length() const { + return std::sqrt(SquaredLength()); + } + void VxVector2::Normalized() { + CKFLOAT len = Length(); + if (len == 0.0f) return; + x /= len; + y /= len; + } + VxVector2 VxVector2::Normalize() const { + CKFLOAT len = Length(); + if (len == 0.0f) return VxVector2(); + else return VxVector2(x / len, y / len); + } + + /* ===== BEGIN USER CUSTOM ===== */ + /* ===== END USER CUSTOM ===== */ + +#pragma endregion + +#pragma region VxVector3 + + VxVector3::VxVector3() :x(0.0f), y(0.0f), z(0.0f) {} + VxVector3::VxVector3(CKFLOAT _x, CKFLOAT _y, CKFLOAT _z) : x(_x), y(_y), z(_z) {} + CKFLOAT& VxVector3::operator[](size_t i) { + switch (i) { + case 0: return x; + case 1: return y; + case 2: return z; + default: throw LogicException("Invalid index for VxVector3::operator[]."); + } + } + const CKFLOAT& VxVector3::operator[](size_t i) const { + switch (i) { + case 0: return x; + case 1: return y; + case 2: return z; + default: throw LogicException("Invalid index for VxVector3::operator[]."); + } + } + bool VxVector3::operator==(const VxVector3& rhs) const { + return (x == rhs.x && y == rhs.y && z == rhs.z); + } + auto VxVector3::operator<=>(const VxVector3& rhs) const { + if (auto cmp = x <=> rhs.x; cmp != 0) return cmp; + if (auto cmp = y <=> rhs.y; cmp != 0) return cmp; + return z <=> rhs.z; + } + VxVector3 VxVector3::operator+() const { + return *this; + } + VxVector3 VxVector3::operator-() const { + return VxVector3(-x, -y, -z); + } + VxVector3& VxVector3::operator+=(const VxVector3& rhs) { + x += rhs.x; + y += rhs.y; + z += rhs.z; + return *this; + } + VxVector3 operator+(const VxVector3& lhs, const VxVector3& rhs) { + return VxVector3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); + } + VxVector3& VxVector3::operator-=(const VxVector3& rhs) { + x -= rhs.x; + y -= rhs.y; + z -= rhs.z; + return *this; + } + VxVector3 operator-(const VxVector3& lhs, const VxVector3& rhs) { + return VxVector3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); + } + VxVector3& VxVector3::operator*=(CKFLOAT rhs) { + x *= rhs; + y *= rhs; + z *= rhs; + return *this; + } + VxVector3 operator*(const VxVector3& lhs, CKFLOAT rhs) { + return VxVector3(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); + } + VxVector3 operator*(CKFLOAT lhs, const VxVector3& rhs) { + return VxVector3(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z); + } + CKFLOAT operator*(const VxVector3& lhs, const VxVector3& rhs) { + return (lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z); + } + VxVector3& VxVector3::operator/=(CKFLOAT rhs) { + if (rhs == 0.0f) return *this; + x /= rhs; + y /= rhs; + z /= rhs; + return *this; + } + VxVector3 operator/(const VxVector3& lhs, CKFLOAT rhs) { + if (rhs == 0.0f) return VxVector3(); + else return VxVector3(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); + } + CKFLOAT VxVector3::SquaredLength() const { + return (x * x + y * y + z * z); + } + CKFLOAT VxVector3::Length() const { + return std::sqrt(SquaredLength()); + } + void VxVector3::Normalized() { + CKFLOAT len = Length(); + if (len == 0.0f) return; + x /= len; + y /= len; + z /= len; + } + VxVector3 VxVector3::Normalize() const { + CKFLOAT len = Length(); + if (len == 0.0f) return VxVector3(); + else return VxVector3(x / len, y / len, z / len); + } + + /* ===== BEGIN USER CUSTOM ===== */ + /* ===== END USER CUSTOM ===== */ + +#pragma endregion + +#pragma region VxVector4 + + VxVector4::VxVector4() :x(0.0f), y(0.0f), z(0.0f), w(0.0f) {} + VxVector4::VxVector4(CKFLOAT _x, CKFLOAT _y, CKFLOAT _z, CKFLOAT _w) : x(_x), y(_y), z(_z), w(_w) {} + CKFLOAT& VxVector4::operator[](size_t i) { + switch (i) { + case 0: return x; + case 1: return y; + case 2: return z; + case 3: return w; + default: throw LogicException("Invalid index for VxVector4::operator[]."); + } + } + const CKFLOAT& VxVector4::operator[](size_t i) const { + switch (i) { + case 0: return x; + case 1: return y; + case 2: return z; + case 3: return w; + default: throw LogicException("Invalid index for VxVector4::operator[]."); + } + } + bool VxVector4::operator==(const VxVector4& rhs) const { + return (x == rhs.x && y == rhs.y && z == rhs.z && w == rhs.w); + } + auto VxVector4::operator<=>(const VxVector4& rhs) const { + if (auto cmp = x <=> rhs.x; cmp != 0) return cmp; + if (auto cmp = y <=> rhs.y; cmp != 0) return cmp; + if (auto cmp = z <=> rhs.z; cmp != 0) return cmp; + return w <=> rhs.w; + } + VxVector4 VxVector4::operator+() const { + return *this; + } + VxVector4 VxVector4::operator-() const { + return VxVector4(-x, -y, -z, -w); + } + VxVector4& VxVector4::operator+=(const VxVector4& rhs) { + x += rhs.x; + y += rhs.y; + z += rhs.z; + w += rhs.w; + return *this; + } + VxVector4 operator+(const VxVector4& lhs, const VxVector4& rhs) { + return VxVector4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); + } + VxVector4& VxVector4::operator-=(const VxVector4& rhs) { + x -= rhs.x; + y -= rhs.y; + z -= rhs.z; + w -= rhs.w; + return *this; + } + VxVector4 operator-(const VxVector4& lhs, const VxVector4& rhs) { + return VxVector4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); + } + VxVector4& VxVector4::operator*=(CKFLOAT rhs) { + x *= rhs; + y *= rhs; + z *= rhs; + w *= rhs; + return *this; + } + VxVector4 operator*(const VxVector4& lhs, CKFLOAT rhs) { + return VxVector4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); + } + VxVector4 operator*(CKFLOAT lhs, const VxVector4& rhs) { + return VxVector4(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z, lhs * rhs.w); + } + CKFLOAT operator*(const VxVector4& lhs, const VxVector4& rhs) { + return (lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z + lhs.w * rhs.w); + } + VxVector4& VxVector4::operator/=(CKFLOAT rhs) { + if (rhs == 0.0f) return *this; + x /= rhs; + y /= rhs; + z /= rhs; + w /= rhs; + return *this; + } + VxVector4 operator/(const VxVector4& lhs, CKFLOAT rhs) { + if (rhs == 0.0f) return VxVector4(); + else return VxVector4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); + } + CKFLOAT VxVector4::SquaredLength() const { + return (x * x + y * y + z * z + w * w); + } + CKFLOAT VxVector4::Length() const { + return std::sqrt(SquaredLength()); + } + void VxVector4::Normalized() { + CKFLOAT len = Length(); + if (len == 0.0f) return; + x /= len; + y /= len; + z /= len; + w /= len; + } + VxVector4 VxVector4::Normalize() const { + CKFLOAT len = Length(); + if (len == 0.0f) return VxVector4(); + else return VxVector4(x / len, y / len, z / len, w / len); + } + + /* ===== BEGIN USER CUSTOM ===== */ + /* ===== END USER CUSTOM ===== */ + +#pragma endregion + +#pragma region VxQuaternion + + VxQuaternion::VxQuaternion() :x(0.0f), y(0.0f), z(0.0f), w(1.0f) {} // SET YOUR CUSTOM INIT + VxQuaternion::VxQuaternion(CKFLOAT _x, CKFLOAT _y, CKFLOAT _z, CKFLOAT _w) : x(_x), y(_y), z(_z), w(_w) {} + CKFLOAT& VxQuaternion::operator[](size_t i) { + switch (i) { + case 0: return x; + case 1: return y; + case 2: return z; + case 3: return w; + default: throw LogicException("Invalid index for VxQuaternion::operator[]."); + } + } + const CKFLOAT& VxQuaternion::operator[](size_t i) const { + switch (i) { + case 0: return x; + case 1: return y; + case 2: return z; + case 3: return w; + default: throw LogicException("Invalid index for VxQuaternion::operator[]."); + } + } + bool VxQuaternion::operator==(const VxQuaternion& rhs) const { + return (x == rhs.x && y == rhs.y && z == rhs.z && w == rhs.w); + } + auto VxQuaternion::operator<=>(const VxQuaternion& rhs) const { + if (auto cmp = x <=> rhs.x; cmp != 0) return cmp; + if (auto cmp = y <=> rhs.y; cmp != 0) return cmp; + if (auto cmp = z <=> rhs.z; cmp != 0) return cmp; + return w <=> rhs.w; + } + + /* ===== BEGIN USER CUSTOM ===== */ + /* ===== END USER CUSTOM ===== */ + +#pragma endregion + +#pragma region VxColor + + VxColor::VxColor() :r(0.0f), g(0.0f), b(0.0f), a(1.0f) {} // SET YOUR CUSTOM INIT + VxColor::VxColor(CKFLOAT _r, CKFLOAT _g, CKFLOAT _b, CKFLOAT _a) : r(_r), g(_g), b(_b), a(_a) {} + CKFLOAT& VxColor::operator[](size_t i) { + switch (i) { + case 0: return r; + case 1: return g; + case 2: return b; + case 3: return a; + default: throw LogicException("Invalid index for VxColor::operator[]."); + } + } + const CKFLOAT& VxColor::operator[](size_t i) const { + switch (i) { + case 0: return r; + case 1: return g; + case 2: return b; + case 3: return a; + default: throw LogicException("Invalid index for VxColor::operator[]."); + } + } + bool VxColor::operator==(const VxColor& rhs) const { + return (r == rhs.r && g == rhs.g && b == rhs.b && a == rhs.a); + } + auto VxColor::operator<=>(const VxColor& rhs) const { + if (auto cmp = r <=> rhs.r; cmp != 0) return cmp; + if (auto cmp = g <=> rhs.g; cmp != 0) return cmp; + if (auto cmp = b <=> rhs.b; cmp != 0) return cmp; + return a <=> rhs.a; + } + + /* ===== BEGIN USER CUSTOM ===== */ + VxColor::VxColor(CKDWORD argb) { FromARGB(argb); } + VxColor::VxColor(CKFLOAT _r, CKFLOAT _g, CKFLOAT _b) : r(_r), g(_g), b(_b), a(1.0f) {} + void VxColor::FromARGB(CKDWORD argb) { + a = ((argb & 0xFF000000) >> 24) / 255.0f; + r = ((argb & 0x00FF0000) >> 16) / 255.0f; + g = ((argb & 0x0000FF00) >> 8) / 255.0f; + b = ((argb & 0x000000FF) >> 0) / 255.0f; + } + CKDWORD VxColor::ToARGB() const { + CKDWORD argb = 0; + argb |= static_cast(a * 255.0f); + argb <<= 8; + argb |= static_cast(r * 255.0f); + argb <<= 8; + argb |= static_cast(g * 255.0f); + argb <<= 8; + argb |= static_cast(b * 255.0f); + return argb; + } + void VxColor::Regulate() { + if (r > 1.0f) r = 1.0f; + else if (r < 0.0f) r = 0.0f; + if (g > 1.0f) g = 1.0f; + else if (g < 0.0f) g = 0.0f; + if (b > 1.0f) b = 1.0f; + else if (b < 0.0f) b = 0.0f; + if (a > 1.0f) a = 1.0f; + else if (a < 0.0f) a = 0.0f; + } + /* ===== END USER CUSTOM ===== */ + +#pragma endregion + +#pragma region VxMatrix + + VxMatrix::VxMatrix() : m_Data() { SetIdentity(); } + VxMatrix::VxMatrix(CKFLOAT m[4][4]) : m_Data() { std::memcpy(m_Data, m, sizeof(m_Data)); } + VxVector4& VxMatrix::operator[](size_t i) { + if (i >= 4) throw LogicException("Invalid index for VxMatrix::operator[]."); + return *(reinterpret_cast(m_Data) + i); + } + const VxVector4& VxMatrix::operator[](size_t i) const { + if (i >= 4) throw LogicException("Invalid index for VxMatrix::operator[]."); + return *(reinterpret_cast(m_Data) + i); + } + bool VxMatrix::operator==(const VxMatrix& rhs) const { + return ((*this)[0] == rhs[0] && (*this)[1] == rhs[1] && (*this)[2] == rhs[2] && (*this)[3] == rhs[3]); + } + auto VxMatrix::operator<=>(const VxMatrix& rhs) const { + if (auto cmp = (*this)[0] <=> rhs[0]; cmp != 0) return cmp; + if (auto cmp = (*this)[1] <=> rhs[1]; cmp != 0) return cmp; + if (auto cmp = (*this)[2] <=> rhs[2]; cmp != 0) return cmp; + return (*this)[3] <=> rhs[3]; + } + + /* ===== BEGIN USER CUSTOM ===== */ + void VxMatrix::Clear() { + std::memset(m_Data, 0, sizeof(m_Data)); + } + void VxMatrix::SetIdentity() { + Clear(); + m_Data[0][0] = m_Data[1][1] = m_Data[2][2] = m_Data[3][3] = 1.0f; + } + void VxMatrix::Perspective(float Fov, float Aspect, float Near_plane, float Far_plane) { + Clear(); + m_Data[0][0] = std::cosf(Fov * 0.5f) / std::sinf(Fov * 0.5f); + m_Data[1][1] = m_Data[0][0] * Aspect; + m_Data[2][2] = Far_plane / (Far_plane - Near_plane); + m_Data[3][2] = -m_Data[2][2] * Near_plane; + m_Data[2][3] = 1; + } + void VxMatrix::PerspectiveRect(float Left, float Right, float Top, float Bottom, float Near_plane, float Far_plane) { + Clear(); + float RL = 1.0f / (Right - Left); + float TB = 1.0f / (Top - Bottom); + m_Data[0][0] = 2.0f * Near_plane * RL; + m_Data[1][1] = 2.0f * Near_plane * TB; + m_Data[2][0] = -(Right + Left) * RL; + m_Data[2][1] = -(Top + Bottom) * TB; + m_Data[2][2] = Far_plane / (Far_plane - Near_plane); + m_Data[3][2] = -m_Data[2][2] * Near_plane; + m_Data[2][3] = 1; + } + void VxMatrix::Orthographic(float Zoom, float Aspect, float Near_plane, float Far_plane) { + Clear(); + float iz = 1.0f / (Far_plane - Near_plane); + m_Data[0][0] = Zoom; + m_Data[1][1] = Zoom * Aspect; + m_Data[2][2] = iz; + m_Data[3][2] = -Near_plane * iz; + m_Data[3][3] = 1.0f; + } + void VxMatrix::OrthographicRect(float Left, float Right, float Top, float Bottom, float Near_plane, float Far_plane) { + Clear(); + float ix = 1.0f / (Right - Left); + float iy = 1.0f / (Top - Bottom); + float iz = 1.0f / (Far_plane - Near_plane); + m_Data[0][0] = 2.0f * ix; + m_Data[1][1] = -2.0f * iy; + m_Data[2][2] = iz; + m_Data[3][0] = -(Left + Right) * ix; + m_Data[3][1] = (Top + Bottom) * iy; + m_Data[3][2] = -Near_plane * iz; + m_Data[3][3] = 1.0f; + } + /* ===== END USER CUSTOM ===== */ + +#pragma endregion + +#pragma region Patched + + namespace NSVxVector { + + float DotProduct(const VxVector2& lhs, const VxVector2& rhs) { + return lhs * rhs; + } + + float DotProduct(const VxVector3& lhs, const VxVector3& rhs) { + return lhs * rhs; + } + + float DotProduct(const VxVector4& lhs, const VxVector4& rhs) { + return lhs * rhs; + } + + VxVector3 CrossProduct(const VxVector3& lhs, const VxVector3& rhs) { + return VxVector3( + lhs.y * rhs.z - lhs.z * rhs.y, + lhs.z * rhs.x - lhs.x * rhs.z, + lhs.x * rhs.y - lhs.y * rhs.x + ); + } + + void Absolute(VxVector3& lhs) { + lhs.x = std::fabs(lhs.x); + lhs.y = std::fabs(lhs.y); + lhs.z = std::fabs(lhs.z); + } + + } + + namespace NSVxMatrix { + + } + +#pragma endregion + +} diff --git a/LibCmo/VxMath/VxTypes.hpp b/LibCmo/VxMath/VxTypes.hpp index 7eade8f..3ba142f 100644 --- a/LibCmo/VxMath/VxTypes.hpp +++ b/LibCmo/VxMath/VxTypes.hpp @@ -7,7 +7,6 @@ #include #include #include -#include /** * @brief The VxMath part of LibCmo. @@ -23,191 +22,75 @@ namespace LibCmo::VxMath { class VxMemoryMappedFile; - // Misc + // ========== Vector-like Definition ========== /** * @brief The representation of a Vector in 2 dimensions. + * @remarks In original Virtools SDK, it was named Vx2DVector. * @see VxVector3 */ struct VxVector2 { CKFLOAT x, y; - VxVector2() : x(0.0f), y(0.0f) {} - VxVector2(CKFLOAT _x, CKFLOAT _y) : x(_x), y(_y) {} + VxVector2(); + VxVector2(CKFLOAT _x, CKFLOAT _y); YYCC_DEF_CLS_COPY_MOVE(VxVector2); - CKFLOAT& operator[](size_t i) { - switch (i) { - case 0: return x; - case 1: return y; - default: throw LogicException("Invalid index for VxVector2::operator[]."); - } - } - const CKFLOAT& operator[](size_t i) const { - switch (i) { - case 0: return x; - case 1: return y; - default: throw LogicException("Invalid index for VxVector2::operator[]."); - } - } - VxVector2& operator+=(const VxVector2& rhs) { - x += rhs.x; - y += rhs.y; - return *this; - } - friend VxVector2 operator+(const VxVector2& lhs, const VxVector2& rhs) { - return VxVector2(lhs.x + rhs.x, lhs.y + rhs.y); - } - VxVector2& operator-=(const VxVector2& rhs) { - x -= rhs.x; - y -= rhs.y; - return *this; - } - friend VxVector2 operator-(const VxVector2& lhs, const VxVector2& rhs) { - return VxVector2(lhs.x - rhs.x, lhs.y - rhs.y); - } - VxVector2& operator*=(CKFLOAT rhs) { - x *= rhs; - y *= rhs; - return *this; - } - friend VxVector2 operator*(const VxVector2& lhs, CKFLOAT rhs) { - return VxVector2(lhs.x * rhs, lhs.y * rhs); - } - friend VxVector2 operator*(CKFLOAT lhs, const VxVector2& rhs) { - return VxVector2(lhs * rhs.x, lhs * rhs.y); - } - friend CKFLOAT operator*(const VxVector2& lhs, const VxVector2& rhs) { - return (lhs.x * rhs.x + lhs.y * rhs.y); - } - VxVector2& operator/=(CKFLOAT rhs) { - if (rhs == 0.0f) return *this; - x /= rhs; - y /= rhs; - return *this; - } - friend VxVector2 operator/(const VxVector2& lhs, CKFLOAT rhs) { - if (rhs == 0.0f) return VxVector2(0.0f, 0.0f); - return VxVector2(lhs.x / rhs, lhs.y / rhs); - } - bool operator==(const VxVector2& rhs) const { - return (x == rhs.x && y == rhs.y); - } - auto operator<=>(const VxVector2& rhs) const { - if (auto cmp = x <=> rhs.x; cmp != 0) return cmp; - return y <=> rhs.y; - } - CKFLOAT SquaredLength() const { - return (x * x + y * y); - } - CKFLOAT Length() const { - return std::sqrt(SquaredLength()); - } - void Normalized() { - CKFLOAT len = Length(); - if (len == 0.0f) return; - x /= len; - y /= len; - } - VxVector2 Normalize() const { - CKFLOAT len = Length(); - if (len == 0.0f) return VxVector2(); - return VxVector2(x / len, y / len); - } + CKFLOAT& operator[](size_t i); + const CKFLOAT& operator[](size_t i) const; + bool operator==(const VxVector2& rhs) const; + auto operator<=>(const VxVector2& rhs) const; + VxVector2 operator+() const; + VxVector2 operator-() const; + VxVector2& operator+=(const VxVector2& rhs); + friend VxVector2 operator+(const VxVector2& lhs, const VxVector2& rhs); + VxVector2& operator-=(const VxVector2& rhs); + friend VxVector2 operator-(const VxVector2& lhs, const VxVector2& rhs); + VxVector2& operator*=(CKFLOAT rhs); + friend VxVector2 operator*(const VxVector2& lhs, CKFLOAT rhs); + friend VxVector2 operator*(CKFLOAT lhs, const VxVector2& rhs); + friend CKFLOAT operator*(const VxVector2& lhs, const VxVector2& rhs); + VxVector2& operator/=(CKFLOAT rhs); + friend VxVector2 operator/(const VxVector2& lhs, CKFLOAT rhs); + CKFLOAT SquaredLength() const; + CKFLOAT Length() const; + void Normalized(); + VxVector2 Normalize() const; + + /* ===== BEGIN USER CUSTOM ===== */ + /* ===== END USER CUSTOM ===== */ }; /** * @brief The representation of a Vector in 3 dimensions + * @remarks In original Virtools SDK, it was named VxVector. */ struct VxVector3 { CKFLOAT x, y, z; - VxVector3() : x(0.0f), y(0.0f), z(0.0f) {} - VxVector3(CKFLOAT _x, CKFLOAT _y, CKFLOAT _z) : x(_x), y(_y), z(_z) {} + VxVector3(); + VxVector3(CKFLOAT _x, CKFLOAT _y, CKFLOAT _z); YYCC_DEF_CLS_COPY_MOVE(VxVector3); - CKFLOAT& operator[](size_t i) { - switch (i) { - case 0: return x; - case 1: return y; - case 2: return z; - default: throw LogicException("Invalid index for VxVector3::operator[]."); - } - } - const CKFLOAT& operator[](size_t i) const { - switch (i) { - case 0: return x; - case 1: return y; - case 2: return z; - default: throw LogicException("Invalid index for VxVector3::operator[]."); - } - } - VxVector3& operator+=(const VxVector3& rhs) { - x += rhs.x; - y += rhs.y; - z += rhs.z; - return *this; - } - friend VxVector3 operator+(const VxVector3& lhs, const VxVector3& rhs) { - return VxVector3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); - } - VxVector3& operator-=(const VxVector3& rhs) { - x -= rhs.x; - y -= rhs.y; - z -= rhs.z; - return *this; - } - friend VxVector3 operator-(const VxVector3& lhs, const VxVector3& rhs) { - return VxVector3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); - } - VxVector3& operator*=(CKFLOAT rhs) { - x *= rhs; - y *= rhs; - z *= rhs; - return *this; - } - friend VxVector3 operator*(const VxVector3& lhs, CKFLOAT rhs) { - return VxVector3(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); - } - friend VxVector3 operator*(CKFLOAT lhs, const VxVector3& rhs) { - return VxVector3(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z); - } - friend CKFLOAT operator*(const VxVector3& lhs, const VxVector3& rhs) { - return (lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z); - } - VxVector3& operator/=(CKFLOAT rhs) { - if (rhs == 0.0f) return *this; - x /= rhs; - y /= rhs; - z /= rhs; - return *this; - } - friend VxVector3 operator/(const VxVector3& lhs, CKFLOAT rhs) { - if (rhs == 0.0f) return VxVector3(0.0f, 0.0f, 0.0f); - return VxVector3(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); - } - bool operator==(const VxVector3& rhs) const { - return (x == rhs.x && y == rhs.y && z == rhs.z); - } - auto operator<=>(const VxVector3& rhs) const { - if (auto cmp = x <=> rhs.x; cmp != 0) return cmp; - if (auto cmp = y <=> rhs.y; cmp != 0) return cmp; - return z <=> rhs.z; - } - CKFLOAT SquaredLength() const { - return (x * x + y * y + z * z); - } - CKFLOAT Length() const { - return std::sqrt(SquaredLength()); - } - void Normalized() { - CKFLOAT len = Length(); - if (len == 0.0f) return; - x /= len; - y /= len; - z /= len; - } - VxVector3 Normalize() const { - CKFLOAT len = Length(); - if (len == 0.0f) return VxVector3(); - return VxVector3(x / len, y / len, z / len); - } + CKFLOAT& operator[](size_t i); + const CKFLOAT& operator[](size_t i) const; + bool operator==(const VxVector3& rhs) const; + auto operator<=>(const VxVector3& rhs) const; + VxVector3 operator+() const; + VxVector3 operator-() const; + VxVector3& operator+=(const VxVector3& rhs); + friend VxVector3 operator+(const VxVector3& lhs, const VxVector3& rhs); + VxVector3& operator-=(const VxVector3& rhs); + friend VxVector3 operator-(const VxVector3& lhs, const VxVector3& rhs); + VxVector3& operator*=(CKFLOAT rhs); + friend VxVector3 operator*(const VxVector3& lhs, CKFLOAT rhs); + friend VxVector3 operator*(CKFLOAT lhs, const VxVector3& rhs); + friend CKFLOAT operator*(const VxVector3& lhs, const VxVector3& rhs); + VxVector3& operator/=(CKFLOAT rhs); + friend VxVector3 operator/(const VxVector3& lhs, CKFLOAT rhs); + CKFLOAT SquaredLength() const; + CKFLOAT Length() const; + void Normalized(); + VxVector3 Normalize() const; + + /* ===== BEGIN USER CUSTOM ===== */ + /* ===== END USER CUSTOM ===== */ }; /** @@ -215,107 +98,37 @@ namespace LibCmo::VxMath { * @details * VxVector4 is used for 3D transformation when the w component is used for perspective information. * Most of the methods available for a VxVector3 are also implemented for the VxVector4. + * @remarks In original Virtools SDK, it was named VxVector4. Not changed. * @see VxVector3 */ struct VxVector4 { CKFLOAT x, y, z, w; - VxVector4() : x(0.0f), y(0.0f), z(0.0f), w(0.0f) {} - VxVector4(CKFLOAT _x, CKFLOAT _y, CKFLOAT _z, CKFLOAT _w) : x(_x), y(_y), z(_z), w(_w) {} + VxVector4(); + VxVector4(CKFLOAT _x, CKFLOAT _y, CKFLOAT _z, CKFLOAT _w); YYCC_DEF_CLS_COPY_MOVE(VxVector4); - CKFLOAT& operator[](size_t i) { - switch (i) { - case 0: return x; - case 1: return y; - case 2: return z; - case 3: return w; - default: throw LogicException("Invalid index for VxVector4::operator[]."); - } - } - const CKFLOAT& operator[](size_t i) const { - switch (i) { - case 0: return x; - case 1: return y; - case 2: return z; - case 3: return w; - default: throw LogicException("Invalid index for VxVector4::operator[]."); - } - } - VxVector4& operator+=(const VxVector4& rhs) { - x += rhs.x; - y += rhs.y; - z += rhs.z; - w += rhs.w; - return *this; - } - friend VxVector4 operator+(const VxVector4& lhs, const VxVector4& rhs) { - return VxVector4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); - } - VxVector4& operator-=(const VxVector4& rhs) { - x -= rhs.x; - y -= rhs.y; - z -= rhs.z; - w -= rhs.w; - return *this; - } - friend VxVector4 operator-(const VxVector4& lhs, const VxVector4& rhs) { - return VxVector4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); - } - VxVector4& operator*=(CKFLOAT rhs) { - x *= rhs; - y *= rhs; - z *= rhs; - w *= rhs; - return *this; - } - friend VxVector4 operator*(const VxVector4& lhs, CKFLOAT rhs) { - return VxVector4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); - } - friend VxVector4 operator*(CKFLOAT lhs, const VxVector4& rhs) { - return VxVector4(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z, lhs * rhs.w); - } - friend CKFLOAT operator*(const VxVector4& lhs, const VxVector4& rhs) { - return (lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z + lhs.w * rhs.w); - } - VxVector4& operator/=(CKFLOAT rhs) { - if (rhs == 0.0f) return *this; - x /= rhs; - y /= rhs; - z /= rhs; - w /= rhs; - return *this; - } - friend VxVector4 operator/(const VxVector4& lhs, CKFLOAT rhs) { - if (rhs == 0.0f) return VxVector4(0.0f, 0.0f, 0.0f, 0.0f); - return VxVector4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); - } - bool operator==(const VxVector4& rhs) const { - return (x == rhs.x && y == rhs.y && z == rhs.z && w == rhs.w); - } - auto operator<=>(const VxVector4& rhs) const { - if (auto cmp = x <=> rhs.x; cmp != 0) return cmp; - if (auto cmp = y <=> rhs.y; cmp != 0) return cmp; - if (auto cmp = z <=> rhs.z; cmp != 0) return cmp; - return w <=> rhs.w; - } - CKFLOAT SquaredLength() const { - return (x * x + y * y + z * z + w * w); - } - CKFLOAT Length() const { - return std::sqrt(SquaredLength()); - } - void Normalized() { - CKFLOAT len = Length(); - if (len == 0.0f) return; - x /= len; - y /= len; - z /= len; - w /= len; - } - VxVector4 Normalize() const { - CKFLOAT len = Length(); - if (len == 0.0f) return VxVector4(); - return VxVector4(x / len, y / len, z / len, w / len); - } + CKFLOAT& operator[](size_t i); + const CKFLOAT& operator[](size_t i) const; + bool operator==(const VxVector4& rhs) const; + auto operator<=>(const VxVector4& rhs) const; + VxVector4 operator+() const; + VxVector4 operator-() const; + VxVector4& operator+=(const VxVector4& rhs); + friend VxVector4 operator+(const VxVector4& lhs, const VxVector4& rhs); + VxVector4& operator-=(const VxVector4& rhs); + friend VxVector4 operator-(const VxVector4& lhs, const VxVector4& rhs); + VxVector4& operator*=(CKFLOAT rhs); + friend VxVector4 operator*(const VxVector4& lhs, CKFLOAT rhs); + friend VxVector4 operator*(CKFLOAT lhs, const VxVector4& rhs); + friend CKFLOAT operator*(const VxVector4& lhs, const VxVector4& rhs); + VxVector4& operator/=(CKFLOAT rhs); + friend VxVector4 operator/(const VxVector4& lhs, CKFLOAT rhs); + CKFLOAT SquaredLength() const; + CKFLOAT Length() const; + void Normalized(); + VxVector4 Normalize() const; + + /* ===== BEGIN USER CUSTOM ===== */ + /* ===== END USER CUSTOM ===== */ }; /** @@ -323,42 +136,22 @@ namespace LibCmo::VxMath { * @details * A Quaternion is defined by 4 floats and is used to represents an orientation in space. * Its common usage is for interpolation between two orientations through the Slerp() method. - * + * * Quaternions can be converted to VxMatrix or Euler Angles. * @see VxMatrix, VxVector3 */ struct VxQuaternion { CKFLOAT x, y, z, w; - VxQuaternion() : x(0.0f), y(0.0f), z(0.0f), w(1.0f) {} // set your custom init. - VxQuaternion(CKFLOAT _x, CKFLOAT _y, CKFLOAT _z, CKFLOAT _w) : x(_x), y(_y), z(_z), w(_w) {} + VxQuaternion(); + VxQuaternion(CKFLOAT _x, CKFLOAT _y, CKFLOAT _z, CKFLOAT _w); YYCC_DEF_CLS_COPY_MOVE(VxQuaternion); - CKFLOAT& operator[](size_t i) { - switch (i) { - case 0: return x; - case 1: return y; - case 2: return z; - case 3: return w; - default: throw LogicException("Invalid index for VxQuaternion::operator[]."); - } - } - const CKFLOAT& operator[](size_t i) const { - switch (i) { - case 0: return x; - case 1: return y; - case 2: return z; - case 3: return w; - default: throw LogicException("Invalid index for VxQuaternion::operator[]."); - } - } - bool operator==(const VxQuaternion& rhs) const { - return (x == rhs.x && y == rhs.y && z == rhs.z && w == rhs.w); - } - auto operator<=>(const VxQuaternion& rhs) const { - if (auto cmp = x <=> rhs.x; cmp != 0) return cmp; - if (auto cmp = y <=> rhs.y; cmp != 0) return cmp; - if (auto cmp = z <=> rhs.z; cmp != 0) return cmp; - return w <=> rhs.w; - } + CKFLOAT& operator[](size_t i); + const CKFLOAT& operator[](size_t i) const; + bool operator==(const VxQuaternion& rhs) const; + auto operator<=>(const VxQuaternion& rhs) const; + + /* ===== BEGIN USER CUSTOM ===== */ + /* ===== END USER CUSTOM ===== */ }; /** @@ -366,71 +159,26 @@ namespace LibCmo::VxMath { * @details * Structure describing a color through 4 floats for each component Red, Green, Blue and Alpha. * And each factor should be clamped between \c 0.0f and \c 1.0f. - * + * * Most methods are used to construct a VxColor or to convert it to a 32 bit ARGB format. */ struct VxColor { CKFLOAT r, g, b, a; - VxColor() : r(0.0f), g(0.0f), b(0.0f), a(1.0f) {} // set your custom init. - VxColor(CKFLOAT _r, CKFLOAT _g, CKFLOAT _b, CKFLOAT _a) : r(_r), g(_g), b(_b), a(_a) {} - VxColor(CKDWORD argb) { FromARGB(argb); } + VxColor(); + VxColor(CKFLOAT _r, CKFLOAT _g, CKFLOAT _b, CKFLOAT _a); YYCC_DEF_CLS_COPY_MOVE(VxColor); - CKFLOAT& operator[](size_t i) { - switch (i) { - case 0: return r; - case 1: return g; - case 2: return b; - case 3: return a; - default: throw LogicException("Invalid index for VxColor::operator[]."); - } - } - const CKFLOAT& operator[](size_t i) const { - switch (i) { - case 0: return r; - case 1: return g; - case 2: return b; - case 3: return a; - default: throw LogicException("Invalid index for VxColor::operator[]."); - } - } - bool operator==(const VxColor& rhs) const { - return (r == rhs.r && g == rhs.g && b == rhs.b && a == rhs.a); - } - auto operator<=>(const VxColor& rhs) const { - if (auto cmp = r <=> rhs.r; cmp != 0) return cmp; - if (auto cmp = g <=> rhs.g; cmp != 0) return cmp; - if (auto cmp = b <=> rhs.b; cmp != 0) return cmp; - return a <=> rhs.a; - } + CKFLOAT& operator[](size_t i); + const CKFLOAT& operator[](size_t i) const; + bool operator==(const VxColor& rhs) const; + auto operator<=>(const VxColor& rhs) const; - VxColor(CKFLOAT _r, CKFLOAT _g, CKFLOAT _b) : r(_r), g(_g), b(_b), a(1.0f) {} - void FromARGB(CKDWORD argb) { - a = ((argb & 0xFF000000) >> 24) / 255.0f; - r = ((argb & 0x00FF0000) >> 16) / 255.0f; - g = ((argb & 0x0000FF00) >> 8) / 255.0f; - b = ((argb & 0x000000FF) >> 0) / 255.0f; - } - CKDWORD ToARGB() const { - CKDWORD argb = 0; - argb |= static_cast(a * 255.0f); - argb <<= 8; - argb |= static_cast(r * 255.0f); - argb <<= 8; - argb |= static_cast(g * 255.0f); - argb <<= 8; - argb |= static_cast(b * 255.0f); - return argb; - } - void Regulate() { - if (r > 1.0f) r = 1.0f; - else if (r < 0.0f) r = 0.0f; - if (g > 1.0f) g = 1.0f; - else if (g < 0.0f) g = 0.0f; - if (b > 1.0f) b = 1.0f; - else if (b < 0.0f) b = 0.0f; - if (a > 1.0f) a = 1.0f; - else if (a < 0.0f) a = 0.0f; - } + /* ===== BEGIN USER CUSTOM ===== */ + VxColor(CKDWORD argb); + VxColor(CKFLOAT _r, CKFLOAT _g, CKFLOAT _b); + void FromARGB(CKDWORD argb); + CKDWORD ToARGB() const; + void Regulate(); + /* ===== END USER CUSTOM ===== */ }; /** @@ -443,26 +191,111 @@ namespace LibCmo::VxMath { private: CKFLOAT m_Data[4][4]; public: - VxMatrix() : m_Data() { ResetToIdentity(); } - VxMatrix(CKFLOAT m[4][4]) : m_Data() { std::memcpy(m_Data, m, sizeof(m_Data)); } + VxMatrix(); + VxMatrix(CKFLOAT m[4][4]); YYCC_DEF_CLS_COPY_MOVE(VxMatrix); - void ResetToIdentity() { - std::memset(m_Data, 0, sizeof(m_Data)); - m_Data[0][0] = m_Data[1][1] = m_Data[2][2] = m_Data[3][3] = 1.0f; - } - VxVector4& operator[](size_t i) { - if (i >= 4) throw LogicException("Invalid index for VxMatrix::operator[]."); - return *(reinterpret_cast(m_Data) + i); - } - const VxVector4& operator[](size_t i) const { - if (i >= 4) throw LogicException("Invalid index for VxMatrix::operator[]."); - return *(reinterpret_cast(m_Data) + i); - } - bool operator==(const VxMatrix& rhs) const { - return std::memcmp(m_Data, rhs.m_Data, sizeof(m_Data)) == 0; - } + VxVector4& operator[](size_t i); + const VxVector4& operator[](size_t i) const; + bool operator==(const VxMatrix& rhs) const; + auto operator<=>(const VxMatrix& rhs) const; + + /* ===== BEGIN USER CUSTOM ===== */ + void Clear(); + void SetIdentity(); + /** + * @brief Constructs a perspective projection matrix. + * @param[in] Fov Field of View. + * @param[in] Aspect Aspect ratio (Width/height) + * @param[in] Near_plane Distance of the near clipping plane. + * @param[in] Far_plane Distance of the far clipping plane. + * @remarks Sets Mat to + * + * A = Cos(Fov/2)/Sin(Fov/2) + * F = Far_plane + * N = Near_plane + * + * [ A 0 0 0] + * [ 0 A*Aspect 0 0] + * MAT= [ 0 0 F/F-N 1] + * [ 0 0 -F.N/F-N 0] + * + * @see PerspectiveRect, Orthographic, OrthographicRect + */ + void Perspective(float Fov, float Aspect, float Near_plane, float Far_plane); + /** + * @brief Constructs a perspective projection matrix given a view rectangle. + * @param[in] Left Left clipping plane value. + * @param[in] Right Right clipping plane value. + * @param[in] Top top clipping plane value. + * @param[in] Bottom bottom clipping plane value. + * @param[in] Near_plane Distance of the near clipping plane. + * @param[in] Far_plane Distance of the far clipping plane. + * @remarks Sets Mat to + * + * F = Far_plane + * N = Near_plane + * R = Right + * L = Left + * T = Top + * B = Bottom + * + * [ 2/(R-L) 0 0 0] + * [ 0 -2/(T-B) 0 0] + * MAT = [ 0 0 1/F-N 0] + * [ -(L+R)/(R-L) (T+B)/(T-B) -N/F-N 1] + * + * @see Perspective, Orthographic, OrthographicRect + */ + void PerspectiveRect(float Left, float Right, float Top, float Bottom, float Near_plane, float Far_plane); + /** + * @brief Constructs a orthographic projection matrix. + * @param[in] Zoom Zoom factor. + * @param[in] Aspect Aspect ratio (Width/height) + * @param[in] Near_plane Distance of the near clipping plane. + * @param[in] Far_plane Distance of the far clipping plane. + * @remarks Sets Mat to + * + * F = Far_plane + * N = Near_plane + * + * [ Zoom 0 0 0] + * [ 0 Zoom*Aspect 0 0] + * MAT = [ 0 0 1/F-N 0] + * [ 0 0 -N/F-N 1] + * + * @see Perspective, OrthographicRect + */ + void Orthographic(float Zoom, float Aspect, float Near_plane, float Far_plane); + /** + * @brief Constructs a orthographic projection matrix. + * @param[in] Left Left clipping plane value. + * @param[in] Right Right clipping plane value. + * @param[in] Top top clipping plane value. + * @param[in] Bottom bottom clipping plane value. + * @param[in] Near_plane Distance of the near clipping plane. + * @param[in] Far_plane Distance of the far clipping plane. + * @remarks Sets Mat to + * + * F = Far_plane + * N = Near_plane + * R = Right + * L = Left + * T = Top + * B = Bottom + * + * [ 2/(R-L) 0 0 0] + * [ 0 -2/(T-B) 0 0] + * MAT = [ 0 0 1/F-N 0] + * [ -(L+R)/(R-L) (T+B)/(T-B) -N/F-N 1] + * + * @see Perspective, Orthographic + */ + void OrthographicRect(float Left, float Right, float Top, float Bottom, float Near_plane, float Far_plane); + /* ===== END USER CUSTOM ===== */ }; + // ========== Misc ========== + /** * @brief Structure for storage of strided data. * @tparam _Ty The data pointer type this class stored. @@ -698,4 +531,96 @@ namespace LibCmo::VxMath { CKBYTE* m_Image; /**< A pointer points to current image in memory */ }; + // ========== Patch Section ========== + + /** + * @brief The patch namespace for VxVector-like classes + * @details This namespace provides VxVector-like classes member functions which presented in original Virtools SDK. + * These functions are put in public namespace in original Virtools SDK. + * We just organise them into an unique namespace. + */ + namespace NSVxVector { + + /** + * @brief Dot product 2 2d vectors. + * @param[in] lhs The left side vector of dot product symbol. + * @param[in] rhs The right side vector of dot product symbol. + * @return The float pointing result of dot product. + */ + CKFLOAT DotProduct(const VxVector2& lhs, const VxVector2& rhs); + /** + * @brief Dot product 2 3d vectors. + * @param[in] lhs The left side vector of dot product symbol. + * @param[in] rhs The right side vector of dot product symbol. + * @return The float pointing result of dot product. + */ + CKFLOAT DotProduct(const VxVector3& lhs, const VxVector3& rhs); + /** + * @brief Dot product 2 4d vectors. + * @param[in] lhs The left side vector of dot product symbol. + * @param[in] rhs The right side vector of dot product symbol. + * @return The float pointing result of dot product. + */ + CKFLOAT DotProduct(const VxVector4& lhs, const VxVector4& rhs); + + /** + * @brief Cross product 2 3d vectors. + * @param[in] lhs The left side vector of cross product symbol. + * @param[in] rhs The right side vector of cross product symbol. + * @return The 3d vector result of cross product. + */ + VxVector3 CrossProduct(const VxVector3& lhs, const VxVector3& rhs); + + /** + * @brief Set all factor in vector to its absolute value. + * @param[in,out] lhs The vector for processing. + * @remarks This function is rarely used. + * Please note this function is not calculate the absolute value of vector. + */ + void Absolute(VxVector3& lhs); + + } + + /** + * @brief The patch namespace for VxMatrix classes + * @details Like NXVxVector, these functions located in this namespace + * are exposed in public namespace in original Virtools SDK. + * And I re-organise them in there. + */ + namespace NSVxMatrix { + + //void Vx3DMatrixIdentity(VxMatrix& Mat); + + //void Vx3DMultiplyMatrixVector(VxVector *ResultVector,const VxMatrix& Mat,const VxVector *Vector); + //void Vx3DMultiplyMatrixVectorMany(VxVector *ResultVectors,const VxMatrix& Mat,const VxVector *Vectors,int count,int stride); + //void Vx3DMultiplyMatrixVector4(VxVector4 *ResultVector,const VxMatrix& Mat,const VxVector4 *Vector); + //void Vx3DMultiplyMatrixVector4(VxVector4 *ResultVector,const VxMatrix& Mat,const VxVector *Vector); // w=1 + //void Vx3DRotateVector(VxVector *ResultVector,const VxMatrix& Mat,const VxVector *Vector); + //void Vx3DRotateVectorMany(VxVector *ResultVector,const VxMatrix& Mat,const VxVector *Vector,int count,int stride); + //void Vx3DMultiplyMatrix(VxMatrix& ResultMat,const VxMatrix& MatA,const VxMatrix& MatB); + //void Vx3DMultiplyMatrix4(VxMatrix& ResultMat,const VxMatrix& MatA,const VxMatrix& MatB); + //void Vx3DInverseMatrix(VxMatrix& InverseMat,const VxMatrix& Mat); + //float Vx3DMatrixDeterminant(const VxMatrix& Mat); + //void Vx3DMatrixFromRotation(VxMatrix& ResultMat,const VxVector& Vector, float Angle); + //void Vx3DMatrixFromRotationAndOrigin(VxMatrix& ResultMat,const VxVector& Vector,const VxVector& Origin, float Angle); + //void Vx3DMatrixFromEulerAngles(VxMatrix& Mat,float eax,float eay,float eaz); + //void Vx3DMatrixToEulerAngles(const VxMatrix& Mat,float *eax,float* eay,float* eaz); + //void Vx3DInterpolateMatrix(float step,VxMatrix& Res,const VxMatrix& A, const VxMatrix& B); + //void Vx3DInterpolateMatrixNoScale(float step,VxMatrix& Res,const VxMatrix& A, const VxMatrix& B); + + //void Vx3DMultiplyMatrixVectorStrided(VxStridedData* Dest,VxStridedData* Src,const VxMatrix& Mat,int count); + //void Vx3DMultiplyMatrixVector4Strided(VxStridedData* Dest,VxStridedData* Src,const VxMatrix& Mat,int count); + //void Vx3DRotateVectorStrided(VxStridedData* Dest,VxStridedData* Src,const VxMatrix& Mat,int count); + + //void Vx3DTransposeMatrix(VxMatrix& Result,const VxMatrix& A); + + //void Vx3DDecomposeMatrix(const VxMatrix& A, VxQuaternion &Quat,VxVector &Pos,VxVector &Scale); + //float Vx3DDecomposeMatrixTotal(const VxMatrix& A, VxQuaternion &Quat,VxVector &Pos,VxVector &Scale,VxQuaternion &URot); + //float Vx3DDecomposeMatrixTotalPtr(const VxMatrix& A, VxQuaternion* Quat,VxVector* Pos,VxVector* Scale,VxQuaternion* URot); + + //void VxInverseProject(const VxMatrix& iProjection, const Vx2DVector& i2D, const float iZ, VxVector* o3D); + + + } + }