moved from h4570/tyra
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../include/models/dff_model.hpp"
|
||||
|
||||
#include "../include/utils/debug.hpp"
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
DffModel::DffModel() {}
|
||||
|
||||
DffModel::~DffModel() {}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
u32 DffModel::getDrawData(u32 splitIndex, VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, VECTOR *o_colors, Vector3 &t_cameraPos, float t_scale, u8 t_shouldBeBackfaceCulled)
|
||||
{
|
||||
u32 result = 0;
|
||||
for (u32 i = 0; i < clump.geometryList.geometries[0].extension.materialSplit.splitInformation[splitIndex].faceIndex; i++)
|
||||
fillNextFace(o_vertices, o_normals, o_coordinates, o_colors, 0,
|
||||
clump.geometryList.geometries[0].extension.materialSplit.splitInformation[splitIndex].vertexInformation[i].vertex1,
|
||||
result++);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void DffModel::fillNextFace(VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, VECTOR *o_colors, u8 geometry, u32 t_getI, u32 t_setI)
|
||||
{
|
||||
o_vertices[t_setI][0] = clump.geometryList.geometries[geometry].data.vertexInformation[t_getI].x;
|
||||
o_vertices[t_setI][1] = clump.geometryList.geometries[geometry].data.vertexInformation[t_getI].y;
|
||||
o_vertices[t_setI][2] = clump.geometryList.geometries[geometry].data.vertexInformation[t_getI].z;
|
||||
o_vertices[t_setI][3] = 1.0F;
|
||||
|
||||
o_normals[t_setI][0] = clump.geometryList.geometries[geometry].data.normalInformation[t_getI].x;
|
||||
o_normals[t_setI][1] = clump.geometryList.geometries[geometry].data.normalInformation[t_getI].y;
|
||||
o_normals[t_setI][2] = clump.geometryList.geometries[geometry].data.normalInformation[t_getI].z;
|
||||
o_normals[t_setI][3] = 1.0F;
|
||||
|
||||
o_coordinates[t_setI][0] = clump.geometryList.geometries[geometry].data.textureMappingInformation[t_getI].u;
|
||||
o_coordinates[t_setI][1] = 1.0F - clump.geometryList.geometries[geometry].data.textureMappingInformation[t_getI].v;
|
||||
o_coordinates[t_setI][2] = 1.0F;
|
||||
o_coordinates[t_setI][3] = 1.0F;
|
||||
|
||||
o_colors[t_setI][0] = 1.0F;
|
||||
o_colors[t_setI][1] = 1.0F;
|
||||
o_colors[t_setI][2] = 1.0F;
|
||||
o_colors[t_setI][3] = 1.0F;
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../../include/models/math/matrix.hpp"
|
||||
|
||||
#include "../../include/utils/math.hpp"
|
||||
#include <stdio.h>
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
/** Create by specifying all points */
|
||||
Matrix::Matrix(float m11, float m12, float m13, float m14,
|
||||
float m21, float m22, float m23, float m24,
|
||||
float m31, float m32, float m33, float m34,
|
||||
float m41, float m42, float m43, 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;
|
||||
}
|
||||
|
||||
/** Create with another matrix values */
|
||||
Matrix::Matrix(const Matrix &v)
|
||||
{
|
||||
data[0] = v.data[0];
|
||||
data[1] = v.data[1];
|
||||
data[2] = v.data[2];
|
||||
data[3] = v.data[3];
|
||||
|
||||
data[4] = v.data[4];
|
||||
data[5] = v.data[5];
|
||||
data[6] = v.data[6];
|
||||
data[7] = v.data[7];
|
||||
|
||||
data[8] = v.data[8];
|
||||
data[9] = v.data[9];
|
||||
data[10] = v.data[10];
|
||||
data[11] = v.data[11];
|
||||
|
||||
data[12] = v.data[12];
|
||||
data[13] = v.data[13];
|
||||
data[14] = v.data[14];
|
||||
data[15] = v.data[15];
|
||||
}
|
||||
|
||||
void Matrix::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));
|
||||
}
|
||||
|
||||
void Matrix::translate(float x, float y, float z)
|
||||
{
|
||||
this->identity();
|
||||
this->data[(3 << 2) + 0] = x; // 3,0
|
||||
this->data[(3 << 2) + 1] = y; // 3,1
|
||||
this->data[(3 << 2) + 2] = z; // 3,2
|
||||
}
|
||||
|
||||
void Matrix::makeZRotation(float t_radians)
|
||||
{
|
||||
this->identity();
|
||||
float c = Math::cos(t_radians);
|
||||
float s = Math::sin(t_radians);
|
||||
this->data[0] = c; // 0,0
|
||||
this->data[1] = s; // 0,1
|
||||
this->data[4] = -s; // 1,0
|
||||
this->data[5] = c; // 1,1
|
||||
}
|
||||
|
||||
Matrix Matrix::operator*(Matrix &t)
|
||||
{
|
||||
Matrix result;
|
||||
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"(result.data), "r"(this->data), "r"(t.data)
|
||||
: "memory");
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Create empty matrix */
|
||||
Matrix::Matrix()
|
||||
{
|
||||
data[0] = 0.0F;
|
||||
data[1] = 0.0F;
|
||||
data[2] = 0.0F;
|
||||
data[3] = 0.0F;
|
||||
|
||||
data[4] = 0.0F;
|
||||
data[5] = 0.0F;
|
||||
data[6] = 0.0F;
|
||||
data[7] = 0.0F;
|
||||
|
||||
data[8] = 0.0F;
|
||||
data[9] = 0.0F;
|
||||
data[10] = 0.0F;
|
||||
data[11] = 0.0F;
|
||||
|
||||
data[12] = 0.0F;
|
||||
data[13] = 0.0F;
|
||||
data[14] = 0.0F;
|
||||
data[15] = 0.0F;
|
||||
}
|
||||
|
||||
Matrix::~Matrix() {}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
/** Set up a perspective projection matrix
|
||||
*
|
||||
* Clone of gluPerspective()
|
||||
* https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml
|
||||
* @param fov (FOV in radians)/2
|
||||
* @param aspect Aspect ratio
|
||||
* @param scrW Half of screen width
|
||||
* @param scrH Half of screen height
|
||||
* @param zNear Distance to near plane
|
||||
* @param zFar Distance to far plane
|
||||
* @param projScale Projection scale
|
||||
*/
|
||||
void Matrix::setPerspective(ScreenSettings &t_screen)
|
||||
{
|
||||
float fovYdiv2 = Math::HALF_ANG2RAD * t_screen.fov;
|
||||
float cotFOV = 1.0F / (Math::sin(fovYdiv2) / Math::cos(fovYdiv2));
|
||||
float w = cotFOV * (t_screen.width / 4096.0F) / t_screen.aspectRatio;
|
||||
float h = cotFOV * (t_screen.height / 4096.0F);
|
||||
|
||||
this->data[0] = w;
|
||||
this->data[1] = 0.0F;
|
||||
this->data[2] = 0.0F;
|
||||
this->data[3] = 0.0F;
|
||||
|
||||
this->data[4] = 0.0F;
|
||||
this->data[5] = -h;
|
||||
this->data[6] = 0.0F;
|
||||
this->data[7] = 0.0F;
|
||||
|
||||
this->data[8] = 0.0F;
|
||||
this->data[9] = 0.0F;
|
||||
this->data[10] =
|
||||
(t_screen.farPlaneDist + t_screen.nearPlaneDist) /
|
||||
(t_screen.farPlaneDist - t_screen.nearPlaneDist);
|
||||
this->data[11] = -1.0F;
|
||||
|
||||
this->data[12] = 0.0F;
|
||||
this->data[13] = 0.0F;
|
||||
this->data[14] =
|
||||
(2.0F * t_screen.farPlaneDist * t_screen.nearPlaneDist) /
|
||||
(t_screen.farPlaneDist - t_screen.nearPlaneDist);
|
||||
this->data[15] = 0.0F;
|
||||
}
|
||||
|
||||
/** Create a view matrix that transforms coordinates in
|
||||
* such a way that the user looks at a target vector
|
||||
* direction from a position vector.
|
||||
*
|
||||
* Clone of OpenGL lookAt function
|
||||
* https://learnopengl.com/Getting-started/Camera
|
||||
*/
|
||||
void Matrix::lookAt(Vector3 &t_up, Vector3 &t_position, Vector3 &t_target)
|
||||
{
|
||||
Vector3 camForward, camUp, camRight;
|
||||
|
||||
camForward = t_position - t_target;
|
||||
camForward.normalize();
|
||||
camRight = t_up * camForward;
|
||||
camRight.normalize();
|
||||
camUp = camForward * camRight;
|
||||
|
||||
data[0] = camRight.x;
|
||||
data[4] = camRight.y;
|
||||
data[8] = camRight.z;
|
||||
data[12] = -camRight.innerProduct(t_position);
|
||||
|
||||
data[1] = camUp.x;
|
||||
data[5] = camUp.y;
|
||||
data[9] = camUp.z;
|
||||
data[13] = -camUp.innerProduct(t_position);
|
||||
|
||||
data[2] = camForward.x;
|
||||
data[6] = camForward.y;
|
||||
data[10] = camForward.z;
|
||||
data[14] = -camForward.innerProduct(t_position);
|
||||
|
||||
data[3] = 0;
|
||||
data[7] = 0;
|
||||
data[11] = 0;
|
||||
data[15] = 1;
|
||||
}
|
||||
|
||||
void Matrix::print()
|
||||
{
|
||||
printf("MATRIX(\n%f, %f, %f, %f\n%f, %f, %f, %f\n%f, %f, %f, %f\n%f, %f, %f, %f\n)\n",
|
||||
data[0], data[1], data[2], data[3],
|
||||
data[4], data[5], data[6], data[7],
|
||||
data[8], data[9], data[10], data[11],
|
||||
data[12], data[13], data[14], data[15]);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../../include/models/math/plane.hpp"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
/** Create empty plane */
|
||||
Plane::Plane() { this->distance = 0; }
|
||||
|
||||
/** Create by specyfying 3 points.
|
||||
* This function assumes that the points
|
||||
* are given in counter clockwise order
|
||||
*/
|
||||
Plane::Plane(Vector3 &a, Vector3 &b, Vector3 &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(Vector3 &a, Vector3 &b, Vector3 &c)
|
||||
{
|
||||
Vector3 aux1 = a - b;
|
||||
Vector3 aux2 = c - b;
|
||||
this->normal = aux2 * aux1;
|
||||
this->normal.normalize();
|
||||
this->distance = -this->normal.innerProduct(b);
|
||||
}
|
||||
|
||||
void Plane::print()
|
||||
{
|
||||
printf("Plane(Vector3(%f, %f, %f), %f)\n", this->normal.x, this->normal.y, this->normal.z, this->distance);
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../../include/models/math/point.hpp"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
/** Create by specifying values */
|
||||
Point::Point(float x, float y)
|
||||
{
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
}
|
||||
|
||||
/** Create empty point */
|
||||
Point::Point()
|
||||
{
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
Point::~Point() {}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
void Point::set(float x, float y)
|
||||
{
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
}
|
||||
|
||||
void Point::print()
|
||||
{
|
||||
printf("Point(%f, %f)\n", x, y);
|
||||
}
|
||||
@@ -0,0 +1,298 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../../include/models/math/vector3.hpp"
|
||||
|
||||
#include "../../include/utils/math.hpp"
|
||||
#include <stdio.h>
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
/** Create by specifying 3 points */
|
||||
Vector3::Vector3(float x, float y, float z)
|
||||
{
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->z = z;
|
||||
}
|
||||
|
||||
/** Create with another vector values */
|
||||
Vector3::Vector3(const Vector3 &another)
|
||||
{
|
||||
x = another.x;
|
||||
y = another.y;
|
||||
z = another.z;
|
||||
}
|
||||
|
||||
void Vector3::setByLerp(const Vector3 &v1, const Vector3 &v2, const float t_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.xyz vf7, vf5, vf4 \n\t" // vf7 = v2 - v1
|
||||
"vmulx.xyz vf8, vf7, vf6 \n\t" // vf8 = vf7 * t
|
||||
"vadd.xyz vf9, vf8, vf4 \n\t" // vf9 = vf8 + vf4
|
||||
"sqc2 vf9, 0x0(%0) \n\t" // v0 = vf9
|
||||
:
|
||||
: "r"(&this->xyz), "r"(&v1.xyz), "r"(&v2.xyz), "f"(t_interp)
|
||||
: "$8");
|
||||
}
|
||||
|
||||
/** Create empty vector */
|
||||
Vector3::Vector3()
|
||||
{
|
||||
x = 0;
|
||||
y = 0;
|
||||
z = 0;
|
||||
}
|
||||
|
||||
Vector3::~Vector3() {}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
Vector3 Vector3::operator+(Vector3 v)
|
||||
{
|
||||
Vector3 result;
|
||||
asm volatile( // VU0 Macro program
|
||||
"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"(result.xyz), "r"(this->xyz), "r"(v.xyz));
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector3 Vector3::operator-(const Vector3 &v)
|
||||
{
|
||||
Vector3 result;
|
||||
asm volatile( // VU0 Macro program
|
||||
"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"(result.xyz), "r"(this->xyz), "r"(v.xyz));
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector3 Vector3::operator-(void)
|
||||
{
|
||||
Vector3 result;
|
||||
result.x = -x;
|
||||
result.y = -y;
|
||||
result.z = -z;
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Also called "cross product" */
|
||||
Vector3 Vector3::operator*(Vector3 &v)
|
||||
{
|
||||
Vector3 res;
|
||||
asm volatile( // VU0 Macro program
|
||||
"lqc2 vf4, 0x0(%1) \n\t" // vf4 = this
|
||||
"lqc2 vf5, 0x0(%2) \n\t" // vf5 = v
|
||||
|
||||
"vmulz.y vf6, vf4, vf5 \n\t" // vf6.y = vf4.y * vf5.z
|
||||
"vmuly.z vf6, vf4, vf5 \n\t"
|
||||
"vsubz.y vf6, vf6, vf6 \n\t" // vf6.y = vf4.y - vf4.z
|
||||
"vaddy.x vf8, vf0, vf6 \n\t" // res.x = vf4.y * vf5.z - vf4.z * vf5.y
|
||||
|
||||
"vmulx.z vf6, vf4, vf5 \n\t"
|
||||
"vmulz.x vf6, vf4, vf5 \n\t"
|
||||
"vsubx.z vf6, vf6, vf6 \n\t"
|
||||
"vaddz.y vf8, vf0, vf6 \n\t" // res.y = vf4.z * vf5.x - vf4.x * vf5.z
|
||||
|
||||
"vmuly.x vf6, vf4, vf5 \n\t"
|
||||
"vmulx.y vf6, vf4, vf5 \n\t"
|
||||
"vsuby.x vf6, vf6, vf6 \n\t"
|
||||
"vaddx.z vf8, vf0, vf6 \n\t" // res.z = vf4.x * vf5.y - vf4.y * vf5.x
|
||||
"sqc2 vf8, 0x0(%0) \n\t"
|
||||
:
|
||||
: "r"(res.xyz), "r"(this->xyz), "r"(v.xyz));
|
||||
// result.x = y * v.z - z * v.y;
|
||||
// result.y = z * v.x - x * v.z;
|
||||
// result.z = x * v.y - y * v.x;
|
||||
return res;
|
||||
}
|
||||
|
||||
Vector3 Vector3::operator*(float t)
|
||||
{
|
||||
Vector3 result;
|
||||
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"(result.xyz), "r"(this->xyz), "f"(t)
|
||||
: "$8");
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector3 Vector3::operator/(float t)
|
||||
{
|
||||
Vector3 result;
|
||||
result.x = x / t;
|
||||
result.y = y / t;
|
||||
result.z = z / t;
|
||||
return result;
|
||||
}
|
||||
|
||||
u8 Vector3::shouldBeBackfaceCulled(const Vector3 *t_cameraPos, const Vector3 *v0, const Vector3 *v1, const Vector3 *v2)
|
||||
{
|
||||
register 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"(t_cameraPos->xyz), "r"(v0->xyz), "r"(v1->xyz), "r"(v2->xyz)
|
||||
: "$2");
|
||||
return dot <= 0.0F;
|
||||
}
|
||||
|
||||
/** Checks intersection with given square */
|
||||
u8 Vector3::collidesSquare(Vector3 &t_min, Vector3 &t_max)
|
||||
{
|
||||
return ((this->x <= t_max.x && this->x >= t_min.x) && (this->y < t_max.y && this->y >= t_min.y) && (this->z <= t_max.z && this->z >= t_min.z)) ? 1 : 0;
|
||||
}
|
||||
|
||||
/** Checks is this vector is on given square */
|
||||
u8 Vector3::isOnSquare(Vector3 &t_min, Vector3 &t_max)
|
||||
{
|
||||
return ((this->x <= t_max.x && this->x >= t_min.x) && (this->y >= t_max.y) && (this->z <= t_max.z && this->z >= t_min.z)) ? 1 : 0;
|
||||
}
|
||||
|
||||
float Vector3::length()
|
||||
{
|
||||
register float result;
|
||||
asm volatile( // VU0 Macro program
|
||||
"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"
|
||||
"vaddq.x vf8, vf0, Q \n\t"
|
||||
"qmfc2 $2, vf8 \n\t"
|
||||
"mtc1 $2, %0 \n\t"
|
||||
: "=f"(result)
|
||||
: "r"(this->xyz)
|
||||
: "$2");
|
||||
return result;
|
||||
// return Math::sqrt(x * x + y * y + z * z);
|
||||
}
|
||||
|
||||
void Vector3::normalize()
|
||||
{
|
||||
asm volatile( // VU0 Macro program
|
||||
"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"
|
||||
"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->xyz));
|
||||
}
|
||||
|
||||
/** Also called dot3 */
|
||||
float Vector3::innerProduct(Vector3 &v)
|
||||
{
|
||||
register float result;
|
||||
asm volatile( // VU0 Macro program
|
||||
"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->xyz), "r"(v.xyz)
|
||||
: "$2");
|
||||
return result;
|
||||
// return (x * v.x + y * v.y + z * v.z);
|
||||
}
|
||||
|
||||
void Vector3::set(float x, float y, float z)
|
||||
{
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->z = z;
|
||||
}
|
||||
|
||||
void Vector3::set(Vector3 &v)
|
||||
{
|
||||
this->x = v.x;
|
||||
this->y = v.y;
|
||||
this->z = v.z;
|
||||
}
|
||||
|
||||
void Vector3::copy(Vector3 &v)
|
||||
{
|
||||
asm volatile( // VU0 Macro program
|
||||
"lq $6, 0x0(%1) \n\t"
|
||||
"sq $6, 0x0(%0) \n\t"
|
||||
:
|
||||
: "r"(v.xyz), "r"(this->xyz)
|
||||
: "$6");
|
||||
}
|
||||
|
||||
float Vector3::distanceTo(Vector3 &v)
|
||||
{
|
||||
register float result;
|
||||
asm volatile( // VU0 Macro program
|
||||
"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"
|
||||
"vaddq.x vf8, vf0, Q \n\t"
|
||||
"qmfc2 $2, vf8 \n\t"
|
||||
"mtc1 $2, %0 \n\t"
|
||||
: "=f"(result)
|
||||
: "r"(this->xyz), "r"(v.xyz)
|
||||
: "$2");
|
||||
return result;
|
||||
// return Math::sqrt((this->x - another.x) * (this->x - another.x) +
|
||||
// (this->y - another.y) * (this->y - another.y) +
|
||||
// (this->z - another.z) * (this->z - another.z));
|
||||
}
|
||||
|
||||
void Vector3::print()
|
||||
{
|
||||
printf("Vector3(%f, %f, %f)\n", x, y, z);
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../include/models/md2_model.hpp"
|
||||
|
||||
#include "../include/utils/anorms.hpp"
|
||||
#include "../include/utils/string.hpp"
|
||||
#include "../include/utils/debug.hpp"
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
MD2Model::MD2Model(char *t_md2File)
|
||||
{
|
||||
filename = String::createWithoutExtension(t_md2File);
|
||||
|
||||
verticesPerFrameCount = 0;
|
||||
coordinatesCount = 0;
|
||||
trianglesCount = 0;
|
||||
framesCount = 0;
|
||||
|
||||
animState.startFrame = 0;
|
||||
animState.endFrame = 0;
|
||||
animState.interpolation = 0.0F;
|
||||
animState.animType = 0;
|
||||
animState.currentFrame = 0;
|
||||
animState.nextFrame = 0;
|
||||
animState.speed = 0.1F;
|
||||
|
||||
vertices = 0;
|
||||
coordinates = 0;
|
||||
normalIndexes = 0;
|
||||
triangles = 0;
|
||||
}
|
||||
|
||||
MD2Model::~MD2Model()
|
||||
{
|
||||
delete[] vertices;
|
||||
delete[] normalIndexes;
|
||||
delete[] coordinates;
|
||||
delete[] triangles;
|
||||
}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
u32 MD2Model::getCurrentFrameData(VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, VECTOR *o_colors, Vector3 &t_cameraPos, float t_scale, u8 t_shouldBeBackfaceCulled)
|
||||
{
|
||||
u32 i = 0;
|
||||
animState.interpolation += animState.speed;
|
||||
if (animState.interpolation >= 1.0F)
|
||||
{
|
||||
animState.interpolation = 0.0F;
|
||||
animState.currentFrame = animState.nextFrame;
|
||||
if (++animState.nextFrame > animState.endFrame)
|
||||
animState.nextFrame = animState.startFrame;
|
||||
}
|
||||
for (u32 iTri = 0; iTri < trianglesCount; iTri++)
|
||||
{
|
||||
for (u32 iVert = 0; iVert < 3; iVert++)
|
||||
{
|
||||
const u32 CURR_VERTICE =
|
||||
triangles[iTri].verticeIndexes[iVert] +
|
||||
(verticesPerFrameCount * animState.currentFrame);
|
||||
|
||||
if (animState.startFrame == animState.endFrame)
|
||||
{
|
||||
calc3Vectors[iVert].x = vertices[CURR_VERTICE].x * t_scale;
|
||||
calc3Vectors[iVert].y = vertices[CURR_VERTICE].y * t_scale;
|
||||
calc3Vectors[iVert].z = vertices[CURR_VERTICE].z * t_scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
const u32 NEXT_VERTICE =
|
||||
triangles[iTri].verticeIndexes[iVert] +
|
||||
(verticesPerFrameCount * animState.nextFrame);
|
||||
calcVector.setByLerp(vertices[CURR_VERTICE], vertices[NEXT_VERTICE], animState.interpolation);
|
||||
calc3Vectors[iVert].x = calcVector.x * t_scale;
|
||||
calc3Vectors[iVert].y = calcVector.y * t_scale;
|
||||
calc3Vectors[iVert].z = calcVector.z * t_scale;
|
||||
}
|
||||
}
|
||||
if (!t_shouldBeBackfaceCulled || Vector3::shouldBeBackfaceCulled(&t_cameraPos, &calc3Vectors[2], &calc3Vectors[1], &calc3Vectors[0]) == 0)
|
||||
for (u32 iVert = 0; iVert < 3; iVert++)
|
||||
{
|
||||
const u32 CURR_VERTICE =
|
||||
triangles[iTri].verticeIndexes[iVert] +
|
||||
(verticesPerFrameCount * animState.currentFrame);
|
||||
|
||||
const u32 CURR_COORD = triangles[iTri].coordIndexes[iVert];
|
||||
|
||||
o_vertices[i][0] = calc3Vectors[iVert].x;
|
||||
o_vertices[i][1] = calc3Vectors[iVert].y;
|
||||
o_vertices[i][2] = calc3Vectors[iVert].z;
|
||||
o_vertices[i][3] = 1.0F;
|
||||
|
||||
o_normals[i][0] = ANORMS[normalIndexes[CURR_VERTICE]][0];
|
||||
o_normals[i][1] = ANORMS[normalIndexes[CURR_VERTICE]][1];
|
||||
o_normals[i][2] = ANORMS[normalIndexes[CURR_VERTICE]][2];
|
||||
o_normals[i][3] = 1.0F;
|
||||
|
||||
o_coordinates[i][0] = coordinates[CURR_COORD].x;
|
||||
o_coordinates[i][1] = 1.0F - coordinates[CURR_COORD].y;
|
||||
o_coordinates[i][2] = 1.0F;
|
||||
o_coordinates[i][3] = 1.0F;
|
||||
|
||||
o_colors[i][0] = 1.0F;
|
||||
o_colors[i][1] = 1.0F;
|
||||
o_colors[i][2] = 1.0F;
|
||||
o_colors[i][3] = 1.0F;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
void MD2Model::allocateMemory()
|
||||
{
|
||||
vertices = new Vector3[verticesPerFrameCount * framesCount];
|
||||
normalIndexes = new u32[verticesPerFrameCount * framesCount];
|
||||
coordinates = new Point[coordinatesCount];
|
||||
triangles = new MD2Triangle[trianglesCount];
|
||||
}
|
||||
@@ -0,0 +1,339 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../include/models/mesh.hpp"
|
||||
|
||||
#include "../include/loaders/obj_loader.hpp"
|
||||
#include "../include/loaders/md2_loader.hpp"
|
||||
#include "../include/loaders/dff_loader.hpp"
|
||||
#include "../include/loaders/bmp_loader.hpp"
|
||||
#include "../include/utils/debug.hpp"
|
||||
#include "../include/utils/string.hpp"
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
Mesh::Mesh()
|
||||
{
|
||||
shouldBeFrustumCulled = true;
|
||||
shouldBeBackfaceCulled = false;
|
||||
shouldBeLighted = false;
|
||||
isMd2Loaded = false;
|
||||
isObjLoaded = false;
|
||||
isDffLoaded = false;
|
||||
isSpecInitialized = false;
|
||||
scale = 1.0F;
|
||||
}
|
||||
|
||||
Mesh::~Mesh()
|
||||
{
|
||||
if (isMd2Loaded)
|
||||
delete md2;
|
||||
if (isObjLoaded)
|
||||
delete obj;
|
||||
if (isDffLoaded)
|
||||
delete dff;
|
||||
}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
void Mesh::loadDff(char *t_subfolder, char *t_dffFile, Vector3 &t_initPos, float t_scale)
|
||||
{
|
||||
createSpecIfNotCreated();
|
||||
DffLoader loader = DffLoader();
|
||||
dff = new DffModel();
|
||||
char *dffPath = String::createConcatenated(t_subfolder, t_dffFile);
|
||||
loader.load(dff->clump, dffPath, t_scale);
|
||||
delete[] dffPath;
|
||||
position = t_initPos;
|
||||
setVerticesReference(
|
||||
dff->clump.geometryList.geometries[0].data.dataHeader.vertexCount,
|
||||
dff->clump.geometryList.geometries[0].data.vertexInformation);
|
||||
setDefaultColor();
|
||||
isDffLoaded = true;
|
||||
loadTextures(t_subfolder, ".bmp");
|
||||
spec->allocateTextureBuffer(spec->textures[0].width, spec->textures[0].height); // wtf?
|
||||
}
|
||||
|
||||
void Mesh::setDff(Vector3 &t_initPos, DffModel *t_dffModel, MeshSpec *t_spec)
|
||||
{
|
||||
position = t_initPos;
|
||||
spec = t_spec;
|
||||
isSpecInitialized = 1;
|
||||
dff = t_dffModel;
|
||||
setVerticesReference(
|
||||
dff->clump.geometryList.geometries[0].data.dataHeader.vertexCount,
|
||||
dff->clump.geometryList.geometries[0].data.vertexInformation);
|
||||
setDefaultColor();
|
||||
isDffLoaded = true;
|
||||
}
|
||||
|
||||
void Mesh::loadObj(char *t_subfolder, char *t_objFile, Vector3 &t_initPos, float t_scale)
|
||||
{
|
||||
createSpecIfNotCreated();
|
||||
ObjLoader loader = ObjLoader();
|
||||
obj = new ObjModel(t_objFile);
|
||||
char *objPath = String::createConcatenated(t_subfolder, t_objFile);
|
||||
loader.load(obj, objPath, t_scale);
|
||||
delete[] objPath;
|
||||
position = t_initPos;
|
||||
setVerticesReference(obj->facesCount, obj->vertices);
|
||||
setDefaultColor();
|
||||
isObjLoaded = true;
|
||||
loadTextures(t_subfolder, ".bmp");
|
||||
spec->allocateTextureBuffer(spec->textures[0].width, spec->textures[0].height); // wtf?
|
||||
}
|
||||
|
||||
void Mesh::setObj(Vector3 &t_initPos, ObjModel *t_objModel, MeshSpec *t_spec)
|
||||
{
|
||||
position = t_initPos;
|
||||
spec = t_spec;
|
||||
isSpecInitialized = true;
|
||||
obj = t_objModel;
|
||||
setVerticesReference(obj->facesCount, obj->vertices);
|
||||
setDefaultColor();
|
||||
isObjLoaded = true;
|
||||
}
|
||||
|
||||
void Mesh::createSpecIfNotCreated()
|
||||
{
|
||||
if (!isSpecInitialized)
|
||||
{
|
||||
isSpecInitialized = true;
|
||||
spec = new MeshSpec();
|
||||
}
|
||||
}
|
||||
|
||||
void Mesh::setAnimSpeed(float t_value)
|
||||
{
|
||||
if (isMd2Loaded == 1)
|
||||
md2->animState.speed = t_value;
|
||||
else
|
||||
PRINT_ERR("Animation speed set is not possible, because no md2 3D model was loaded!");
|
||||
}
|
||||
|
||||
void Mesh::setVerticesReference(u32 t_verticesCount, Vector3 *t_verticesRef)
|
||||
{
|
||||
verticesCount = t_verticesCount;
|
||||
vertices = t_verticesRef;
|
||||
computeBoundingBox();
|
||||
}
|
||||
|
||||
u32 Mesh::getVertexCount()
|
||||
{
|
||||
if (isMd2Loaded)
|
||||
return md2->trianglesCount * 3;
|
||||
else if (isObjLoaded)
|
||||
return obj->facesCount;
|
||||
else if (isDffLoaded)
|
||||
return dff->clump.geometryList.geometries[0].data.dataHeader.triangleCount * 3;
|
||||
else
|
||||
{
|
||||
PRINT_ERR("Can't get vertex count, because no 3D model was loaded!");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Mesh::setDefaultWrapSettings(texwrap_t &t_wrapSettings)
|
||||
{
|
||||
t_wrapSettings.horizontal = WRAP_REPEAT;
|
||||
t_wrapSettings.vertical = WRAP_REPEAT;
|
||||
t_wrapSettings.maxu = 0;
|
||||
t_wrapSettings.maxv = 0;
|
||||
t_wrapSettings.minu = 0;
|
||||
t_wrapSettings.minv = 0;
|
||||
}
|
||||
|
||||
void Mesh::loadTextures(char *t_subfolder, char *t_extension)
|
||||
{
|
||||
BmpLoader bmpLoader = BmpLoader();
|
||||
if (isMd2Loaded || isObjLoaded)
|
||||
{
|
||||
spec->textures = new Texture[1];
|
||||
if (isMd2Loaded)
|
||||
bmpLoader.load(spec->textures[0], t_subfolder, md2->filename, t_extension);
|
||||
if (isObjLoaded)
|
||||
bmpLoader.load(spec->textures[0], t_subfolder, obj->filename, t_extension);
|
||||
setDefaultWrapSettings(spec->textures[0].wrapSettings);
|
||||
}
|
||||
else if (isDffLoaded)
|
||||
{
|
||||
spec->textures = new Texture[dff->clump.geometryList.geometries[0].materialList.data.materialCount];
|
||||
for (u8 i = 0; i < dff->clump.geometryList.geometries[0].materialList.data.materialCount; i++)
|
||||
for (u8 j = 0; j < dff->clump.geometryList.geometries[0].materialList.materials[i].data.textureCount; j++)
|
||||
{
|
||||
bmpLoader.load(spec->textures[i], t_subfolder, dff->clump.geometryList.geometries[0].materialList.materials[i].textures[j].textureName.text, t_extension);
|
||||
setDefaultWrapSettings(spec->textures[i].wrapSettings);
|
||||
}
|
||||
}
|
||||
else
|
||||
PRINT_ERR("Can't load textures, because no 3D model was loaded!");
|
||||
}
|
||||
|
||||
// TODO refactor
|
||||
u32 Mesh::getDrawData(u32 splitIndex, VECTOR *t_vertices, VECTOR *t_normals, VECTOR *t_coordinates, VECTOR *t_colors, Vector3 &t_cameraPos)
|
||||
{
|
||||
if (isMd2Loaded)
|
||||
return md2->getCurrentFrameData(t_vertices, t_normals, t_coordinates, t_colors, t_cameraPos, scale, shouldBeBackfaceCulled);
|
||||
else if (isObjLoaded)
|
||||
return obj->getDrawData(t_vertices, t_normals, t_coordinates, t_colors, t_cameraPos, scale, shouldBeBackfaceCulled);
|
||||
else if (isDffLoaded)
|
||||
return dff->getDrawData(splitIndex, t_vertices, t_normals, t_coordinates, t_colors, t_cameraPos, scale, shouldBeBackfaceCulled);
|
||||
PRINT_ERR("Can't get draw data, because no 3D model was loaded!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Set object position and specification */
|
||||
void Mesh::loadMD2(char *t_subfolder, char *t_md2File, Vector3 &t_initPos, float t_scale)
|
||||
{
|
||||
createSpecIfNotCreated();
|
||||
md2 = new MD2Model(t_md2File);
|
||||
MD2Loader loader = MD2Loader();
|
||||
position = t_initPos;
|
||||
char *md2Path = String::createConcatenated(t_subfolder, t_md2File);
|
||||
loader.load(md2, md2Path, t_scale);
|
||||
delete[] md2Path;
|
||||
setVerticesReference(md2->verticesPerFrameCount * md2->framesCount, md2->vertices);
|
||||
setDefaultColor();
|
||||
isMd2Loaded = true;
|
||||
loadTextures(t_subfolder, ".bmp");
|
||||
spec->allocateTextureBuffer(spec->textures[0].width, spec->textures[0].height); // wtf?
|
||||
}
|
||||
|
||||
/** Set's default object color + no transparency */
|
||||
void Mesh::setDefaultColor()
|
||||
{
|
||||
color.r = 0x80;
|
||||
color.g = 0x80;
|
||||
color.b = 0x80;
|
||||
color.a = 0x80;
|
||||
color.q = 1.0F;
|
||||
}
|
||||
|
||||
/** Calculates minimum and maximum X, Y, Z of this 3D objects vertices + current position */
|
||||
void Mesh::getMinMax(Vector3 *t_min, Vector3 *t_max)
|
||||
{
|
||||
Vector3 calc = Vector3();
|
||||
u8 isInitialized = 0;
|
||||
for (u32 i = 0; i < 8; i++)
|
||||
{
|
||||
getFarthestVertex(&calc, i);
|
||||
if (isInitialized == 0)
|
||||
{
|
||||
isInitialized = 1;
|
||||
t_min->set(calc);
|
||||
t_max->set(calc);
|
||||
}
|
||||
|
||||
if (t_min->x > calc.x)
|
||||
t_min->x = calc.x;
|
||||
if (calc.x > t_max->x)
|
||||
t_max->x = calc.x;
|
||||
|
||||
if (t_min->y > calc.y)
|
||||
t_min->y = calc.y;
|
||||
if (calc.y > t_max->y)
|
||||
t_max->y = calc.y;
|
||||
|
||||
if (t_min->z > calc.z)
|
||||
t_min->z = calc.z;
|
||||
if (calc.z > t_max->z)
|
||||
t_max->z = calc.z;
|
||||
}
|
||||
}
|
||||
|
||||
void Mesh::playAnimation(u32 t_startFrame, u32 t_endFrame)
|
||||
{
|
||||
if (isMd2Loaded == 1)
|
||||
{
|
||||
md2->animState.startFrame = t_startFrame;
|
||||
md2->animState.endFrame = t_endFrame;
|
||||
}
|
||||
else
|
||||
PRINT_ERR("Animation is only supported in MD2 format!");
|
||||
}
|
||||
|
||||
/** Returns next farthest vertex of 3D object
|
||||
* @param offset Max 8 (because, box have 8 corners)
|
||||
*/
|
||||
void Mesh::getFarthestVertex(Vector3 *o_result, int t_offset)
|
||||
{
|
||||
o_result->x = boxVertices[t_offset].x + position.x;
|
||||
o_result->y = boxVertices[t_offset].y + position.y;
|
||||
o_result->z = boxVertices[t_offset].z + position.z;
|
||||
}
|
||||
|
||||
/** Check if box is visible in view frustum */
|
||||
u8 Mesh::isInFrustum(Plane *t_frustumPlanes)
|
||||
{
|
||||
Vector3 boxCalcTemp;
|
||||
int boxResult = 1, boxIn = 0, boxOut = 0;
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
boxOut = 0;
|
||||
boxIn = 0;
|
||||
// for each corner of the box do ...
|
||||
// get out of the cycle as soon as a box as corners
|
||||
// both inside and out of the frustum
|
||||
for (int y = 0; y < 8 && (boxIn == 0 || boxOut == 0); y++)
|
||||
{
|
||||
getFarthestVertex(&boxCalcTemp, y);
|
||||
if (t_frustumPlanes[i].distanceTo(boxCalcTemp) < 0)
|
||||
boxOut++;
|
||||
else
|
||||
boxIn++;
|
||||
}
|
||||
//if all corners are out
|
||||
if (boxIn == 0)
|
||||
return 0;
|
||||
else if (boxOut)
|
||||
boxResult = 1;
|
||||
}
|
||||
return boxResult;
|
||||
}
|
||||
|
||||
/** Compute 8 farthest corners for intersection check */
|
||||
void Mesh::computeBoundingBox()
|
||||
{
|
||||
float lowX, lowY, lowZ, hiX, hiY, hiZ;
|
||||
lowX = hiX = vertices[0].x;
|
||||
lowY = hiY = vertices[0].y;
|
||||
lowZ = hiZ = vertices[0].z;
|
||||
for (u32 i = 0; i < verticesCount; i++)
|
||||
{
|
||||
if (lowX > vertices[i].x)
|
||||
lowX = vertices[i].x;
|
||||
if (hiX < vertices[i].x)
|
||||
hiX = vertices[i].x;
|
||||
|
||||
if (lowY > vertices[i].y)
|
||||
lowY = vertices[i].y;
|
||||
if (hiY < vertices[i].y)
|
||||
hiY = vertices[i].y;
|
||||
|
||||
if (lowZ > vertices[i].z)
|
||||
lowZ = vertices[i].z;
|
||||
if (hiZ < vertices[i].z)
|
||||
hiZ = vertices[i].z;
|
||||
}
|
||||
boxVertices[0].set(lowX, lowY, lowZ);
|
||||
boxVertices[1].set(lowX, lowY, hiZ);
|
||||
boxVertices[2].set(lowX, hiY, lowZ);
|
||||
boxVertices[3].set(lowX, hiY, hiZ);
|
||||
|
||||
boxVertices[4].set(hiX, lowY, lowZ);
|
||||
boxVertices[5].set(hiX, lowY, hiZ);
|
||||
boxVertices[6].set(hiX, hiY, lowZ);
|
||||
boxVertices[7].set(hiX, hiY, hiZ);
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../include/models/mesh_spec.hpp"
|
||||
|
||||
#include "../include/utils/debug.hpp"
|
||||
#include "../include/utils/math.hpp"
|
||||
#include <graph_vram.h>
|
||||
#include <gs_psm.h>
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
MeshSpec::MeshSpec()
|
||||
{
|
||||
PRINT_LOG("Creating object 3D spec");
|
||||
this->setupLodAndClut();
|
||||
PRINT_LOG("Object 3D spec created!");
|
||||
}
|
||||
|
||||
/** Release memory if object was initialized */
|
||||
MeshSpec::~MeshSpec()
|
||||
{
|
||||
if (this->isTextureVRAMAllocated == true)
|
||||
graph_vram_free(this->textureBuffer.address);
|
||||
}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
/** Configure and allocate vRAM for texture buffer */
|
||||
void MeshSpec::allocateTextureBuffer(u16 t_width, u16 t_height)
|
||||
{
|
||||
this->textureBuffer.width = t_width;
|
||||
this->textureBuffer.psm = GS_PSM_24;
|
||||
this->textureBuffer.address = graph_vram_allocate(t_width, t_height, GS_PSM_24, GRAPH_ALIGN_BLOCK);
|
||||
if (this->textureBuffer.address <= 1)
|
||||
PRINT_ERR("Texture buffer allocation error. No memory!");
|
||||
this->textureBuffer.info.width = draw_log2(t_width);
|
||||
this->textureBuffer.info.height = draw_log2(t_height);
|
||||
this->textureBuffer.info.components = TEXTURE_COMPONENTS_RGB;
|
||||
this->textureBuffer.info.function = TEXTURE_FUNCTION_MODULATE;
|
||||
this->isTextureVRAMAllocated = true;
|
||||
}
|
||||
|
||||
/** Configure and allocate vRAM for texture buffer */
|
||||
void MeshSpec::deallocateTextureBuffer()
|
||||
{
|
||||
if (this->isTextureVRAMAllocated)
|
||||
{
|
||||
graph_vram_free(textureBuffer.address);
|
||||
this->isTextureVRAMAllocated = false;
|
||||
}
|
||||
}
|
||||
|
||||
/** Sets texture level of details settings and CLUT settings */
|
||||
void MeshSpec::setupLodAndClut()
|
||||
{
|
||||
PRINT_LOG("Setting LOD, CLUT");
|
||||
this->lod.calculation = LOD_USE_K;
|
||||
this->lod.max_level = 0;
|
||||
this->lod.mag_filter = LOD_MAG_NEAREST;
|
||||
this->lod.min_filter = LOD_MIN_NEAREST;
|
||||
this->lod.l = 0;
|
||||
this->lod.k = 0.0F;
|
||||
|
||||
this->clut.storage_mode = CLUT_STORAGE_MODE1;
|
||||
this->clut.start = 0;
|
||||
this->clut.psm = 0;
|
||||
this->clut.load_method = CLUT_NO_LOAD;
|
||||
this->clut.address = 0;
|
||||
PRINT_LOG("LOD, CLUT set!");
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../include/models/obj_model.hpp"
|
||||
|
||||
#include "../include/utils/debug.hpp"
|
||||
#include "../include/utils/string.hpp"
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
ObjModel::ObjModel(char *t_objFile)
|
||||
{
|
||||
filename = String::createWithoutExtension(t_objFile);
|
||||
}
|
||||
|
||||
ObjModel::~ObjModel()
|
||||
{
|
||||
if (isMemoryAllocated == true)
|
||||
{
|
||||
delete[] vertices;
|
||||
delete[] coordinates;
|
||||
delete[] normals;
|
||||
|
||||
delete[] verticeFaces;
|
||||
delete[] coordinateFaces;
|
||||
delete[] normalFaces;
|
||||
}
|
||||
}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
u32 ObjModel::getDrawData(VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, VECTOR *o_colors, Vector3 &t_cameraPos, float t_scale, u8 t_shouldBeBackfaceCulled)
|
||||
{
|
||||
u32 addedFaces = 0;
|
||||
for (u32 i = 0; i < facesCount; i += 3)
|
||||
if (!t_shouldBeBackfaceCulled || Vector3::shouldBeBackfaceCulled(
|
||||
&t_cameraPos,
|
||||
&vertices[verticeFaces[i]],
|
||||
&vertices[verticeFaces[i + 1]],
|
||||
&vertices[verticeFaces[i + 2]]) == 0)
|
||||
{
|
||||
fillNextFace(o_vertices, o_normals, o_coordinates, o_colors, i, addedFaces++);
|
||||
fillNextFace(o_vertices, o_normals, o_coordinates, o_colors, i + 1, addedFaces++);
|
||||
fillNextFace(o_vertices, o_normals, o_coordinates, o_colors, i + 2, addedFaces++);
|
||||
}
|
||||
|
||||
return addedFaces;
|
||||
}
|
||||
|
||||
/** Allocate memory for vertices,coords etc.
|
||||
* Called by ObjLoader
|
||||
*/
|
||||
void ObjModel::allocateMemory()
|
||||
{
|
||||
PRINT_LOG("Allocating 3D object specification memory");
|
||||
vertices = new Vector3[verticesCount];
|
||||
coordinates = new Vector3[coordinatesCount];
|
||||
normals = new Vector3[normalsCount];
|
||||
|
||||
verticeFaces = new u32[facesCount];
|
||||
coordinateFaces = new u32[facesCount];
|
||||
normalFaces = new u32[facesCount];
|
||||
isMemoryAllocated = true;
|
||||
PRINT_LOG("3D object specification memory allocated!");
|
||||
}
|
||||
|
||||
void ObjModel::fillNextFace(VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, VECTOR *o_colors, u32 t_getI, u32 t_setI)
|
||||
{
|
||||
o_vertices[t_setI][0] = vertices[verticeFaces[t_getI]].x;
|
||||
o_vertices[t_setI][1] = vertices[verticeFaces[t_getI]].y;
|
||||
o_vertices[t_setI][2] = vertices[verticeFaces[t_getI]].z;
|
||||
o_vertices[t_setI][3] = 1.0F;
|
||||
|
||||
o_normals[t_setI][0] = normals[normalFaces[t_getI]].x;
|
||||
o_normals[t_setI][1] = normals[normalFaces[t_getI]].y;
|
||||
o_normals[t_setI][2] = normals[normalFaces[t_getI]].z;
|
||||
o_normals[t_setI][3] = 1.0F;
|
||||
|
||||
o_coordinates[t_setI][0] = coordinates[coordinateFaces[t_getI]].x;
|
||||
o_coordinates[t_setI][1] = coordinates[coordinateFaces[t_getI]].y;
|
||||
o_coordinates[t_setI][2] = 1.0F;
|
||||
o_coordinates[t_setI][3] = 1.0F;
|
||||
|
||||
o_colors[t_setI][0] = 1.0F;
|
||||
o_colors[t_setI][1] = 1.0F;
|
||||
o_colors[t_setI][2] = 1.0F;
|
||||
o_colors[t_setI][3] = 1.0F;
|
||||
}
|
||||
Reference in New Issue
Block a user