tyrav2 init

This commit is contained in:
h4570
2022-07-17 10:21:35 +02:00
parent 44c1ee4fe8
commit c8b22ff331
249 changed files with 18187 additions and 0 deletions
+390
View File
@@ -0,0 +1,390 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include <stdio.h>
#include <string>
#include <sstream>
#include "math/m4x4.hpp"
namespace Tyra {
VECTOR M4x4::upVec = {0.0F, 1.0F, 0.0F, 1.0F};
VECTOR M4x4::viewVec = {0.0F, 0.0F, 0.0F, 1.0F};
M4x4::M4x4(const bool& t_identity) {
if (t_identity) identity();
}
void M4x4::copy(M4x4* out, const float* in) {
asm volatile(
"lqc2 $vf1, 0x00(%1) \n"
"lqc2 $vf2, 0x10(%1) \n"
"lqc2 $vf3, 0x20(%1) \n"
"lqc2 $vf4, 0x30(%1) \n"
"sqc2 $vf1, 0x00(%0) \n"
"sqc2 $vf2, 0x10(%0) \n"
"sqc2 $vf3, 0x20(%0) \n"
"sqc2 $vf4, 0x30(%0) \n"
:
: "r"(out->data), "r"(in));
}
void M4x4::operator=(const M4x4& v) { copy(this, v); }
Vec4 M4x4::operator*(const Vec4& v) const {
Vec4 result;
asm volatile(
"lqc2 $vf1, 0x00(%2) \n"
"lqc2 $vf2, 0x10(%2) \n"
"lqc2 $vf3, 0x20(%2) \n"
"lqc2 $vf4, 0x30(%2) \n"
"lqc2 $vf5, 0x00(%1) \n"
"vmulaw $ACC, $vf4, $vf0\n"
"vmaddax $ACC, $vf1, $vf5\n"
"vmadday $ACC, $vf2, $vf5\n"
"vmaddz $vf6, $vf3, $vf5\n"
"sqc2 $vf6, 0x00(%0) \n"
:
: "r"(result.xyzw), "r"(v.xyzw), "r"(this->data));
return result;
}
void M4x4::set(const float& m11, const float& m12, const float& m13,
const float& m14, const float& m21, const float& m22,
const float& m23, const float& m24, const float& m31,
const float& m32, const float& m33, const float& m34,
const float& m41, const float& m42, const float& m43,
const float& m44) {
data[0] = m11;
data[1] = m12;
data[2] = m13;
data[3] = m14;
data[4] = m21;
data[5] = m22;
data[6] = m23;
data[7] = m24;
data[8] = m31;
data[9] = m32;
data[10] = m33;
data[11] = m34;
data[12] = m41;
data[13] = m42;
data[14] = m43;
data[15] = m44;
}
void M4x4::identity() {
asm volatile(
"vsub.xyzw $vf4, $vf0, $vf0 \n\t"
"vadd.w $vf4, $vf4, $vf0 \n\t"
"vmr32.xyzw $vf5, $vf4 \n\t"
"vmr32.xyzw $vf6, $vf5 \n\t"
"vmr32.xyzw $vf7, $vf6 \n\t"
"sqc2 $vf4, 0x30(%0) \n\t"
"sqc2 $vf5, 0x20(%0) \n\t"
"sqc2 $vf6, 0x10(%0) \n\t"
"sqc2 $vf7, 0x0(%0) \n\t"
:
: "r"(this->data));
}
M4x4 M4x4::perspective(const float& fov, const float& width,
const float& height, const float& projectionScale,
const float& aspectRatio, const float& near,
const float& far) {
M4x4 res;
float fovYdiv2 = Math::HALF_ANG2RAD * fov;
float cotFOV = 1.0F / (Math::sin(fovYdiv2) / Math::cos(fovYdiv2));
float w = cotFOV * (width / projectionScale) / aspectRatio;
float h = cotFOV * (height / projectionScale);
res.data[0] = w;
res.data[1] = 0.0F;
res.data[2] = 0.0F;
res.data[3] = 0.0F;
res.data[4] = 0.0F;
res.data[5] = -h;
res.data[6] = 0.0F;
res.data[7] = 0.0F;
res.data[8] = 0.0F;
res.data[9] = 0.0F;
res.data[10] = (far + near) / (far - near);
res.data[11] = -1.0F;
res.data[12] = 0.0F;
res.data[13] = 0.0F;
res.data[14] = (2.0F * far * near) / (far - near);
res.data[15] = 0.0F;
return res;
}
M4x4 M4x4::lookAt(const Vec4& position, const Vec4& target) {
M4x4 res(true);
lookAt(&res, position, target);
return res;
}
void M4x4::lookAt(M4x4* res, const Vec4& position, const Vec4& target) {
float eye[4] alignas(sizeof(float) * 4) = {position.x, position.y, position.z,
1.0F};
float obj[4] alignas(sizeof(float) * 4) = {target.x, target.y, target.z,
1.0F};
asm volatile(
// eye
"lqc2 $vf4, 0x00(%2) \n\t"
// obj
"lqc2 $vf5, 0x00(%3) \n\t"
// view_vec = $vf7
"vsub.xyz $vf7, $vf4, $vf5 \n\t"
"vmove.xyzw $vf6, $vf0 \n\t"
// $vf6 = { 0.0f, 1.0f, 0.0f, 1.0f }
"vaddw.y $vf6, $vf0, $vf0 \n\t"
"vopmula.xyz $ACC, $vf6, $vf7 \n\t"
// vec = $vf9
"vopmsub.xyz $vf9, $vf7, $vf6 \n\t"
"vopmula.xyz $ACC, $vf7, $vf9 \n\t"
// up_vec = $vf8
"vopmsub.xyz $vf8, $vf9, $vf7 \n\t"
// view_vec
"sqc2 $vf7, 0x00(%0) \n\t"
// up_vec
"sqc2 $vf6, 0x00(%1) \n\t"
:
: "r"(viewVec), "r"(upVec), "r"(eye), "r"(obj));
M4x4 temp = setCamera(eye, viewVec, upVec);
res->identity();
cross(res->data, res->data, temp.data);
}
void M4x4::cross(float res[16], const float a[16], const float b[16]) {
asm volatile(
"lqc2 $vf1, 0x00(%1) \n\t"
"lqc2 $vf2, 0x10(%1) \n\t"
"lqc2 $vf3, 0x20(%1) \n\t"
"lqc2 $vf4, 0x30(%1) \n\t"
"lqc2 $vf5, 0x00(%2) \n\t"
"lqc2 $vf6, 0x10(%2) \n\t"
"lqc2 $vf7, 0x20(%2) \n\t"
"lqc2 $vf8, 0x30(%2) \n\t"
"vmulax.xyzw $ACC, $vf5, $vf1 \n\t"
"vmadday.xyzw $ACC, $vf6, $vf1 \n\t"
"vmaddaz.xyzw $ACC, $vf7, $vf1 \n\t"
"vmaddw.xyzw $vf1, $vf8, $vf1 \n\t"
"vmulax.xyzw $ACC, $vf5, $vf2 \n\t"
"vmadday.xyzw $ACC, $vf6, $vf2 \n\t"
"vmaddaz.xyzw $ACC, $vf7, $vf2 \n\t"
"vmaddw.xyzw $vf2, $vf8, $vf2 \n\t"
"vmulax.xyzw $ACC, $vf5, $vf3 \n\t"
"vmadday.xyzw $ACC, $vf6, $vf3 \n\t"
"vmaddaz.xyzw $ACC, $vf7, $vf3 \n\t"
"vmaddw.xyzw $vf3, $vf8, $vf3 \n\t"
"vmulax.xyzw $ACC, $vf5, $vf4 \n\t"
"vmadday.xyzw $ACC, $vf6, $vf4 \n\t"
"vmaddaz.xyzw $ACC, $vf7, $vf4 \n\t"
"vmaddw.xyzw $vf4, $vf8, $vf4 \n\t"
"sqc2 $vf1, 0x00(%0) \n\t"
"sqc2 $vf2, 0x10(%0) \n\t"
"sqc2 $vf3, 0x20(%0) \n\t"
"sqc2 $vf4, 0x30(%0) \n\t"
:
: "r"(res), "r"(b), "r"(a)
: "memory");
}
void M4x4::rotationX(const float& v) {
float c = Math::cos(v);
float s = Math::sin(v);
this->data[5] = c; // 1,1
this->data[6] = s; // 1,2
this->data[9] = -s; // 2,1
this->data[10] = c; // 2,2
}
void M4x4::rotationY(const float& v) {
float c = Math::cos(v);
float s = Math::sin(v);
this->data[0] = c; // 0,0
this->data[2] = -s; // 0,3
this->data[8] = s; // 2,0
this->data[10] = c; // 2,2
}
void M4x4::rotationZ(const float& v) {
float c = Math::cos(v);
float s = Math::sin(v);
this->data[0] = c; // 0,0
this->data[1] = s; // 0,1
this->data[4] = -s; // 1,0
this->data[5] = c; // 1,1
}
void M4x4::rotationByAngle(const float& angle, const Vec4& axis) {
Vec4 localAxis = Vec4(axis);
localAxis.normalize();
float x = localAxis.x;
float y = localAxis.y;
float z = localAxis.z;
float c = Math::cos(angle);
float s = Math::sin(angle);
this->data[0] = x * x * (1 - c) + c;
this->data[1] = y * x * (1 - c) + z * s;
this->data[2] = x * z * (1 - c) - y * s;
this->data[3] = 0.0F;
this->data[4] = x * y * (1 - c) - z * s;
this->data[5] = y * y * (1 - c) + c;
this->data[6] = y * z * (1 - c) + x * s;
this->data[7] = 0.0F;
this->data[8] = x * z * (1 - c) + y * s;
this->data[9] = y * z * (1 - c) - x * s;
this->data[10] = z * z * (1 - c) + c;
this->data[11] = 0.0F;
this->data[12] = 0.0F;
this->data[13] = 0.0F;
this->data[14] = 0.0F;
this->data[15] = 1.0F;
}
void M4x4::translationX(const float& val) {
this->data[12] = val; // 3,0
}
void M4x4::translationY(const float& val) {
this->data[13] = val; // 3,1
}
void M4x4::translationZ(const float& val) {
this->data[14] = val; // 3,2
}
void M4x4::setScale(const Vec4& val) {
this->data[0] = val.x;
this->data[5] = val.y;
this->data[10] = val.z;
this->data[15] = 1.0F;
}
M4x4 M4x4::setCamera(const float pos[4], const float vz[4], const float vy[4]) {
M4x4 res;
// M4x4 $vf4, $vf5, $vf6, $vf7
// pos $vf8
// vz $vf9
// vy $vf10
// vtmp $vf11
asm volatile(
"lqc2 $vf9, 0x00(%2) \n\t"
// mtmp.unit()
"lqc2 $vf10, 0x00(%3) \n\t"
// mtmp[1][PW] = 0.0F
"vsub.w $vf5, $vf0, $vf0 \n\t"
// vtmp.outerProduct(vy, vz);
"vopmula.xyz $ACC, $vf10, $vf9 \n\t"
"vopmsub.xyz $vf11, $vf9, $vf10 \n\t"
// mtmp[0] = vtmp.normalize();
"vmul.xyz $vf12, $vf11, $vf11 \n\t"
"vaddy.x $vf12, $vf12, $vf12 \n\t"
"vaddz.x $vf12, $vf12, $vf12 \n\t"
"vrsqrt $Q, $vf0w, $vf12x \n\t"
"vsub.xyzw $vf4, $vf0, $vf0 \n\t"
"vwaitq \n\t"
"vmulq.xyz $vf4, $vf11, $Q \n\t"
// mtmp[2] = vz.normalize();
"vmul.xyz $vf12, $vf9, $vf9 \n\t"
"vaddy.x $vf12, $vf12, $vf12 \n\t"
"vaddz.x $vf12, $vf12, $vf12 \n\t"
"vrsqrt $Q, $vf0w, $vf12x \n\t"
"vsub.xyzw $vf6, $vf0, $vf0 \n\t"
"vwaitq \n\t"
"vmulq.xyz $vf6, $vf9, $Q \n\t"
// mtmp[1].outerProduct(mtmp[2], mtmp[0]);
"vopmula.xyz $ACC, $vf6, $vf4 \n\t"
"vopmsub.xyz $vf5, $vf4, $vf6 \n\t"
// mtmp.transpose(pos);
"lqc2 $vf7, 0x00(%1) \n\t"
// m = mtmp.inverse();
"qmfc2.ni $11, $vf0 \n\t"
"qmfc2.ni $8, $vf4 \n\t"
"qmfc2.ni $9, $vf5 \n\t"
"qmfc2.ni $10, $vf6 \n\t"
"pextlw $12, $9, $8 \n\t"
"pextuw $13, $9, $8 \n\t"
"pextlw $14, $11, $10 \n\t"
"pextuw $15, $11, $10 \n\t"
"pcpyld $8, $14, $12 \n\t"
"pcpyud $9, $12, $14 \n\t"
"pcpyld $10, $15, $13 \n\t"
"qmtc2.ni $8, $vf16 \n\t"
"qmtc2.ni $9, $vf17 \n\t"
"qmtc2.ni $10, $vf18 \n\t"
"vmulax.xyz $ACC, $vf16, $vf7 \n\t"
"vmadday.xyz $ACC, $vf17, $vf7 \n\t"
"vmaddz.xyz $vf5, $vf18, $vf7 \n\t"
"vsub.xyzw $vf5, $vf0, $vf5 \n\t"
"sq $8, 0x00(%0) \n\t"
"sq $9, 0x10(%0) \n\t"
"sq $10, 0x20(%0) \n\t"
"sqc2 $vf5, 0x30(%0) \n\t"
:
: "r"(res.data), "r"(pos), "r"(vz), "r"(vy));
return res;
}
void M4x4::print() const {
auto text = getPrint(nullptr);
printf("%s\n", text.c_str());
}
void M4x4::print(const char* name) const {
auto text = getPrint(name);
printf("%s\n", text.c_str());
}
std::string M4x4::getPrint(const char* name) const {
std::stringstream res;
if (name) {
res << name << "(";
} else {
res << "M4x4(";
}
res << std::fixed << std::setprecision(2);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
auto index = (i * 4) + j;
res << data[index];
if (index != 15) {
res << ", ";
}
}
if (i != 3) {
res << std::endl;
}
}
res << ")";
return res.str();
}
} // namespace Tyra
+161
View File
@@ -0,0 +1,161 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#ifdef __INTELLISENSE__
#pragma diag_suppress 1118
#endif
#include "math/math.hpp"
namespace Tyra {
float Math::cos(float x) {
float r;
asm volatile(
"lui $9, 0x3f00 \n\t"
".set noreorder \n\t"
".align 3 \n\t"
"abs.s %0, %1 \n\t"
"lui $8, 0xbe22 \n\t"
"mtc1 $9, $f1 \n\t"
"ori $8, $8, 0xf983 \n\t"
"mtc1 $8, $f8 \n\t"
"lui $9, 0x4b00 \n\t"
"mtc1 $9, $f3 \n\t"
"lui $8, 0x3f80 \n\t"
"mtc1 $8, $f2 \n\t"
"mula.s %0, $f8 \n\t"
"msuba.s $f3, $f2 \n\t"
"madda.s $f3, $f2 \n\t"
"lui $8, 0x40c9 \n\t"
"msuba.s %0, $f8 \n\t"
"ori $8, 0x0fdb \n\t"
"msub.s %0, $f1, $f2 \n\t"
"lui $9, 0xc225 \n\t"
"abs.s %0, %0 \n\t"
"lui $10, 0x3e80 \n\t"
"mtc1 $10, $f7 \n\t"
"ori $9, 0x5de1 \n\t"
"sub.s %0, %0, $f7 \n\t"
"lui $10, 0x42a3 \n\t"
"mtc1 $8, $f3 \n\t"
"ori $10, 0x3458 \n\t"
"mtc1 $9, $f4 \n\t"
"lui $8, 0xc299 \n\t"
"mtc1 $10, $f5 \n\t"
"ori $8, 0x2663 \n\t"
"mul.s $f8, %0, %0 \n\t"
"lui $9, 0x421e \n\t"
"mtc1 $8, $f6 \n\t"
"ori $9, 0xd7bb \n\t"
"mtc1 $9, $f7 \n\t"
"nop \n\t"
"mul.s $f1, %0, $f8 \n\t"
"mul.s $f9, $f8, $f8 \n\t"
"mula.s $f3, %0 \n\t"
"mul.s $f2, $f1, $f8 \n\t"
"madda.s $f4, $f1 \n\t"
"mul.s $f1, $f1, $f9 \n\t"
"mul.s %0, $f2, $f9 \n\t"
"madda.s $f5, $f2 \n\t"
"madda.s $f6, $f1 \n\t"
"madd.s %0, $f7, %0 \n\t"
".set reorder \n\t"
: "=&f"(r)
: "f"(x)
: "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", "$f9", "$8",
"$9", "$10");
return r;
}
float Math::invSqrt(float x) { return 1.0F / sqrt(x); }
float Math::asin(float x) {
float r;
asm volatile(
"lui $9, 0x3f00 \n\t"
".set noreorder \n\t"
".align 3 \n\t"
"abs.s %0, %1 \n\t"
"lui $8, 0xbe22 \n\t"
"mtc1 $9, $f1 \n\t"
"ori $8, $8, 0xf983 \n\t"
"mtc1 $8, $f8 \n\t"
"lui $9, 0x4b00 \n\t"
"mtc1 $9, $f3 \n\t"
"lui $8, 0x3f80 \n\t"
"mtc1 $8, $f2 \n\t"
"mula.s %0, $f8 \n\t"
"msuba.s $f3, $f2 \n\t"
"madda.s $f3, $f2 \n\t"
"lui $8, 0x40c9 \n\t"
"msuba.s %0, $f8 \n\t"
"ori $8, 0x0fdb \n\t"
"msub.s %0, $f1, $f2 \n\t"
"lui $9, 0xc225 \n\t"
"abs.s %0, %0 \n\t"
"lui $10, 0x3e80 \n\t"
"mtc1 $10, $f7 \n\t"
"ori $9, 0x5de1 \n\t"
"sub.s %0, %0, $f7 \n\t"
"lui $10, 0x42a3 \n\t"
"mtc1 $8, $f3 \n\t"
"ori $10, 0x3458 \n\t"
"mtc1 $9, $f4 \n\t"
"lui $8, 0xc299 \n\t"
"mtc1 $10, $f5 \n\t"
"ori $8, 0x2663 \n\t"
"mul.s $f8, %0, %0 \n\t"
"lui $9, 0x421e \n\t"
"mtc1 $8, $f6 \n\t"
"ori $9, 0xd7bb \n\t"
"mtc1 $9, $f7 \n\t"
"nop \n\t"
"mul.s $f1, %0, $f8 \n\t"
"mul.s $f9, $f8, $f8 \n\t"
"mula.s $f3, %0 \n\t"
"mul.s $f2, $f1, $f8 \n\t"
"madda.s $f4, $f1 \n\t"
"mul.s $f1, $f1, $f9 \n\t"
"mul.s %0, $f2, $f9 \n\t"
"madda.s $f5, $f2 \n\t"
"madda.s $f6, $f1 \n\t"
"madd.s %0, $f7, %0 \n\t"
".set reorder \n\t"
: "=&f"(r)
: "f"(x)
: "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", "$f9", "$8",
"$9", "$10");
return r;
}
float Math::mod(float x, float y) {
/*
* Portable fmod(x,y) implementation for systems
* that don't have it. Adapted from code found here:
* http://www.opensource.apple.com/source/python/python-3/python/Python/fmod.c
*/
float i, f;
if (fabs(y) < 0.00001F) {
return 0.0F;
}
i = floorf(x / y);
f = x - i * y;
if ((x < 0.0f) != (y < 0.0f)) {
f = f - y;
}
return f;
}
} // namespace Tyra
+67
View File
@@ -0,0 +1,67 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include <string>
#include "math/vec4.hpp"
#include "math/plane.hpp"
namespace Tyra {
Plane::Plane() { this->distance = 0; }
/** Create by specyfying 3 points.
* This function assumes that the points
* are given in counter clockwise order
*/
Plane::Plane(const Vec4& a, const Vec4& b, const Vec4& c) {
this->update(a, b, c);
}
Plane::~Plane() {}
// ----
// Methods
// ----
/** Set plane by specyfying 3 points.
* This function assumes that the points
* are given in counter clockwise order
*/
void Plane::update(const Vec4& a, const Vec4& b, const Vec4& c) {
Vec4 aux1 = a - b;
Vec4 aux2 = c - b;
this->normal = aux2.cross(aux1);
this->normal.normalize();
this->distance = -this->normal.innerProduct(b);
}
void Plane::print() const {
auto text = getPrint(nullptr);
printf("%s\n", text.c_str());
}
void Plane::print(const char* name) const {
auto text = getPrint(name);
printf("%s\n", text.c_str());
}
std::string Plane::getPrint(const char* name) const {
std::stringstream res;
if (name) {
res << name << "(";
} else {
res << "Plane(";
}
res << std::fixed << std::setprecision(4);
res << "distance: " << distance << ", " << normal.getPrint("normal") << ")";
return res.str();
}
} // namespace Tyra
+78
View File
@@ -0,0 +1,78 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "math/vec2.hpp"
namespace Tyra {
Vec2::Vec2(const float& t_x, const float& t_y) {
x = t_x;
y = t_y;
}
Vec2::Vec2(const Vec2& v) {
x = v.x;
y = v.y;
}
Vec2::Vec2() {
x = 0;
y = 0;
}
Vec2::~Vec2() {}
void Vec2::set(const float& t_x, const float& t_y) {
x = t_x;
y = t_y;
}
void Vec2::set(const Vec2& v) {
x = v.x;
y = v.y;
}
void Vec2::rotate(const float& t_angle, const float& t_x, const float& t_y) {
float s = Math::sin(t_angle);
float c = Math::cos(t_angle);
x -= t_x;
y -= t_y;
float xnew = x * c - y * s;
float ynew = x * s + y * c;
x = xnew + t_x;
y = ynew + t_y;
}
void Vec2::print() const {
auto text = getPrint(nullptr);
printf("%s\n", text.c_str());
}
void Vec2::print(const char* name) const {
auto text = getPrint(name);
printf("%s\n", text.c_str());
}
std::string Vec2::getPrint(const char* name) const {
std::stringstream res;
if (name) {
res << name << "(";
} else {
res << "Vec2(";
}
res << std::fixed << std::setprecision(4);
res << x << ", " << y << ")";
return res.str();
}
} // namespace Tyra
+299
View File
@@ -0,0 +1,299 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "math/vec4.hpp"
namespace Tyra {
void Vec4::set(const float& t_x, const float& t_y, const float& t_z,
const float& t_w) {
x = t_x;
y = t_y;
z = t_z;
w = t_w;
}
Vec4 Vec4::operator+(const Vec4& v) const {
Vec4 res;
asm volatile(
"lqc2 $vf4, 0x0(%1) \n\t"
"lqc2 $vf5, 0x0(%2) \n\t"
"vadd.xyz $vf6, $vf4, $vf5 \n\t"
"sqc2 $vf6, 0x0(%0) \n\t"
:
: "r"(res.xyzw), "r"(this->xyzw), "r"(v.xyzw));
return res;
}
Vec4 Vec4::operator-(const Vec4& v) const {
Vec4 res;
asm volatile(
"lqc2 $vf4, 0x0(%1) \n\t"
"lqc2 $vf5, 0x0(%2) \n\t"
"vsub.xyz $vf6, $vf4, $vf5 \n\t"
"sqc2 $vf6, 0x0(%0) \n\t"
:
: "r"(res.xyzw), "r"(this->xyzw), "r"(v.xyzw));
return res;
}
Vec4 Vec4::operator*(const Vec4& v) const {
Vec4 res;
asm volatile(
"lqc2 $vf4, 0x0(%1) \n\t"
"lqc2 $vf5, 0x0(%2) \n\t"
"vmul.xyzw $vf6, $vf4, $vf5 \n\t"
"sqc2 $vf6, 0x0(%0) \n\t"
:
: "r"(res.xyzw), "r"(this->xyzw), "r"(v.xyzw));
return res;
}
Vec4 Vec4::operator*(const float& v) const {
Vec4 res;
asm volatile(
"lqc2 $vf4, 0x0(%1) \n\t"
"mfc1 $8, %2 \n\t"
"qmtc2 $8, $vf5 \n\t"
"vmulx.xyz $vf6, $vf4, $vf5 \n\t"
"sqc2 $vf6, 0x0(%0) \n\t"
:
: "r"(res.xyzw), "r"(this->xyzw), "f"(v));
res.w = w; // Comment below. TODO: fix it in asm
return res;
}
Vec4 Vec4::operator/(const float& v) const {
return Vec4(x / v, y / v, z / v, w);
}
void Vec4::operator+=(const Vec4& v) {
asm volatile(
"lqc2 $vf4, 0x0(%0) \n\t"
"lqc2 $vf5, 0x0(%1) \n\t"
"vadd.xyz $vf4, $vf4, $vf5 \n\t"
"sqc2 $vf4, 0x0(%0) \n\t"
:
: "r"(this->xyzw), "r"(v.xyzw));
}
void Vec4::operator*=(const Vec4& v) {
asm volatile(
"lqc2 $vf4, 0x0(%0) \n\t"
"lqc2 $vf5, 0x0(%1) \n\t"
"vmul.xyzw $vf6, $vf4, $vf5 \n\t"
"sqc2 $vf6, 0x0(%0) \n\t"
:
: "r"(this->xyzw), "r"(v.xyzw));
}
void Vec4::operator*=(const float& v) {
// Hmm... we don't want to modify W in most of the cases
// It should be touched only during rendering process
auto tempW = w;
asm volatile(
"lqc2 $vf4, 0x0(%0) \n\t"
"mfc1 $8, %1 \n\t"
"qmtc2 $8, $vf5 \n\t"
"vmulx.xyz $vf4, $vf4, $vf5 \n\t"
"sqc2 $vf4, 0x0(%0) \n\t"
:
: "r"(this->xyzw), "f"(v));
w = tempW;
}
void Vec4::operator/=(const float& v) {
x /= v;
y /= v;
z /= v;
}
void Vec4::operator=(const Vec4& v) { copy(this, v); }
Vec4 Vec4::operator-(void) const { return Vec4(-x, -y, -z); }
void Vec4::copy(Vec4* out, const float* in) {
asm volatile(
"lqc2 $vf1, 0x00(%1) \n"
"sqc2 $vf1, 0x00(%0) \n"
:
: "r"(out->xyzw), "r"(in));
}
Vec4 Vec4::cross(const Vec4& v) const {
Vec4 res;
asm volatile(
"lqc2 $vf4, 0x0(%1) \n\t"
"lqc2 $vf5, 0x0(%2) \n\t"
"vopmula.xyz $ACC, $vf4, $vf5 \n\t"
"vopmsub.xyz $vf8, $vf5, $vf4 \n\t"
"vsub.w $vf8, $vf0, $vf0 \n\t"
"sqc2 $vf8, 0x0(%0) \n\t"
:
: "r"(res.xyzw), "r"(this->xyzw), "r"(v.xyzw));
return res;
}
void Vec4::rotateZ(const int& angle) {
auto s = Math::sin(angle);
auto c = Math::cos(angle);
x = x * c - y * s;
y = x * s + y * c;
}
int Vec4::getRelativeCosBetween(const Vec4& v) const {
return dot3(v) / (length() * v.length());
}
int Vec4::getRelativeAngleBetween(const Vec4& v) const {
return acos(getRelativeCosBetween(v));
}
float Vec4::innerProduct(const Vec4& v) const {
float result;
asm volatile(
"lqc2 $vf4, 0x0(%1) \n\t"
"lqc2 $vf5, 0x0(%2) \n\t"
"vmul.xyz $vf6, $vf4, $vf5 \n\t"
"vaddy.x $vf6, $vf6, $vf6 \n\t"
"vaddz.x $vf6, $vf6, $vf6 \n\t"
"qmfc2 $2, $vf6 \n\t"
"mtc1 $2, %0 \n\t"
: "=f"(result)
: "r"(this->xyzw), "r"(v.xyzw));
return result;
}
float Vec4::length() const {
float result;
asm volatile(
"lqc2 $vf4, 0x0(%1) \n\t"
"vmul.xyz $vf5, $vf4, $vf4 \n\t"
"vaddy.x $vf5, $vf5, $vf5 \n\t"
"vaddz.x $vf5, $vf5, $vf5 \n\t"
"vsqrt $Q , $vf5x \n\t"
"vwaitq \n\t"
"vaddq.x $vf8, $vf0, $Q \n\t"
"qmfc2 $2, $vf8 \n\t"
"mtc1 $2, %0 \n\t"
: "=f"(result)
: "r"(this->xyzw));
return result;
}
void Vec4::normalize() {
asm volatile(
"lqc2 $vf4, 0x0(%0) \n\t"
"vmul.xyz $vf5, $vf4, $vf4 \n\t"
"vaddy.x $vf5, $vf5, $vf5 \n\t"
"vaddz.x $vf5, $vf5, $vf5 \n\t"
"vrsqrt $Q, $vf0w, $vf5x \n\t"
"vwaitq \n\t"
"vsub.xyz $vf6, $vf0, $vf0 \n\t"
"vaddw.xyz $vf6, $vf6, $vf4 \n\t"
"vwaitq \n\t"
"vmulq.xyz $vf6, $vf4, $Q \n\t"
"sqc2 $vf6, 0x0(%0) \n\t"
:
: "r"(this->xyzw));
}
float Vec4::distanceTo(const Vec4& v) const {
float result;
asm volatile(
"lqc2 $vf4, 0x0(%1) \n\t"
"lqc2 $vf5, 0x0(%2) \n\t"
"vsub.xyz $vf6, $vf4, $vf5 \n\t"
"vmul.xyz $vf7, $vf6, $vf6 \n\t"
"vaddy.x $vf7, $vf7, $vf7 \n\t"
"vaddz.x $vf7, $vf7, $vf7 \n\t"
"vsqrt $Q , $vf7x \n\t"
"vwaitq \n\t"
"vaddq.x $vf8, $vf0, $Q \n\t"
"qmfc2 $2, $vf8 \n\t"
"mtc1 $2, %0 \n\t"
: "=f"(result)
: "r"(this->xyzw), "r"(v.xyzw));
return result;
}
u8 Vec4::shouldBeBackfaceCulled(const Vec4* cameraPos, const Vec4* v0,
const Vec4* v1, const Vec4* v2) {
float dot;
asm volatile(
"lqc2 $vf4, 0x0(%1) \n\t" // $vf4 = cameraPos
"lqc2 $vf5, 0x0(%2) \n\t" // $vf5 = v0
"lqc2 $vf6, 0x0(%3) \n\t" // $vf6 = v1
"lqc2 $vf7, 0x0(%4) \n\t" // $vf7 = v2
"vsub.xyz $vf8, $vf7, $vf5 \n\t" // $vf8 = $vf7(v2) - $vf5(v0)
"vsub.xyz $vf9, $vf6, $vf5 \n\t" // $vf9 = $vf6(v1) - $vf5(v0)
"vopmula.xyz $ACC, $vf8, $vf9 \n\t" // $vf6 = cross($vf8, $vf9)
"vopmsub.xyz $vf6, $vf9, $vf8 \n\t"
"vsub.w $vf6, $vf6, $vf6 \n\t"
"vsub.xyz $vf7, $vf5, $vf4 \n\t" // $vf7 = $vf5(v0) - $vf4(cameraPos)
"vmul.xyz $vf5, $vf7, $vf6 \n\t" // $vf5 = dot($vf7, $vf6)
"vaddy.x $vf5, $vf5, $vf5 \n\t"
"vaddz.x $vf5, $vf5, $vf5 \n\t"
"qmfc2 $2, $vf5 \n\t" // store result on `dot` variable
"mtc1 $2, %0 \n\t"
: "=f"(dot)
: "r"(cameraPos->xyzw), "r"(v0->xyzw), "r"(v1->xyzw), "r"(v2->xyzw));
return dot <= 0.0F;
}
void Vec4::lerp(const Vec4& v1, const Vec4& v2, const float& interp) {
setLerp(this, v1, v2, interp);
}
Vec4 Vec4::getByLerp(const Vec4& v1, const Vec4& v2, const float& interp) {
Vec4 result;
setLerp(&result, v1, v2, interp);
return result;
}
void Vec4::setLerp(Vec4* output, const Vec4& v1, const Vec4& v2,
const float& interp) {
asm volatile(
"lqc2 $vf4, 0x0(%1) \n\t" // $vf4 = v1
"lqc2 $vf5, 0x0(%2) \n\t" // $vf5 = v2
"mfc1 $8, %3 \n\t" // $vf6 = t
"qmtc2 $8, $vf6 \n\t" // lerp:
"vsub.xyzw $vf7, $vf5, $vf4 \n\t" // $vf7 = v2 - v1
"vmulx.xyzw $vf8, $vf7, $vf6 \n\t" // $vf8 = $vf7 * t
"vadd.xyzw $vf9, $vf8, $vf4 \n\t" // $vf9 = $vf8 + $vf4
"sqc2 $vf9, 0x0(%0) \n\t" // v0 = $vf9
:
: "r"(&output->xyzw), "r"(&v1.xyzw), "r"(&v2.xyzw), "f"(interp));
}
void Vec4::print() const {
auto text = getPrint(nullptr);
printf("%s\n", text.c_str());
}
void Vec4::print(const char* name) const {
auto text = getPrint(name);
printf("%s\n", text.c_str());
}
std::string Vec4::getPrint(const char* name) const {
std::stringstream res;
if (name) {
res << name << "(";
} else {
res << "Vec4(";
}
res << std::fixed << std::setprecision(4);
res << x << ", " << y << ", " << z << ", " << w << ")";
return res.str();
}
} // namespace Tyra