refactor: refactor VxVector and its generator.

- refactor VxVector-like struct. split their declaration and implementatio because their implementation is too long. and occupy too much space in header.
- refactor VxVector struct generator. use jinja2 template engine, rather ran hand-written format string to make it is easy to read (although it still tough when first reading).
- add unary operator overloading for VxVector-like struct.
- add some VxMatrix functions which are essential to CKCamera.
- rename VxMatrix::ResetToIdentity to VxMatrix::SetIdentity to make it same as original Virtools SDK.
- the spaceship overloading with auto return value still may have bugs. please watch it carefully.
This commit is contained in:
yyc12345 2024-12-24 16:49:34 +08:00
parent 3eeb1f6cb6
commit 4bfc4782b5
15 changed files with 1199 additions and 644 deletions

View File

@ -1,2 +1,3 @@
# Result
*.hpp
VxTypes.hpp
VxTypes.cpp

View File

@ -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

View File

@ -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 ===== */
};

View File

@ -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 %}

View File

@ -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', ))

View File

@ -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', )))

View File

@ -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<VxMath::VxVector3*>(&m_WorldMatrix[0]));
chunk->ReadStruct(reinterpret_cast<VxMath::VxVector3*>(&m_WorldMatrix[1]));

View File

@ -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
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -36,6 +36,7 @@ PRIVATE
CK2/ObjImpls/CKTargetCamera.cpp
# VxMath
VxMath/VxMemoryMappedFile.cpp
VxMath/VxTypes.cpp
VxMath/VxMath.cpp
# X Container
XContainer/XTypes.cpp

View File

@ -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
}

View File

@ -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);
}
}

529
LibCmo/VxMath/VxTypes.cpp Normal file
View File

@ -0,0 +1,529 @@
#include "VxTypes.hpp"
#include <cmath>
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<CKDWORD>(a * 255.0f);
argb <<= 8;
argb |= static_cast<CKDWORD>(r * 255.0f);
argb <<= 8;
argb |= static_cast<CKDWORD>(g * 255.0f);
argb <<= 8;
argb |= static_cast<CKDWORD>(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<VxVector4*>(m_Data) + i);
}
const VxVector4& VxMatrix::operator[](size_t i) const {
if (i >= 4) throw LogicException("Invalid index for VxMatrix::operator[].");
return *(reinterpret_cast<const VxVector4*>(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
}

View File

@ -7,7 +7,6 @@
#include <vector>
#include <cstring>
#include <cinttypes>
#include <cmath>
/**
* @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<CKDWORD>(a * 255.0f);
argb <<= 8;
argb |= static_cast<CKDWORD>(r * 255.0f);
argb <<= 8;
argb |= static_cast<CKDWORD>(g * 255.0f);
argb <<= 8;
argb |= static_cast<CKDWORD>(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<VxVector4*>(m_Data) + i);
}
const VxVector4& operator[](size_t i) const {
if (i >= 4) throw LogicException("Invalid index for VxMatrix::operator[].");
return *(reinterpret_cast<const VxVector4*>(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);
}
}