moved from h4570/tyra

This commit is contained in:
Sandro Sobczyński
2020-10-28 09:16:49 +01:00
commit 68eb496e11
90 changed files with 8066 additions and 0 deletions
+59
View File
@@ -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;
}
+263
View File
@@ -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]);
}
+50
View File
@@ -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);
}
+48
View File
@@ -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);
}
+298
View File
@@ -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);
}
+132
View File
@@ -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];
}
+339
View File
@@ -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);
}
+82
View File
@@ -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!");
}
+99
View File
@@ -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;
}