+5
-2
@@ -6,6 +6,7 @@ EE_OBJS = \
|
||||
models/math/point.o \
|
||||
models/math/vector3.o \
|
||||
models/mesh_frame.o \
|
||||
models/bounding_box.o \
|
||||
models/mesh_material.o \
|
||||
models/mesh.o \
|
||||
models/sprite.o \
|
||||
@@ -34,8 +35,10 @@ all: $(EE_OBJS)
|
||||
ar rcs $(LIB_NAME) $(EE_OBJS)
|
||||
rm -f $(EE_OBJS)
|
||||
|
||||
# https://github.com/microsoft/wsl/issues/2468#issuecomment-374904520
|
||||
#%.vsm: %.vcl # sudo service binfmt-support start
|
||||
#%.vcl: %.vclpp
|
||||
# $(EE_VCLPP) $< $@
|
||||
|
||||
#%.vsm: %.vcl
|
||||
# $(EE_VCL) $< >> $@
|
||||
|
||||
%.o: %.vsm
|
||||
|
||||
@@ -5,6 +5,7 @@ EE_CFLAGS := -DHAVE_LIBPNG -DHAVE_ZLIB $(EE_CFLAGS)
|
||||
EE_CXXFLAGS := -DHAVE_LIBPNG -DHAVE_ZLIB $(EE_CXXFLAGS)
|
||||
EE_DVP = dvp-as
|
||||
EE_VCL = vcl
|
||||
EE_VCLPP = vclpp
|
||||
LIB_NAME = libtyra.a
|
||||
|
||||
include $(PS2SDK)/samples/Makefile.pref
|
||||
|
||||
@@ -41,13 +41,13 @@ Engine::~Engine() {}
|
||||
|
||||
void Engine::setDefaultScreen()
|
||||
{
|
||||
screen.projectionScale = 4096.0F;
|
||||
screen.nearPlaneDist = 2.0F;
|
||||
screen.farPlaneDist = 2000.0F;
|
||||
screen.fov = 60.0F;
|
||||
screen.aspectRatio = 4.0F / 3.0F;
|
||||
screen.width = 640.0F;
|
||||
screen.height = 480.0F;
|
||||
screen.aspectRatio = screen.width / screen.height;
|
||||
screen.projectionScale = 4096.0F; // PS2 have 4k drawing area
|
||||
}
|
||||
|
||||
void Engine::init(Game *t_game, u32 t_gifPacketSize)
|
||||
@@ -77,8 +77,9 @@ void Engine::firePS2()
|
||||
{
|
||||
SifInitRpc(0);
|
||||
srand(time(NULL));
|
||||
fileService.startThread();
|
||||
audio.startThread(&fileService);
|
||||
// fileService.startThread();
|
||||
// audio.startThread(&fileService);
|
||||
audio.startThread(NULL);
|
||||
isInitialized = 0;
|
||||
mainThreadId = GetThreadId();
|
||||
}
|
||||
@@ -94,7 +95,7 @@ void Engine::gameLoop()
|
||||
fps = timer.getFPS();
|
||||
fpsDelayer = 0;
|
||||
}
|
||||
timer.primeTimer();
|
||||
timer.prime();
|
||||
renderer->endFrame(fps);
|
||||
/** -6~ FPS */
|
||||
SetAlarm(150, &Engine::wakeup, &mainThreadId);
|
||||
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
void init(Game *t_game, u32 t_gifPacketSize);
|
||||
void setDefaultScreen();
|
||||
Renderer *renderer;
|
||||
FileService fileService;
|
||||
// FileService fileService;
|
||||
Audio audio;
|
||||
ScreenSettings screen;
|
||||
Pad pad;
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Michał Mostowik <mostek3pl@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _TYRA_BOUNDING_BOX_
|
||||
#define _TYRA_BOUNDING_BOX_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <tamtypes.h>
|
||||
#include "math/point.hpp"
|
||||
#include "math/vector3.hpp"
|
||||
|
||||
/**
|
||||
* Struct containing face data used in
|
||||
* bounding box class.
|
||||
*/
|
||||
struct BoundingBoxFace
|
||||
{
|
||||
BoundingBoxFace(){
|
||||
|
||||
};
|
||||
BoundingBoxFace(const Vector3 &t_minCorner, const Vector3 &t_maxCorner, float t_axisPos)
|
||||
{
|
||||
minCorner = t_minCorner;
|
||||
maxCorner = t_maxCorner;
|
||||
axisPosition = t_axisPos;
|
||||
}
|
||||
/** Position of the face on it's respective axis. */
|
||||
float axisPosition;
|
||||
/** Corner of the face with lower coordinates */
|
||||
Vector3 minCorner;
|
||||
/** Corner of the face with higher coordinates */
|
||||
Vector3 maxCorner;
|
||||
};
|
||||
|
||||
/**
|
||||
* Class containing bounding box data
|
||||
* which can be used for collision detection.
|
||||
*/
|
||||
class BoundingBox
|
||||
{
|
||||
public:
|
||||
BoundingBox(Vector3 *t_vertices);
|
||||
~BoundingBox();
|
||||
const float &getHeight() { return _height; };
|
||||
const float &getDepth() { return _depth; };
|
||||
const float &getWidth() { return _width; };
|
||||
/** @returns the vector directly in middle of the bounding box. */
|
||||
const Vector3 &getCenter() { return _centerVector; };
|
||||
/** @returns the front face (further on z-axis) */
|
||||
const BoundingBoxFace &getFrontFace() { return _frontFace; };
|
||||
/** @returns the back face (nearer on z-axis) */
|
||||
const BoundingBoxFace &getBackFace() { return _backFace; };
|
||||
/** @returns the left face (further on x-axis) */
|
||||
const BoundingBoxFace &getLeftFace() { return _leftFace; };
|
||||
/** @returns the right face (nearer on x-axis) */
|
||||
const BoundingBoxFace &getRightFace() { return _rightFace; };
|
||||
/** @returns the top face (further on y-axis) */
|
||||
const BoundingBoxFace &getTopFace() { return _topFace; };
|
||||
/** @returns the bottom face (nearer on y-axis) */
|
||||
const BoundingBoxFace &getBottomFace() { return _bottomFace; };
|
||||
/**
|
||||
* @returns bounding box raw vertices array.
|
||||
* Total length: 8
|
||||
*/
|
||||
const Vector3 &getVertex(const u8 &i) { return _vertices[i]; };
|
||||
/** @returns single vertex from raw vertices array.*/
|
||||
Vector3 *getVertices() { return _vertices; };
|
||||
|
||||
private:
|
||||
Vector3 _vertices[8];
|
||||
float _height, _depth, _width;
|
||||
Vector3 _centerVector;
|
||||
/** Front face (further on z-axis) */
|
||||
BoundingBoxFace _frontFace;
|
||||
/** Back face (nearer on z-axis) */
|
||||
BoundingBoxFace _backFace;
|
||||
/** Left face (nearer on x-axis) */
|
||||
BoundingBoxFace _leftFace;
|
||||
/** Right face (further on x-axis) */
|
||||
BoundingBoxFace _rightFace;
|
||||
/** Top face (further on y-axis) */
|
||||
BoundingBoxFace _topFace;
|
||||
/** Bottom face (nearer on y-axis) */
|
||||
BoundingBoxFace _bottomFace;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -17,7 +17,7 @@
|
||||
struct LightBulb
|
||||
{
|
||||
Vector3 position;
|
||||
u16 intensity;
|
||||
u8 intensity;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,29 +13,174 @@
|
||||
|
||||
#include "vector3.hpp"
|
||||
#include "../screen_settings.hpp"
|
||||
#include <string.h>
|
||||
|
||||
/** https://en.wikipedia.org/wiki/Matrix_(mathematics) */
|
||||
/** 4x4 Matrix class. */
|
||||
class Matrix
|
||||
{
|
||||
|
||||
public:
|
||||
float data[16];
|
||||
float data[16] __attribute__((aligned(64)));
|
||||
|
||||
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);
|
||||
Matrix(const Matrix &v);
|
||||
Matrix operator*(Matrix &v);
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
/** Create empty matrix. */
|
||||
Matrix();
|
||||
~Matrix();
|
||||
|
||||
void lookAt(Vector3 &t_up, Vector3 &t_position, Vector3 &t_target);
|
||||
/**
|
||||
* Create identity/empty matrix.
|
||||
* @param t_do_identity Identity matrix if true, random matrix values otherwise
|
||||
*/
|
||||
Matrix(const u8 &t_do_identity)
|
||||
{
|
||||
if (t_do_identity)
|
||||
identity();
|
||||
}
|
||||
|
||||
/** Init matrix with given values. */
|
||||
Matrix(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);
|
||||
|
||||
/** Init matrix with other matrix values. */
|
||||
Matrix(const Matrix &v) { memcpy(data, v.data, 16 * sizeof(float)); }
|
||||
|
||||
// ----
|
||||
// Operators
|
||||
// ----
|
||||
|
||||
Vector3 operator*(const Vector3 &v) const;
|
||||
|
||||
Matrix operator*(const Matrix &v) const
|
||||
{
|
||||
Matrix result;
|
||||
cross(result.data, this->data, v.data);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline void operator*=(const Matrix &v) { cross(this->data, this->data, v.data); }
|
||||
|
||||
float &operator[](const u8 &t_index) { return data[t_index]; }
|
||||
|
||||
// ----
|
||||
// Functions
|
||||
// ----
|
||||
|
||||
/**
|
||||
* 1 0 0 0
|
||||
* 0 1 0 0
|
||||
* 0 0 1 0
|
||||
* 0 0 0 1
|
||||
*/
|
||||
void identity();
|
||||
void makeZRotation(float t_radians);
|
||||
void translate(float t_x, float t_y, float t_z);
|
||||
void setPerspective(ScreenSettings &screen);
|
||||
|
||||
/**
|
||||
* 1 0 0 0
|
||||
* 0 1 0 0
|
||||
* 0 0 1 0
|
||||
* 0 0 0 1
|
||||
*/
|
||||
inline void unit() { identity(); };
|
||||
|
||||
/** Translate matrix. */
|
||||
inline void translate(const Vector3 &t_val)
|
||||
{
|
||||
Matrix temp = Matrix(true);
|
||||
temp.translation(t_val);
|
||||
cross(this->data, temp.data, this->data);
|
||||
}
|
||||
|
||||
/** Rotate matrix. */
|
||||
inline void rotate(const Vector3 &t_val)
|
||||
{
|
||||
Matrix temp = Matrix(true);
|
||||
|
||||
temp.rotationZ(t_val.z);
|
||||
cross(this->data, temp.data, this->data);
|
||||
|
||||
temp.identity();
|
||||
temp.rotationY(t_val.y);
|
||||
cross(this->data, temp.data, this->data);
|
||||
|
||||
temp.identity();
|
||||
temp.rotationX(t_val.x);
|
||||
cross(this->data, temp.data, this->data);
|
||||
}
|
||||
|
||||
/** Rotate matrix by X. */
|
||||
inline void rotateX(const float &t_radians)
|
||||
{
|
||||
Matrix temp = Matrix(true);
|
||||
temp.rotationX(t_radians);
|
||||
cross(this->data, temp.data, this->data);
|
||||
}
|
||||
|
||||
/** Rotate matrix by Y. */
|
||||
inline void rotateY(const float &t_radians)
|
||||
{
|
||||
Matrix temp = Matrix(true);
|
||||
temp.rotationY(t_radians);
|
||||
cross(this->data, temp.data, this->data);
|
||||
}
|
||||
|
||||
/** Rotate matrix by Z. */
|
||||
inline void rotateZ(const float &t_radians)
|
||||
{
|
||||
Matrix temp = Matrix(true);
|
||||
temp.rotationZ(t_radians);
|
||||
cross(this->data, temp.data, this->data);
|
||||
}
|
||||
|
||||
/** Rotate matrix by angle. */
|
||||
void rotateByAngle(const float &t_angle, const Vector3 &t_axis)
|
||||
{
|
||||
Matrix temp;
|
||||
temp.rotationByAngle(t_angle, t_axis);
|
||||
cross(this->data, temp.data, this->data);
|
||||
}
|
||||
|
||||
/** Scale matrix. */
|
||||
void scale(const Vector3 &t_val)
|
||||
{
|
||||
Matrix temp = Matrix(true);
|
||||
temp.setScale(t_val);
|
||||
cross(this->data, temp.data, this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create perspective projection matrix.
|
||||
*
|
||||
* Complies with OpenGL standard (gluPerspective).
|
||||
* @see https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml
|
||||
* @param screen Screen settings
|
||||
*/
|
||||
void setPerspective(const ScreenSettings &screen);
|
||||
|
||||
/**
|
||||
* Create a view matrix that transforms coordinates in
|
||||
* such a way that the user looks at a target vector
|
||||
* direction from a position vector.
|
||||
*
|
||||
* Complies with OpenGL standard (glLookAt).
|
||||
* @see https://learnopengl.com/Getting-started/Camera
|
||||
*/
|
||||
void lookAt(const Vector3 &t_position, const Vector3 &t_target);
|
||||
|
||||
/** Print matrix (printf). */
|
||||
const void print() const;
|
||||
|
||||
private:
|
||||
void rotationX(const float &t_radians);
|
||||
void rotationY(const float &t_radians);
|
||||
void rotationZ(const float &t_radians);
|
||||
void rotationByAngle(const float &t_angle, const Vector3 &t_axis);
|
||||
void translation(const Vector3 &t_val);
|
||||
void setScale(const Vector3 &t_val);
|
||||
void setCamera(const float t_pos[4], const float t_vz[4], const float t_vy[4]);
|
||||
void cross(float res[16], const float a[16], const float b[16]) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#define _TYRA_VECTOR3_
|
||||
|
||||
#include <tamtypes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
class Math; // Forward definition
|
||||
|
||||
@@ -20,6 +21,7 @@ class Vector3
|
||||
{
|
||||
|
||||
public:
|
||||
/** This trick will allow use to use vec.x and vex[0] */
|
||||
union
|
||||
{
|
||||
struct
|
||||
@@ -31,31 +33,91 @@ public:
|
||||
float xyz[3] __attribute__((__aligned__(16)));
|
||||
};
|
||||
|
||||
Vector3(float t_x, float t_y, float t_z);
|
||||
Vector3(const Vector3 &v);
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
/** Create empty vector. */
|
||||
Vector3();
|
||||
~Vector3();
|
||||
|
||||
Vector3 operator+(Vector3 v);
|
||||
Vector3 operator-(const Vector3 &v);
|
||||
Vector3 operator*(Vector3 &v);
|
||||
Vector3 operator*(float t);
|
||||
Vector3 operator/(float t);
|
||||
Vector3 operator-(void);
|
||||
/** Create vector with given vector values. */
|
||||
Vector3(const Vector3 &t_v) { set(t_v); }
|
||||
|
||||
static u8 shouldBeBackfaceCulled(const Vector3 *t_cameraPos, const Vector3 *v0, const Vector3 *v1, const Vector3 *v2);
|
||||
u8 collidesSquare(Vector3 &t_min, Vector3 &t_max);
|
||||
u8 isOnSquare(Vector3 &t_min, Vector3 &t_max);
|
||||
float length();
|
||||
void normalize();
|
||||
void setByLerp(const Vector3 &v1, const Vector3 &v2, const float &t_interp, const float &t_scale);
|
||||
float innerProduct(Vector3 &v);
|
||||
/** Create vector with given values. */
|
||||
Vector3(const float &t_x, const float &t_y, const float &t_z) { set(t_x, t_y, t_z); }
|
||||
|
||||
// ----
|
||||
// Operators
|
||||
// ----
|
||||
|
||||
Vector3 operator+(const Vector3 &v) const;
|
||||
Vector3 operator-(const Vector3 &v) const;
|
||||
/** Also called "cross product" */
|
||||
Vector3 operator*(const Vector3 &v) const;
|
||||
Vector3 operator*(const float &t) const;
|
||||
Vector3 operator/(const float &t) const;
|
||||
Vector3 operator-(void) const { return Vector3(-x, -y, -z); }
|
||||
void operator+=(const Vector3 &t);
|
||||
void operator*=(const float &t);
|
||||
|
||||
// ----
|
||||
// Functions
|
||||
// ----
|
||||
|
||||
/** Set vector values via VU0. */
|
||||
void set(const Vector3 &v);
|
||||
void rotate(const Vector3 &v, u8 inversed = false);
|
||||
|
||||
/** Set vector values. */
|
||||
void set(const float &t_x, const float &t_y, const float &t_z);
|
||||
void copy(Vector3 &v);
|
||||
float distanceTo(Vector3 &v);
|
||||
const void print() const;
|
||||
|
||||
/** Also called dot3. */
|
||||
float innerProduct(const Vector3 &v) const;
|
||||
|
||||
/** Get vector length */
|
||||
float length() const;
|
||||
|
||||
/** Normalize vector. */
|
||||
void normalize();
|
||||
|
||||
/** Returns distance between two vectors */
|
||||
float distanceTo(const Vector3 &v) const;
|
||||
|
||||
/**
|
||||
* Checks intersection with given box
|
||||
* @param t_min Opposite min vertex (ex. near, left, down vertex of bounding box)
|
||||
* @param t_max Opposite max vertex (ex. far, right, up vertex of bounding box)
|
||||
*/
|
||||
u8 collidesBox(const Vector3 &t_min, const Vector3 &t_max) const
|
||||
{
|
||||
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 if this vector is on given box (this->y >= box.y)
|
||||
* @param t_min Opposite min vertex (ex. near, left, down vertex of bounding box)
|
||||
* @param t_max Opposite max vertex (ex. far, right, up vertex of bounding box)
|
||||
*/
|
||||
u8 isOnBox(const Vector3 &t_min, const Vector3 &t_max) const
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/** Check if given triangle should be backface culled. */
|
||||
static u8 shouldBeBackfaceCulled(const Vector3 *t_cameraPos, const Vector3 *t_v0, const Vector3 *t_v1, const Vector3 *t_v2);
|
||||
|
||||
/**
|
||||
* Set by linear interpolation between two vertices (animation).
|
||||
* @param t_v1 Before vertex
|
||||
* @param t_v2 After vertex
|
||||
* @param t_interp State of interpolation
|
||||
* @param t_scale Scale
|
||||
*/
|
||||
void setByLerp(const Vector3 &t_v1, const Vector3 &t_v2, const float &t_interp, const float &t_scale);
|
||||
|
||||
const void print() const
|
||||
{
|
||||
printf("Vector3(%f, %f, %f)\n", x, y, z);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -94,10 +94,13 @@ public:
|
||||
* Returns bounding vertex of current frame.
|
||||
* @param i 0-7. Because, bounding box have 8 corners
|
||||
*/
|
||||
Vector3 &getCurrentBoundingBoxVertex(const u8 &i) { return frames[animState.currentFrame].getBoundingBoxVertex(i); };
|
||||
const Vector3 &getCurrentBoundingBoxVertex(const u8 &i) { return frames[animState.currentFrame].getBoundingBoxVertex(i); };
|
||||
|
||||
/** Returns bounding box of current frame. Size: 8 */
|
||||
Vector3 *getCurrentBoundingBox() const { return frames[animState.currentFrame].getBoundingBox(); };
|
||||
/** @returns bounding box vertex array of current frame. Size: 8 */
|
||||
const Vector3 *getCurrentBoundingBoxVertices() const { return frames[animState.currentFrame].getBoundingBoxVertices(); };
|
||||
|
||||
/** @returns bounding box object of current frame. */
|
||||
const BoundingBox *getCurrentBoundingBox() const { return frames[animState.currentFrame].getBoundingBox(); };
|
||||
|
||||
// ----
|
||||
// Setters
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <tamtypes.h>
|
||||
#include "bounding_box.hpp"
|
||||
#include "math/point.hpp"
|
||||
#include "math/vector3.hpp"
|
||||
#include "./mesh_material.hpp"
|
||||
@@ -76,16 +77,21 @@ public:
|
||||
MeshMaterial *getMaterials() const { return materials; };
|
||||
|
||||
/**
|
||||
* Returns bounding box (AABB).
|
||||
* @returns bounding box (AABB).
|
||||
* Total length: 8
|
||||
*/
|
||||
Vector3 *getBoundingBox() { return boundingBox; };
|
||||
Vector3 *getBoundingBoxVertices() { return boundingBoxObj->getVertices(); };
|
||||
|
||||
/**
|
||||
* Returns bounding box (AABB) vertex.
|
||||
* @returns bounding box (AABB) vertex.
|
||||
* Total length: 8
|
||||
*/
|
||||
Vector3 &getBoundingBoxVertex(const u8 &i) { return boundingBox[i]; };
|
||||
const Vector3 &getBoundingBoxVertex(const u8 &i) { return boundingBoxObj->getVertex(i); };
|
||||
|
||||
/**
|
||||
* @returns bounding box (AABB) object pointer.
|
||||
*/
|
||||
BoundingBox *getBoundingBox() { return boundingBoxObj; };
|
||||
|
||||
// ----
|
||||
// Setters
|
||||
@@ -139,7 +145,7 @@ public:
|
||||
void calculateBoundingBoxes();
|
||||
|
||||
private:
|
||||
Vector3 boundingBox[8];
|
||||
BoundingBox *boundingBoxObj;
|
||||
u8 _areSTsAllocated,
|
||||
_areVerticesAllocated,
|
||||
_areNormalsAllocated,
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#define _TYRA_MESH_MATERIAL_
|
||||
|
||||
#include <tamtypes.h>
|
||||
#include "bounding_box.hpp"
|
||||
#include "./math/vector3.hpp"
|
||||
#include "./math/plane.hpp"
|
||||
|
||||
@@ -62,16 +63,21 @@ public:
|
||||
u32 *getNormalFaces() const { return normalFaces; };
|
||||
|
||||
/**
|
||||
* Returns bounding box (AABB).
|
||||
* @returns bounding box (AABB).
|
||||
* Total length: 8
|
||||
*/
|
||||
Vector3 *getBoundingBox() { return boundingBox; };
|
||||
Vector3 *getBoundingBoxVertices() { return boundingBoxObj->getVertices(); };
|
||||
|
||||
/**
|
||||
* Returns bounding box (AABB) vertex.
|
||||
* @returns bounding box (AABB) vertex.
|
||||
* Total length: 8
|
||||
*/
|
||||
Vector3 &getBoundingBoxVertex(const u8 &i) { return boundingBox[i]; };
|
||||
const Vector3 &getBoundingBoxVertex(const u8 &i) { return boundingBoxObj->getVertex(i); };
|
||||
|
||||
/**
|
||||
* @returns bounding box (AABB) object pointer.
|
||||
*/
|
||||
BoundingBox *getBoundingBox() { return boundingBoxObj; };
|
||||
|
||||
// ----
|
||||
// Setters
|
||||
@@ -119,7 +125,7 @@ public:
|
||||
u8 isInFrustum(Plane *t_frustumPlanes, const Vector3 &position);
|
||||
|
||||
private:
|
||||
Vector3 boundingBox[8];
|
||||
BoundingBox *boundingBoxObj;
|
||||
u32 facesCount, id;
|
||||
u32 *vertexFaces, *stFaces, *normalFaces;
|
||||
u8 _isNameSet, _areFacesAllocated, _isBoundingBoxCalculated;
|
||||
|
||||
@@ -22,10 +22,18 @@ struct RenderData
|
||||
{
|
||||
LightBulb *bulbs;
|
||||
u16 bulbsCount;
|
||||
/** Camera (lookAt) */
|
||||
Matrix *worldView;
|
||||
/** Perspective projection */
|
||||
Matrix *perspective;
|
||||
/**
|
||||
* Camera matrix (glLookAt)
|
||||
* OpenGL name: View
|
||||
* Sony name: World view
|
||||
*/
|
||||
Matrix *view;
|
||||
/**
|
||||
* Projection matrix (glPerspective)
|
||||
* OpenGL name: Projection
|
||||
* Sony name: View screen
|
||||
*/
|
||||
Matrix *projection;
|
||||
Vector3 *cameraPosition;
|
||||
Plane *frustumPlanes;
|
||||
prim_t *prim;
|
||||
|
||||
@@ -15,6 +15,12 @@
|
||||
#include <draw_types.h>
|
||||
#include <draw_buffers.h>
|
||||
|
||||
enum SpriteMode
|
||||
{
|
||||
MODE_STRETCH,
|
||||
MODE_REPEAT
|
||||
};
|
||||
|
||||
/**
|
||||
* Class which have contain 2D image data.
|
||||
*/
|
||||
@@ -37,10 +43,16 @@ public:
|
||||
/** Auto generated unique Id. */
|
||||
inline const u32 &getId() const { return id; };
|
||||
|
||||
/** Get sprite drawing mode. */
|
||||
inline const SpriteMode &getMode() const { return mode; };
|
||||
|
||||
// ----
|
||||
// Setters
|
||||
// ----
|
||||
|
||||
/** Set sprite drawing mode. */
|
||||
void setMode(const SpriteMode &t_val) { mode = t_val; }
|
||||
|
||||
// ----
|
||||
// Other
|
||||
// ----
|
||||
@@ -59,6 +71,7 @@ public:
|
||||
|
||||
private:
|
||||
u32 id;
|
||||
SpriteMode mode;
|
||||
u8 _isSizeSet, _flipH, _flipV;
|
||||
void setDefaultColor();
|
||||
void setDefaultLODAndClut();
|
||||
|
||||
@@ -47,38 +47,38 @@ public:
|
||||
* again texture in renderer, when last sent texture id
|
||||
* by renderer will be equal to this id.
|
||||
*/
|
||||
const u32 &getId() const { return id; };
|
||||
inline const u32 getId() const { return id; };
|
||||
|
||||
const u8 &getWidth() const { return width; };
|
||||
inline const u16 getWidth() const { return width; };
|
||||
|
||||
const u8 &getHeight() const { return height; };
|
||||
inline const u16 getHeight() const { return height; };
|
||||
|
||||
const TextureType &getType() const { return _type; };
|
||||
inline const TextureType getType() const { return _type; };
|
||||
|
||||
u32 getTextureLinksCount() const { return static_cast<u32>(texLinks.size()); };
|
||||
inline u32 getTextureLinksCount() const { return static_cast<u32>(texLinks.size()); };
|
||||
|
||||
texwrap_t *getWrapSettings() { return &wrapSettings; };
|
||||
inline texwrap_t *getWrapSettings() { return &wrapSettings; };
|
||||
|
||||
/**
|
||||
* Returns always width * width * 3/4.
|
||||
* 3 for RGB, 4 for RGBA.
|
||||
*/
|
||||
u32 getDataSize() const { return _type == TEX_TYPE_RGB ? width * height * 3 : width * height * 4; };
|
||||
inline u32 getDataSize() const { return _type == TEX_TYPE_RGB ? width * height * 3 : width * height * 4; };
|
||||
|
||||
/**
|
||||
* Texture data, used by renderer.
|
||||
* Array of size getDataSize().
|
||||
*/
|
||||
unsigned char *getData() const { return data; };
|
||||
inline unsigned char *getData() const { return data; };
|
||||
|
||||
/**
|
||||
* Get texture name.
|
||||
* For "textures/abc.bmp" result will be: "abc"
|
||||
*/
|
||||
char *getName() const { return name; };
|
||||
inline char *getName() const { return name; };
|
||||
|
||||
/** Array of texture links. Size of getTextureLinksCount() */
|
||||
const std::vector<TextureLink> &getTextureLinks() const { return texLinks; };
|
||||
inline const std::vector<TextureLink> &getTextureLinks() const { return texLinks; };
|
||||
|
||||
/**
|
||||
* Returns index of link.
|
||||
@@ -189,7 +189,8 @@ private:
|
||||
TextureType _type;
|
||||
std::vector<TextureLink> texLinks;
|
||||
u32 id;
|
||||
u8 width, height, _isNameSet, _isSizeSet;
|
||||
u16 width, height;
|
||||
u8 _isNameSet, _isSizeSet;
|
||||
unsigned char *data;
|
||||
};
|
||||
|
||||
|
||||
@@ -87,7 +87,8 @@ public:
|
||||
// ADPCM
|
||||
|
||||
/**
|
||||
* Load ADPCM sample.
|
||||
* Load ADPCM sample. ADPCM sample is an output from
|
||||
* "adpenc" tool, shipped with PS2SDK.
|
||||
* @param t_path Example: "hit.adpcm" or "folder/jump.adpcm"
|
||||
*/
|
||||
audsrv_adpcm_t *loadADPCM(char *t_path);
|
||||
@@ -125,7 +126,7 @@ public:
|
||||
|
||||
private:
|
||||
u8 songLoaded, volume, realVolume, songPlaying, songInLoop, songFinished;
|
||||
std::vector<AudioListenerRef> songListeners;
|
||||
std::vector<AudioListenerRef *> songListeners;
|
||||
FILE *wav;
|
||||
audsrv_fmt_t format;
|
||||
FileService *fileService;
|
||||
|
||||
@@ -21,7 +21,7 @@ class CameraBase
|
||||
{
|
||||
|
||||
public:
|
||||
CameraBase(ScreenSettings *t_screen, Vector3 *t_position, Vector3 *t_up);
|
||||
CameraBase(ScreenSettings *t_screen, Vector3 *t_position);
|
||||
virtual ~CameraBase(){};
|
||||
|
||||
/**
|
||||
@@ -31,10 +31,10 @@ public:
|
||||
Plane planes[6];
|
||||
|
||||
/**
|
||||
* Projection matrix
|
||||
* View matrix
|
||||
* Set by lookAt() method.
|
||||
*/
|
||||
Matrix worldView;
|
||||
Matrix view;
|
||||
|
||||
protected:
|
||||
/** Pointer to screen settings */
|
||||
@@ -42,7 +42,7 @@ protected:
|
||||
|
||||
/**
|
||||
* Adaption of OpenGL lookAt camera.
|
||||
* Calculates worldView matrix and update frustum planes
|
||||
* Calculates view matrix and update frustum planes
|
||||
* Should be called every frame.
|
||||
*/
|
||||
void lookAt(Vector3 &t_target);
|
||||
@@ -56,9 +56,10 @@ protected:
|
||||
void updatePlanes(Vector3 t_target);
|
||||
|
||||
private:
|
||||
Vector3 *p_position, *p_up;
|
||||
Vector3 *p_position;
|
||||
float farPlaneDist, nearPlaneDist, nearHeight, nearWidth, farHeight, farWidth;
|
||||
Vector3 ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr;
|
||||
Vector3 up; // always 0.0F, 1.0F, 0.0F
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <draw_primitives.h>
|
||||
#include <math3d.h>
|
||||
#include <packet2.h>
|
||||
#include "./light.hpp"
|
||||
#include "../models/mesh.hpp"
|
||||
#include "../models/math/matrix.hpp"
|
||||
#include "../models/screen_settings.hpp"
|
||||
@@ -29,17 +30,18 @@ class GifSender
|
||||
{
|
||||
|
||||
public:
|
||||
GifSender(u32 t_packetSize, ScreenSettings *t_screen);
|
||||
GifSender(u32 t_packetSize, ScreenSettings *t_screen, Light *t_light);
|
||||
~GifSender();
|
||||
|
||||
void initPacket(u8 context);
|
||||
void addObject(RenderData *t_renderData, Mesh &t_mesh, u32 vertexCount, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer);
|
||||
void addClear(zbuffer_t *t_zBuffer);
|
||||
void addClear(zbuffer_t *t_zBuffer, color_t *t_rgb);
|
||||
void sendPacket();
|
||||
void sendClear(zbuffer_t *t_zBuffer);
|
||||
void sendClear(zbuffer_t *t_zBuffer, color_t *t_rgb);
|
||||
static void sendTexture(Texture &texture, texbuffer_t *t_texBuffer);
|
||||
|
||||
private:
|
||||
Light *light;
|
||||
xyz_t *xyz;
|
||||
color_t *rgbaq;
|
||||
texel_t *st;
|
||||
|
||||
@@ -23,10 +23,14 @@ public:
|
||||
Light();
|
||||
~Light();
|
||||
|
||||
static u16 getLightsCount(u32 t_bulbsCount);
|
||||
static void calculateLight(VECTOR *t_lightDirections, VECTOR *t_lightColors, int *t_lightTypes, LightBulb *t_bulbs, u32 t_bulbsCount, Vector3 t_objPosition);
|
||||
u16 getLightsCount(u32 t_bulbsCount);
|
||||
|
||||
/** Values from 0.0000F to 1.0000F */
|
||||
void setAmbientLight(const Vector3 &t_rgb);
|
||||
void calculateLight(VECTOR *t_lightDirections, VECTOR *t_lightColors, int *t_lightTypes, LightBulb *t_bulbs, u32 t_lightsCount, Vector3 t_objPosition);
|
||||
|
||||
private:
|
||||
Vector3 ambientLight;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,9 +13,12 @@
|
||||
|
||||
#include <draw_buffers.h>
|
||||
#include <draw_primitives.h>
|
||||
#include <gs_privileged.h>
|
||||
#include <draw.h>
|
||||
#include <packet2.h>
|
||||
#include "gif_sender.hpp"
|
||||
#include "vif_sender.hpp"
|
||||
#include "light.hpp"
|
||||
#include "../models/math/plane.hpp"
|
||||
#include "../models/sprite.hpp"
|
||||
#include "../models/screen_settings.hpp"
|
||||
@@ -38,11 +41,33 @@ public:
|
||||
void enableVSync() { isVSyncEnabled = true; }
|
||||
void disableVSync() { isVSyncEnabled = false; }
|
||||
|
||||
/// --- Draw: PATH3
|
||||
/** Reset draw wait flag. */
|
||||
inline void resetWaitFlag()
|
||||
{
|
||||
*GS_REG_CSR |= 2;
|
||||
}
|
||||
|
||||
/** Checks if draw wait flag is set */
|
||||
inline u8 isWaitFlagSet() const
|
||||
{
|
||||
return *GS_REG_CSR & 2;
|
||||
}
|
||||
|
||||
/** Waits for draw wait flag and reset it. */
|
||||
inline void waitForRender()
|
||||
{
|
||||
while (!isWaitFlagSet())
|
||||
;
|
||||
resetWaitFlag();
|
||||
}
|
||||
|
||||
/** 2D draw. */
|
||||
void draw(Sprite &t_sprite);
|
||||
|
||||
/// --- Draw: PATH3
|
||||
|
||||
/**
|
||||
* WARNING: THIS FUNC CAUSE VISUAL ARTIFACTS!
|
||||
* Draw many meshes with lighting information.
|
||||
* Slowest way of rendering (PATH 3, using EE and GIF).
|
||||
* NOTICE: Animation supported, lighting supported
|
||||
@@ -50,6 +75,7 @@ public:
|
||||
void drawByPath3(Mesh *t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount);
|
||||
|
||||
/**
|
||||
* WARNING: THIS FUNC CAUSE VISUAL ARTIFACTS!
|
||||
* Draw mesh with lighting information.
|
||||
* Slowest way of rendering (PATH 3, using EE and GIF).
|
||||
* NOTICE: Animation supported, lighting supported
|
||||
@@ -57,6 +83,7 @@ public:
|
||||
void drawByPath3(Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount);
|
||||
|
||||
/**
|
||||
* WARNING: THIS FUNC CAUSE VISUAL ARTIFACTS!
|
||||
* Draw many meshes without lighting information.
|
||||
* Slowest way of rendering (PATH 3, using EE and GIF).
|
||||
* NOTICE: Animation supported, lighting supported
|
||||
@@ -64,6 +91,7 @@ public:
|
||||
void drawByPath3(Mesh *t_meshes, u16 t_amount);
|
||||
|
||||
/**
|
||||
* WARNING: THIS FUNC CAUSE VISUAL ARTIFACTS!
|
||||
* Draw mesh without lighting information.
|
||||
* Slowest way of rendering (PATH 3, using EE and GIF).
|
||||
* NOTICE: Animation supported, lighting supported
|
||||
@@ -74,10 +102,11 @@ public:
|
||||
|
||||
/**
|
||||
* Draw many meshes with lighting information.
|
||||
* Draw in array mode, can be A LOT faster than for looping!
|
||||
* Fastest way of rendering (PATH 1, using VU1).
|
||||
* NOTICE: Animation supported, lighting NOT supported (at this moment)
|
||||
*/
|
||||
void draw(Mesh *t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount);
|
||||
void draw(Mesh **t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount);
|
||||
|
||||
/**
|
||||
* Draw mesh with lighting information.
|
||||
@@ -88,10 +117,11 @@ public:
|
||||
|
||||
/**
|
||||
* Draw many meshes without lighting information.
|
||||
* Draw in array mode, can be A LOT faster than for looping!
|
||||
* Fastest way of rendering (PATH 1, using VU1).
|
||||
* NOTICE: Animation supported, lighting NOT supported (at this moment)
|
||||
*/
|
||||
void draw(Mesh *t_meshes, u16 t_amount);
|
||||
void draw(Mesh **t_meshes, u16 t_amount);
|
||||
|
||||
/**
|
||||
* Draw mesh without lighting information.
|
||||
@@ -102,11 +132,19 @@ public:
|
||||
|
||||
void setCameraDefinitions(Matrix *t_worldView, Vector3 *t_cameraPos, Plane *t_planes);
|
||||
|
||||
void setWorldColor(const color_t &t_rgb);
|
||||
|
||||
void endFrame(float fps);
|
||||
|
||||
TextureRepository *getTextureRepository() { return &textureRepo; };
|
||||
void setAmbientLight(const Vector3 &t_rgb) { light.setAmbientLight(t_rgb); }
|
||||
|
||||
TextureRepository *getTextureRepository()
|
||||
{
|
||||
return &textureRepo;
|
||||
};
|
||||
|
||||
private:
|
||||
// We have some GCC bug here. Just try to reorder declarations. For example move worldColor up - game will crash.
|
||||
void changeTexture(Texture *t_tex);
|
||||
u32 lastTextureId;
|
||||
texbuffer_t textureBuffer;
|
||||
@@ -116,15 +154,17 @@ private:
|
||||
void flipBuffers();
|
||||
void beginFrameIfNeeded();
|
||||
u8 isFrameEmpty;
|
||||
Matrix perspective;
|
||||
Matrix perspective, camRotation;
|
||||
Light light;
|
||||
RenderData renderData;
|
||||
TextureRepository textureRepo;
|
||||
ScreenSettings *screen;
|
||||
GifSender *gifSender;
|
||||
VifSender *vifSender;
|
||||
packet2_t *flipPacket;
|
||||
void allocateBuffers(float t_screenW, float t_screenH);
|
||||
void initDrawingEnv(float t_screenW, float t_screenH);
|
||||
color_t worldColor;
|
||||
void allocateBuffers(int t_screenW, int t_screenH);
|
||||
void initDrawingEnv();
|
||||
void setPrim();
|
||||
};
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#define _TYRA_TIMER_
|
||||
|
||||
#include <tamtypes.h>
|
||||
#include <timer.h>
|
||||
|
||||
/** Class responsible for fps counting */
|
||||
class Timer
|
||||
@@ -22,7 +23,7 @@ public:
|
||||
~Timer();
|
||||
|
||||
u32 getTimeDelta();
|
||||
void primeTimer();
|
||||
inline void prime() { lastTime = *T3_COUNT; }
|
||||
float getFPS();
|
||||
|
||||
private:
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <tamtypes.h>
|
||||
#include <packet2_utils.h>
|
||||
#include "../models/render_data.hpp"
|
||||
#include "./light.hpp"
|
||||
#include "../models/light_bulb.hpp"
|
||||
#include "../models/mesh.hpp"
|
||||
#include "../models/math/matrix.hpp"
|
||||
@@ -24,22 +25,36 @@ class VifSender
|
||||
{
|
||||
|
||||
public:
|
||||
VifSender();
|
||||
VifSender(Light *t_light);
|
||||
~VifSender();
|
||||
|
||||
// TODO refactor
|
||||
void drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 vertCount2, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer);
|
||||
void sendMatrices(const RenderData &t_renderData, const Vector3 &t_position, const Vector3 &t_rotation);
|
||||
void calcMatrix(const RenderData &t_renderData, const Vector3 &t_position, const Vector3 &t_rotation);
|
||||
void drawTheSameWithOtherMatrices(const RenderData &t_renderData, Mesh **t_meshes, const u32 &t_skip, const u32 &t_count);
|
||||
void enableWait() { isDrawWaitEnabled = true; }
|
||||
void disableWait() { isDrawWaitEnabled = false; }
|
||||
|
||||
private:
|
||||
u32 lastVertCount; // needed for drawTheSameWithOtherMatrices()
|
||||
u8 isDrawWaitEnabled;
|
||||
Light *light;
|
||||
void uploadMicroProgram();
|
||||
void setDoubleBuffer();
|
||||
void drawVertices(Mesh &t_mesh, u32 t_start, u32 t_end, VECTOR *t_vertices, VECTOR *t_coordinates, prim_t *t_prim, texbuffer_t *textureBuffer);
|
||||
void setDoubleBufferAddStaticData();
|
||||
void drawVertices(Mesh &t_mesh, u32 t_start, u32 t_end, VECTOR *t_vertices, VECTOR *t_coordinates, prim_t *t_prim, texbuffer_t *t_textureBuffer, u8 t_addDrawWait);
|
||||
packet2_t *packets[2] __attribute__((aligned(64)));
|
||||
packet2_t *currPacket;
|
||||
/**
|
||||
* OpenGL name: Model
|
||||
* Sony name: local world
|
||||
*/
|
||||
Matrix model;
|
||||
/**
|
||||
* OpenGL name: ModelViewProjection
|
||||
* Sony name: local screen
|
||||
*/
|
||||
Matrix modelViewProj;
|
||||
u8 context;
|
||||
packet2_t *matricesPacket __attribute__((aligned(64)));
|
||||
MATRIX localWorld, localScreen;
|
||||
VECTOR position, rotation;
|
||||
u32 vertCount;
|
||||
};
|
||||
|
||||
@@ -24,13 +24,23 @@ class Math
|
||||
{
|
||||
|
||||
public:
|
||||
const static float HALF_ANG2RAD = 3.14159265358979323846 / 360.0;
|
||||
const static float HALF_ANG2RAD = 3.14159265358979323846F / 360.0F;
|
||||
const static float ANG2RAD = 3.14159265358979323846F / 180.0F;
|
||||
const static float PI = 3.1415926535897932384626433832795F;
|
||||
const static float HALF_PI = 1.5707963267948966192313216916398F;
|
||||
static float cos(float x);
|
||||
static float asin(float x);
|
||||
static float mod(float x, float y);
|
||||
static inline float sin(float x) { return cos(x - HALF_PI); };
|
||||
static inline float tan(float x) { return sin(x) / cos(x); }
|
||||
static float sqrt(float x);
|
||||
static float invSqrt(float x);
|
||||
static inline u32 max(u32 a, u32 b) { return (a > b) ? a : b; }
|
||||
static inline s32 max(s32 a, s32 b) { return (a > b) ? a : b; }
|
||||
static inline float max(float a, float b) { return (a > b) ? a : b; }
|
||||
static inline u32 min(u32 a, u32 b) { return (a < b) ? a : b; }
|
||||
static inline s32 min(s32 a, s32 b) { return (a < b) ? a : b; }
|
||||
static inline float min(float a, float b) { return (a < b) ? a : b; }
|
||||
|
||||
private:
|
||||
Math();
|
||||
|
||||
@@ -38,13 +38,11 @@ void PngLoader::load(Texture &o_texture, char *t_subfolder, char *t_name, char *
|
||||
char *path = String::createConcatenated(path_part2, t_extension);
|
||||
delete[] path_part1;
|
||||
delete[] path_part2;
|
||||
|
||||
FILE *file = fopen(path, "rb");
|
||||
|
||||
if (file == NULL)
|
||||
{
|
||||
PRINT_ERR("Failed to load .png file!");
|
||||
return;
|
||||
}
|
||||
PRINT_ERR("Failed to open .png file!");
|
||||
|
||||
png_structp png_ptr;
|
||||
png_infop info_ptr;
|
||||
@@ -56,29 +54,15 @@ void PngLoader::load(Texture &o_texture, char *t_subfolder, char *t_name, char *
|
||||
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL);
|
||||
|
||||
if (!png_ptr)
|
||||
{
|
||||
printf("PNG Read Struct Init Failed\n");
|
||||
fclose(file);
|
||||
return;
|
||||
}
|
||||
PRINT_ERR("PNG struct info init failed(1)!");
|
||||
|
||||
info_ptr = png_create_info_struct(png_ptr);
|
||||
|
||||
if (!info_ptr)
|
||||
{
|
||||
printf("PNG Info Struct Init Failed\n");
|
||||
fclose(file);
|
||||
png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
|
||||
return;
|
||||
}
|
||||
PRINT_ERR("PNG struct info init failed(2)!");
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr)))
|
||||
{
|
||||
printf("Got PNG Error!\n");
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
||||
fclose(file);
|
||||
return;
|
||||
}
|
||||
PRINT_ERR("PNG reader fatal error!");
|
||||
|
||||
png_init_io(png_ptr, file);
|
||||
|
||||
@@ -114,80 +98,39 @@ void PngLoader::load(Texture &o_texture, char *t_subfolder, char *t_name, char *
|
||||
type = TEX_TYPE_RGB;
|
||||
break;
|
||||
default:
|
||||
PRINT_ERR("This png format is not supported!");
|
||||
PRINT_ERR("This png format is not supported! RGB/RGBA only.");
|
||||
}
|
||||
|
||||
o_texture.setSize(width, height, type);
|
||||
printf("PNGLoader - width: %d | height: %d\n", width, height);
|
||||
|
||||
if (type == TEX_TYPE_RGBA)
|
||||
{
|
||||
int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||
size_t row_bytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||
png_byte *row_pointers[height];
|
||||
|
||||
for (row = 0; row < height; row++)
|
||||
row_pointers[row] = new png_byte[row_bytes];
|
||||
|
||||
png_read_image(png_ptr, row_pointers);
|
||||
|
||||
struct pixel
|
||||
{
|
||||
u8 r, g, b, a;
|
||||
};
|
||||
|
||||
u32 x = 0;
|
||||
|
||||
for (i = 0; i < height; i++)
|
||||
{
|
||||
for (j = 0; j < width; j++)
|
||||
{
|
||||
o_texture.setData(x, row_pointers[i][4 * j]);
|
||||
o_texture.setData(x + 1, row_pointers[i][4 * j + 1]);
|
||||
o_texture.setData(x + 2, row_pointers[i][4 * j + 2]);
|
||||
if (type == TEX_TYPE_RGBA)
|
||||
{
|
||||
o_texture.setData(x + 3, ((int)row_pointers[i][4 * j + 3] * 128 / 255));
|
||||
x += 4;
|
||||
}
|
||||
}
|
||||
|
||||
for (row = 0; row < height; row++)
|
||||
delete row_pointers[row];
|
||||
}
|
||||
else if (type == TEX_TYPE_RGB)
|
||||
{
|
||||
int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||
png_byte *row_pointers[height];
|
||||
|
||||
for (row = 0; row < height; row++)
|
||||
row_pointers[row] = new png_byte[row_bytes];
|
||||
|
||||
png_read_image(png_ptr, row_pointers);
|
||||
|
||||
struct pixel3
|
||||
{
|
||||
u8 r, g, b;
|
||||
};
|
||||
|
||||
u32 x = 0;
|
||||
for (i = 0; i < height; i++)
|
||||
{
|
||||
for (j = 0; j < width; j++)
|
||||
{
|
||||
o_texture.setData(x, row_pointers[i][4 * j]);
|
||||
o_texture.setData(x + 1, row_pointers[i][4 * j + 1]);
|
||||
o_texture.setData(x + 2, row_pointers[i][4 * j + 2]);
|
||||
x += 3;
|
||||
}
|
||||
}
|
||||
|
||||
for (row = 0; row < height; row++)
|
||||
delete row_pointers[row];
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("This texture depth is not supported yet!\n");
|
||||
return;
|
||||
}
|
||||
delete[] row_pointers[row];
|
||||
|
||||
// Texture->Filter = GS_FILTER_NEAREST;
|
||||
png_read_end(png_ptr, NULL);
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Michał Mostowik <mostek3pl@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../include/models/bounding_box.hpp"
|
||||
#include "../include/utils/debug.hpp"
|
||||
#include <cstring>
|
||||
|
||||
/**
|
||||
* Construct a BoundingBox class
|
||||
* Allows for user friendly access to bounding box data.
|
||||
* @param t_vertices Array of 8 Vector3 elements.
|
||||
*/
|
||||
BoundingBox::BoundingBox(Vector3 *t_vertices)
|
||||
{
|
||||
//Perform a deep copy of vertex array parameter
|
||||
memcpy(_vertices, t_vertices, 8 * sizeof(Vector3));
|
||||
|
||||
//This might be shortened with Vector3 operator overloading, but current
|
||||
//implementation is more human readable.
|
||||
_height = _vertices[0].y - _vertices[2].y;
|
||||
_width = _vertices[0].x - _vertices[4].x;
|
||||
_depth = _vertices[0].z - _vertices[1].z;
|
||||
|
||||
_centerVector = _vertices[0];
|
||||
_centerVector.x += (_width / 2);
|
||||
_centerVector.y += (_height / 2);
|
||||
_centerVector.z += (_depth / 2);
|
||||
|
||||
//Z-Axis faces
|
||||
_frontFace = BoundingBoxFace(_vertices[1], _vertices[7], _vertices[1].z);
|
||||
_backFace = BoundingBoxFace(_vertices[0], _vertices[6], _vertices[0].z);
|
||||
//X-Axis faces
|
||||
_leftFace = BoundingBoxFace(_vertices[0], _vertices[3], _vertices[0].x);
|
||||
_rightFace = BoundingBoxFace(_vertices[4], _vertices[7], _vertices[4].x);
|
||||
//Y-Axis faces
|
||||
_topFace = BoundingBoxFace(_vertices[2], _vertices[7], _vertices[2].y);
|
||||
_bottomFace = BoundingBoxFace(_vertices[0], _vertices[5], _vertices[0].y);
|
||||
}
|
||||
|
||||
BoundingBox::~BoundingBox()
|
||||
{
|
||||
}
|
||||
+264
-156
@@ -17,11 +17,16 @@
|
||||
// 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)
|
||||
Matrix::Matrix()
|
||||
{
|
||||
for (u8 i = 0; i < 16; i++)
|
||||
data[i] = 0.0F;
|
||||
}
|
||||
|
||||
Matrix::Matrix(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;
|
||||
@@ -44,30 +49,34 @@ Matrix::Matrix(float m11, float m12, float m13, float m14,
|
||||
data[15] = m44;
|
||||
}
|
||||
|
||||
/** Create with another matrix values */
|
||||
Matrix::Matrix(const Matrix &v)
|
||||
// ----
|
||||
// Operators
|
||||
// ----
|
||||
|
||||
Vector3 Matrix::operator*(const Vector3 &v) const
|
||||
{
|
||||
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];
|
||||
float a[4] = {v.x, v.y, v.z, 1.0F};
|
||||
float res[4];
|
||||
asm volatile(
|
||||
"lqc2 vf4, 0x00(%1) \n\t"
|
||||
"lqc2 vf5, 0x10(%1) \n\t"
|
||||
"lqc2 vf6, 0x20(%1) \n\t"
|
||||
"lqc2 vf7, 0x30(%1) \n\t"
|
||||
"lqc2 vf8, 0x00(%2) \n\t"
|
||||
"vmulax.xyzw ACC, vf4, vf8 \n\t"
|
||||
"vmadday.xyzw ACC, vf5, vf8 \n\t"
|
||||
"vmaddaz.xyzw ACC, vf6, vf8 \n\t"
|
||||
"vmaddw.xyzw vf9, vf7, vf8 \n\t"
|
||||
"sqc2 vf9, 0x00(%0) \n\t"
|
||||
:
|
||||
: "r"(res), "r"(this->data), "r"(a));
|
||||
return Vector3(res[0], res[1], res[2]);
|
||||
}
|
||||
|
||||
// ----
|
||||
// Functions
|
||||
// ----
|
||||
|
||||
void Matrix::identity()
|
||||
{
|
||||
asm volatile(
|
||||
@@ -84,106 +93,7 @@ void Matrix::identity()
|
||||
: "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)
|
||||
void Matrix::setPerspective(const ScreenSettings &t_screen)
|
||||
{
|
||||
float fovYdiv2 = Math::HALF_ANG2RAD * t_screen.fov;
|
||||
float cotFOV = 1.0F / (Math::sin(fovYdiv2) / Math::cos(fovYdiv2));
|
||||
@@ -215,42 +125,57 @@ void Matrix::setPerspective(ScreenSettings &t_screen)
|
||||
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)
|
||||
void Matrix::lookAt(const Vector3 &t_position, const Vector3 &t_target)
|
||||
{
|
||||
Vector3 camForward, camUp, camRight;
|
||||
VECTOR up_vec, view_vec;
|
||||
VECTOR eye = {t_position.x, t_position.y, t_position.z, 1.0F};
|
||||
VECTOR obj = {t_target.x, t_target.y, t_target.z, 1.0F};
|
||||
asm volatile(
|
||||
"lqc2 vf4, 0x00(%2) # eye \n\t"
|
||||
"lqc2 vf5, 0x00(%3) # obj \n\t"
|
||||
"vsub.xyz vf7, vf4, vf5 # view_vec = vf7 \n\t"
|
||||
"vmove.xyzw vf6, vf0 \n\t"
|
||||
"vaddw.y vf6, vf0, vf0 # vf6 = { 0.0f, 1.0f, 0.0f, 1.0f } \n\t"
|
||||
"vopmula.xyz ACC, vf6, vf7 \n\t"
|
||||
"vopmsub.xyz vf9, vf7, vf6 # vec = vf9 \n\t"
|
||||
"vopmula.xyz ACC, vf7, vf9 \n\t"
|
||||
"vopmsub.xyz vf8, vf9, vf7 # up_vec = vf8 \n\t"
|
||||
"sqc2 vf7, 0x00(%0) # view_vec \n\t"
|
||||
"sqc2 vf6, 0x00(%1) # up_vec \n\t"
|
||||
:
|
||||
: "r"(view_vec), "r"(up_vec), "r"(eye), "r"(obj));
|
||||
Matrix temp;
|
||||
temp.setCamera(eye, view_vec, up_vec);
|
||||
identity();
|
||||
cross(this->data, this->data, temp.data);
|
||||
|
||||
camForward = t_position - t_target;
|
||||
camForward.normalize();
|
||||
camRight = t_up * camForward;
|
||||
camRight.normalize();
|
||||
camUp = camForward * camRight;
|
||||
// Vector3 camForward, camUp, camRight;
|
||||
// Vector3 t_up = Vector3(0.0F, 1.0F, 0.0F);
|
||||
// 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[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[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[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;
|
||||
// data[3] = 0;
|
||||
// data[7] = 0;
|
||||
// data[11] = 0;
|
||||
// data[15] = 1;
|
||||
}
|
||||
|
||||
const void Matrix::print() const
|
||||
@@ -261,3 +186,186 @@ const void Matrix::print() const
|
||||
data[8], data[9], data[10], data[11],
|
||||
data[12], data[13], data[14], data[15]);
|
||||
}
|
||||
|
||||
// ----
|
||||
// Private
|
||||
// ----
|
||||
|
||||
void Matrix::rotationX(const float &t_radians)
|
||||
{
|
||||
float c = Math::cos(t_radians);
|
||||
float s = Math::sin(t_radians);
|
||||
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 Matrix::rotationY(const float &t_radians)
|
||||
{
|
||||
float c = Math::cos(t_radians);
|
||||
float s = Math::sin(t_radians);
|
||||
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 Matrix::rotationZ(const float &t_radians)
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
void Matrix::rotationByAngle(const float &t_angle, const Vector3 &t_axis)
|
||||
{
|
||||
Vector3 localAxis = Vector3(t_axis);
|
||||
localAxis.normalize();
|
||||
float x = localAxis.x;
|
||||
float y = localAxis.y;
|
||||
float z = localAxis.z;
|
||||
|
||||
float c = Math::cos(t_angle);
|
||||
float s = Math::sin(t_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 Matrix::translation(const Vector3 &t_val)
|
||||
{
|
||||
this->data[12] = t_val.x; // 3,0
|
||||
this->data[13] = t_val.y; // 3,1
|
||||
this->data[14] = t_val.z; // 3,2
|
||||
}
|
||||
|
||||
void Matrix::setScale(const Vector3 &t_val)
|
||||
{
|
||||
this->data[0] = t_val.x;
|
||||
this->data[5] = t_val.y;
|
||||
this->data[10] = t_val.z;
|
||||
this->data[15] = 1.0F;
|
||||
}
|
||||
|
||||
void Matrix::setCamera(const float t_pos[4], const float t_vz[4], const float t_vy[4])
|
||||
{
|
||||
// Matrix vf4, vf5, vf6, vf7
|
||||
// t_pos vf8
|
||||
// t_vz vf9
|
||||
// t_vy vf10
|
||||
// vtmp vf11
|
||||
asm volatile(
|
||||
"lqc2 vf9, 0x00(%2) \n\t"
|
||||
"lqc2 vf10, 0x00(%3) \n\t"
|
||||
// mtmp.unit()
|
||||
"vsub.w vf5, vf0, vf0 # mtmp[1][PW] = 0.0F \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"(this->data), "r"(t_pos), "r"(t_vz), "r"(t_vy));
|
||||
}
|
||||
|
||||
void Matrix::cross(float res[16], const float a[16], const float b[16]) const
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
+143
-216
@@ -9,64 +9,24 @@
|
||||
*/
|
||||
|
||||
#include "../../include/models/math/vector3.hpp"
|
||||
|
||||
#include "../../include/utils/math.hpp"
|
||||
#include <stdio.h>
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
/** Create by specifying 3 points */
|
||||
Vector3::Vector3(float t_x, float t_y, float t_z)
|
||||
{
|
||||
x = t_x;
|
||||
y = t_y;
|
||||
z = t_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, const float &t_scale)
|
||||
{
|
||||
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");
|
||||
x *= t_scale;
|
||||
y *= t_scale;
|
||||
z *= t_scale;
|
||||
}
|
||||
|
||||
/** Create empty vector */
|
||||
Vector3::Vector3()
|
||||
{
|
||||
x = 0;
|
||||
y = 0;
|
||||
z = 0;
|
||||
x = 0.0F;
|
||||
y = 0.0F;
|
||||
z = 0.0F;
|
||||
}
|
||||
|
||||
Vector3::~Vector3() {}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// Operators
|
||||
// ----
|
||||
|
||||
Vector3 Vector3::operator+(Vector3 v)
|
||||
Vector3 Vector3::operator+(const Vector3 &v) const
|
||||
{
|
||||
Vector3 result;
|
||||
asm volatile( // VU0 Macro program
|
||||
@@ -79,7 +39,7 @@ Vector3 Vector3::operator+(Vector3 v)
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector3 Vector3::operator-(const Vector3 &v)
|
||||
Vector3 Vector3::operator-(const Vector3 &v) const
|
||||
{
|
||||
Vector3 result;
|
||||
asm volatile( // VU0 Macro program
|
||||
@@ -92,17 +52,7 @@ Vector3 Vector3::operator-(const Vector3 &v)
|
||||
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 Vector3::operator*(const Vector3 &v) const
|
||||
{
|
||||
Vector3 res;
|
||||
asm volatile( // VU0 Macro program
|
||||
@@ -120,7 +70,7 @@ Vector3 Vector3::operator*(Vector3 &v)
|
||||
return res;
|
||||
}
|
||||
|
||||
Vector3 Vector3::operator*(float t)
|
||||
Vector3 Vector3::operator*(const float &t) const
|
||||
{
|
||||
Vector3 result;
|
||||
asm volatile(
|
||||
@@ -130,12 +80,11 @@ Vector3 Vector3::operator*(float t)
|
||||
"vmulx.xyz vf6, vf4, vf5 \n\t"
|
||||
"sqc2 vf6, 0x0(%0) \n\t"
|
||||
:
|
||||
: "r"(result.xyz), "r"(this->xyz), "f"(t)
|
||||
: "$8");
|
||||
: "r"(result.xyz), "r"(this->xyz), "f"(t));
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector3 Vector3::operator/(float t)
|
||||
Vector3 Vector3::operator/(const float &t) const
|
||||
{
|
||||
Vector3 result;
|
||||
result.x = x / t;
|
||||
@@ -144,7 +93,127 @@ Vector3 Vector3::operator/(float t)
|
||||
return result;
|
||||
}
|
||||
|
||||
u8 Vector3::shouldBeBackfaceCulled(const Vector3 *t_cameraPos, const Vector3 *v0, const Vector3 *v1, const Vector3 *v2)
|
||||
void Vector3::operator+=(const Vector3 &t)
|
||||
{
|
||||
asm volatile( // VU0 Macro program
|
||||
"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->xyz), "r"(t.xyz));
|
||||
}
|
||||
|
||||
void Vector3::operator*=(const float &t)
|
||||
{
|
||||
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->xyz), "f"(t));
|
||||
}
|
||||
|
||||
// ----
|
||||
// Functions
|
||||
// ----
|
||||
|
||||
void Vector3::set(const Vector3 &v)
|
||||
{
|
||||
asm volatile( // VU0 Macro program
|
||||
"lq $6, 0x0(%1) \n\t"
|
||||
"sq $6, 0x0(%0) \n\t"
|
||||
:
|
||||
: "r"(this->xyz), "r"(v.xyz));
|
||||
}
|
||||
|
||||
void Vector3::set(const float &t_x, const float &t_y, const float &t_z)
|
||||
{
|
||||
x = t_x;
|
||||
y = t_y;
|
||||
z = t_z;
|
||||
}
|
||||
|
||||
float Vector3::innerProduct(const Vector3 &v) const
|
||||
{
|
||||
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));
|
||||
return result;
|
||||
// return (x * v.x + y * v.y + z * v.z);
|
||||
}
|
||||
|
||||
float Vector3::length() const
|
||||
{
|
||||
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"
|
||||
"vwaitq \n\t"
|
||||
"vaddq.x vf8, vf0, Q \n\t"
|
||||
"qmfc2 $2, vf8 \n\t"
|
||||
"mtc1 $2, %0 \n\t"
|
||||
: "=f"(result)
|
||||
: "r"(this->xyz));
|
||||
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"
|
||||
"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->xyz));
|
||||
}
|
||||
|
||||
float Vector3::distanceTo(const Vector3 &v) const
|
||||
{
|
||||
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"
|
||||
"vwaitq \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));
|
||||
return result;
|
||||
// return Math::sqrt((this->x - v.x) * (this->x - v.x) +
|
||||
// (this->y - v.y) * (this->y - v.y) +
|
||||
// (this->z - v.z) * (this->z - v.z));
|
||||
}
|
||||
|
||||
u8 Vector3::shouldBeBackfaceCulled(const Vector3 *t_cameraPos, const Vector3 *t_v0, const Vector3 *t_v1, const Vector3 *t_v2)
|
||||
{
|
||||
register float dot;
|
||||
asm volatile(
|
||||
@@ -164,164 +233,22 @@ u8 Vector3::shouldBeBackfaceCulled(const Vector3 *t_cameraPos, const Vector3 *v0
|
||||
"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");
|
||||
: "r"(t_cameraPos->xyz), "r"(t_v0->xyz), "r"(t_v1->xyz), "r"(t_v2->xyz));
|
||||
return dot <= 0.0F;
|
||||
}
|
||||
|
||||
/** Checks intersection with given square */
|
||||
u8 Vector3::collidesSquare(Vector3 &t_min, Vector3 &t_max)
|
||||
void Vector3::setByLerp(const Vector3 &t_v1, const Vector3 &t_v2, const float &t_interp, const float &t_scale)
|
||||
{
|
||||
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(const float &t_x, const float &t_y, const float &t_z)
|
||||
{
|
||||
x = t_x;
|
||||
y = t_y;
|
||||
z = t_z;
|
||||
}
|
||||
|
||||
void Vector3::rotate(const Vector3 &v, u8 inversed)
|
||||
{
|
||||
VECTOR cameraPos = {x, y, z, 0.0F};
|
||||
VECTOR rotation;
|
||||
if (inversed)
|
||||
{
|
||||
rotation[0] = -v.x;
|
||||
rotation[1] = -v.y;
|
||||
rotation[2] = -v.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
rotation[0] = v.x;
|
||||
rotation[1] = v.y;
|
||||
rotation[2] = v.z;
|
||||
}
|
||||
rotation[3] = 0.0F;
|
||||
|
||||
MATRIX rotationMatrix;
|
||||
matrix_unit(rotationMatrix);
|
||||
matrix_rotate(rotationMatrix, rotationMatrix, rotation);
|
||||
VECTOR result;
|
||||
asm volatile(
|
||||
"lqc2 vf4, 0x0(%1) \n\t"
|
||||
"lqc2 vf5, 0x10(%1) \n\t"
|
||||
"lqc2 vf6, 0x20(%1) \n\t"
|
||||
"lqc2 vf7, 0x30(%1) \n\t"
|
||||
"lqc2 vf8, 0x0(%2) \n\t"
|
||||
"vmulax.xyzw ACC, vf4, vf8 \n\t"
|
||||
"vmadday.xyzw ACC, vf5, vf8 \n\t"
|
||||
"vmaddaz.xyzw ACC, vf6, vf8 \n\t"
|
||||
"vmaddw.xyzw vf9, vf7, vf8 \n\t"
|
||||
"sqc2 vf9, 0x0(%0) \n\t"
|
||||
"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"(&result), "r"(&rotationMatrix), "r"(&cameraPos));
|
||||
set(Vector3(result[0], result[1], result[2]));
|
||||
}
|
||||
|
||||
void Vector3::set(const 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));
|
||||
}
|
||||
|
||||
const void Vector3::print() const
|
||||
{
|
||||
printf("Vector3(%f, %f, %f)\n", x, y, z);
|
||||
: "r"(&this->xyz), "r"(&t_v1.xyz), "r"(&t_v2.xyz), "f"(t_interp));
|
||||
operator*=(t_scale);
|
||||
}
|
||||
|
||||
@@ -347,7 +347,7 @@ u8 Mesh::isInFrustum(Plane *t_frustumPlanes)
|
||||
{
|
||||
Vector3 boxCalcTemp;
|
||||
u8 boxResult = 1, boxIn = 0, boxOut = 0;
|
||||
Vector3 *currentBoundingBox = getCurrentBoundingBox();
|
||||
const Vector3 *currentBoundingBox = getCurrentBoundingBoxVertices();
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
boxOut = 0;
|
||||
|
||||
@@ -37,6 +37,7 @@ MeshFrame::~MeshFrame()
|
||||
delete[] normals;
|
||||
if (_areMaterialsAllocated)
|
||||
delete[] materials;
|
||||
delete boundingBoxObj;
|
||||
}
|
||||
|
||||
// ----
|
||||
@@ -93,6 +94,7 @@ void MeshFrame::allocateMaterials(const u32 &t_val)
|
||||
|
||||
void MeshFrame::calculateBoundingBoxes()
|
||||
{
|
||||
Vector3 boundingBox[8];
|
||||
if (!_areVerticesAllocated)
|
||||
{
|
||||
PRINT_ERR("Can't calculate bounding box, because vertices were not allocated!");
|
||||
@@ -121,6 +123,7 @@ void MeshFrame::calculateBoundingBoxes()
|
||||
if (hiZ < vertices[i].z)
|
||||
hiZ = vertices[i].z;
|
||||
}
|
||||
|
||||
boundingBox[0].set(lowX, lowY, lowZ);
|
||||
boundingBox[1].set(lowX, lowY, hiZ);
|
||||
boundingBox[2].set(lowX, hiY, lowZ);
|
||||
@@ -131,4 +134,8 @@ void MeshFrame::calculateBoundingBoxes()
|
||||
boundingBox[6].set(hiX, hiY, lowZ);
|
||||
boundingBox[7].set(hiX, hiY, hiZ);
|
||||
_isBoundingBoxCalculated = true;
|
||||
|
||||
//BoundingBox is declared on the heap to prevent any ill-formed default
|
||||
//constructor instantiated BoundingBox objects.
|
||||
boundingBoxObj = new BoundingBox(boundingBox);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
*/
|
||||
|
||||
#include "../include/models/mesh_material.hpp"
|
||||
#include "../include/models/bounding_box.hpp"
|
||||
#include "../include/utils/debug.hpp"
|
||||
#include "../include/utils/string.hpp"
|
||||
#include <cstdlib>
|
||||
@@ -82,9 +83,9 @@ u8 MeshMaterial::isInFrustum(Plane *t_frustumPlanes, const Vector3 &position)
|
||||
for (u8 y = 0; y < 8 && (boxIn == 0 || boxOut == 0); y++)
|
||||
{
|
||||
boxCalcTemp.set(
|
||||
boundingBox[y].x + position.x,
|
||||
boundingBox[y].y + position.y,
|
||||
boundingBox[y].z + position.z);
|
||||
boundingBoxObj->getVertex(y).x + position.x,
|
||||
boundingBoxObj->getVertex(y).y + position.y,
|
||||
boundingBoxObj->getVertex(y).z + position.z);
|
||||
if (t_frustumPlanes[i].distanceTo(boxCalcTemp) < 0)
|
||||
boxOut++;
|
||||
else
|
||||
@@ -101,6 +102,7 @@ u8 MeshMaterial::isInFrustum(Plane *t_frustumPlanes, const Vector3 &position)
|
||||
|
||||
void MeshMaterial::calculateBoundingBox(Vector3 *t_vertices, u32 t_vertCount)
|
||||
{
|
||||
Vector3 boundingBox[8];
|
||||
float lowX, lowY, lowZ, hiX, hiY, hiZ;
|
||||
lowX = hiX = t_vertices[vertexFaces[0]].x;
|
||||
lowY = hiY = t_vertices[vertexFaces[0]].y;
|
||||
@@ -132,4 +134,8 @@ void MeshMaterial::calculateBoundingBox(Vector3 *t_vertices, u32 t_vertCount)
|
||||
boundingBox[6].set(hiX, hiY, lowZ);
|
||||
boundingBox[7].set(hiX, hiY, hiZ);
|
||||
_isBoundingBoxCalculated = true;
|
||||
|
||||
//BoundingBox is declared on the heap to prevent any ill-formed default
|
||||
//constructor instantiated BoundingBox objects.
|
||||
boundingBoxObj = new BoundingBox(boundingBox);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ Sprite::Sprite()
|
||||
_flipH = false;
|
||||
_flipV = false;
|
||||
scale = 1.0F;
|
||||
mode = MODE_REPEAT;
|
||||
setDefaultColor();
|
||||
setDefaultLODAndClut();
|
||||
}
|
||||
|
||||
@@ -89,24 +89,25 @@ void Audio::setSongVolume(const u8 &t_vol)
|
||||
|
||||
u32 Audio::addSongListener(AudioListener *t_listener)
|
||||
{
|
||||
AudioListenerRef ref;
|
||||
ref.id = rand() % 1000000;
|
||||
ref.listener = t_listener;
|
||||
AudioListenerRef *ref = new AudioListenerRef;
|
||||
ref->id = rand() % 1000000;
|
||||
ref->listener = t_listener;
|
||||
songListeners.push_back(ref);
|
||||
return ref.id;
|
||||
return ref->id;
|
||||
}
|
||||
|
||||
void Audio::removeSongListener(const u32 &t_id)
|
||||
{
|
||||
s32 index = -1;
|
||||
for (u32 i = 0; i < songListeners.size(); i++)
|
||||
if (songListeners[i].id == t_id)
|
||||
if (songListeners[i]->id == t_id)
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
if (index == -1)
|
||||
PRINT_ERR("Cant remove listener because given id was not found!");
|
||||
delete songListeners[index];
|
||||
songListeners.erase(songListeners.begin() + index);
|
||||
}
|
||||
|
||||
@@ -160,7 +161,7 @@ void Audio::playADPCM(audsrv_adpcm_t *t_adpcm, const s8 &t_ch)
|
||||
void Audio::startThread(FileService *t_fileService)
|
||||
{
|
||||
PRINT_LOG("Creating audio thread");
|
||||
fileService = t_fileService;
|
||||
// fileService = t_fileService;
|
||||
extern void *_gp;
|
||||
thread.func = (void *)Audio::mainThread;
|
||||
thread.stack = threadStack;
|
||||
@@ -186,7 +187,7 @@ void Audio::threadLoop()
|
||||
{
|
||||
printf("Running again.\n");
|
||||
for (u32 i = 0; i < getSongListenersCount(); i++)
|
||||
songListeners[i].listener->onAudioFinish();
|
||||
songListeners[i]->listener->onAudioFinish();
|
||||
rewindSongToStart();
|
||||
}
|
||||
else
|
||||
@@ -202,7 +203,7 @@ void Audio::threadLoop()
|
||||
WaitSema(fillbufferSema); // wait until previous chunk wasn't finished
|
||||
audsrv_play_audio(wavChunk, chunkReadStatus);
|
||||
for (u32 i = 0; i < getSongListenersCount(); i++)
|
||||
songListeners[i].listener->onAudioTick();
|
||||
songListeners[i]->listener->onAudioTick();
|
||||
}
|
||||
|
||||
chunkReadStatus = fread(wavChunk, 1, sizeof(wavChunk), wav);
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
CameraBase::CameraBase(ScreenSettings *t_screen, Vector3 *t_position, Vector3 *t_up)
|
||||
CameraBase::CameraBase(ScreenSettings *t_screen, Vector3 *t_position)
|
||||
: screen(t_screen)
|
||||
{
|
||||
PRINT_LOG("Initializing frustum");
|
||||
@@ -30,7 +30,7 @@ CameraBase::CameraBase(ScreenSettings *t_screen, Vector3 *t_position, Vector3 *t
|
||||
farHeight = tang * farPlaneDist;
|
||||
farWidth = farHeight * screen->aspectRatio;
|
||||
p_position = t_position;
|
||||
p_up = t_up;
|
||||
up.set(0.0F, 1.0F, 0.0F);
|
||||
PRINT_LOG("CameraBase initialized!");
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ CameraBase::CameraBase(ScreenSettings *t_screen, Vector3 *t_position, Vector3 *t
|
||||
void CameraBase::lookAt(Vector3 &t_target)
|
||||
{
|
||||
updatePlanes(t_target);
|
||||
worldView.lookAt(*p_up, *p_position, t_target);
|
||||
view.lookAt(*p_position, t_target);
|
||||
}
|
||||
|
||||
void CameraBase::updatePlanes(Vector3 t_target)
|
||||
@@ -51,7 +51,7 @@ void CameraBase::updatePlanes(Vector3 t_target)
|
||||
Z = *p_position - t_target;
|
||||
Z.normalize();
|
||||
// X axis of camera of given "up" vector and Z axis
|
||||
X = *p_up * Z;
|
||||
X = up * Z;
|
||||
X.normalize();
|
||||
// the real "up" vector is the cross product of Z and X
|
||||
Y = Z * X;
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
#include "../include/utils/math.hpp"
|
||||
#include "../include/utils/debug.hpp"
|
||||
#include "../include/modules/light.hpp"
|
||||
#include <packet2_chain.h>
|
||||
#include <kernel.h>
|
||||
#include <dma.h>
|
||||
@@ -29,9 +28,10 @@
|
||||
/** Initializes vars and creates data transfer packets
|
||||
* @param packetSize Size of data packet, should be increased when more data will be rendered
|
||||
*/
|
||||
GifSender::GifSender(u32 t_packetSize, ScreenSettings *t_screen) : screen(t_screen)
|
||||
GifSender::GifSender(u32 t_packetSize, ScreenSettings *t_screen, Light *t_light) : screen(t_screen)
|
||||
{
|
||||
PRINT_LOG("Initializing GifSender");
|
||||
light = t_light;
|
||||
packetSize = t_packetSize;
|
||||
packets[0] = packet2_create(t_packetSize, P2_TYPE_NORMAL, P2_MODE_CHAIN, false);
|
||||
packets[1] = packet2_create(t_packetSize, P2_TYPE_NORMAL, P2_MODE_CHAIN, false);
|
||||
@@ -76,7 +76,7 @@ void GifSender::sendTexture(Texture &texture, texbuffer_t *t_texBuffer)
|
||||
packet2_free(packet2);
|
||||
}
|
||||
|
||||
void GifSender::sendClear(zbuffer_t *t_zBuffer)
|
||||
void GifSender::sendClear(zbuffer_t *t_zBuffer, color_t *t_rgb)
|
||||
{
|
||||
packet2_t *packet2 = packet2_create(36, P2_TYPE_NORMAL, P2_MODE_CHAIN, false);
|
||||
packet2_chain_open_end(packet2, 0, 0);
|
||||
@@ -84,7 +84,7 @@ void GifSender::sendClear(zbuffer_t *t_zBuffer)
|
||||
packet2_update(packet2, draw_clear(packet2->next, 0,
|
||||
2048.0F - (screen->width / 2), 2048.0F - (screen->height / 2),
|
||||
screen->width, screen->height,
|
||||
0x10, 0x10, 0x10));
|
||||
t_rgb->r, t_rgb->g, t_rgb->b));
|
||||
packet2_update(packet2, draw_enable_tests(packet2->next, 0, t_zBuffer));
|
||||
packet2_update(packet2, draw_finish(packet2->next));
|
||||
packet2_chain_close_tag(packet2);
|
||||
@@ -118,24 +118,19 @@ void GifSender::sendPacket()
|
||||
}
|
||||
|
||||
/** Adds clear screen to current packet */
|
||||
void GifSender::addClear(zbuffer_t *t_zBuffer)
|
||||
void GifSender::addClear(zbuffer_t *t_zBuffer, color_t *t_rgb)
|
||||
{
|
||||
packet2_chain_open_cnt(currentPacket, 0, 0, 0);
|
||||
packet2_update(currentPacket, draw_disable_tests(currentPacket->next, 0, t_zBuffer));
|
||||
packet2_update(currentPacket, draw_clear(currentPacket->next, 0,
|
||||
2048.0F - (screen->width / 2), 2048.0F - (screen->height / 2),
|
||||
screen->width, screen->height,
|
||||
0x10, 0x10, 0x10));
|
||||
t_rgb->r, t_rgb->g, t_rgb->b));
|
||||
packet2_update(currentPacket, draw_enable_tests(currentPacket->next, 0, t_zBuffer));
|
||||
packet2_chain_close_tag(currentPacket);
|
||||
}
|
||||
|
||||
/** Adds 3D objects to current packet
|
||||
* @param worldView Matrix
|
||||
* @param perspective Matrix with .setPerpsective() used [clone of gluPerspective]
|
||||
* @param objects3D Array of 3D objects pointers
|
||||
* @param amount Amount of 3D objects
|
||||
*/
|
||||
/** Adds meshes to current packet */
|
||||
void GifSender::addObject(RenderData *t_renderData, Mesh &t_mesh, u32 vertexCount, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer)
|
||||
{
|
||||
packet2_chain_open_cnt(currentPacket, 0, 0, 0);
|
||||
@@ -145,7 +140,7 @@ void GifSender::addObject(RenderData *t_renderData, Mesh &t_mesh, u32 vertexCoun
|
||||
xyz = new xyz_t[vertexCount];
|
||||
rgbaq = new color_t[vertexCount];
|
||||
st = new texel_t[vertexCount];
|
||||
calc3DObject(*t_renderData->perspective, t_mesh, vertexCount, vertices, normals, coordinates, t_renderData, t_bulbs, t_bulbsCount);
|
||||
calc3DObject(*t_renderData->projection, t_mesh, vertexCount, vertices, normals, coordinates, t_renderData, t_bulbs, t_bulbsCount);
|
||||
addCurrentCalcs(vertexCount);
|
||||
delete[] xyz;
|
||||
delete[] rgbaq;
|
||||
@@ -155,10 +150,7 @@ void GifSender::addObject(RenderData *t_renderData, Mesh &t_mesh, u32 vertexCoun
|
||||
}
|
||||
|
||||
/** Calculates 3D object data into xyz, rgbq, st
|
||||
* After it addCurrentSTQ() can be done
|
||||
* @param worldView Matrix
|
||||
* @param perspective Matrix with .setPerpsective() used [clone of gluPerspective]
|
||||
* @param mesh 3D object
|
||||
* After it addCurrentCalcs() can be done
|
||||
*/
|
||||
void GifSender::calc3DObject(Matrix t_perspective, Mesh &t_mesh, u32 vertexCount, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, RenderData *t_renderData, LightBulb *t_bulbs, u16 t_bulbsCount)
|
||||
{
|
||||
@@ -176,11 +168,11 @@ void GifSender::calc3DObject(Matrix t_perspective, Mesh &t_mesh, u32 vertexCount
|
||||
create_local_light(localLight, rotation);
|
||||
|
||||
// I cant put perspective from renderData here. ee-gcc bug?
|
||||
create_local_screen(localScreen, localWorld, t_renderData->worldView->data, t_perspective.data);
|
||||
create_local_screen(localScreen, localWorld, t_renderData->view->data, t_perspective.data);
|
||||
|
||||
if (SHOULD_BE_LIGHTED)
|
||||
{
|
||||
const u16 lightsCount = Light::getLightsCount(t_bulbsCount);
|
||||
const u16 lightsCount = light->getLightsCount(t_bulbsCount);
|
||||
VECTOR *lightDirections = new VECTOR[lightsCount];
|
||||
VECTOR *lightColors = new VECTOR[lightsCount];
|
||||
int *lightTypes = new int[lightsCount];
|
||||
@@ -188,16 +180,16 @@ void GifSender::calc3DObject(Matrix t_perspective, Mesh &t_mesh, u32 vertexCount
|
||||
VECTOR *lights = new VECTOR[vertexCount];
|
||||
calculate_normals(normals, vertexCount, normals, localLight);
|
||||
|
||||
Light::calculateLight(lightDirections, lightColors, lightTypes, t_bulbs, t_bulbsCount, t_mesh.position);
|
||||
light->calculateLight(lightDirections, lightColors, lightTypes, t_bulbs, lightsCount, t_mesh.position);
|
||||
|
||||
calculate_lights(lights, vertexCount, normals, lightDirections, lightColors, lightTypes, lightsCount);
|
||||
|
||||
for (u32 i = 0; i < vertexCount; i++)
|
||||
{
|
||||
// Apply the light value to the colour.
|
||||
colors[i][0] = (t_mesh.color.r * lights[i][0] / 128.0F);
|
||||
colors[i][1] = (t_mesh.color.g * lights[i][1] / 128.0F);
|
||||
colors[i][2] = (t_mesh.color.b * lights[i][2] / 128.0F);
|
||||
colors[i][0] = (t_mesh.color.r * lights[i][0]);
|
||||
colors[i][1] = (t_mesh.color.g * lights[i][1]);
|
||||
colors[i][2] = (t_mesh.color.b * lights[i][2]);
|
||||
vector_clamp(colors[i], colors[i], 0.00F, 1.99F);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,11 +23,15 @@ Light::~Light() {}
|
||||
// ----
|
||||
|
||||
const u8 ADDITIONAL_LIGHTS = 1; // Ambient
|
||||
const float LIGHT_MAX = 255.0F;
|
||||
const float LIGHT_DIS_MOD = 4.0F;
|
||||
|
||||
void Light::setAmbientLight(const Vector3 &t_rgb) { ambientLight.set(t_rgb); }
|
||||
|
||||
u16 Light::getLightsCount(u32 t_bulbsCount) { return t_bulbsCount + ADDITIONAL_LIGHTS; }
|
||||
|
||||
/** Calculates lighting. Used in gifSender in object 3D calculations */
|
||||
void Light::calculateLight(VECTOR *t_lightDirections, VECTOR *t_lightColors, int *t_lightTypes, LightBulb *t_bulbs, u32 t_bulbsCount, Vector3 t_objPosition)
|
||||
void Light::calculateLight(VECTOR *t_lightDirections, VECTOR *t_lightColors, int *t_lightTypes, LightBulb *t_bulbs, u32 t_lightsCount, Vector3 t_objPosition)
|
||||
{
|
||||
// --- Ambient light
|
||||
|
||||
@@ -38,34 +42,37 @@ void Light::calculateLight(VECTOR *t_lightDirections, VECTOR *t_lightColors, int
|
||||
t_lightDirections[0][2] = 0.0F;
|
||||
t_lightDirections[0][3] = 1.0F;
|
||||
|
||||
t_lightColors[0][0] = 0.0F;
|
||||
t_lightColors[0][1] = 0.0F;
|
||||
t_lightColors[0][2] = 0.0F;
|
||||
t_lightColors[0][0] = ambientLight.x;
|
||||
t_lightColors[0][1] = ambientLight.y;
|
||||
t_lightColors[0][2] = ambientLight.z;
|
||||
t_lightColors[0][3] = 1.0F;
|
||||
|
||||
// ---
|
||||
|
||||
for (u8 i = 0; i < t_bulbsCount; i++)
|
||||
for (u8 i = 1; i < t_lightsCount; i++)
|
||||
{
|
||||
t_lightTypes[i + 1] = LIGHT_DIRECTIONAL;
|
||||
|
||||
Vector3 newLight = Vector3(t_objPosition.x - t_bulbs[i].position.x,
|
||||
t_objPosition.y - t_bulbs[i].position.y,
|
||||
t_objPosition.z - t_bulbs[i].position.z);
|
||||
t_lightTypes[i] = LIGHT_DIRECTIONAL;
|
||||
|
||||
Vector3 newLight = Vector3(t_objPosition.x - t_bulbs[i - 1].position.x,
|
||||
t_objPosition.y - t_bulbs[i - 1].position.y,
|
||||
t_objPosition.z - t_bulbs[i - 1].position.z);
|
||||
newLight.normalize();
|
||||
newLight = newLight *
|
||||
(.1F +
|
||||
(t_bulbs[i].intensity / t_bulbs[i].position.distanceTo(t_objPosition)));
|
||||
t_lightDirections[i][0] = newLight.x;
|
||||
t_lightDirections[i][1] = newLight.y;
|
||||
t_lightDirections[i][2] = newLight.z;
|
||||
t_lightDirections[i][3] = 1.0F;
|
||||
|
||||
t_lightDirections[i + 1][0] = newLight.x;
|
||||
t_lightDirections[i + 1][1] = newLight.y;
|
||||
t_lightDirections[i + 1][2] = newLight.z;
|
||||
t_lightDirections[i + 1][3] = 1.0F;
|
||||
|
||||
t_lightColors[i + 1][0] = 0.8F;
|
||||
t_lightColors[i + 1][1] = 0.8F;
|
||||
t_lightColors[i + 1][2] = 0.8F;
|
||||
t_lightColors[i + 1][3] = 1.0F;
|
||||
// Intensity range 0.0F - 1.0F
|
||||
float intensity = t_bulbs[i - 1].intensity / LIGHT_MAX;
|
||||
// Distance range 0.0F - LIGHT_MAX * LIGHT_DIS_MOD (1020.0F at this time)
|
||||
float distance = t_bulbs[i - 1].position.distanceTo(t_objPosition);
|
||||
// printf("Distance:%f\n", distance);
|
||||
distance = distance > (LIGHT_MAX - LIGHT_DIS_MOD) * LIGHT_DIS_MOD ? LIGHT_MAX - LIGHT_DIS_MOD : distance;
|
||||
intensity /= 1.0F + (distance / LIGHT_DIS_MOD); // intensity /= 1.0F - 251.0F
|
||||
intensity /= 3.0F; // it looks better
|
||||
t_lightColors[i][0] = intensity;
|
||||
t_lightColors[i][1] = intensity;
|
||||
t_lightColors[i][2] = intensity;
|
||||
t_lightColors[i][3] = 1.0F;
|
||||
}
|
||||
}
|
||||
|
||||
+103
-41
@@ -13,8 +13,6 @@
|
||||
#include <dma.h>
|
||||
#include <graph.h>
|
||||
#include <packet.h>
|
||||
#include <draw.h>
|
||||
#include <gs_psm.h>
|
||||
#include "../include/utils/debug.hpp"
|
||||
#include "../include/utils/math.hpp"
|
||||
|
||||
@@ -22,6 +20,9 @@
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
static const float GS_CENTER = 4096.0F;
|
||||
static const float SCREEN_CENTER = GS_CENTER / 2.0F;
|
||||
|
||||
/** Initialize DMA<->GIF channel
|
||||
* Allocate buffers
|
||||
* Initialize screen
|
||||
@@ -35,20 +36,23 @@ Renderer::Renderer(u32 t_packetSize, ScreenSettings *t_screen)
|
||||
PRINT_LOG("Initializing renderer");
|
||||
dma_channel_initialize(DMA_CHANNEL_GIF, NULL, 0); // Initialize DMA to enable data transfer
|
||||
dma_channel_fast_waits(DMA_CHANNEL_GIF);
|
||||
screen = t_screen;
|
||||
context = 0;
|
||||
isTextureVRAMAllocated = false;
|
||||
isVSyncEnabled = true;
|
||||
isFrameEmpty = false;
|
||||
lastTextureId = 0;
|
||||
flipPacket = packet2_create(4, P2_TYPE_UNCACHED_ACCL, P2_MODE_NORMAL, 0);
|
||||
allocateBuffers(t_screen->width, t_screen->height);
|
||||
initDrawingEnv(t_screen->width, t_screen->height);
|
||||
allocateBuffers((int)t_screen->width, (int)t_screen->height);
|
||||
initDrawingEnv();
|
||||
setPrim();
|
||||
screen = t_screen;
|
||||
gifSender = new GifSender(t_packetSize, t_screen);
|
||||
vifSender = new VifSender();
|
||||
worldColor.r = 0x10;
|
||||
worldColor.g = 0x10;
|
||||
worldColor.b = 0x10;
|
||||
gifSender = new GifSender(t_packetSize, t_screen, &light);
|
||||
vifSender = new VifSender(&light);
|
||||
perspective.setPerspective(*t_screen);
|
||||
renderData.perspective = &perspective;
|
||||
renderData.projection = &perspective;
|
||||
PRINT_LOG("Renderer initialized!");
|
||||
}
|
||||
|
||||
@@ -101,11 +105,30 @@ void Renderer::changeTexture(Texture *t_tex)
|
||||
|
||||
void Renderer::draw(Sprite &t_sprite)
|
||||
{
|
||||
Texture *texture = textureRepo.getBySprite(t_sprite.getId());
|
||||
texrect_t rect;
|
||||
rect.t0.s = t_sprite.isFlippedHorizontally() ? 128.0F : 0.0F;
|
||||
rect.t0.t = t_sprite.isFlippedVertically() ? 128.0F : 0.0F;
|
||||
rect.t1.s = t_sprite.isFlippedHorizontally() ? 0.0F : 128.0F;
|
||||
rect.t1.t = t_sprite.isFlippedVertically() ? 0.0F : 128.0F;
|
||||
float sizeX, sizeY;
|
||||
if (t_sprite.getMode() == MODE_REPEAT)
|
||||
{
|
||||
sizeX = t_sprite.size.x;
|
||||
sizeY = t_sprite.size.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
sizeX = (float)texture->getWidth();
|
||||
sizeY = (float)texture->getHeight();
|
||||
}
|
||||
|
||||
float texS, texT;
|
||||
float texMax = texT = texS = sizeX > sizeY ? sizeX : sizeY;
|
||||
if (sizeX > sizeY)
|
||||
texT = texMax / (sizeX / sizeY);
|
||||
else if (sizeY > sizeX)
|
||||
texS = texMax / (sizeY / sizeX);
|
||||
rect.t0.s = t_sprite.isFlippedHorizontally() ? texS : 0.0F;
|
||||
rect.t0.t = t_sprite.isFlippedVertically() ? texT : 0.0F;
|
||||
rect.t1.s = t_sprite.isFlippedHorizontally() ? 0.0F : texS;
|
||||
rect.t1.t = t_sprite.isFlippedVertically() ? 0.0F : texT;
|
||||
rect.color.r = t_sprite.color.r;
|
||||
rect.color.g = t_sprite.color.g;
|
||||
rect.color.b = t_sprite.color.b;
|
||||
@@ -118,17 +141,20 @@ void Renderer::draw(Sprite &t_sprite)
|
||||
rect.v1.y = (t_sprite.size.y * t_sprite.scale) + t_sprite.position.y;
|
||||
rect.v1.z = (u32)-1;
|
||||
beginFrameIfNeeded();
|
||||
changeTexture(textureRepo.getBySprite(t_sprite.getId()));
|
||||
changeTexture(texture);
|
||||
packet2_t *packet2 = packet2_create(12, P2_TYPE_NORMAL, P2_MODE_NORMAL, 0);
|
||||
packet2_update(packet2, draw_primitive_xyoffset(packet2->next, 0, 2048, 2048));
|
||||
packet2_update(packet2, draw_primitive_xyoffset(packet2->next, 0, SCREEN_CENTER, SCREEN_CENTER));
|
||||
packet2_utils_gif_add_set(packet2, 1);
|
||||
packet2_utils_gs_add_texbuff_clut(packet2, &textureBuffer, &t_sprite.clut);
|
||||
draw_enable_blending();
|
||||
packet2_update(packet2, draw_rect_textured(packet2->next, 0, &rect));
|
||||
packet2_update(packet2,
|
||||
draw_primitive_xyoffset(
|
||||
packet2->next,
|
||||
0,
|
||||
(2048 - (screen->width / 2)), (2048 - (screen->height / 2))));
|
||||
SCREEN_CENTER - (screen->width / 2.0F),
|
||||
SCREEN_CENTER - (screen->height / 2.0F)));
|
||||
draw_disable_blending();
|
||||
packet2_update(packet2, draw_finish(packet2->next));
|
||||
dma_channel_wait(DMA_CHANNEL_GIF, 0);
|
||||
dma_channel_send_packet2(packet2, DMA_CHANNEL_GIF, true);
|
||||
@@ -136,14 +162,14 @@ void Renderer::draw(Sprite &t_sprite)
|
||||
}
|
||||
|
||||
/** Initializes drawing environment (1st app packet) */
|
||||
void Renderer::initDrawingEnv(float t_screenW, float t_screenH)
|
||||
void Renderer::initDrawingEnv()
|
||||
{
|
||||
PRINT_LOG("Initializing drawing environment");
|
||||
u16 halfW = (u16)t_screenW / 2;
|
||||
u16 halfH = (u16)t_screenH / 2;
|
||||
packet2_t *packet2 = packet2_create(20, P2_TYPE_NORMAL, P2_MODE_NORMAL, 0);
|
||||
packet2_update(packet2, draw_setup_environment(packet2->base, 0, frameBuffers, &(zBuffer)));
|
||||
packet2_update(packet2, draw_primitive_xyoffset(packet2->next, 0, (2048 - halfW), (2048 - halfH)));
|
||||
packet2_update(packet2, draw_primitive_xyoffset(packet2->next, 0,
|
||||
SCREEN_CENTER - (screen->width / 2.0F),
|
||||
SCREEN_CENTER - (screen->height / 2.0F)));
|
||||
packet2_update(packet2, draw_finish(packet2->next));
|
||||
dma_channel_send_packet2(packet2, DMA_CHANNEL_GIF, true);
|
||||
dma_channel_wait(DMA_CHANNEL_GIF, 0);
|
||||
@@ -166,30 +192,37 @@ void Renderer::setPrim()
|
||||
PRINT_LOG("Prim set!");
|
||||
}
|
||||
|
||||
/** Defines and allocates framebuffers and zbuffer */
|
||||
void Renderer::allocateBuffers(float t_screenW, float t_screenH)
|
||||
void Renderer::setWorldColor(const color_t &t_rgb)
|
||||
{
|
||||
frameBuffers[0].width = (u16)t_screenW;
|
||||
frameBuffers[0].height = (u16)t_screenH;
|
||||
worldColor.r = t_rgb.r;
|
||||
worldColor.g = t_rgb.g;
|
||||
worldColor.b = t_rgb.b;
|
||||
}
|
||||
|
||||
/** Defines and allocates framebuffers and zbuffer */
|
||||
void Renderer::allocateBuffers(int t_screenW, int t_screenH)
|
||||
{
|
||||
frameBuffers[0].width = (unsigned int)t_screenW;
|
||||
frameBuffers[0].height = (unsigned int)t_screenH;
|
||||
frameBuffers[0].mask = 0;
|
||||
frameBuffers[0].psm = GS_PSM_32;
|
||||
frameBuffers[0].address = graph_vram_allocate((u16)t_screenW, (u16)t_screenH, frameBuffers[0].psm, GRAPH_ALIGN_PAGE);
|
||||
frameBuffers[0].address = graph_vram_allocate(t_screenW, t_screenH, frameBuffers[0].psm, GRAPH_ALIGN_PAGE);
|
||||
|
||||
frameBuffers[1].width = (u16)t_screenW;
|
||||
frameBuffers[1].height = (u16)t_screenH;
|
||||
frameBuffers[1].width = (unsigned int)t_screenW;
|
||||
frameBuffers[1].height = (unsigned int)t_screenH;
|
||||
frameBuffers[1].mask = 0;
|
||||
frameBuffers[1].psm = GS_PSM_32;
|
||||
frameBuffers[1].address = graph_vram_allocate((u16)t_screenW, (u16)t_screenH, frameBuffers[1].psm, GRAPH_ALIGN_PAGE);
|
||||
frameBuffers[1].address = graph_vram_allocate(t_screenW, t_screenH, frameBuffers[1].psm, GRAPH_ALIGN_PAGE);
|
||||
|
||||
zBuffer.enable = DRAW_ENABLE;
|
||||
zBuffer.mask = 0;
|
||||
zBuffer.method = ZTEST_METHOD_GREATER_EQUAL;
|
||||
zBuffer.zsm = GS_ZBUF_32;
|
||||
zBuffer.address = graph_vram_allocate((u16)t_screenW, (u16)t_screenH, zBuffer.zsm, GRAPH_ALIGN_PAGE);
|
||||
zBuffer.zsm = GS_ZBUF_24;
|
||||
zBuffer.address = graph_vram_allocate(t_screenW, t_screenH, zBuffer.zsm, GRAPH_ALIGN_PAGE);
|
||||
PRINT_LOG("Framebuffers, zBuffer set and allocated!");
|
||||
|
||||
// Initialize the screen and tie the first framebuffer to the read circuits.
|
||||
graph_initialize(frameBuffers[1].address, frameBuffers[1].width, frameBuffers[1].height, frameBuffers[1].psm, 0, 0);
|
||||
graph_initialize(frameBuffers[0].address, frameBuffers[0].width, frameBuffers[0].height, frameBuffers[0].psm, 0, 0);
|
||||
}
|
||||
|
||||
/// --- Draw: PATH3
|
||||
@@ -233,21 +266,50 @@ void Renderer::drawByPath3(Mesh &t_mesh) { drawByPath3(t_mesh, NULL, 0); }
|
||||
|
||||
/// --- Draw: PATH1
|
||||
|
||||
void Renderer::draw(Mesh *t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount)
|
||||
void Renderer::draw(Mesh **t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount)
|
||||
{
|
||||
beginFrameIfNeeded();
|
||||
if (!t_meshes[0]->isDataLoaded())
|
||||
PRINT_ERR("Can't draw, because no mesh data was loaded!");
|
||||
else if (
|
||||
t_amount >= 3 &&
|
||||
!t_meshes[0]->shouldBeBackfaceCulled &&
|
||||
t_meshes[0]->getFramesCount() == 1 &&
|
||||
t_meshes[0]->getMaterialsCount() == 1 &&
|
||||
t_meshes[0]->getFrame(0).getVertexCount() <= 96)
|
||||
{
|
||||
vifSender->disableWait();
|
||||
Mesh **meshesInFrustum = new Mesh *[t_amount];
|
||||
u16 addedMeshes = 0;
|
||||
for (u16 i = 0; i < t_amount; i++)
|
||||
draw(t_meshes[i], t_bulbs, t_bulbsCount);
|
||||
if (t_meshes[i]->getMaterial(0).isInFrustum(renderData.frustumPlanes, t_meshes[i]->position))
|
||||
meshesInFrustum[addedMeshes++] = t_meshes[i];
|
||||
draw(*meshesInFrustum[0], t_bulbs, t_bulbsCount);
|
||||
draw(*meshesInFrustum[1], t_bulbs, t_bulbsCount);
|
||||
vifSender->enableWait();
|
||||
resetWaitFlag();
|
||||
vifSender->drawTheSameWithOtherMatrices(renderData, meshesInFrustum, 2, addedMeshes);
|
||||
if (isWaitFlagSet())
|
||||
resetWaitFlag();
|
||||
else
|
||||
waitForRender();
|
||||
delete[] meshesInFrustum;
|
||||
}
|
||||
else
|
||||
for (u16 i = 0; i < t_amount; i++)
|
||||
draw(*t_meshes[i], t_bulbs, t_bulbsCount);
|
||||
}
|
||||
|
||||
void Renderer::draw(Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount)
|
||||
{
|
||||
beginFrameIfNeeded();
|
||||
vifSender->sendMatrices(renderData, t_mesh.position, t_mesh.rotation);
|
||||
vifSender->calcMatrix(renderData, t_mesh.position, t_mesh.rotation);
|
||||
if (!t_mesh.isDataLoaded())
|
||||
PRINT_ERR("Can't draw, because no mesh data was loaded!");
|
||||
|
||||
Vector3 rotatedCamera = Vector3(*renderData.cameraPosition);
|
||||
rotatedCamera.rotate(t_mesh.rotation, true);
|
||||
camRotation.identity();
|
||||
camRotation.rotate(-t_mesh.rotation);
|
||||
Vector3 rotatedCamera = Vector3(camRotation * *renderData.cameraPosition);
|
||||
|
||||
if (t_mesh.getCurrentAnimationFrame() != t_mesh.getNextAnimationFrame())
|
||||
t_mesh.animate();
|
||||
@@ -256,9 +318,9 @@ void Renderer::draw(Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount)
|
||||
if (t_mesh.shouldBeFrustumCulled && !t_mesh.getMaterial(i).isInFrustum(renderData.frustumPlanes, t_mesh.position))
|
||||
return;
|
||||
u32 vertCount = t_mesh.getMaterial(i).getFacesCount();
|
||||
VECTOR __attribute__((aligned(16))) vertices[vertCount];
|
||||
VECTOR __attribute__((aligned(16))) normals[vertCount];
|
||||
VECTOR __attribute__((aligned(16))) coordinates[vertCount];
|
||||
VECTOR vertices[vertCount] __attribute__((aligned(16)));
|
||||
VECTOR normals[vertCount] __attribute__((aligned(16)));
|
||||
VECTOR coordinates[vertCount] __attribute__((aligned(16)));
|
||||
Texture *tex = textureRepo.getByMesh(t_mesh.getId(), t_mesh.getMaterial(i).getId());
|
||||
changeTexture(tex);
|
||||
vertCount = t_mesh.getDrawData(i, vertices, normals, coordinates, rotatedCamera);
|
||||
@@ -266,7 +328,7 @@ void Renderer::draw(Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount)
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::draw(Mesh *t_meshes, u16 t_amount) { draw(t_meshes, t_amount, NULL, 0); }
|
||||
void Renderer::draw(Mesh **t_meshes, u16 t_amount) { draw(t_meshes, t_amount, NULL, 0); }
|
||||
|
||||
void Renderer::draw(Mesh &t_mesh) { draw(t_mesh, NULL, 0); }
|
||||
|
||||
@@ -274,7 +336,7 @@ void Renderer::draw(Mesh &t_mesh) { draw(t_mesh, NULL, 0); }
|
||||
|
||||
void Renderer::setCameraDefinitions(Matrix *t_worldView, Vector3 *t_cameraPos, Plane *t_planes)
|
||||
{
|
||||
renderData.worldView = t_worldView;
|
||||
renderData.view = t_worldView;
|
||||
renderData.cameraPosition = t_cameraPos;
|
||||
renderData.frustumPlanes = t_planes;
|
||||
}
|
||||
@@ -284,7 +346,7 @@ void Renderer::beginFrameIfNeeded()
|
||||
if (isFrameEmpty)
|
||||
{
|
||||
isFrameEmpty = false;
|
||||
gifSender->sendClear(&zBuffer);
|
||||
gifSender->sendClear(&zBuffer, &worldColor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,16 +10,11 @@
|
||||
|
||||
#include "../include/modules/timer.hpp"
|
||||
|
||||
#include <timer.h>
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
Timer::Timer()
|
||||
{
|
||||
this->lastTime = *T3_COUNT;
|
||||
}
|
||||
Timer::Timer() { prime(); }
|
||||
|
||||
Timer::~Timer() {}
|
||||
|
||||
@@ -29,20 +24,13 @@ Timer::~Timer() {}
|
||||
|
||||
u32 Timer::getTimeDelta()
|
||||
{
|
||||
this->time = *T3_COUNT;
|
||||
time = *T3_COUNT;
|
||||
|
||||
if (this->time < this->lastTime) // The counter has wrapped
|
||||
this->change = this->time + (65536 - this->lastTime);
|
||||
if (time < lastTime) // The counter has wrapped
|
||||
change = time + (65536 - lastTime);
|
||||
else
|
||||
this->change = this->time - this->lastTime;
|
||||
|
||||
this->lastTime = this->time;
|
||||
return this->change;
|
||||
}
|
||||
|
||||
void Timer::primeTimer()
|
||||
{
|
||||
lastTime = *T3_COUNT;
|
||||
change = time - lastTime;
|
||||
return change;
|
||||
}
|
||||
|
||||
float Timer::getFPS()
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
#include "../include/utils/debug.hpp"
|
||||
|
||||
const u32 VU1_PACKAGE_VERTS_PER_BUFF = 96; // Remember to modify buffer size in vu1 also
|
||||
const u32 VU1_PACKAGES_PER_PACKET = 6;
|
||||
const u32 VU1_PACKET_SIZE = 128;
|
||||
const u32 VU1_PACKAGES_PER_PACKET = 9;
|
||||
const u32 VU1_PACKET_SIZE = 256; // should be 128, but 256 is more safe for future
|
||||
const u8 VU1_PARAMS_ADDRESS = 4;
|
||||
const u8 VU1_RGBA_ADDRESS = 8;
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
@@ -29,25 +31,26 @@ extern u32 VU1Draw3D_CodeStart __attribute__((section(".vudata")));
|
||||
extern u32 VU1Draw3D_CodeEnd __attribute__((section(".vudata")));
|
||||
//
|
||||
|
||||
VifSender::VifSender()
|
||||
VifSender::VifSender(Light *t_light)
|
||||
{
|
||||
PRINT_LOG("Initializing VifSender");
|
||||
PRINT_LOG("VifSender initialized!");
|
||||
light = t_light;
|
||||
lastVertCount = 0;
|
||||
isDrawWaitEnabled = true;
|
||||
dma_channel_initialize(DMA_CHANNEL_VIF1, NULL, 0);
|
||||
dma_channel_fast_waits(DMA_CHANNEL_VIF1);
|
||||
uploadMicroProgram();
|
||||
packets[0] = packet2_create(VU1_PACKET_SIZE, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
|
||||
packets[1] = packet2_create(VU1_PACKET_SIZE, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
|
||||
matricesPacket = packet2_create(4, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
|
||||
context = 0;
|
||||
setDoubleBuffer();
|
||||
setDoubleBufferAddStaticData();
|
||||
PRINT_LOG("VifSender initialized!");
|
||||
}
|
||||
|
||||
VifSender::~VifSender()
|
||||
{
|
||||
packet2_free(packets[0]);
|
||||
packet2_free(packets[1]);
|
||||
packet2_free(matricesPacket);
|
||||
}
|
||||
|
||||
// ----
|
||||
@@ -68,17 +71,16 @@ void VifSender::uploadMicroProgram()
|
||||
packet2_free(packet2);
|
||||
}
|
||||
|
||||
void VifSender::sendMatrices(const RenderData &t_renderData, const Vector3 &t_position, const Vector3 &t_rotation)
|
||||
void VifSender::calcMatrix(const RenderData &t_renderData, const Vector3 &t_position, const Vector3 &t_rotation)
|
||||
{
|
||||
vec3ToNative(position, t_position, 1.0F);
|
||||
vec3ToNative(rotation, t_rotation, 1.0F);
|
||||
create_local_world(localWorld, position, rotation);
|
||||
create_local_screen(localScreen, localWorld, t_renderData.worldView->data, t_renderData.perspective->data);
|
||||
packet2_reset(matricesPacket, false);
|
||||
packet2_utils_vu_add_unpack_data(matricesPacket, 0, &localScreen, 8, 0);
|
||||
packet2_utils_vu_add_end_tag(matricesPacket);
|
||||
dma_channel_wait(DMA_CHANNEL_VIF1, 0);
|
||||
dma_channel_send_packet2(matricesPacket, DMA_CHANNEL_VIF1, 1);
|
||||
model.identity();
|
||||
model.rotate(t_rotation);
|
||||
model.translate(t_position);
|
||||
|
||||
modelViewProj.identity();
|
||||
modelViewProj = model * modelViewProj;
|
||||
modelViewProj = *t_renderData.view * modelViewProj;
|
||||
modelViewProj = *t_renderData.projection * modelViewProj;
|
||||
}
|
||||
|
||||
void VifSender::drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 vertCount2, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer)
|
||||
@@ -95,7 +97,7 @@ void VifSender::drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 ver
|
||||
i -= 3;
|
||||
|
||||
const u32 endI = i + (VU1_PACKAGE_VERTS_PER_BUFF - 1) > vertCount2 ? vertCount2 : i + (VU1_PACKAGE_VERTS_PER_BUFF - 1);
|
||||
drawVertices(t_mesh, i, endI, vertices, coordinates, t_renderData->prim, textureBuffer);
|
||||
drawVertices(t_mesh, i, endI, vertices, coordinates, t_renderData->prim, textureBuffer, isDrawWaitEnabled ? endI == vertCount2 : false);
|
||||
if (endI == vertCount2) // if there are no more vertices to draw, break
|
||||
{
|
||||
i = vertCount2;
|
||||
@@ -111,80 +113,132 @@ void VifSender::drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 ver
|
||||
}
|
||||
}
|
||||
|
||||
void VifSender::setDoubleBuffer()
|
||||
void VifSender::setDoubleBufferAddStaticData()
|
||||
{
|
||||
packet2_t *settings = packet2_create(2, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
|
||||
packet2_utils_vu_add_double_buffer(settings, 8, 496);
|
||||
packet2_t *settings = packet2_create(10, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
|
||||
packet2_utils_vu_open_unpack(settings, 0, false);
|
||||
{
|
||||
packet2_utils_gs_add_draw_finish_giftag(settings);
|
||||
packet2_utils_gif_add_set(settings, 1);
|
||||
}
|
||||
packet2_utils_vu_close_unpack(settings);
|
||||
packet2_utils_vu_add_double_buffer(settings, 10, 498);
|
||||
packet2_utils_vu_add_end_tag(settings);
|
||||
dma_channel_send_packet2(settings, DMA_CHANNEL_VIF1, 1);
|
||||
dma_channel_send_packet2(settings, DMA_CHANNEL_VIF1, true);
|
||||
dma_channel_wait(DMA_CHANNEL_VIF1, 0);
|
||||
packet2_free(settings);
|
||||
}
|
||||
|
||||
/** Draw using PATH1 */
|
||||
void VifSender::drawVertices(Mesh &t_mesh, u32 t_start, u32 t_end, VECTOR *t_vertices, VECTOR *t_coordinates, prim_t *t_prim, texbuffer_t *textureBuffer)
|
||||
void VifSender::drawVertices(Mesh &t_mesh, u32 t_start, u32 t_end, VECTOR *t_vertices, VECTOR *t_coordinates, prim_t *t_prim, texbuffer_t *t_texBuff, u8 t_addDrawWait)
|
||||
{
|
||||
const u32 vertCount = t_end - t_start;
|
||||
u32 vif_added_bytes = 0;
|
||||
packet2_utils_vu_open_unpack(currPacket, 0, 1);
|
||||
// TODO get this via screensettings
|
||||
packet2_add_float(currPacket, 2048.0F); // scale
|
||||
packet2_add_float(currPacket, 2048.0F); // scale
|
||||
packet2_add_float(currPacket, ((float)0xFFFFFF) / 32.0F); // scale
|
||||
packet2_add_u32(currPacket, vertCount); // vertex count
|
||||
packet2_utils_gif_add_set(currPacket, 1);
|
||||
lastVertCount = vertCount;
|
||||
packet2_utils_vu_open_unpack(currPacket, 0, true);
|
||||
packet2_add_data(currPacket, modelViewProj.data, 4);
|
||||
packet2_add_u32(currPacket, t_addDrawWait); // Draw finish?
|
||||
packet2_add_u32(currPacket, vertCount); // Vertex count
|
||||
packet2_add_u32(currPacket, vertCount / 3); // Triangles count
|
||||
packet2_add_u32(currPacket, 0); // Free
|
||||
packet2_utils_gs_add_lod(currPacket, &t_mesh.lod);
|
||||
packet2_utils_gs_add_texbuff_clut(currPacket, textureBuffer, &t_mesh.clut);
|
||||
packet2_utils_gs_add_texbuff_clut(currPacket, t_texBuff, &t_mesh.clut);
|
||||
packet2_utils_gs_add_prim_giftag(currPacket, t_prim, vertCount, DRAW_STQ2_REGLIST, 3, 0);
|
||||
|
||||
for (u8 j = 0; j < 4; j++)
|
||||
packet2_add_u32(currPacket, 128);
|
||||
|
||||
// Clipping tests start
|
||||
|
||||
// // const float minZ = 1;
|
||||
// // const float maxZ = 65535;
|
||||
// // const int iGuardDimXY = 2048;
|
||||
|
||||
// // vu1.addFloat(1.0F); // f_TODO clipping maybe there is problem?
|
||||
// // vu1.addFloat(1.0F);
|
||||
// // vu1.addFloat(1.0F);
|
||||
// // vu1.addFloat(1.0F);
|
||||
// // float xClip = (float)2048.0f/(drawContext.GetFBWidth() * 0.5f * 2.0f);
|
||||
// // packet += Math::Max( xClip, 1.0f );
|
||||
// // float yClip = (float)2048.0f/(drawContext.GetFBHeight() * 0.5f * 2.0f);
|
||||
// // packet += Math::Max( yClip, 1.0f );
|
||||
// // float depthClip = 2048.0f / depthClipToGs;
|
||||
// // // F_FIXME: maybe these 2048's should be 2047.5s...
|
||||
// // depthClip *= 1.003f; // round up a bit for fp error (????)
|
||||
// // packet += depthClip;
|
||||
// // // enable/disable clipping
|
||||
// // packet += (drawContext.GetDoClipping()) ? 1 : 0;
|
||||
|
||||
// u32 depthBits = 24; // or 28(fog) or 16
|
||||
// float depthClipToGs = (float)((1 << depthBits) - 1) / 2.0f;
|
||||
// vu1.addFloat(2048.0f / (640.0F * 0.5f * 2.0f));
|
||||
// vu1.addFloat(2048.0f / (480.0F * 0.5f * 2.0f));
|
||||
// vu1.addFloat((2048.0f / depthClipToGs) * 1.003F);
|
||||
// // vu1.addFloat(2048.0F); // scale
|
||||
// // vu1.addFloat(2048.0F); // scale
|
||||
// // vu1.addFloat(((float)0xFFFFFF) / 32.0F); // scale
|
||||
// vu1.addFloat(0.0F);
|
||||
// // vu1.addFloat(0.5f * iGuardDimXY);
|
||||
// // vu1.addFloat(-0.5f * iGuardDimXY);
|
||||
// // vu1.addFloat(1.0F);
|
||||
// // vu1.addFloat(500.0F); // far
|
||||
|
||||
packet2_add_float(currPacket, 0.0F);
|
||||
packet2_add_float(currPacket, 0.0F);
|
||||
packet2_add_float(currPacket, 0.0F);
|
||||
packet2_add_float(currPacket, 0.0F);
|
||||
|
||||
//// Clipping tests end
|
||||
vif_added_bytes += packet2_utils_vu_close_unpack(currPacket);
|
||||
packet2_utils_vu_add_unpack_data(currPacket, vif_added_bytes, t_vertices + t_start, vertCount, 1);
|
||||
packet2_add_u32(currPacket, t_mesh.color.r);
|
||||
packet2_add_u32(currPacket, t_mesh.color.g);
|
||||
packet2_add_u32(currPacket, t_mesh.color.b);
|
||||
packet2_add_u32(currPacket, t_mesh.color.a);
|
||||
u32 vif_added_bytes = packet2_utils_vu_close_unpack(currPacket);
|
||||
packet2_utils_vu_add_unpack_data(currPacket, vif_added_bytes, t_vertices + t_start, vertCount, true);
|
||||
vif_added_bytes += vertCount;
|
||||
packet2_utils_vu_add_unpack_data(currPacket, vif_added_bytes, t_coordinates + t_start, vertCount, 1);
|
||||
packet2_utils_vu_add_unpack_data(currPacket, vif_added_bytes, t_coordinates + t_start, vertCount, true);
|
||||
vif_added_bytes += vertCount;
|
||||
packet2_utils_vu_add_start_program(currPacket, 0);
|
||||
}
|
||||
|
||||
void VifSender::drawTheSameWithOtherMatrices(const RenderData &t_renderData, Mesh **t_meshes, const u32 &t_skip, const u32 &t_count)
|
||||
{
|
||||
// Standard double buffering (packets)
|
||||
packet2_t *packet1 = packet2_create(300, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
|
||||
packet2_t *packet2 = packet2_create(300, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
|
||||
packet2_t *currMPacket = packet1;
|
||||
u8 currPacketIndex = 1;
|
||||
|
||||
// We are sending 32 matrices max per one VU1 send
|
||||
u8 switchCounter = 0;
|
||||
for (u32 i = t_skip; i < t_count; i++)
|
||||
{
|
||||
model.identity();
|
||||
model.rotate(t_meshes[i]->rotation);
|
||||
model.translate(t_meshes[i]->position);
|
||||
|
||||
modelViewProj.identity();
|
||||
modelViewProj = model * modelViewProj;
|
||||
modelViewProj = *t_renderData.view * modelViewProj;
|
||||
modelViewProj = *t_renderData.projection * modelViewProj;
|
||||
|
||||
packet2_utils_vu_open_unpack(currMPacket, 0, true);
|
||||
{
|
||||
packet2_add_data(currMPacket, modelViewProj.data, 4);
|
||||
}
|
||||
packet2_utils_vu_close_unpack(currMPacket);
|
||||
packet2_utils_vu_open_unpack(currMPacket, VU1_RGBA_ADDRESS, true);
|
||||
{
|
||||
packet2_add_u32(currMPacket, t_meshes[i]->color.r);
|
||||
packet2_add_u32(currMPacket, t_meshes[i]->color.g);
|
||||
packet2_add_u32(currMPacket, t_meshes[i]->color.b);
|
||||
packet2_add_u32(currMPacket, t_meshes[i]->color.a);
|
||||
}
|
||||
packet2_utils_vu_close_unpack(currMPacket);
|
||||
|
||||
if (i != t_count - 1) // if it is last, we must also add draw wait finish interrupt.
|
||||
packet2_utils_vu_add_start_program(currMPacket, 0);
|
||||
|
||||
if (switchCounter++ >= 32)
|
||||
{
|
||||
switchCounter = 0;
|
||||
if (i == t_count - 1) // is last
|
||||
{
|
||||
packet2_utils_vu_open_unpack(currMPacket, VU1_PARAMS_ADDRESS, true);
|
||||
{
|
||||
packet2_add_u32(currMPacket, true); // Draw wait finish?
|
||||
packet2_add_u32(currMPacket, lastVertCount); // Vertex count
|
||||
packet2_add_u32(currMPacket, lastVertCount / 3); // Triangles count
|
||||
packet2_add_u32(currMPacket, 0); // Free
|
||||
}
|
||||
packet2_utils_vu_close_unpack(currMPacket);
|
||||
packet2_utils_vu_add_start_program(currMPacket, 0); // and start program
|
||||
}
|
||||
packet2_utils_vu_add_end_tag(currMPacket);
|
||||
dma_channel_wait(DMA_CHANNEL_VIF1, 0);
|
||||
dma_channel_send_packet2(currMPacket, DMA_CHANNEL_VIF1, 1);
|
||||
if (currPacketIndex == 1) // Switch double buffer (packets)
|
||||
{
|
||||
currPacketIndex = 2;
|
||||
currMPacket = packet2;
|
||||
}
|
||||
else
|
||||
{
|
||||
currPacketIndex = 1;
|
||||
currMPacket = packet1;
|
||||
}
|
||||
packet2_reset(currMPacket, false);
|
||||
}
|
||||
}
|
||||
if (switchCounter != 0) // if there are any not sended matrices
|
||||
{
|
||||
packet2_utils_vu_open_unpack(currMPacket, VU1_PARAMS_ADDRESS, true);
|
||||
{
|
||||
packet2_add_u32(currMPacket, true); // Draw wait finish?
|
||||
packet2_add_u32(currMPacket, lastVertCount); // Vertex count
|
||||
packet2_add_u32(currMPacket, lastVertCount / 3); // Triangles count
|
||||
packet2_add_u32(currMPacket, 0); // Free
|
||||
}
|
||||
packet2_utils_vu_close_unpack(currMPacket);
|
||||
packet2_utils_vu_add_start_program(currMPacket, 0);
|
||||
packet2_utils_vu_add_end_tag(currMPacket);
|
||||
dma_channel_wait(DMA_CHANNEL_VIF1, 0);
|
||||
dma_channel_send_packet2(currMPacket, DMA_CHANNEL_VIF1, 1);
|
||||
}
|
||||
packet2_free(packet1);
|
||||
packet2_free(packet2);
|
||||
}
|
||||
|
||||
@@ -99,3 +99,87 @@ void manyVec3ToNative(VECTOR *o_result, Vector3 *t_vec, int t_amount, float t_fo
|
||||
for (int i = 0; i < t_amount; i++)
|
||||
vec3ToNative(o_result[i], t_vec[i], t_fourthVal);
|
||||
}
|
||||
|
||||
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 (y == 0.0f)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
i = floorf(x / y);
|
||||
f = x - i * y;
|
||||
|
||||
if ((x < 0.0f) != (y < 0.0f))
|
||||
{
|
||||
f = f - y;
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
; ______ ____ ___
|
||||
; | \/ ____| |___|
|
||||
; | | | \ | |
|
||||
;---------------------------
|
||||
; Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
; Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
;
|
||||
;---------------------------------------------------------------
|
||||
; draw3D.vcl |
|
||||
;---------------------------------------------------------------
|
||||
; A VU1 microprogram to draw 3D object using XYZ2, RGBAQ and ST|
|
||||
; This program uses double buffering (xtop) |
|
||||
; |
|
||||
; Many thanks to: |
|
||||
; - Dr Henry Fortuna |
|
||||
; - Jesper Svennevid, Daniel Collin |
|
||||
; - Guilherme Lampert |
|
||||
;---------------------------------------------------------------
|
||||
|
||||
; TODO
|
||||
; - Fix vertex clipping (is clipping visible triangles :/)
|
||||
; - Move lerp() from EE to VU1 (performance)
|
||||
; - Add dynamic lighting (feature)
|
||||
; - Add --cont + MSCNT instead of alltime MSCAL (performance)
|
||||
|
||||
.syntax new
|
||||
.name VU1Draw3D
|
||||
.vu
|
||||
.init_vf_all
|
||||
.init_vi_all
|
||||
|
||||
--enter
|
||||
--endenter
|
||||
|
||||
;//////////// --- Load data 1 --- /////////////
|
||||
; Updated once per frame
|
||||
lq matrixRow0, 0(vi00) ; load view-projection matrix
|
||||
lq matrixRow1, 1(vi00)
|
||||
lq matrixRow2, 2(vi00)
|
||||
lq matrixRow3, 3(vi00)
|
||||
;/////////////////////////////////////////////
|
||||
|
||||
fcset 0x000000 ; VCL won't let us use CLIP without first zeroing
|
||||
; the clip flags
|
||||
|
||||
;//////////// --- Load data 2 --- /////////////
|
||||
; Updated dynamically
|
||||
xtop iBase
|
||||
|
||||
lq.xyz scale, 0(iBase) ; load program params
|
||||
; float : X, Y, Z - scale vector that we will use to scale the verts after projecting them.
|
||||
; float : W - vert count.
|
||||
lq gifSetTag, 1(iBase) ; GIF tag - set
|
||||
lq texGifTag1, 2(iBase) ; GIF tag - texture LOD
|
||||
lq texGifTag2, 3(iBase) ; GIF tag - texture buffer & CLUT
|
||||
lq primTag, 4(iBase) ; GIF tag - tell GS how many data we will send
|
||||
lq rgba, 5(iBase) ; RGBA
|
||||
;lq clipScale, 6(iBase) ; TODO clipping tests
|
||||
; u32 : R, G, B, A (0-128)
|
||||
iaddiu vertexData, iBase, 7 ; pointer to vertex data
|
||||
ilw.w vertCount, 0(iBase) ; load vert count from scale vector
|
||||
iadd stqData, vertexData, vertCount ; pointer to stq
|
||||
iadd kickAddress, stqData, vertCount ; pointer for XGKICK
|
||||
iadd destAddress, stqData, vertCount ; helper pointer for data inserting
|
||||
;////////////////////////////////////////////
|
||||
|
||||
;/////////// --- Store tags --- /////////////
|
||||
sqi gifSetTag, (destAddress++) ;
|
||||
sqi texGifTag1, (destAddress++) ; texture LOD tag
|
||||
sqi gifSetTag, (destAddress++) ;
|
||||
sqi texGifTag2, (destAddress++) ; texture buffer & CLUT tag
|
||||
sqi primTag, (destAddress++) ; prim + tell gs how many data will be
|
||||
;////////////////////////////////////////////
|
||||
|
||||
;/////////////// --- Loop --- ///////////////
|
||||
iadd vertexCounter, iBase, vertCount ; loop vertCount times
|
||||
vertexLoop:
|
||||
|
||||
;////////// --- Load loop data --- //////////
|
||||
lq vertex, 0(vertexData) ; load xyz
|
||||
; float : X, Y, Z
|
||||
; any32 : _ = 0
|
||||
lq stq, 0(stqData) ; load stq
|
||||
; float : S, T
|
||||
; any32 : Q = 1 ; 1, because we will mul this by 1/vert[w] and this
|
||||
; will be our q for texture perspective correction
|
||||
; any32 : _ = 0
|
||||
;////////////////////////////////////////////
|
||||
|
||||
|
||||
;////////////// --- Vertex --- //////////////
|
||||
mul acc, matrixRow0, vertex[x] ; transform each vertex by the matrix
|
||||
madd acc, matrixRow1, vertex[y]
|
||||
madd acc, matrixRow2, vertex[z]
|
||||
madd vertex, matrixRow3, vertex[w]
|
||||
|
||||
;add.z acc, vf0, clipScale[w] ; TODO clipping maybe this?
|
||||
;madd.z clipVec, clipScale, vertex
|
||||
;mul.xy clipVec, clipScale, vertex
|
||||
;mul.w clipVec, vf0, vertex[z]
|
||||
|
||||
;mul.xyz clipVec, vertex, clipScale ; TODO clipping maybe this?
|
||||
|
||||
clipw.xyz vertex, vertex ; Dr. Fortuna: This instruction checks if the vertex is outside
|
||||
; the viewing frustum. If it is, then the appropriate
|
||||
; clipping flags are set
|
||||
fcand VI01, 0x3FFFF ; Bitwise AND the clipping flags with 0x3FFFF, this makes
|
||||
; sure that we get the clipping judgement for the last three
|
||||
; verts (i.e. that make up the triangle we are about to draw)
|
||||
iaddiu iADC, VI01, 0x7FFF ; Add 0x7FFF. If any of the clipping flags were set this will
|
||||
; cause the triangle not to be drawn (any values above 0x8000
|
||||
; that are stored in the w component of XYZ2 will set the ADC
|
||||
; bit, which tells the GS not to perform a drawing kick on this
|
||||
; triangle.
|
||||
|
||||
;ilw.w iNoDraw, UVStart(Counter) ; Load the iNoDraw flag. If true we should set the ADC bit so the vert isn't drawn
|
||||
;iadd iADC, iADC, iNoDraw ; TODO clipping maybe this?
|
||||
|
||||
isw.w iADC, 2(destAddress)
|
||||
|
||||
div q, vf00[w], vertex[w] ; perspective divide (1/vert[w]):
|
||||
mul.xyz vertex, vertex, q
|
||||
mula.xyz acc, scale, vf00[w] ; scale to GS screen space
|
||||
madd.xyz vertex, vertex, scale ; multiply and add the scales -> vert = vert * scale + scale
|
||||
ftoi4.xyz vertex, vertex ; convert vertex to 12:4 fixed point format
|
||||
;////////////////////////////////////////////
|
||||
|
||||
|
||||
;//////////////// --- ST --- ////////////////
|
||||
mulq modStq, stq, q
|
||||
;////////////////////////////////////////////
|
||||
|
||||
|
||||
;//////////// --- Store data --- ////////////
|
||||
sq modStq, 0(destAddress) ; STQ
|
||||
sq rgba, 1(destAddress) ; RGBA ; q is grabbed from stq
|
||||
sq.xyz vertex, 2(destAddress) ; XYZ2
|
||||
;////////////////////////////////////////////
|
||||
|
||||
iaddiu vertexData, vertexData, 1
|
||||
iaddiu stqData, stqData, 1
|
||||
iaddiu destAddress, destAddress, 3
|
||||
|
||||
iaddi vertexCounter, vertexCounter, -1 ; decrement the loop counter
|
||||
ibne vertexCounter, iBase, vertexLoop ; and repeat if needed
|
||||
|
||||
;////////////////////////////////////////////
|
||||
|
||||
--barrier
|
||||
|
||||
xgkick kickAddress ; dispatch to the GS rasterizer.
|
||||
|
||||
--exit
|
||||
--endexit
|
||||
@@ -0,0 +1,153 @@
|
||||
; ______ ____ ___
|
||||
; | \/ ____| |___|
|
||||
; | | | \ | |
|
||||
;---------------------------
|
||||
; Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
; Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
;
|
||||
;---------------------------------------------------------------
|
||||
; draw3D.vcl |
|
||||
;---------------------------------------------------------------
|
||||
; First tyra VU1 microprogram. |
|
||||
; Features: |
|
||||
; - Draw triangles (no strip) with STQ (textures) and 1 RGBA. |
|
||||
; This program uses double buffering (xtop) |
|
||||
; |
|
||||
; I want to say thank you to: |
|
||||
; - Dr Henry Fortuna - for teaching how things work |
|
||||
; - Jesper Svennevid, Daniel Collin - for openvcl samples |
|
||||
; - Guilherme Lampert - for VU1 idea for PS2 Quake and vclpp |
|
||||
; - Tyler Daniel - for PS2GL source code for PS2 Linux |
|
||||
;---------------------------------------------------------------
|
||||
|
||||
; TODO
|
||||
; - Add dynamic lighting (feature)
|
||||
; - Add --cont + MSCNT instead of alltime MSCAL
|
||||
|
||||
#include "/repos/tyra/src/engine/vu1_progs/geometry.inc"
|
||||
#include "/repos/tyra/src/engine/vu1_progs/matrix.inc"
|
||||
#include "/repos/tyra/src/engine/vu1_progs/vector.inc"
|
||||
|
||||
#vuprog draw3D
|
||||
|
||||
.syntax new
|
||||
.name VU1Draw3D
|
||||
.vu
|
||||
.init_vf_all
|
||||
.init_vi_all
|
||||
|
||||
--enter
|
||||
--endenter
|
||||
|
||||
;///////////// LOAD STATIC DATA /////////////
|
||||
lq gif_draw_finish_tag, 0(vi00) ; GIF tag - wait
|
||||
lq gif_set_tag, 1(vi00) ; GIF tag - set
|
||||
;////////////////////////////////////////////
|
||||
|
||||
xtop double_buffer
|
||||
|
||||
;//////// LOAD CURRENT BUFFER DATA //////////
|
||||
MatrixLoad{ matrix, 0, double_buffer }
|
||||
ilw.x do_draw_finish, 4(double_buffer) ; Add draw finish tag? (sync)
|
||||
ilw.y vertex_count, 4(double_buffer) ; Vertex count
|
||||
ilw.z triangles_count, 4(double_buffer) ; Triangles count
|
||||
lq tex_gif_tag_1, 5(double_buffer) ; GIF tag - texture LOD
|
||||
lq tex_gif_tag_2, 6(double_buffer) ; GIF tag - texture buffer & CLUT
|
||||
lq prim_tag, 7(double_buffer) ; GIF tag - tell GS how many data we will send
|
||||
lq rgba, 8(double_buffer) ; Mesh RGBA
|
||||
|
||||
iaddiu vertex_data, double_buffer, 9 ; pointer to vertex data
|
||||
iadd stq_data, vertex_data, vertex_count ; pointer to stq
|
||||
iadd kick_address, stq_data, vertex_count ; pointer for XGKICK
|
||||
iadd dest_address, stq_data, vertex_count ; helper pointer for data inserting
|
||||
;////////////////////////////////////////////
|
||||
|
||||
LoadScaleConstant{ gs_scale }
|
||||
fcset 0x000000 ; VCL won't let us use CLIP without first zeroing the clip flags
|
||||
|
||||
;/////////////// STORE TAGS /////////////////
|
||||
sqi gif_set_tag, (dest_address++) ;
|
||||
sqi tex_gif_tag_1, (dest_address++) ; texture LOD tag
|
||||
sqi gif_set_tag, (dest_address++) ;
|
||||
sqi tex_gif_tag_2, (dest_address++) ; texture buffer & CLUT tag
|
||||
iblez do_draw_finish, kick
|
||||
sqi gif_set_tag, (dest_address++) ;
|
||||
sqi gif_draw_finish_tag, (dest_address++) ; do draw_finish is needed
|
||||
kick:
|
||||
sqi prim_tag, (dest_address++) ; prim + tell gs how many data will be
|
||||
;////////////////////////////////////////////
|
||||
|
||||
;//////// FIX ADC BIT FOR CLIPPING //////////
|
||||
iaddiu adc_bit, vi00, 0x7FFF
|
||||
iaddiu adc_bit, adc_bit, 1
|
||||
;////////////////////////////////////////////
|
||||
|
||||
;/////////// START TRIANGLE LOOP ////////////
|
||||
iaddiu triangle_counter, vi00, 0 ; Reset counter
|
||||
triangle_loop: --LoopCS 1,3
|
||||
|
||||
;//////////////// VERTEX 1 //////////////////
|
||||
VectorLoad{ vertex, vertex_data, 0 }
|
||||
VectorLoad{ stq1, stq_data, 0 }
|
||||
MatrixXForm{ xformed_vertex, matrix, vertex }
|
||||
VectorClip{ gs_vertex, xformed_vertex }
|
||||
VectorPerspectiveDivide{ xformed_vertex }
|
||||
VectorAddGSScales{ gs_vertex, xformed_vertex, gs_scale }
|
||||
VectorTexturePerspectiveCorrection{ pers_stq, stq1 }
|
||||
VectorStore{ pers_stq, dest_address, 0 }
|
||||
VectorStore{ rgba, dest_address, 1 }
|
||||
VectorStore{ gs_vertex, dest_address, 2 }
|
||||
;////////////////////////////////////////////
|
||||
|
||||
;//////////////// VERTEX 2 //////////////////
|
||||
VectorLoad{ vertex, vertex_data, 1 }
|
||||
VectorLoad{ stq2, stq_data, 1 }
|
||||
MatrixXForm{ xformed_vertex, matrix, vertex }
|
||||
VectorClip{ gs_vertex, xformed_vertex }
|
||||
VectorPerspectiveDivide{ xformed_vertex }
|
||||
VectorAddGSScales{ gs_vertex, xformed_vertex, gs_scale }
|
||||
VectorTexturePerspectiveCorrection{ pers_stq, stq2 }
|
||||
VectorStore{ pers_stq, dest_address, 3 }
|
||||
VectorStore{ rgba, dest_address, 4 }
|
||||
VectorStore{ gs_vertex, dest_address, 5 }
|
||||
;////////////////////////////////////////////
|
||||
|
||||
;//////////////// VERTEX 3 //////////////////
|
||||
VectorLoad{ vertex, vertex_data, 2 }
|
||||
VectorLoad{ stq3, stq_data, 2 }
|
||||
MatrixXForm{ xformed_vertex, matrix, vertex }
|
||||
VectorClip{ gs_vertex, xformed_vertex }
|
||||
VectorPerspectiveDivide{ xformed_vertex }
|
||||
VectorAddGSScales{ gs_vertex, xformed_vertex, gs_scale }
|
||||
VectorTexturePerspectiveCorrection{ pers_stq, stq3 }
|
||||
VectorStore{ pers_stq, dest_address, 6 }
|
||||
VectorStore{ rgba, dest_address, 7 }
|
||||
|
||||
fcand vi01, 0x03FFFF
|
||||
iaddiu new_adc_bit, vi01, 0x7FFF
|
||||
mfir.w gs_vertex, new_adc_bit
|
||||
VectorStore{ gs_vertex, dest_address, 8 }
|
||||
;////////////////////////////////////////////
|
||||
|
||||
;////////////// LOOP CONTROL ////////////////
|
||||
iaddiu vertex_data, vertex_data, 3
|
||||
iaddiu stq_data, stq_data, 3
|
||||
iaddiu dest_address, dest_address, 9
|
||||
|
||||
iaddiu triangle_counter, triangle_counter, 1 // Incrementing this
|
||||
// by other value than 1 is causing HUGE problems, but.. why?
|
||||
// My first idea was do vertex_counter and incrementing by 3
|
||||
ibne triangle_counter, triangles_count, triangle_loop
|
||||
;////////////////////////////////////////////
|
||||
|
||||
;////////////////////////////////////////////
|
||||
|
||||
--barrier
|
||||
|
||||
|
||||
xgkick kick_address ; dispatch to the GS rasterizer.
|
||||
|
||||
--exit
|
||||
--endexit
|
||||
|
||||
#endvuprog
|
||||
+152
-40
@@ -3,6 +3,10 @@
|
||||
;-----VCL CODE------------
|
||||
;-------------------------
|
||||
;-------------------------
|
||||
; === __LP__ EXPL_draw3D_vcl_triangle_loop__MAIN_LOOP:
|
||||
; === hDown : optimal=30 clid=0 mlid=2 size=(31)
|
||||
; === dUp : optimal=30 clid=0 mlid=2 size=(31)
|
||||
; === another : optimal=30 clid=0 mlid=2 size=(31)
|
||||
; =================================================
|
||||
; flowMon::Emit() vcl 1.4beta7 produced this code:
|
||||
.vu
|
||||
@@ -11,63 +15,171 @@
|
||||
.global VU1Draw3D_CodeEnd
|
||||
VU1Draw3D_CodeStart:
|
||||
__v_draw3D_vcl_4:
|
||||
; _LNOPT_w=[ normal2 ] 23 [23 0] 23 [__v_draw3D_vcl_4]
|
||||
NOP lq VF01,0(VI00)
|
||||
NOP xtop VI02
|
||||
; _LNOPT_w=[ normal2 ] 26 [26 0] 26 [__v_draw3D_vcl_4]
|
||||
NOP xtop VI05
|
||||
NOP lq VF02,1(VI00)
|
||||
NOP lq VF06,1(VI02)
|
||||
NOP lq VF09,2(VI02)
|
||||
NOP lq VF08,3(VI02)
|
||||
NOP lq VF07,4(VI02)
|
||||
NOP lq VF03,2(VI00)
|
||||
NOP iaddiu VI03,VI02,0x00000007
|
||||
NOP ilw.w VI07,0(VI02)
|
||||
NOP lq VF04,3(VI00)
|
||||
NOP fcset 0
|
||||
NOP lq.xyz VF05,0(VI02)
|
||||
NOP lq VF01,0(VI00)
|
||||
NOP ilw.x VI01,4(VI05)
|
||||
NOP ilw.y VI07,4(VI05)
|
||||
NOP lq VF03,0(VI05)
|
||||
NOP lq VF08,5(VI05)
|
||||
NOP lq VF10,6(VI05)
|
||||
NOP lq VF04,1(VI05)
|
||||
NOP lq VF05,2(VI05)
|
||||
NOP iaddiu VI03,VI05,0x00000009
|
||||
NOP iadd VI04,VI03,VI07
|
||||
NOP lq VF06,3(VI05)
|
||||
NOP iadd VI06,VI04,VI07
|
||||
NOP sqi VF06,(VI06++)
|
||||
NOP sqi VF09,(VI06++)
|
||||
NOP sqi VF06,(VI06++)
|
||||
NOP loi 0x44fff000
|
||||
NOP ilw.z VI02,4(VI05)
|
||||
NOP lq VF07,7(VI05)
|
||||
NOP sqi VF02,(VI06++)
|
||||
NOP sqi VF08,(VI06++)
|
||||
NOP lq VF06,5(VI02)
|
||||
NOP sqi VF02,(VI06++)
|
||||
NOP lq VF08,8(VI05)
|
||||
NOP iadd VI05,VI04,VI07
|
||||
addi.xy VF09,VF00,I loi 0x492aaaaa
|
||||
NOP fcset 0
|
||||
NOP iblez VI01,kick
|
||||
addi.z VF09,VF00,I sqi VF10,(VI06++)
|
||||
; _LNOPT_w=[ normal2 ] 2 [2 0] 2 [__v_draw3D_vcl_5]
|
||||
NOP sqi VF02,(VI06++)
|
||||
NOP sqi VF01,(VI06++)
|
||||
kick:
|
||||
; _LNOPT_w=[ normal2 ] 27 [27 0] 32 [kick]
|
||||
NOP sqi VF07,(VI06++)
|
||||
NOP iadd VI07,VI02,VI07
|
||||
vertexLoop:
|
||||
; _LNOPT_w=[ normal2 ] 21 [31 14] 31 [vertexLoop]
|
||||
NOP lq VF07,0(VI03)
|
||||
mulax ACC,VF01,VF07x sq VF06,1(VI06) ; STALL_LATENCY ?3
|
||||
madday ACC,VF02,VF07y lq VF08,0(VI04)
|
||||
maddaz ACC,VF03,VF07z iaddiu VI06,VI06,0x00000003
|
||||
maddw VF07,VF04,VF07w NOP
|
||||
clipw.xyz VF07xyz,VF07w div Q,VF00w,VF07w ; STALL_LATENCY ?3
|
||||
mulax ACC,VF03,VF07x lq VF14,1(VI03) ; STALL_LATENCY ?3
|
||||
madday ACC,VF04,VF07y sq VF08,1(VI06)
|
||||
maddaz ACC,VF05,VF07z sq VF08,7(VI06)
|
||||
maddw VF11,VF06,VF07w NOP
|
||||
mulax ACC,VF03,VF14x lq VF07,2(VI03)
|
||||
madday ACC,VF04,VF14y NOP
|
||||
maddaz ACC,VF05,VF14z NOP
|
||||
maddw VF14,VF06,VF14w div Q,VF00w,VF11w
|
||||
mulax ACC,VF03,VF07x NOP
|
||||
madday ACC,VF04,VF07y iaddiu VI07,VI00,0x00007fff
|
||||
maddaz ACC,VF05,VF07z iaddiu VI07,VI07,0x00000001
|
||||
maddw VF07,VF06,VF07w iaddiu VI08,VI00,0
|
||||
clipw.xyz VF11xyz,VF11w iaddiu VI04,VI04,0
|
||||
clipw.xyz VF14xyz,VF14w div Q,VF00w,VF14w ; STALL_THRUPUT ?1
|
||||
clipw.xyz VF07xyz,VF07w lq VF15,0(VI04)
|
||||
mulq.xyz VF02,VF11,Q sq VF08,4(VI06)
|
||||
mulaw.xyz ACC,VF09,VF00w iaddiu VI03,VI03,0
|
||||
mulq VF11,VF15,Q iaddiu VI06,VI06,0 ; STALL_LATENCY ?1
|
||||
madd.xyz VF01,VF02,VF09 lq VF02,1(VI04)
|
||||
NOP div Q,VF00w,VF07w
|
||||
mulq.xyz VF15,VF14,Q iaddiu VI08,VI08,0x00000001
|
||||
mulaw.xyz ACC,VF09,VF00w sq VF11,0(VI06)
|
||||
mulq VF14,VF02,Q mfir.w VF11,VI07
|
||||
ftoi4.xyz VF11,VF01 ibeq VI08,VI02,EXPL_draw3D_vcl_triangle_loop__EPI1
|
||||
madd.xyz VF02,VF15,VF09 lq VF15,2(VI04)
|
||||
; _LNOPT_w=[ ] 31 [29 0] 31 [EXPL_draw3D_vcl_triangle_loop__PRO1]
|
||||
NOP lq VF12,3(VI03)
|
||||
NOP NOP
|
||||
mulq.xyz VF01,VF07,Q NOP
|
||||
mulq VF11,VF15,Q sq VF11,2(VI06)
|
||||
mulax ACC,VF03,VF12x lq VF10,4(VI03)
|
||||
madday ACC,VF04,VF12y NOP
|
||||
maddaz ACC,VF05,VF12z NOP
|
||||
maddw VF11,VF06,VF12w sq VF11,6(VI06)
|
||||
mulax ACC,VF03,VF10x lq VF07,5(VI03)
|
||||
madday ACC,VF04,VF10y sq VF14,3(VI06)
|
||||
maddaz ACC,VF05,VF10z sq VF08,10(VI06)
|
||||
maddw VF10,VF06,VF10w div Q,VF00w,VF11w
|
||||
mulax ACC,VF03,VF07x sq VF08,13(VI06)
|
||||
madday ACC,VF04,VF07y sq VF08,16(VI06)
|
||||
maddaz ACC,VF05,VF07z iaddiu VI03,VI03,0x00000006
|
||||
maddw VF07,VF06,VF07w iaddiu VI04,VI04,0x00000006
|
||||
clipw.xyz VF11xyz,VF11w lq VF12,-3(VI04)
|
||||
clipw.xyz VF10xyz,VF10w iaddiu VI06,VI06,0x00000012
|
||||
mulq.xyz VF14,VF11,Q div Q,VF00w,VF10w
|
||||
clipw.xyz VF07xyz,VF07w fcand VI01,262143
|
||||
mulq VF12,VF12,Q iaddiu VI08,VI08,0x00000001
|
||||
ftoi4.xyz VF11,VF02 iaddiu VI01,VI01,0x00007fff
|
||||
mulaw.xyz ACC,VF09,VF00w mfir.w VF11,VI07
|
||||
madd.xyz VF14,VF14,VF09 mfir.w VF10,VI01
|
||||
mulaw.xyz ACC,VF09,VF00w lq VF02,-2(VI04)
|
||||
madd.xyz VF01,VF01,VF09 div Q,VF00w,VF07w
|
||||
mulq.xyz VF10,VF10,Q lq VF15,-1(VI04)
|
||||
ftoi4.xyz VF11,VF14 sq VF11,-13(VI06)
|
||||
mulq VF14,VF02,Q sq VF12,-9(VI06)
|
||||
mulaw.xyz ACC,VF09,VF00w ibeq VI08,VI02,EXPL_draw3D_vcl_triangle_loop__EPI0
|
||||
madd.xyz VF02,VF10,VF09 mfir.w VF11,VI07
|
||||
EXPL_draw3D_vcl_triangle_loop__MAIN_LOOP:
|
||||
; _LPOPT_w=[ hDown ] 31 [30 30] 31 [EXPL_draw3D_vcl_triangle_loop__MAIN_LOOP]
|
||||
ftoi4.xyz VF10,VF01 lq VF13,0(VI03)
|
||||
NOP lq VF12,1(VI03)
|
||||
mulq.xyz VF01,VF07,Q sq VF14,-6(VI06)
|
||||
mulq VF11,VF15,Q sq VF11,-7(VI06)
|
||||
mulax ACC,VF03,VF13x sq VF10,-10(VI06)
|
||||
madday ACC,VF04,VF13y sq VF08,1(VI06)
|
||||
maddaz ACC,VF05,VF13z NOP
|
||||
maddw VF11,VF06,VF13w sq VF11,-3(VI06)
|
||||
mulax ACC,VF03,VF12x lq VF07,2(VI03)
|
||||
madday ACC,VF04,VF12y sq VF08,4(VI06)
|
||||
maddaz ACC,VF05,VF12z sq VF08,7(VI06)
|
||||
maddw VF10,VF06,VF12w div Q,VF00w,VF11w
|
||||
mulax ACC,VF03,VF07x NOP
|
||||
madday ACC,VF04,VF07y iaddiu VI03,VI03,0x00000003
|
||||
maddaz ACC,VF05,VF07z NOP
|
||||
maddw VF07,VF06,VF07w iaddiu VI04,VI04,0x00000003
|
||||
clipw.xyz VF11xyz,VF11w lq VF12,-3(VI04)
|
||||
clipw.xyz VF10xyz,VF10w iaddiu VI06,VI06,0x00000009
|
||||
mulq.xyz VF13,VF11,Q fcand VI01,262143
|
||||
clipw.xyz VF07xyz,VF07w div Q,VF00w,VF10w
|
||||
mulq VF12,VF12,Q iaddiu VI08,VI08,0x00000001
|
||||
ftoi4.xyz VF11,VF02 iaddiu VI01,VI01,0x00007fff
|
||||
mulaw.xyz ACC,VF09,VF00w mfir.w VF10,VI01
|
||||
madd.xyz VF13,VF13,VF09 mfir.w VF11,VI07
|
||||
mulaw.xyz ACC,VF09,VF00w lq VF02,-2(VI04)
|
||||
madd.xyz VF01,VF01,VF09 sq VF12,-9(VI06)
|
||||
mulq.xyz VF10,VF10,Q div Q,VF00w,VF07w
|
||||
ftoi4.xyz VF11,VF13 sq VF11,-13(VI06)
|
||||
mulq VF14,VF02,Q mfir.w VF11,VI07
|
||||
mulaw.xyz ACC,VF09,VF00w ibne VI08,VI02,EXPL_draw3D_vcl_triangle_loop__MAIN_LOOP
|
||||
madd.xyz VF02,VF10,VF09 lq VF15,-1(VI04)
|
||||
EXPL_draw3D_vcl_triangle_loop__EPI0:
|
||||
; _LNOPT_w=[ ] 13 [13 0] 15 [EXPL_draw3D_vcl_triangle_loop__EPI0]
|
||||
NOP NOP
|
||||
ftoi4.xyz VF10,VF01 fcand VI01,262143
|
||||
mulq.xyz VF01,VF07,Q sq VF14,-6(VI06)
|
||||
mulq VF11,VF15,Q sq VF11,-7(VI06)
|
||||
mulaw.xyz ACC,VF09,VF00w iaddiu VI01,VI01,0x00007fff
|
||||
madd.xyz VF01,VF01,VF09 sq VF10,-10(VI06) ; STALL_LATENCY ?1
|
||||
ftoi4.xyz VF11,VF02 sq VF11,-3(VI06)
|
||||
NOP mfir.w VF11,VI07
|
||||
NOP mfir.w VF10,VI01
|
||||
ftoi4.xyz VF10,VF01 NOP
|
||||
NOP sq VF11,-4(VI06) ; STALL_LATENCY ?1
|
||||
NOP b EXPL_draw3D_vcl_triangle_loop__EXIT_POINT
|
||||
NOP sq VF10,-1(VI06)
|
||||
EXPL_draw3D_vcl_triangle_loop__EPI1:
|
||||
; _LNOPT_w=[ ] 12 [13 0] 14 [EXPL_draw3D_vcl_triangle_loop__EPI1]
|
||||
NOP NOP
|
||||
mulq.xyz VF14,VF07,Q sq VF14,3(VI06)
|
||||
NOP NOP
|
||||
NOP NOP
|
||||
NOP NOP
|
||||
mulq.xyz VF07,VF07,Q fcand VI01,262143
|
||||
mulaw.xyz ACC,VF05,VF00w iaddiu VI03,VI03,0x00000001
|
||||
madd.xyz VF07,VF07,VF05 iaddiu VI04,VI04,0x00000001 ; STALL_LATENCY ?2
|
||||
mulq VF08,VF08,Q isubiu VI07,VI07,1
|
||||
ftoi4.xyz VF07,VF07 iaddiu VI01,VI01,0x00007fff ; STALL_LATENCY ?2
|
||||
NOP isw.w VI01,-1(VI06)
|
||||
NOP sq VF08,-3(VI06)
|
||||
NOP ibne VI07,VI02,vertexLoop
|
||||
NOP sq.xyz VF07,-1(VI06)
|
||||
; _LNOPT_w=[ normal2 ] 3 [1 0] 3 [__v_draw3D_vcl_7]
|
||||
mulq VF11,VF15,Q sq VF11,2(VI06)
|
||||
mulaw.xyz ACC,VF09,VF00w fcand VI01,262143
|
||||
madd.xyz VF14,VF14,VF09 iaddiu VI01,VI01,0x00007fff
|
||||
NOP mfir.w VF14,VI01
|
||||
ftoi4.xyz VF11,VF02 sq VF11,6(VI06)
|
||||
NOP mfir.w VF11,VI07
|
||||
ftoi4.xyz VF14,VF14 NOP
|
||||
NOP sq VF11,5(VI06) ; STALL_LATENCY ?2
|
||||
NOP sq VF14,8(VI06)
|
||||
EXPL_draw3D_vcl_triangle_loop__EXIT_POINT:
|
||||
; _LNOPT_w=[ ] 0 [0 0] 0 [EXPL_draw3D_vcl_triangle_loop__EXIT_POINT]
|
||||
; _LNOPT_w=[ normal2 ] 3 [1 0] 3 [__v_draw3D_vcl_9]
|
||||
NOP xgkick VI05
|
||||
NOP[E] NOP
|
||||
NOP NOP
|
||||
.align 4
|
||||
VU1Draw3D_CodeEnd:
|
||||
; iCount=47
|
||||
; iCount=145
|
||||
; register stats:
|
||||
; 8 VU User integer
|
||||
; 10 VU User floating point
|
||||
; 9 VU User integer
|
||||
; 16 VU User floating point
|
||||
;-------------------------
|
||||
;-------------------------
|
||||
;-------------------------
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
; Load GS offsets to center xformed vertex in gs coord space and color clamping constant
|
||||
#macro LoadScaleConstant: gs_scale
|
||||
loi 2047.5
|
||||
addi.xy gs_scale, vf00, i
|
||||
loi 699050.625000 // ((float)0xFFFFFF) / 24.0F
|
||||
addi.z gs_scale, vf00, i
|
||||
#endmacro
|
||||
@@ -0,0 +1,13 @@
|
||||
#macro MatrixLoad: matrix, offset, vumem
|
||||
lq matrix[0], offset+0(vumem)
|
||||
lq matrix[1], offset+1(vumem)
|
||||
lq matrix[2], offset+2(vumem)
|
||||
lq matrix[3], offset+3(vumem)
|
||||
#endmacro
|
||||
|
||||
#macro MatrixXForm: output_vertex, matrix, input_vertex
|
||||
mul acc, matrix[0], input_vertex[x]
|
||||
madd acc, matrix[1], input_vertex[y]
|
||||
madd acc, matrix[2], input_vertex[z]
|
||||
madd output_vertex, matrix[3], input_vertex[w]
|
||||
#endmacro
|
||||
@@ -0,0 +1,27 @@
|
||||
#macro VectorPerspectiveDivide: vertex
|
||||
div q, vf00[w], vertex[w]
|
||||
mulq.xyz vertex, vertex, q
|
||||
#endmacro
|
||||
|
||||
#macro VectorAddGSScales: output_vertex, input_vertex, gs_scale
|
||||
mula.xyz acc, gs_scale, vf00[w]
|
||||
madd.xyz output_vertex, input_vertex, gs_scale
|
||||
ftoi4.xyz output_vertex, output_vertex
|
||||
#endmacro
|
||||
|
||||
#macro VectorTexturePerspectiveCorrection: output_vertex, input_vertex
|
||||
mulq output_vertex, input_vertex, q
|
||||
#endmacro
|
||||
|
||||
#macro VectorStore: vertex, vumem, num
|
||||
sq vertex, num(vumem)
|
||||
#endmacro
|
||||
|
||||
#macro VectorClip: output_vertex, input_vertex
|
||||
clipw.xyz input_vertex, input_vertex
|
||||
mfir.w output_vertex, adc_bit
|
||||
#endmacro
|
||||
|
||||
#macro VectorLoad: output_vertex, vumem, offset
|
||||
lq output_vertex, offset(vumem)
|
||||
#endmacro
|
||||
@@ -1,19 +0,0 @@
|
||||
## Ari sample
|
||||
|
||||
### Description
|
||||
|
||||
* .obj (skybox, water)
|
||||
* .dff (island)
|
||||
* .md2 (ari)
|
||||
* mesh cloning (water)
|
||||
|
||||
Testing demo. In future there will be Ariana Grande demo.
|
||||
|
||||
### Assets
|
||||
[Download](http://apgcglz.cluster028.hosting.ovh.net/tyra/1.1.0/samples/ari/assets.zip)
|
||||
|
||||
### Screenshot
|
||||
|
||||
[![Ari screenshot][ari-screenshot]](#)
|
||||
|
||||
[ari-screenshot]: http://apgcglz.cluster028.hosting.ovh.net/tyra/1.1.0/samples/ari/ari.gif
|
||||
@@ -1,137 +0,0 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "ari.hpp"
|
||||
|
||||
#include "utils/math.hpp"
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
const u8 WATER_TILES_COUNT = 64;
|
||||
|
||||
Ari::Ari(Engine *t_engine) : engine(t_engine), camera(&engine->screen)
|
||||
{
|
||||
waterFloors = new Mesh[WATER_TILES_COUNT];
|
||||
spirals = new Point[WATER_TILES_COUNT];
|
||||
}
|
||||
|
||||
Ari::~Ari() {}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
void Ari::onInit()
|
||||
{
|
||||
engine->renderer->setCameraDefinitions(&camera.worldView, &camera.position, camera.planes);
|
||||
engine->audio.setSongVolume(40);
|
||||
// engine->audio.loadSong("MOV-CIRC.WAV");
|
||||
engine->audio.loadSong("nob-else.wav");
|
||||
|
||||
adpcm1 = engine->audio.loadADPCM("ziobro1.adpcm");
|
||||
adpcm2 = engine->audio.loadADPCM("ziobro2.adpcm");
|
||||
|
||||
texRepo = engine->renderer->getTextureRepository();
|
||||
engine->renderer->disableVSync();
|
||||
island.loadDff("sunnyisl/", "sunnyisl", 0.1F, false);
|
||||
island.rotation.x = -1.6F;
|
||||
island.position.set(0.0F, 10.0F, 20.0F);
|
||||
island.shouldBeBackfaceCulled = true;
|
||||
island.shouldBeFrustumCulled = false;
|
||||
|
||||
fist.size.set(100.0F, 100.0F);
|
||||
Texture *fistTex = texRepo->add("2d/", "fist", PNG);
|
||||
fistTex->addLink(fist.getId());
|
||||
|
||||
islandAddons.loadDff("sunnyisl/", "sunnyisl3", 0.1F, false);
|
||||
islandAddons.shouldBeBackfaceCulled = true;
|
||||
islandAddons.rotation.x = -1.6F;
|
||||
islandAddons.position.set(0.0F, 10.0F, 20.0F);
|
||||
|
||||
skybox.loadObj("skybox/", "skybox", 100.0F, false);
|
||||
skybox.shouldBeFrustumCulled = false;
|
||||
|
||||
waterFloors[0].loadObj("water/", "water", 5.0F, false);
|
||||
waterFloors[0].position.set(0.0F, 8.0F, 0.0F);
|
||||
texRepo->addByMesh("water/", waterFloors[0], BMP);
|
||||
for (u8 i = 0; i < WATER_TILES_COUNT; i++)
|
||||
{
|
||||
spirals[i].x = 1.0F;
|
||||
spirals[i].y = 2.0F;
|
||||
}
|
||||
u32 spiralOffset = (u32)Math::sqrt(WATER_TILES_COUNT);
|
||||
calcSpiral(spiralOffset, spiralOffset);
|
||||
for (u8 i = 1; i < WATER_TILES_COUNT; i++)
|
||||
{
|
||||
waterFloors[i].loadFrom(waterFloors[0]);
|
||||
waterFloors[i].position.set(10.0F * spirals[i].x, 8.0F, 10.0F * spirals[i].y);
|
||||
texRepo->getByMesh(waterFloors[0].getId(), waterFloors[0].getMaterial(0).getId())
|
||||
->addLink(waterFloors[i].getId(), waterFloors[i].getMaterial(0).getId());
|
||||
}
|
||||
|
||||
texRepo->addByMesh("sunnyisl/", island, BMP);
|
||||
texRepo->addByMesh("sunnyisl/", islandAddons, BMP);
|
||||
texRepo->addByMesh("skybox/", skybox, BMP);
|
||||
texRepo->addByMesh("ari/", player.mesh, BMP);
|
||||
// engine->audio.playSong();
|
||||
}
|
||||
|
||||
void Ari::initBulb()
|
||||
{
|
||||
bulb.intensity = 15;
|
||||
bulb.position.set(5.0F, 10.0F, 10.0F);
|
||||
}
|
||||
|
||||
void Ari::onUpdate()
|
||||
{
|
||||
if (engine->pad.isCrossClicked)
|
||||
{
|
||||
// engine->audio.loadSong("nob-else.wav");
|
||||
engine->audio.playADPCM(adpcm1);
|
||||
printf("FPS:%f\n", engine->fps);
|
||||
}
|
||||
if (engine->pad.isCircleClicked)
|
||||
engine->audio.playADPCM(adpcm2);
|
||||
camera.update(engine->pad, player.mesh);
|
||||
engine->renderer->draw(skybox);
|
||||
engine->renderer->draw(fist);
|
||||
engine->renderer->draw(island);
|
||||
engine->renderer->draw(islandAddons);
|
||||
engine->renderer->draw(player.mesh);
|
||||
for (u8 i = 0; i < WATER_TILES_COUNT; i++)
|
||||
engine->renderer->draw(waterFloors[i]);
|
||||
}
|
||||
|
||||
void Ari::calcSpiral(int X, int Y)
|
||||
{
|
||||
int x, y, dx;
|
||||
x = y = dx = 0;
|
||||
int dy = -1;
|
||||
int t = X > Y ? X : Y;
|
||||
int maxI = t * t;
|
||||
for (int i = 0; i < maxI; i++)
|
||||
{
|
||||
if ((-X / 2 <= x) && (x <= X / 2) && (-Y / 2 <= y) && (y <= Y / 2))
|
||||
{
|
||||
spirals[i].x = x;
|
||||
spirals[i].y = y;
|
||||
}
|
||||
if ((x == y) || ((x < 0) && (x == -y)) || ((x > 0) && (x == 1 - y)))
|
||||
{
|
||||
t = dx;
|
||||
dx = -dy;
|
||||
dy = t;
|
||||
}
|
||||
x += dx;
|
||||
y += dy;
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _ARI_
|
||||
#define _ARI_
|
||||
|
||||
#include <tamtypes.h>
|
||||
#include <audsrv.h>
|
||||
#include <game.hpp>
|
||||
#include <engine.hpp>
|
||||
#include "objects/player.hpp"
|
||||
#include <models/light_bulb.hpp>
|
||||
#include <models/sprite.hpp>
|
||||
#include <modules/texture_repository.hpp>
|
||||
#include "./camera.hpp"
|
||||
|
||||
class Ari : public Game
|
||||
{
|
||||
|
||||
public:
|
||||
Ari(Engine *t_engine);
|
||||
~Ari();
|
||||
|
||||
void onInit();
|
||||
void onUpdate();
|
||||
|
||||
Engine *engine;
|
||||
|
||||
private:
|
||||
void initBulb();
|
||||
void calcSpiral(int X, int Y);
|
||||
LightBulb bulb;
|
||||
Player player;
|
||||
Mesh island, islandAddons, skybox;
|
||||
Mesh *waterFloors;
|
||||
Sprite fist;
|
||||
audsrv_adpcm_t *adpcm1, *adpcm2;
|
||||
Point *spirals;
|
||||
Camera camera;
|
||||
TextureRepository *texRepo;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "player.hpp"
|
||||
|
||||
#include <loaders/obj_loader.hpp>
|
||||
#include <loaders/bmp_loader.hpp>
|
||||
#include <modules/gif_sender.hpp>
|
||||
#include <utils/debug.hpp>
|
||||
#include <utils/math.hpp>
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
Player::Player()
|
||||
{
|
||||
PRINT_LOG("Creating player object");
|
||||
this->gravity = 0.1F;
|
||||
this->lift = -1.0F;
|
||||
this->mesh.loadMD2("ari/", "ari", 0.0001F, true);
|
||||
this->mesh.position.set(0.0F, 10.0F, 0.0F);
|
||||
this->mesh.shouldBeBackfaceCulled = true;
|
||||
this->mesh.shouldBeFrustumCulled = false;
|
||||
this->mesh.shouldBeLighted = true;
|
||||
this->mesh.setAnimSpeed(0.05F);
|
||||
this->mesh.playAnimation(0, 1);
|
||||
PRINT_LOG("Player object created!");
|
||||
}
|
||||
|
||||
Player::~Player()
|
||||
{
|
||||
}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// ----
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _PLAYER_
|
||||
#define _PLAYER_
|
||||
|
||||
#include "../camera.hpp"
|
||||
#include <modules/pad.hpp>
|
||||
#include <tamtypes.h>
|
||||
|
||||
/** Player 3D object class */
|
||||
class Player
|
||||
{
|
||||
|
||||
public:
|
||||
float gravity, velocity, lift;
|
||||
u8 isOnFloor, isCollideFloor, indexOfCurrentFloor;
|
||||
Mesh mesh;
|
||||
Player();
|
||||
~Player();
|
||||
|
||||
private:
|
||||
Vector3 playerNextPosition;
|
||||
};
|
||||
|
||||
// TODO Rysowanie idzie wg tekstur
|
||||
|
||||
// 2 Graczy, 1 mesh 2 tekstury
|
||||
// sharedFrames = objLoader.load("meshes/", "block", 1.0F);
|
||||
// var addedTextures = texturesRepo.addByMaterialNames("textures/dirt/", sharedFrames);
|
||||
// var addedTexture = texturesRepo.add("textures/blocks/sand.bmp");
|
||||
// dirt = new Mesh(sharedFrames);
|
||||
// sand = new Mesh(sharedFrames);
|
||||
// addedTextures[0].addUsage(dirt.Id, sharedFrames.getMaterialId(0));
|
||||
// addedTexture.addUsage(sand.Id, sand.getMaterialId(0));
|
||||
|
||||
// 1 gracz, 2 dynamic tekstury
|
||||
// sharedFrames = objLoader.load("meshes/", "block", 1.0F);
|
||||
// var addedTexture1 = texturesRepo.add("textures/blocks/sand.bmp");
|
||||
// var addedTexture2 = texturesRepo.add("textures/blocks/sand_damaged.bmp");
|
||||
// sand = new Mesh(sharedFrames);
|
||||
// addedTexture1.removeUsage(sand.Id, sand.getMaterialId(0));
|
||||
// draw()
|
||||
// addedTexture2.addUsage(sand.Id, sand.getMaterialId(0));
|
||||
|
||||
// 2 różne obj, te same tekstury
|
||||
// frames1 = objLoader.load("meshes/", "island", 1.0F);
|
||||
// frames2 = objLoader.load("meshes/", "islandAddons", 1.0F);
|
||||
// island = new Mesh(frames1);
|
||||
// islandAddons = new Mesh(frames2);
|
||||
// var addedTextures1 = texturesRepo.addByMaterialNames("textures/island/",frames1);
|
||||
// var addedTextures2 = texturesRepo.addByMaterialNames("textures/island/",frames2);
|
||||
// texturesRepo.remove(addedTextures2[0]); // duplicate
|
||||
// addedTextures1[0].addUsage(islandAddons.Id, islandAddons.getMaterialId(0));
|
||||
|
||||
// Mesh -> position, rotation, color, scale, shouldBeLighted, clut, lod
|
||||
|
||||
#endif
|
||||
Regular → Executable
+4
-2
@@ -1,11 +1,13 @@
|
||||
EE_BIN = ari.elf
|
||||
EE_BIN = dolphin.elf
|
||||
|
||||
TYRA_DIR = ./../../engine
|
||||
|
||||
EE_OBJS = \
|
||||
camera.o \
|
||||
objects/player.o \
|
||||
ari.o \
|
||||
objects/collectible.o \
|
||||
objects/mine.o \
|
||||
dolphin.o \
|
||||
main.o
|
||||
|
||||
EE_LIBS = -ltyra
|
||||
Regular → Executable
+12
-40
@@ -5,78 +5,50 @@
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
# Michał Mostowik <mostek3pl@gmail.com>
|
||||
*/
|
||||
|
||||
#include "camera.hpp"
|
||||
|
||||
#include <utils/math.hpp>
|
||||
#include <utils/debug.hpp>
|
||||
|
||||
const float CAMERA_Y = 15.0F;
|
||||
const float CAMERA_Y = 25.0F;
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
Camera::Camera(ScreenSettings *t_screen) : CameraBase(t_screen, &position, &up)
|
||||
Camera::Camera(ScreenSettings *t_screen) : CameraBase(t_screen, &position)
|
||||
{
|
||||
PRINT_LOG("Initializing camera");
|
||||
verticalLevel = 80.0F;
|
||||
up.x = 0.0F;
|
||||
up.y = 1.0F;
|
||||
up.z = 0.0F;
|
||||
PRINT_LOG("Camera initialized!");
|
||||
verticalLevel = 30.0F;
|
||||
}
|
||||
|
||||
Camera::~Camera() {}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
void Camera::update(Pad &t_pad, Mesh &t_mesh)
|
||||
{
|
||||
float cameraRot = (t_mesh.rotation.z * 180 / Math::PI) - (horizontalLevel * 180 / Math::PI);
|
||||
cameraRot += 180;
|
||||
cameraRot /= 15;
|
||||
horizontalLevel += cameraRot / (180 / Math::PI);
|
||||
rotate(t_pad);
|
||||
followBy(t_mesh);
|
||||
Vector3 lookPos = Vector3(t_mesh.position.x, t_mesh.position.y + 10.0F, t_mesh.position.z);
|
||||
lookAt(lookPos);
|
||||
}
|
||||
|
||||
/** Set camera rotation by pad right joy and update unit circle
|
||||
* https://en.wikipedia.org/wiki/Unit_circle
|
||||
* https://www.desmos.com/calculator/3e7iypw4ow
|
||||
*/
|
||||
void Camera::rotate(Pad &t_pad)
|
||||
{
|
||||
if (t_pad.rJoyH <= 50)
|
||||
|
||||
if (t_pad.rJoyH <= 100)
|
||||
horizontalLevel -= 0.08;
|
||||
else if (t_pad.rJoyH >= 200)
|
||||
horizontalLevel += 0.04;
|
||||
if (t_pad.rJoyV <= 50 && verticalLevel > 25.0F)
|
||||
verticalLevel -= 0.9F;
|
||||
else if (t_pad.rJoyV >= 200 && verticalLevel < 80.0F)
|
||||
verticalLevel += 0.9F;
|
||||
horizontalLevel += 0.08;
|
||||
|
||||
unitCirclePosition.x = (Math::sin(horizontalLevel) * verticalLevel);
|
||||
unitCirclePosition.y = CAMERA_Y;
|
||||
unitCirclePosition.z = (Math::cos(horizontalLevel) * verticalLevel);
|
||||
}
|
||||
|
||||
/** Rotate camera around 3D object */
|
||||
void Camera::followBy(Mesh &t_mesh)
|
||||
{
|
||||
position.x = unitCirclePosition.x + t_mesh.position.x;
|
||||
position.y = unitCirclePosition.y + t_mesh.position.y;
|
||||
position.z = unitCirclePosition.z + t_mesh.position.z;
|
||||
|
||||
if (position.x > (-0.04F * verticalLevel) &&
|
||||
position.x < 0.0F &&
|
||||
position.z > (0.998F * verticalLevel))
|
||||
{
|
||||
// TODO
|
||||
// position.x = 0.0F;
|
||||
// position.y = 0.0F;
|
||||
// position.z = 0.0F;
|
||||
// horizontalLevel = 0.0F;
|
||||
}
|
||||
}
|
||||
Regular → Executable
+2
-4
@@ -5,7 +5,7 @@
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
# Michał Mostowik <mostek3pl@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _CAMERA_
|
||||
@@ -18,12 +18,11 @@
|
||||
#include <modules/camera_base.hpp>
|
||||
#include <tamtypes.h>
|
||||
|
||||
/** 3D camera which follow by 3D object. Can be rotated via pad */
|
||||
class Camera : public CameraBase
|
||||
{
|
||||
|
||||
public:
|
||||
Vector3 up, position, unitCirclePosition;
|
||||
Vector3 position, up, unitCirclePosition;
|
||||
float horizontalLevel, verticalLevel;
|
||||
|
||||
Camera(ScreenSettings *t_screen);
|
||||
@@ -35,7 +34,6 @@ public:
|
||||
|
||||
protected:
|
||||
Vector3 *getPosition() { return &position; };
|
||||
Vector3 *getUp() { return &up; };
|
||||
ScreenSettings screen;
|
||||
};
|
||||
|
||||
Executable
+299
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Michał Mostowik <mostek3pl@gmail.com>
|
||||
*/
|
||||
|
||||
#include "dolphin.hpp"
|
||||
#include "utils/math.hpp"
|
||||
|
||||
float Dolphin::engineFPS = 60.0F;
|
||||
const float WATER_TILE_SCALE = 6.0F;
|
||||
const u8 WATER_SIZE = 4;
|
||||
const u8 MINES_COUNT = 15;
|
||||
const u8 OYSTERS_COUNT = 5;
|
||||
|
||||
Dolphin::Dolphin(Engine *t_engine) : engine(t_engine), camera(&engine->screen)
|
||||
{
|
||||
oysters = new Collectible[OYSTERS_COUNT];
|
||||
mines = new Mine[MINES_COUNT];
|
||||
}
|
||||
|
||||
Dolphin::~Dolphin()
|
||||
{
|
||||
delete[] oysters;
|
||||
delete[] mines;
|
||||
delete[] waterDrawList;
|
||||
}
|
||||
|
||||
void Dolphin::onInit()
|
||||
{
|
||||
player.init(engine);
|
||||
engine->renderer->setCameraDefinitions(&camera.view, &camera.position, camera.planes);
|
||||
|
||||
engine->audio.loadSong("sound/dirediredocks.wav");
|
||||
engine->audio.playSong();
|
||||
engine->audio.setSongVolume(60);
|
||||
|
||||
surfaceAmbient = engine->audio.loadADPCM("sound/surface.sad");
|
||||
underwaterAmbient = engine->audio.loadADPCM("sound/underwater.sad");
|
||||
pickupSound = engine->audio.loadADPCM("sound/pickup.sad");
|
||||
boomSound = engine->audio.loadADPCM("sound/boom.sad");
|
||||
|
||||
engine->audio.playADPCM(surfaceAmbient, 0);
|
||||
engine->audio.playADPCM(underwaterAmbient, 1);
|
||||
|
||||
texRepo = engine->renderer->getTextureRepository();
|
||||
|
||||
engine->renderer->disableVSync();
|
||||
|
||||
printf("loading island..\n");
|
||||
island.loadDff("sunnyisl/", "sunnyisl", 5.0F, false);
|
||||
printf("Loaded..\n");
|
||||
island.rotation.x = -1.6F;
|
||||
island.position.set(0.0F, 60.0F, 20.0F);
|
||||
island.shouldBeBackfaceCulled = true;
|
||||
island.shouldBeFrustumCulled = false;
|
||||
|
||||
gameOver.size.set(640.0F, 480.0F);
|
||||
Texture *gameOverTex = texRepo->add("2d/", "gameover", PNG);
|
||||
gameOver.setMode(MODE_STRETCH);
|
||||
gameOverTex->addLink(gameOver.getId());
|
||||
|
||||
printf("Loading water overlay...\n");
|
||||
waterOverlay.size.set(640.0F, 480.0F);
|
||||
Texture *watOverlayTex = texRepo->add("2d/", "underwater_overlay", PNG);
|
||||
waterOverlay.setMode(MODE_STRETCH);
|
||||
watOverlayTex->addLink(waterOverlay.getId());
|
||||
printf("Loaded.\n");
|
||||
|
||||
printf("Loading water...\n");
|
||||
|
||||
u32 spiralOffset = (u32)Math::sqrt(WATER_TILES_COUNT);
|
||||
waterDrawList = new Mesh *[WATER_TILES_COUNT];
|
||||
calcSpiral(spiralOffset, spiralOffset);
|
||||
water[0].loadObj("water/", "water", WATER_TILE_SCALE, false);
|
||||
water[0].position.set(0.0F, WATER_LEVEL, 0.0F);
|
||||
texRepo->addByMesh("water/", water[0], BMP);
|
||||
water[0].shouldBeFrustumCulled = true;
|
||||
water[0].shouldBeBackfaceCulled = false;
|
||||
waterDrawList[0] = &water[0];
|
||||
for (size_t i = 1; i < WATER_TILES_COUNT; i++)
|
||||
{
|
||||
water[i].loadFrom(water[0]);
|
||||
water[i].shouldBeFrustumCulled = true;
|
||||
water[i].shouldBeBackfaceCulled = false;
|
||||
water[i].position.set(WATER_TILE_SCALE * 2.0F * spirals[i].x, WATER_LEVEL, WATER_TILE_SCALE * 2.0F * spirals[i].y);
|
||||
texRepo->getByMesh(water[0].getId(), water[0].getMaterial(0).getId())
|
||||
->addLink(water[i].getId(), water[i].getMaterial(0).getId());
|
||||
waterDrawList[i] = &water[i];
|
||||
}
|
||||
|
||||
printf("Loading seabed...\n");
|
||||
seabed.loadObj("seabed/", "seabed", 10.0F, false);
|
||||
seabed.position.set(0, -250.0F, 0);
|
||||
texRepo->addByMesh("seabed/", seabed, BMP);
|
||||
seabed.shouldBeBackfaceCulled = false;
|
||||
seabed.shouldBeFrustumCulled = false;
|
||||
|
||||
skybox.loadObj("skybox/", "skybox", 400.0F, false);
|
||||
skybox.shouldBeFrustumCulled = false;
|
||||
|
||||
waterbox.loadObj("waterbox/", "waterbox", 250.0F, false);
|
||||
waterbox.shouldBeFrustumCulled = false;
|
||||
waterbox.shouldBeBackfaceCulled = false;
|
||||
waterbox.rotation.x = Math::PI;
|
||||
waterbox.position.y = -100.F;
|
||||
|
||||
printf("Loading oyster dff\n");
|
||||
oysters[0].mesh.loadObj("oyster/", "oyster", 10.F, false);
|
||||
printf("Loaded.");
|
||||
oysters[0].mesh.shouldBeBackfaceCulled = false;
|
||||
oysters[0].mesh.shouldBeFrustumCulled = false;
|
||||
oysters[0].mesh.position.set(15, 0, 15);
|
||||
texRepo->addByMesh("oyster/", oysters[0].mesh, BMP);
|
||||
printf("Adding oyster texture.\n");
|
||||
for (int i = 1; i < OYSTERS_COUNT; i++)
|
||||
{
|
||||
printf("Processing oyster %d\n", i);
|
||||
oysters[i].mesh.loadFrom(oysters[0].mesh);
|
||||
oysters[i].mesh.shouldBeBackfaceCulled = false;
|
||||
oysters[i].mesh.shouldBeFrustumCulled = false;
|
||||
texRepo->getByMesh(oysters[0].mesh.getId(), oysters[0].mesh.getMaterial(0).getId())
|
||||
->addLink(oysters[i].mesh.getId(), oysters[i].mesh.getMaterial(0).getId());
|
||||
oysters[i].mesh.position.set(i * -100, 5.0F, i * -100);
|
||||
}
|
||||
|
||||
printf("Loading mine .obj\n");
|
||||
mines[0].mesh.loadObj("mine/", "mine", 10.F, false);
|
||||
mines[0].mesh.shouldBeBackfaceCulled = false;
|
||||
mines[0].mesh.shouldBeFrustumCulled = false;
|
||||
mines[0].mesh.position.set(5, -15, 32);
|
||||
texRepo->addByMesh("mine/", mines[0].mesh, BMP);
|
||||
printf("Adding mine texture.\n");
|
||||
for (int i = 1; i < MINES_COUNT; i++)
|
||||
{
|
||||
printf("Processing mine %d\n", i);
|
||||
mines[i].mesh.loadFrom(mines[0].mesh);
|
||||
mines[i].mesh.shouldBeBackfaceCulled = false;
|
||||
mines[i].mesh.shouldBeFrustumCulled = false;
|
||||
texRepo->getByMesh(mines[0].mesh.getId(), mines[0].mesh.getMaterial(0).getId())
|
||||
->addLink(mines[i].mesh.getId(), mines[i].mesh.getMaterial(0).getId());
|
||||
mines[i].mesh.position.set(i * -10, 0.0F, i * -68);
|
||||
}
|
||||
|
||||
Texture *pLifeTex = texRepo->add("2d/", "life", PNG);
|
||||
// pLifeTex->addLink(lifeSprites[0].getId());
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
lifeSprites[i].size.set(64.0F, 64.0F);
|
||||
lifeSprites[i].setMode(MODE_STRETCH);
|
||||
lifeSprites[i].position.set(395 + (64 * i), 0);
|
||||
pLifeTex->addLink(lifeSprites[i].getId());
|
||||
}
|
||||
|
||||
texRepo->addByMesh("dolphin/", player.mesh, BMP);
|
||||
texRepo->addByMesh("sunnyisl/", island, BMP);
|
||||
texRepo->addByMesh("skybox/", skybox, BMP);
|
||||
texRepo->addByMesh("waterbox/", waterbox, BMP);
|
||||
|
||||
bulb.intensity = 55;
|
||||
bulb.position.set(5.0F, 10.0F, 10.0f);
|
||||
printf("Finished initialization\n");
|
||||
}
|
||||
|
||||
void Dolphin::onUpdate()
|
||||
{
|
||||
if (player.getLifes() <= 0)
|
||||
{
|
||||
engine->audio.stopSong();
|
||||
engine->audio.setADPCMVolume(0, 0);
|
||||
engine->audio.setADPCMVolume(75, 1);
|
||||
engine->renderer->draw(gameOver);
|
||||
return;
|
||||
}
|
||||
|
||||
Dolphin::engineFPS = engine->fps;
|
||||
// if (engine->pad.isCrossClicked)
|
||||
// printf("Delta multiplier: %f\n", 60.0F / engine->fps);
|
||||
|
||||
float xDist = player.mesh.position.x - water[0].position.x;
|
||||
float zDist = player.mesh.position.z - water[0].position.z;
|
||||
if (xDist < 0)
|
||||
xDist *= -1;
|
||||
if (zDist < 0)
|
||||
zDist *= -1;
|
||||
if (xDist > WATER_SIZE * WATER_TILE_SCALE / 4 ||
|
||||
zDist > WATER_SIZE * WATER_TILE_SCALE / 4)
|
||||
{
|
||||
for (size_t i = 0; i < WATER_TILES_COUNT; i++)
|
||||
{
|
||||
water[i].position.x = player.mesh.position.x + (WATER_TILE_SCALE * 2.0F * spirals[i].x);
|
||||
water[i].position.z = player.mesh.position.z + (WATER_TILE_SCALE * 2.0F * spirals[i].y);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < OYSTERS_COUNT; i++)
|
||||
{
|
||||
oysters[i].update();
|
||||
Vector3 vecDist = oysters[i].mesh.position - player.mesh.position;
|
||||
float dist = vecDist.length();
|
||||
if (dist < 20.F && player.isJumping() && oysters[i].isActive())
|
||||
{
|
||||
printf("Pickup:%d Dist:%f\n", i, dist);
|
||||
oysters[i].disappear();
|
||||
player.setLife(player.getLifes() + 1);
|
||||
engine->audio.setADPCMVolume(30, 3);
|
||||
engine->audio.playADPCM(pickupSound, 3);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < MINES_COUNT; i++)
|
||||
{
|
||||
mines[i].update();
|
||||
Vector3 vecDist = mines[i].mesh.position - player.mesh.position;
|
||||
float dist = vecDist.length();
|
||||
|
||||
if (dist < 20.F && !mines[i].getExplosionTicks())
|
||||
{
|
||||
printf("Vecdist: %f,%f,%f\n", vecDist.x, vecDist.y, vecDist.z);
|
||||
printf("Explode:%d Dist:%f\n", i, dist);
|
||||
mines[i].explode();
|
||||
player.setLife(player.getLifes() - 1);
|
||||
// Buffer switching to prevent playing two sounds on one buffer
|
||||
engine->audio.setADPCMVolume(65, Mine::lastSoundBuffer);
|
||||
engine->audio.playADPCM(boomSound, Mine::lastSoundBuffer);
|
||||
Mine::lastSoundBuffer = Mine::lastSoundBuffer == 4 ? 5 : 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (player.mesh.position.y > WATER_LEVEL - 5)
|
||||
player.mesh.position.y = WATER_LEVEL - 5;
|
||||
|
||||
player.update(engine->pad);
|
||||
camera.update(engine->pad, player.mesh);
|
||||
|
||||
skybox.position.set(player.mesh.position.x, +200.0F, player.mesh.position.z);
|
||||
waterbox.position.set(player.mesh.position.x, -260.0F, player.mesh.position.z);
|
||||
|
||||
engine->renderer->draw(island);
|
||||
engine->renderer->draw(waterDrawList, WATER_TILES_COUNT);
|
||||
engine->renderer->draw(skybox);
|
||||
engine->renderer->draw(waterbox);
|
||||
engine->renderer->draw(seabed);
|
||||
|
||||
for (u8 i = 0; i < OYSTERS_COUNT; i++)
|
||||
if (oysters[i].isActive())
|
||||
engine->renderer->draw(oysters[i].mesh);
|
||||
|
||||
for (u8 i = 0; i < MINES_COUNT; i++)
|
||||
if (mines[i].getExplosionTicks() < MINE_EXPLOSION_TICKS)
|
||||
engine->renderer->draw(mines[i].mesh);
|
||||
|
||||
for (u8 i = 0; i < player.getLifes(); i++)
|
||||
engine->renderer->draw(lifeSprites[i]);
|
||||
|
||||
engine->renderer->draw(player.mesh);
|
||||
|
||||
if (camera.position.y < WATER_LEVEL)
|
||||
{
|
||||
engine->renderer->draw(waterOverlay);
|
||||
engine->audio.setADPCMVolume(0, 0); // Surface ambient
|
||||
engine->audio.setADPCMVolume(65, 1); // Underwater ambient
|
||||
}
|
||||
else
|
||||
{
|
||||
engine->audio.setADPCMVolume(50, 0); //Surface ambient
|
||||
engine->audio.setADPCMVolume(0, 1); //Underwater ambient
|
||||
}
|
||||
}
|
||||
|
||||
void Dolphin::calcSpiral(int X, int Y)
|
||||
{
|
||||
int x, y, dx;
|
||||
x = y = dx = 0;
|
||||
int dy = -1;
|
||||
int t = X > Y ? X : Y;
|
||||
int maxI = t * t;
|
||||
for (int i = 0; i < maxI; i++)
|
||||
{
|
||||
if ((-X / 2 <= x) && (x <= X / 2) && (-Y / 2 <= y) && (y <= Y / 2))
|
||||
{
|
||||
spirals[i].x = x;
|
||||
spirals[i].y = y;
|
||||
}
|
||||
if ((x == y) || ((x < 0) && (x == -y)) || ((x > 0) && (x == 1 - y)))
|
||||
{
|
||||
t = dx;
|
||||
dx = -dy;
|
||||
dy = t;
|
||||
}
|
||||
x += dx;
|
||||
y += dy;
|
||||
}
|
||||
}
|
||||
Executable
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Michał Mostowik <mostek3pl@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _DRIVER_
|
||||
#define _DRIVER_
|
||||
|
||||
#include <tamtypes.h>
|
||||
#include <audsrv.h>
|
||||
#include <game.hpp>
|
||||
#include <engine.hpp>
|
||||
#include <models/light_bulb.hpp>
|
||||
#include <models/sprite.hpp>
|
||||
#include <modules/texture_repository.hpp>
|
||||
#include "./camera.hpp"
|
||||
#include "./objects/player.hpp"
|
||||
#include "./objects/collectible.hpp"
|
||||
#include "./objects/mine.hpp"
|
||||
|
||||
class Dolphin : public Game
|
||||
{
|
||||
|
||||
public:
|
||||
Dolphin(Engine *t_engine);
|
||||
~Dolphin();
|
||||
|
||||
void onInit();
|
||||
void onUpdate();
|
||||
|
||||
Engine *engine;
|
||||
static float engineFPS;
|
||||
|
||||
private:
|
||||
void calcSpiral(int X, int Y);
|
||||
static const u16 WATER_TILES_COUNT = 1024;
|
||||
|
||||
Point spirals[WATER_TILES_COUNT];
|
||||
Mesh **waterDrawList;
|
||||
/**
|
||||
* DO NOT TOUCH ORDER OF DECLARATION!
|
||||
* GCC BUG CAUSES RENDERING TO FAIL IN ANY OTHER ORDER OF DECLARATION!
|
||||
*/
|
||||
Mesh seabed;
|
||||
Mesh island;
|
||||
Mesh skybox;
|
||||
Mesh mine;
|
||||
LightBulb bulb;
|
||||
Player player;
|
||||
Camera camera;
|
||||
Collectible *oysters;
|
||||
TextureRepository *texRepo;
|
||||
Sprite waterOverlay;
|
||||
Mesh water[WATER_TILES_COUNT];
|
||||
Mesh waterbox;
|
||||
Sprite lifeSprites[3];
|
||||
Sprite gameOver;
|
||||
audsrv_adpcm_t *underwaterAmbient, *surfaceAmbient;
|
||||
audsrv_adpcm_t *pickupSound;
|
||||
audsrv_adpcm_t *boomSound;
|
||||
Mine *mines;
|
||||
};
|
||||
|
||||
#endif
|
||||
Regular → Executable
+4
-3
@@ -5,15 +5,16 @@
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
# Michał Mostowik <mostek3pl@gmail.com>
|
||||
*/
|
||||
|
||||
#include "ari.hpp"
|
||||
#include "dolphin.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
Engine engine = Engine();
|
||||
Ari game = Ari(&engine);
|
||||
engine.screen.fov = 75.F;
|
||||
Dolphin game = Dolphin(&engine);
|
||||
game.engine->init(&game, 128);
|
||||
SleepThread();
|
||||
return 0;
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Michał Mostowik <mostek3pl@gmail.com>
|
||||
*/
|
||||
|
||||
#include "collectible.hpp"
|
||||
|
||||
#include <loaders/obj_loader.hpp>
|
||||
#include <loaders/bmp_loader.hpp>
|
||||
#include <modules/gif_sender.hpp>
|
||||
#include <utils/debug.hpp>
|
||||
#include <utils/math.hpp>
|
||||
|
||||
Collectible::Collectible()
|
||||
{
|
||||
mesh.loadObj("oyster/", "oyster", 10.F, false);
|
||||
mesh.shouldBeFrustumCulled = false;
|
||||
mesh.position.set(0.0F, 0.0F, 0.0f);
|
||||
bActive = true;
|
||||
bDisappearing = false;
|
||||
}
|
||||
|
||||
void Collectible::disappear()
|
||||
{
|
||||
bDisappearing = true;
|
||||
lift = 10;
|
||||
}
|
||||
|
||||
void Collectible::update()
|
||||
{
|
||||
mesh.rotation.y += 0.08F;
|
||||
if (bDisappearing)
|
||||
{
|
||||
mesh.position.y += lift;
|
||||
lift = lift > 0 ? lift / 2 : 0;
|
||||
if (lift < 1)
|
||||
{
|
||||
setActive(false);
|
||||
bDisappearing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Michał Mostowik <mostek3pl@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _COLLECTIBLE_
|
||||
#define _COLLECTIBLE_
|
||||
|
||||
#include "../camera.hpp"
|
||||
#include <tamtypes.h>
|
||||
|
||||
class Collectible
|
||||
{
|
||||
|
||||
public:
|
||||
float rotation;
|
||||
Mesh mesh;
|
||||
Collectible();
|
||||
void update();
|
||||
void disappear();
|
||||
void setActive(const u8 &b) { bActive = b; }
|
||||
u8 isActive() { return bActive; }
|
||||
|
||||
private:
|
||||
u8 bActive, bDisappearing;
|
||||
u8 lift;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Michał Mostowik <mostek3pl@gmail.com>
|
||||
*/
|
||||
|
||||
#include "mine.hpp"
|
||||
|
||||
u8 Mine::lastSoundBuffer = 4;
|
||||
|
||||
Mine::Mine()
|
||||
{
|
||||
mesh.position.set(0.0F, 0.0F, 0.0F);
|
||||
|
||||
bExploding = false;
|
||||
explosionTicks = 0;
|
||||
}
|
||||
|
||||
void Mine::update()
|
||||
{
|
||||
if (bExploding && explosionTicks < MINE_EXPLOSION_TICKS)
|
||||
{
|
||||
explosionTicks++;
|
||||
mesh.scale++;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Michał Mostowik <mostek3pl@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _MINE_
|
||||
#define _MINE_
|
||||
|
||||
#include <tamtypes.h>
|
||||
#include <models/mesh.hpp>
|
||||
|
||||
#define MINE_EXPLOSION_TICKS 10
|
||||
|
||||
class Mine
|
||||
{
|
||||
public:
|
||||
static u8 lastSoundBuffer;
|
||||
Mesh mesh;
|
||||
void explode() { bExploding = true; }
|
||||
void update();
|
||||
Mine();
|
||||
const u8 &getExplosionTicks() { return explosionTicks; }
|
||||
|
||||
private:
|
||||
u8 bExploding;
|
||||
u8 explosionTicks;
|
||||
};
|
||||
|
||||
#endif
|
||||
Executable
+98
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Michał Mostowik <mostek3pl@gmail.com>
|
||||
*/
|
||||
|
||||
#include "player.hpp"
|
||||
#include "dolphin.hpp"
|
||||
|
||||
#include <loaders/obj_loader.hpp>
|
||||
#include <loaders/bmp_loader.hpp>
|
||||
#include <modules/gif_sender.hpp>
|
||||
#include <utils/debug.hpp>
|
||||
#include <utils/math.hpp>
|
||||
|
||||
Player::Player()
|
||||
{
|
||||
mesh.loadMD2("dolphin/", "dolphin", 0.025F, true);
|
||||
mesh.shouldBeFrustumCulled = false;
|
||||
mesh.position.set(0.0F, 0.0F, 10.0f);
|
||||
mesh.rotation.x = -1.6F;
|
||||
mesh.setAnimSpeed(0.04F);
|
||||
bIsJumping = false;
|
||||
lifes = 3;
|
||||
}
|
||||
|
||||
void Player::init(Engine *t_engine)
|
||||
{
|
||||
pEngine = t_engine;
|
||||
waterImpact = t_engine->audio.loadADPCM("sound/water_impact.sad");
|
||||
}
|
||||
|
||||
void Player::update(Pad &t_pad)
|
||||
{
|
||||
if (lift > 0.0F)
|
||||
lift -= 0.05F;
|
||||
if (lift < 0.0F)
|
||||
lift += 0.05F;
|
||||
if (lift < 0.1F && lift > -0.1F)
|
||||
lift = 0;
|
||||
if (t_pad.lJoyV <= 100)
|
||||
velocity = 1;
|
||||
else if (t_pad.lJoyV >= 200)
|
||||
velocity = -1;
|
||||
|
||||
if (t_pad.lJoyH >= 200)
|
||||
mesh.rotation.z -= 0.05;
|
||||
else if (t_pad.lJoyH <= 100)
|
||||
mesh.rotation.z += 0.05;
|
||||
|
||||
if (t_pad.rJoyV >= 200 && lift <= 1)
|
||||
lift += 0.2F;
|
||||
else if (t_pad.rJoyV <= 100 && lift >= -1)
|
||||
lift -= 0.2F;
|
||||
|
||||
if (t_pad.isCrossClicked && mesh.getCurrentAnimationFrame() <= 14 && WATER_LEVEL - 15 < mesh.position.y)
|
||||
{
|
||||
mesh.setAnimSpeed(1.0F);
|
||||
mesh.playAnimation(14, 58, 0);
|
||||
}
|
||||
|
||||
if (mesh.getCurrentAnimationFrame() > 25 && mesh.getCurrentAnimationFrame() < 47)
|
||||
bIsJumping = true;
|
||||
else
|
||||
bIsJumping = false;
|
||||
|
||||
if (velocity > 0 && mesh.getCurrentAnimationFrame() == 0)
|
||||
{
|
||||
mesh.setAnimSpeed(0.05F);
|
||||
mesh.playAnimation(1, 14, 0);
|
||||
}
|
||||
if (mesh.getCurrentAnimationFrame() == 42)
|
||||
{
|
||||
if (!bIsImpactingWater)
|
||||
{
|
||||
pEngine->audio.setADPCMVolume(50, 2);
|
||||
pEngine->audio.playADPCM(waterImpact, 2);
|
||||
}
|
||||
bIsImpactingWater = true;
|
||||
}
|
||||
else if (bIsImpactingWater)
|
||||
{
|
||||
bIsImpactingWater = false;
|
||||
}
|
||||
|
||||
velocity *= 60.0F / Dolphin::engineFPS; // Moving by deltatime of last frame.
|
||||
mesh.position.z +=
|
||||
Math::cos(mesh.rotation.z) * velocity * (bIsJumping + 1);
|
||||
mesh.position.x +=
|
||||
Math::sin(mesh.rotation.z) * velocity * (bIsJumping + 1);
|
||||
mesh.position.y += lift;
|
||||
|
||||
velocity = 0;
|
||||
}
|
||||
Executable
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Michał Mostowik <mostek3pl@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _PLAYER_
|
||||
#define _PLAYER_
|
||||
|
||||
#define WATER_LEVEL -5.0F
|
||||
|
||||
#include "../camera.hpp"
|
||||
#include <audsrv.h>
|
||||
#include <modules/pad.hpp>
|
||||
#include <tamtypes.h>
|
||||
class Engine;
|
||||
class Player
|
||||
{
|
||||
|
||||
public:
|
||||
float gravity, velocity, lift;
|
||||
Mesh mesh;
|
||||
Player();
|
||||
void init(Engine *t_engine);
|
||||
void update(Pad &t_pad);
|
||||
const u8 &isJumping() { return bIsJumping; }
|
||||
const u8 &getLifes() { return lifes; }
|
||||
void setLife(const u8 &l) { lifes = lifes = l < 4 ? l : 3; }
|
||||
|
||||
private:
|
||||
u8 bIsJumping;
|
||||
Vector3 playerNextPosition;
|
||||
u8 lifes;
|
||||
audsrv_adpcm_t *waterImpact;
|
||||
Engine *pEngine;
|
||||
u8 bIsImpactingWater;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -6,8 +6,10 @@ EE_OBJS = \
|
||||
managers/light_manager.o \
|
||||
managers/floor_manager.o \
|
||||
camera.o \
|
||||
objects/enemy.o \
|
||||
objects/floor.o \
|
||||
objects/player.o \
|
||||
ui.o \
|
||||
utils.o \
|
||||
floors.o \
|
||||
main.o
|
||||
|
||||
@@ -19,13 +19,10 @@ const float CAMERA_Y = 30.0F;
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
Camera::Camera(ScreenSettings *t_screen) : CameraBase(t_screen, &position, &up)
|
||||
Camera::Camera(ScreenSettings *t_screen) : CameraBase(t_screen, &position)
|
||||
{
|
||||
PRINT_LOG("Initializing camera");
|
||||
verticalLevel = 80.0F;
|
||||
up.x = 0.0F;
|
||||
up.y = 1.0F;
|
||||
up.z = 0.0F;
|
||||
PRINT_LOG("Camera initialized!");
|
||||
}
|
||||
|
||||
@@ -48,10 +45,10 @@ void Camera::update(Pad &t_pad, Mesh &t_mesh)
|
||||
*/
|
||||
void Camera::rotate(Pad &t_pad)
|
||||
{
|
||||
if (t_pad.rJoyH <= 50)
|
||||
if (t_pad.rJoyH <= 100)
|
||||
horizontalLevel -= 0.08;
|
||||
else if (t_pad.rJoyH >= 200)
|
||||
horizontalLevel += 0.04;
|
||||
horizontalLevel += 0.08;
|
||||
if (t_pad.rJoyV <= 50 && verticalLevel > 25.0F)
|
||||
verticalLevel -= 0.9F;
|
||||
else if (t_pad.rJoyV >= 200 && verticalLevel < 80.0F)
|
||||
@@ -67,15 +64,4 @@ void Camera::followBy(Mesh &t_mesh)
|
||||
position.x = unitCirclePosition.x + t_mesh.position.x;
|
||||
position.y = unitCirclePosition.y + t_mesh.position.y;
|
||||
position.z = unitCirclePosition.z + t_mesh.position.z;
|
||||
|
||||
if (position.x > (-0.04F * verticalLevel) &&
|
||||
position.x < 0.0F &&
|
||||
position.z > (0.998F * verticalLevel))
|
||||
{
|
||||
// TODO
|
||||
// position.x = 0.0F;
|
||||
// position.y = 0.0F;
|
||||
// position.z = 0.0F;
|
||||
// horizontalLevel = 0.0F;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ public:
|
||||
|
||||
protected:
|
||||
Vector3 *getPosition() { return &position; };
|
||||
Vector3 *getUp() { return &up; };
|
||||
ScreenSettings screen;
|
||||
};
|
||||
|
||||
|
||||
@@ -14,15 +14,22 @@
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
const u8 FLOORS_COUNT = 144; // Temp change it also in floor_manager.hpp
|
||||
const u16 FLOORS_COUNT = 144; // Temp change it also in floor_manager.hpp
|
||||
|
||||
Floors::Floors(Engine *t_engine)
|
||||
: engine(t_engine), floorManager(FLOORS_COUNT), camera(&t_engine->screen)
|
||||
: engine(t_engine), floorManager(), camera(&t_engine->screen)
|
||||
{
|
||||
audioTicks = 0;
|
||||
skip1Beat = 0;
|
||||
}
|
||||
|
||||
Floors::~Floors() {}
|
||||
Floors::~Floors()
|
||||
{
|
||||
delete enemy;
|
||||
delete ui;
|
||||
delete floorManager;
|
||||
delete player;
|
||||
}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
@@ -30,43 +37,61 @@ Floors::~Floors() {}
|
||||
|
||||
void Floors::onInit()
|
||||
{
|
||||
engine->renderer->setCameraDefinitions(&camera.worldView, &camera.unitCirclePosition, camera.planes);
|
||||
engine->audio.addSongListener(this);
|
||||
engine->audio.loadSong("NF-CHILL.WAV");
|
||||
engine->audio.setSongVolume(100);
|
||||
engine->audio.playSong();
|
||||
texRepo = engine->renderer->getTextureRepository();
|
||||
texRepo->addByMesh("warrior/", player.mesh, BMP);
|
||||
texRepo->addByMesh("floor/", floorManager.floors[0].mesh, BMP);
|
||||
for (u32 i = 1; i < floorManager.floorAmount; i++)
|
||||
texRepo->getByMesh(floorManager.floors[0].mesh.getId(), floorManager.floors[0].mesh.getMaterial(0).getId())
|
||||
->addLink(floorManager.floors[i].mesh.getId(), floorManager.floors[i].mesh.getMaterial(0).getId());
|
||||
enemy = new Enemy(texRepo);
|
||||
ui = new Ui(texRepo);
|
||||
floorManager = new FloorManager(FLOORS_COUNT, texRepo); // we must init FloorManager before starting audio!
|
||||
player = new Player(&engine->audio, texRepo);
|
||||
setBgColorAndAmbientColor();
|
||||
engine->renderer->setCameraDefinitions(&camera.view, &camera.unitCirclePosition, camera.planes);
|
||||
engine->audio.addSongListener(this);
|
||||
engine->audio.loadSong("sounds/mafikizolo-loot.wav");
|
||||
engine->audio.playSong();
|
||||
engine->audio.setSongVolume(80);
|
||||
}
|
||||
|
||||
void Floors::onUpdate()
|
||||
{
|
||||
if (engine->pad.isCrossClicked)
|
||||
printf("FPS:%f\n", engine->fps);
|
||||
ui->update(*player);
|
||||
enemy->update(*floorManager);
|
||||
lightManager.update();
|
||||
camera.update(engine->pad, player.mesh);
|
||||
floorManager.update(player);
|
||||
player.update(engine->pad, camera, floorManager);
|
||||
engine->renderer->draw(player.mesh);
|
||||
for (u8 i = 0; i < FLOORS_COUNT; i++)
|
||||
engine->renderer->drawByPath3(floorManager.floors[i].mesh, lightManager.bulbs, lightManager.bulbsCount);
|
||||
camera.update(engine->pad, player->mesh);
|
||||
floorManager->update(*player);
|
||||
player->update(engine->pad, camera, *floorManager, *enemy);
|
||||
engine->renderer->draw(player->mesh);
|
||||
engine->renderer->draw(enemy->getMeshes(), enemy->getMeshesCount());
|
||||
|
||||
// You can draw array of meshes in draw() function also. It can be A LOT faster than for looping!
|
||||
// Why? When given mesh is small, is not animated and is not backface culled, vertex data are send once!
|
||||
engine->renderer->draw(floorManager->getMeshes(), FLOORS_COUNT, lightManager.bulbs, lightManager.bulbsCount);
|
||||
|
||||
ui->render(engine->renderer); // 2D rendering ist LAST step, because layers gonna play there.
|
||||
}
|
||||
|
||||
void Floors::onAudioTick()
|
||||
{
|
||||
if ((++audioTicks + 20) % 41 == 0)
|
||||
if ((++audioTicks + 20) % 21 == 0)
|
||||
{
|
||||
floorManager.onAudioTick();
|
||||
if (skip1Beat)
|
||||
floorManager->onAudioTick();
|
||||
lightManager.onAudioTick();
|
||||
skip1Beat = !skip1Beat;
|
||||
}
|
||||
if (audioTicks > 10000)
|
||||
audioTicks = 0;
|
||||
}
|
||||
|
||||
void Floors::setBgColorAndAmbientColor()
|
||||
{
|
||||
color_t bgColor;
|
||||
bgColor.r = 0x20;
|
||||
bgColor.g = 0x20;
|
||||
bgColor.b = 0x20;
|
||||
engine->renderer->setWorldColor(bgColor);
|
||||
Vector3 ambient = Vector3(0.003F, 0.003F, 0.003F);
|
||||
engine->renderer->setAmbientLight(ambient);
|
||||
}
|
||||
|
||||
void Floors::onAudioFinish()
|
||||
{
|
||||
audioTicks = 0;
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
#include "managers/light_manager.hpp"
|
||||
#include "modules/texture_repository.hpp"
|
||||
#include "objects/player.hpp"
|
||||
#include "objects/enemy.hpp"
|
||||
#include "./camera.hpp"
|
||||
#include "./ui.hpp"
|
||||
|
||||
class Floors : public Game, AudioListener
|
||||
{
|
||||
@@ -35,12 +37,16 @@ public:
|
||||
Engine *engine;
|
||||
|
||||
private:
|
||||
void setBgColorAndAmbientColor();
|
||||
u32 audioTicks;
|
||||
u8 skip1Beat;
|
||||
TextureRepository *texRepo;
|
||||
LightManager lightManager;
|
||||
FloorManager floorManager;
|
||||
Player player;
|
||||
FloorManager *floorManager;
|
||||
Player *player;
|
||||
Camera camera;
|
||||
Ui *ui;
|
||||
Enemy *enemy;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -20,14 +20,19 @@
|
||||
/** Calculate square spiral offsets and initialize floors
|
||||
* @param floorAmount must be a number from square root table
|
||||
*/
|
||||
FloorManager::FloorManager(int t_floorAmount)
|
||||
FloorManager::FloorManager(int t_floorAmount, TextureRepository *t_texRepo)
|
||||
{
|
||||
meshes = new Mesh *[t_floorAmount];
|
||||
texRepo = t_texRepo;
|
||||
floorAmount = t_floorAmount;
|
||||
spirals = new Point[t_floorAmount];
|
||||
int floorSpiralMaxOffset = (int)Math::sqrt(t_floorAmount);
|
||||
calcSpiral(floorSpiralMaxOffset, floorSpiralMaxOffset);
|
||||
initFloors();
|
||||
audioOffset = audioMode = audioTick = 0;
|
||||
trick = 0.0F;
|
||||
isTimeForChangeTriggerColor = true;
|
||||
isTimeForChangeDefaultColor = true;
|
||||
audioOffset = audioMode = audioTick = trickMode = 0;
|
||||
}
|
||||
|
||||
FloorManager::~FloorManager()
|
||||
@@ -77,11 +82,19 @@ void FloorManager::calcSpiral(int X, int Y)
|
||||
void FloorManager::initFloors()
|
||||
{
|
||||
PRINT_LOG("Initializing floors");
|
||||
floors[0].mesh.loadObj("floor/", "floor", 3.0F, false);
|
||||
floors[0].mesh.loadObj("meshes/floor/", "floor", 3.0F, false);
|
||||
floors[0].mesh.shouldBeFrustumCulled = true;
|
||||
floors[0].mesh.shouldBeLighted = true;
|
||||
for (u8 i = 1; i < floorAmount; i++)
|
||||
meshes[0] = &floors[0].mesh;
|
||||
texRepo->addByMesh("meshes/floor/", floors[0].mesh, BMP);
|
||||
for (u16 i = 1; i < floorAmount; i++)
|
||||
{
|
||||
floors[i].mesh.shouldBeFrustumCulled = true;
|
||||
floors[i].init(floors[0].mesh, spirals[i], i);
|
||||
texRepo->getByMesh(floors[0].mesh.getId(), floors[0].mesh.getMaterial(0).getId())
|
||||
->addLink(floors[i].mesh.getId(), floors[i].mesh.getMaterial(0).getId());
|
||||
meshes[i] = &floors[i].mesh;
|
||||
}
|
||||
PRINT_LOG("Floors initialized!");
|
||||
}
|
||||
|
||||
@@ -92,25 +105,75 @@ void FloorManager::initFloors()
|
||||
*/
|
||||
void FloorManager::update(Player &t_player)
|
||||
{
|
||||
for (u8 i = 0; i < floorAmount; i++)
|
||||
if (isTimeForChangeTriggerColor)
|
||||
{
|
||||
isTimeForChangeTriggerColor = false;
|
||||
trigColor.r = rand() % (128 - 64 + 1) + 64;
|
||||
trigColor.g = rand() % (128 - 64 + 1) + 64;
|
||||
trigColor.b = rand() % (128 - 64 + 1) + 64;
|
||||
}
|
||||
if (isTimeForChangeDefaultColor)
|
||||
{
|
||||
isTimeForChangeDefaultColor = false;
|
||||
defaultColor.r = rand() % (64 + 1);
|
||||
defaultColor.g = rand() % (64 + 1);
|
||||
defaultColor.b = rand() % (64 + 1);
|
||||
}
|
||||
doTheTrick();
|
||||
for (u16 i = 0; i < floorAmount; i++)
|
||||
{
|
||||
floors[i].animate(t_player);
|
||||
|
||||
if (floors[i].isByAudioTriggered == true)
|
||||
floors[i].mesh.color.a = 0x20;
|
||||
else
|
||||
floors[i].mesh.color.a = 0x80;
|
||||
if (floors[i].isByAudioTriggered)
|
||||
{
|
||||
floors[i].mesh.color.r = trigColor.r;
|
||||
floors[i].mesh.color.g = trigColor.g;
|
||||
floors[i].mesh.color.b = trigColor.b;
|
||||
}
|
||||
else
|
||||
{
|
||||
floors[i].mesh.color.r = defaultColor.r;
|
||||
floors[i].mesh.color.g = defaultColor.g;
|
||||
floors[i].mesh.color.b = defaultColor.b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FloorManager::doTheTrick()
|
||||
{
|
||||
if (trickMode == 0)
|
||||
{
|
||||
if (trick > 3.0F)
|
||||
{
|
||||
isTimeForChangeTriggerColor = true;
|
||||
trickMode = 1;
|
||||
}
|
||||
trick += 0.01F;
|
||||
}
|
||||
else if (trickMode == 1)
|
||||
{
|
||||
if (trick <= 0.1F)
|
||||
{
|
||||
isTimeForChangeTriggerColor = true;
|
||||
trickMode = 0;
|
||||
}
|
||||
trick -= 0.01F;
|
||||
}
|
||||
floors[0].mesh.getFrames()[0].getST(1).set(trick, trick);
|
||||
floors[0].mesh.getFrames()[0].getST(4).set(trick, trick);
|
||||
floors[0].mesh.getFrames()[0].getST(7).set(trick, trick);
|
||||
floors[0].mesh.getFrames()[0].getST(10).set(trick, trick);
|
||||
floors[0].mesh.getFrames()[0].getST(13).set(trick, trick);
|
||||
}
|
||||
|
||||
/** Called by audio thread */
|
||||
void FloorManager::onAudioTick()
|
||||
{
|
||||
if (audioTick++ > 16)
|
||||
if (audioTick++ > 19)
|
||||
{
|
||||
if (audioMode == 0)
|
||||
{
|
||||
for (u8 i = 0; i < floorAmount; i++)
|
||||
for (u16 i = 0; i < floorAmount; i++)
|
||||
{
|
||||
if ((i + audioOffset) % 2 == 0)
|
||||
floors[i].isByAudioTriggered = true;
|
||||
@@ -120,12 +183,13 @@ void FloorManager::onAudioTick()
|
||||
if (++audioOffset > 3)
|
||||
{
|
||||
audioOffset = 0;
|
||||
isTimeForChangeDefaultColor = true;
|
||||
audioMode = 1;
|
||||
}
|
||||
}
|
||||
else if (audioMode == 1)
|
||||
{
|
||||
for (u8 i = 0; i < floorAmount; i++)
|
||||
for (u16 i = 0; i < floorAmount; i++)
|
||||
{
|
||||
if (i < floorAmount / (audioOffset + 1))
|
||||
floors[i].isByAudioTriggered = true;
|
||||
@@ -135,12 +199,13 @@ void FloorManager::onAudioTick()
|
||||
if (++audioOffset > 3)
|
||||
{
|
||||
audioOffset = 0;
|
||||
isTimeForChangeDefaultColor = true;
|
||||
audioMode = 2;
|
||||
}
|
||||
}
|
||||
else if (audioMode == 2)
|
||||
{
|
||||
for (u8 i = 0; i < floorAmount; i++)
|
||||
for (u16 i = 0; i < floorAmount; i++)
|
||||
{
|
||||
if ((i + audioOffset) % 4 == 0)
|
||||
floors[i].isByAudioTriggered = true;
|
||||
@@ -150,14 +215,15 @@ void FloorManager::onAudioTick()
|
||||
if (++audioOffset > 3)
|
||||
{
|
||||
audioOffset = 0;
|
||||
isTimeForChangeDefaultColor = true;
|
||||
audioMode = 3;
|
||||
}
|
||||
}
|
||||
else if (audioMode == 3)
|
||||
{
|
||||
for (u8 i = 0; i < floorAmount; i++)
|
||||
for (u16 i = 0; i < floorAmount; i++)
|
||||
{
|
||||
if (u8(i + 1) > floorAmount / (audioOffset + 1))
|
||||
if (u16(i + 1) > floorAmount / (audioOffset + 1))
|
||||
floors[i].isByAudioTriggered = true;
|
||||
else
|
||||
floors[i].isByAudioTriggered = false;
|
||||
@@ -165,6 +231,7 @@ void FloorManager::onAudioTick()
|
||||
if (++audioOffset > 3)
|
||||
{
|
||||
audioOffset = 0;
|
||||
isTimeForChangeDefaultColor = true;
|
||||
audioMode = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
class Player; // Forward definition
|
||||
|
||||
#include <models/math/point.hpp>
|
||||
#include <modules/texture_repository.hpp>
|
||||
#include <modules/camera_base.hpp>
|
||||
#include <models/audio_listener.hpp>
|
||||
|
||||
@@ -24,18 +25,26 @@ class FloorManager
|
||||
{
|
||||
|
||||
public:
|
||||
FloorManager(int t_floorAmount);
|
||||
FloorManager(int t_floorAmount, TextureRepository *t_texRepo);
|
||||
~FloorManager();
|
||||
Floor floors[144]; // Temp change it also in floors.cpp
|
||||
u32 floorAmount;
|
||||
u16 floorAmount;
|
||||
void update(Player &t_player);
|
||||
void onAudioTick();
|
||||
Mesh **getMeshes() { return meshes; }
|
||||
|
||||
private:
|
||||
Mesh **meshes;
|
||||
TextureRepository *texRepo;
|
||||
u8 audioOffset, audioMode;
|
||||
u32 audioTick;
|
||||
float trick;
|
||||
u8 isTimeForChangeTriggerColor, isTimeForChangeDefaultColor;
|
||||
color_t trigColor, defaultColor;
|
||||
u8 trickMode;
|
||||
Point *spirals;
|
||||
void calcSpiral(int X, int Y);
|
||||
void doTheTrick();
|
||||
void initFloors();
|
||||
};
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ void LightManager::onAudioTick()
|
||||
}
|
||||
else
|
||||
{
|
||||
bulbs[0].intensity += 6;
|
||||
bulbs[1].intensity += 6;
|
||||
bulbs[0].intensity += 9;
|
||||
bulbs[1].intensity += 9;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "enemy.hpp"
|
||||
#include "../utils.hpp"
|
||||
|
||||
#include <loaders/md2_loader.hpp>
|
||||
#include <loaders/bmp_loader.hpp>
|
||||
#include <modules/gif_sender.hpp>
|
||||
#include <utils/debug.hpp>
|
||||
#include <utils/math.hpp>
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
Enemy::Enemy(TextureRepository *t_texRepo)
|
||||
{
|
||||
PRINT_LOG("Creating enemy object");
|
||||
|
||||
meshes = new Mesh[getMeshesCount()];
|
||||
drawMeshes = new Mesh *[getMeshesCount()];
|
||||
|
||||
meshes[0].loadMD2("meshes/enemy/", "poss_head", 0.3F, false);
|
||||
meshes[1].loadMD2("meshes/enemy/", "poss_body", 0.3F, false);
|
||||
meshes[2].loadMD2("meshes/enemy/", "poss_weapon", 0.3F, false);
|
||||
|
||||
for (u8 i = 0; i < 3; i++)
|
||||
{
|
||||
meshes[i].rotation.x = -1.566F;
|
||||
meshes[i].rotation.z = 1.566F;
|
||||
meshes[i].shouldBeFrustumCulled = false;
|
||||
t_texRepo->addByMesh("meshes/enemy/", meshes[i], PNG);
|
||||
meshes[i].playAnimation(1, 6);
|
||||
drawMeshes[i] = &meshes[i];
|
||||
}
|
||||
|
||||
Vector3 initPos = Vector3(0.00F, 40.00F, 0.00F);
|
||||
setPosition(initPos);
|
||||
|
||||
isKilled = true;
|
||||
|
||||
PRINT_LOG("Enemy object created!");
|
||||
}
|
||||
|
||||
Enemy::~Enemy()
|
||||
{
|
||||
delete[] meshes;
|
||||
}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
void Enemy::setPosition(const Vector3 &t_vec)
|
||||
{
|
||||
position.set(t_vec);
|
||||
for (u8 i = 0; i < getMeshesCount(); i++)
|
||||
meshes[i].position.set(t_vec);
|
||||
}
|
||||
|
||||
void Enemy::setPosition(const float &t_y)
|
||||
{
|
||||
position.y = t_y;
|
||||
for (u8 i = 0; i < getMeshesCount(); i++)
|
||||
meshes[i].position.y = t_y;
|
||||
}
|
||||
|
||||
/** Called by player class. */
|
||||
void Enemy::kill(const Player &player)
|
||||
{
|
||||
isKilled = true;
|
||||
}
|
||||
|
||||
void Enemy::update(const FloorManager &floorManager)
|
||||
{
|
||||
if (isKilled)
|
||||
{
|
||||
isKilled = false;
|
||||
int randFloor = rand() % (floorManager.floorAmount + 1);
|
||||
currentFloor = &floorManager.floors[randFloor];
|
||||
setPosition(currentFloor->mesh.position);
|
||||
}
|
||||
updateGravity();
|
||||
}
|
||||
|
||||
void Enemy::updateGravity()
|
||||
{
|
||||
Utils::getMinMax(currentFloor->mesh, currFloorMin, currFloorMax);
|
||||
setPosition(currFloorMax.y);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _ENEMY_
|
||||
#define _ENEMY_
|
||||
|
||||
#include <tamtypes.h>
|
||||
#include "../managers/floor_manager.hpp"
|
||||
#include <modules/texture_repository.hpp>
|
||||
|
||||
/** Player 3D object class */
|
||||
class Enemy
|
||||
{
|
||||
|
||||
public:
|
||||
s16 indexOfCurrentFloor;
|
||||
Enemy(TextureRepository *t_texRepo);
|
||||
~Enemy();
|
||||
|
||||
inline Mesh **getMeshes() const { return drawMeshes; }
|
||||
inline u8 getMeshesCount() const { return 3; }
|
||||
inline Vector3 getPosition() const { return position; }
|
||||
void setPosition(const Vector3 &t_vec);
|
||||
void setPosition(const float &t_y);
|
||||
void kill(const Player &player);
|
||||
void update(const FloorManager &t_floorManager);
|
||||
|
||||
private:
|
||||
/** 0 - head, 1 - body, 2 - weapon */
|
||||
Mesh *meshes;
|
||||
/** Only for draw() method. */
|
||||
Mesh **drawMeshes;
|
||||
const Floor *currentFloor;
|
||||
Vector3 position, currFloorMin, currFloorMax;
|
||||
u8 isKilled;
|
||||
void updateGravity();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -23,7 +23,13 @@ const float FLOOR_ANIMATION_Y_MAX = 10.0F;
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
Floor::Floor() {}
|
||||
Floor::Floor()
|
||||
{
|
||||
animTimer = 0;
|
||||
animDirection = 0;
|
||||
initOffset = 0;
|
||||
isByAudioTriggered = false;
|
||||
}
|
||||
|
||||
Floor::~Floor() {}
|
||||
|
||||
@@ -31,11 +37,6 @@ Floor::~Floor() {}
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
/** Init floor position and animation timer position
|
||||
* @param spec pointer to 3D object specification
|
||||
* @param spiral Spiral position
|
||||
* @param initOffset Number of floor (index)
|
||||
*/
|
||||
void Floor::init(const Mesh &mother, const Point &spiral, const u8 &initOffset)
|
||||
{
|
||||
this->mesh.position.set(0.00F, -10.00F, 0.00F);
|
||||
@@ -44,7 +45,6 @@ void Floor::init(const Mesh &mother, const Point &spiral, const u8 &initOffset)
|
||||
this->animTimer = rand() % FLOOR_ANIMATION_LENGTH;
|
||||
this->mesh.shouldBeLighted = true;
|
||||
this->mesh.shouldBeFrustumCulled = true;
|
||||
this->animDirection = 0;
|
||||
this->mesh.position.x = spiral.x * 80.0F;
|
||||
this->mesh.position.z = spiral.y * 80.0F;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ class Floor
|
||||
|
||||
public:
|
||||
u16 animTimer;
|
||||
u8 animDirection, initOffset, isByAudioTriggered;
|
||||
s16 animDirection, initOffset, isByAudioTriggered;
|
||||
Mesh mesh;
|
||||
|
||||
Floor();
|
||||
|
||||
@@ -9,8 +9,9 @@
|
||||
*/
|
||||
|
||||
#include "player.hpp"
|
||||
#include "../utils.hpp"
|
||||
|
||||
#include <loaders/obj_loader.hpp>
|
||||
#include <loaders/md2_loader.hpp>
|
||||
#include <loaders/bmp_loader.hpp>
|
||||
#include <modules/gif_sender.hpp>
|
||||
#include <utils/debug.hpp>
|
||||
@@ -20,20 +21,38 @@
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
Player::Player()
|
||||
Player::Player(Audio *t_audio, TextureRepository *t_texRepo)
|
||||
{
|
||||
PRINT_LOG("Creating player object");
|
||||
this->gravity = 0.1F;
|
||||
this->lift = -1.0F;
|
||||
texRepo = t_texRepo;
|
||||
audio = t_audio;
|
||||
gravity = 0.1F;
|
||||
lift = -1.0F;
|
||||
jumpCounter = 0;
|
||||
speed = 1.0F;
|
||||
killedEnemies = 0;
|
||||
isWalking = false;
|
||||
isFighting = false;
|
||||
isWalkingAnimationSet = false;
|
||||
isJumpingAnimationSet = false;
|
||||
isFightingAnimationSet = false;
|
||||
|
||||
this->mesh.loadMD2("warrior/", "warrior", 0.2F, true);
|
||||
this->mesh.position.set(0.00F, 20.00F, 0.00F);
|
||||
this->mesh.rotation.x = -1.6F;
|
||||
this->mesh.shouldBeBackfaceCulled = false;
|
||||
this->mesh.shouldBeFrustumCulled = false;
|
||||
mesh.loadMD2("meshes/player/", "warrior", 0.2F, true);
|
||||
mesh.position.set(0.00F, 40.00F, 0.00F);
|
||||
mesh.rotation.x = -1.566F;
|
||||
mesh.rotation.z = 1.566F;
|
||||
mesh.shouldBeBackfaceCulled = false;
|
||||
mesh.shouldBeFrustumCulled = false;
|
||||
mesh.setAnimSpeed(0.17F);
|
||||
mesh.playAnimation(0, 0);
|
||||
|
||||
texRepo->addByMesh("meshes/player/", mesh, BMP);
|
||||
|
||||
walkAdpcm = audio->loadADPCM("sounds/walk.adpcm");
|
||||
jumpAdpcm = audio->loadADPCM("sounds/jump.adpcm");
|
||||
boomAdpcm = audio->loadADPCM("sounds/boom.adpcm");
|
||||
audio->setADPCMVolume(70, 0);
|
||||
|
||||
this->mesh.setAnimSpeed(0.2F);
|
||||
this->mesh.playAnimation(0, 24);
|
||||
PRINT_LOG("Player object created!");
|
||||
}
|
||||
|
||||
@@ -45,139 +64,167 @@ Player::~Player()
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
/** Update player position and control gravity */
|
||||
void Player::update(Pad &pad, Camera &camera, FloorManager &floorManager)
|
||||
void Player::update(const Pad &t_pad, const Camera &t_camera, const FloorManager &floorManager, Enemy &enemy)
|
||||
{
|
||||
this->updatePosition(pad, camera, floorManager);
|
||||
this->updateGravity(pad, floorManager);
|
||||
if (mesh.position.y < -60.0F)
|
||||
Vector3 *nextPos = getNextPosition(t_pad, t_camera);
|
||||
FloorsCheck *floorsCheck = checkFloors(floorManager, *nextPos);
|
||||
if (floorsCheck->currentFloor != NULL)
|
||||
indexOfCurrentFloor = floorsCheck->currentFloor->initOffset;
|
||||
updatePosition(t_pad, t_camera, floorManager, *floorsCheck, *nextPos, enemy);
|
||||
updateGravity(floorsCheck);
|
||||
delete floorsCheck;
|
||||
delete nextPos;
|
||||
}
|
||||
|
||||
Vector3 *Player::getNextPosition(const Pad &t_pad, const Camera &t_camera)
|
||||
{
|
||||
mesh.position.y = 60.0F;
|
||||
velocity = 0;
|
||||
Vector3 *result = new Vector3(mesh.position);
|
||||
Vector3 normalizedCamera = Vector3(t_camera.unitCirclePosition);
|
||||
normalizedCamera.normalize();
|
||||
normalizedCamera *= speed;
|
||||
if (t_pad.lJoyV <= 100)
|
||||
{
|
||||
result->x += -normalizedCamera.x;
|
||||
result->z += -normalizedCamera.z;
|
||||
}
|
||||
else if (t_pad.lJoyV >= 200)
|
||||
{
|
||||
result->x += normalizedCamera.x;
|
||||
result->z += normalizedCamera.z;
|
||||
}
|
||||
if (t_pad.lJoyH <= 100)
|
||||
{
|
||||
result->x += -normalizedCamera.z;
|
||||
result->z += normalizedCamera.x;
|
||||
}
|
||||
else if (t_pad.lJoyH >= 200)
|
||||
{
|
||||
result->x += normalizedCamera.z;
|
||||
result->z += -normalizedCamera.x;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Player::updatePosition(const Pad &t_pad, const Camera &t_camera, const FloorManager &t_floorManager, const FloorsCheck &t_floorsCheck, const Vector3 &t_nextPos, Enemy &enemy)
|
||||
{
|
||||
if (t_pad.rJoyH >= 200)
|
||||
mesh.rotation.z += 0.08;
|
||||
else if (t_pad.rJoyH <= 100)
|
||||
mesh.rotation.z -= 0.08;
|
||||
|
||||
isWalking = mesh.position.x != t_nextPos.x || mesh.position.z != t_nextPos.z;
|
||||
isFighting = isFighting || t_pad.isCircleClicked;
|
||||
|
||||
if (isFighting)
|
||||
{
|
||||
if (!isFightingAnimationSet)
|
||||
{
|
||||
isFightingAnimationSet = true;
|
||||
mesh.playAnimation(8, 19, 0);
|
||||
fightTimer.prime();
|
||||
}
|
||||
if (fightTimer.getTimeDelta() > 25000)
|
||||
{ // end of fighting
|
||||
float distance = getPosition().distanceTo(enemy.getPosition());
|
||||
if (16.0F > distance)
|
||||
{
|
||||
enemy.kill(*this);
|
||||
audio->playADPCM(boomAdpcm);
|
||||
speed += .5F;
|
||||
killedEnemies++;
|
||||
}
|
||||
isFightingAnimationSet = false;
|
||||
isFighting = false;
|
||||
}
|
||||
}
|
||||
else if (isWalking)
|
||||
{
|
||||
if (!isWalkingAnimationSet)
|
||||
{
|
||||
isWalkingAnimationSet = true;
|
||||
this->mesh.playAnimation(1, 8);
|
||||
}
|
||||
if (walkTimer.getTimeDelta() > 8000)
|
||||
{
|
||||
walkTimer.prime();
|
||||
audio->playADPCM(walkAdpcm, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
isWalkingAnimationSet = false;
|
||||
mesh.playAnimation(0, 0);
|
||||
}
|
||||
|
||||
if (t_floorsCheck.willCollideFloor == NULL && !isFighting)
|
||||
{
|
||||
mesh.position.x = t_nextPos.x;
|
||||
mesh.position.z = t_nextPos.z;
|
||||
}
|
||||
|
||||
if (t_pad.isCrossClicked == 1)
|
||||
{
|
||||
velocity = lift;
|
||||
audio->playADPCM(jumpAdpcm);
|
||||
jumpCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
/** Move player when pad move buttons are pressed and is not blocked by any floor side */
|
||||
void Player::updatePosition(Pad &pad, Camera &camera, FloorManager &floorManager)
|
||||
{
|
||||
|
||||
if (pad.isDpadUpPressed == 1)
|
||||
{
|
||||
this->playerNextPosition.x = this->mesh.position.x + 0.01F * -camera.unitCirclePosition.x;
|
||||
this->playerNextPosition.z = this->mesh.position.z + 0.01F * -camera.unitCirclePosition.z;
|
||||
}
|
||||
if (pad.isDpadDownPressed == 1)
|
||||
{
|
||||
this->playerNextPosition.x = this->mesh.position.x + 0.01F * camera.unitCirclePosition.x;
|
||||
this->playerNextPosition.z = this->mesh.position.z + 0.01F * camera.unitCirclePosition.z;
|
||||
}
|
||||
if (pad.isDpadLeftPressed == 1)
|
||||
{
|
||||
this->playerNextPosition.x = this->mesh.position.x + 0.01F * -camera.unitCirclePosition.z;
|
||||
this->playerNextPosition.z = this->mesh.position.z + 0.01F * camera.unitCirclePosition.x;
|
||||
}
|
||||
if (pad.isDpadRightPressed == 1)
|
||||
{
|
||||
this->playerNextPosition.x = this->mesh.position.x + 0.01F * camera.unitCirclePosition.z;
|
||||
this->playerNextPosition.z = this->mesh.position.z + 0.01F * -camera.unitCirclePosition.x;
|
||||
}
|
||||
this->playerNextPosition.y = this->mesh.position.y;
|
||||
this->isCollideFloor = 0;
|
||||
Vector3 min = Vector3();
|
||||
Vector3 max = Vector3();
|
||||
for (u32 i = 0; i < floorManager.floorAmount; i++)
|
||||
{
|
||||
getMinMax(&floorManager.floors[i].mesh, &min, &max);
|
||||
this->isCollideFloor = this->playerNextPosition.collidesSquare(min, max);
|
||||
if (this->isCollideFloor == 1)
|
||||
break;
|
||||
}
|
||||
if (this->isCollideFloor == 0)
|
||||
{
|
||||
this->mesh.position.x = this->playerNextPosition.x;
|
||||
this->mesh.position.z = this->playerNextPosition.z;
|
||||
}
|
||||
}
|
||||
|
||||
/** Do not call this.
|
||||
/**
|
||||
* Do not call this.
|
||||
* This is called by Floor::animate() on player's floor move in Y direction
|
||||
*/
|
||||
void Player::onBeforePlayerFloorMove(Floor *floor, float &newY)
|
||||
void Player::onBeforePlayerFloorMove(Floor *t_floor, float &t_newY)
|
||||
{
|
||||
if (floor->animDirection == 0 && newY > 0.0F)
|
||||
this->mesh.position.y += newY * 1.05F;
|
||||
else if ((floor->animDirection == 1 && -newY < 0.0F))
|
||||
this->mesh.position.y -= -newY * 1.05F;
|
||||
}
|
||||
|
||||
/** Calculates minimum and maximum X, Y, Z of mesh vertices + current position */
|
||||
void Player::getMinMax(Mesh *t_mesh, Vector3 *t_min, Vector3 *t_max)
|
||||
{
|
||||
Vector3 calc = Vector3();
|
||||
u8 isInitialized = 0;
|
||||
Vector3 *boundingBox = t_mesh->getCurrentBoundingBox();
|
||||
for (u32 i = 0; i < 8; i++)
|
||||
{
|
||||
calc.set(
|
||||
boundingBox[i].x + t_mesh->position.x,
|
||||
boundingBox[i].y + t_mesh->position.y,
|
||||
boundingBox[i].z + t_mesh->position.z);
|
||||
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;
|
||||
}
|
||||
if (t_floor->animDirection == 0 && t_newY > 0.0F)
|
||||
this->mesh.position.y += t_newY * 1.05F;
|
||||
else if ((t_floor->animDirection == 1 && -t_newY < 0.0F))
|
||||
this->mesh.position.y -= -t_newY * 1.05F;
|
||||
}
|
||||
|
||||
/** Update player position by gravity and update index of current floor */
|
||||
void Player::updateGravity(Pad &pad, FloorManager &floorManager)
|
||||
void Player::updateGravity(FloorsCheck *t_floorsCheck)
|
||||
{
|
||||
Vector3 min = Vector3();
|
||||
Vector3 max = Vector3();
|
||||
|
||||
if (pad.isCrossClicked == 1)
|
||||
this->velocity = this->lift;
|
||||
|
||||
this->isOnFloor = 0;
|
||||
for (u32 i = 0; i < floorManager.floorAmount; i++)
|
||||
{
|
||||
getMinMax(&floorManager.floors[i].mesh, &min, &max);
|
||||
this->isOnFloor = this->mesh.position.isOnSquare(min, max);
|
||||
if (this->isOnFloor == 1)
|
||||
{
|
||||
this->indexOfCurrentFloor = floorManager.floors[i].initOffset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this->velocity += this->gravity;
|
||||
this->mesh.position.y -= this->velocity;
|
||||
u8 isOnFloor = t_floorsCheck->currentFloor != NULL && mesh.position.y < t_floorsCheck->currFloorMax.y;
|
||||
|
||||
if (this->mesh.position.y >= 60.0F)
|
||||
if (this->mesh.position.y >= 60.0F || mesh.position.y < -60.0F)
|
||||
{
|
||||
this->mesh.position.y = 60.0F;
|
||||
this->velocity = 0;
|
||||
}
|
||||
else if ((this->mesh.position.y) < max.y && this->isOnFloor)
|
||||
else if (isOnFloor)
|
||||
{
|
||||
this->mesh.position.y = max.y;
|
||||
this->mesh.position.y = t_floorsCheck->currFloorMax.y;
|
||||
this->velocity = 0;
|
||||
}
|
||||
}
|
||||
|
||||
FloorsCheck *Player::checkFloors(const FloorManager &t_floorManager, const Vector3 &t_nextPos)
|
||||
{
|
||||
FloorsCheck *result = new FloorsCheck;
|
||||
result->currentFloor = NULL;
|
||||
result->willCollideFloor = NULL;
|
||||
Vector3 min = Vector3();
|
||||
Vector3 max = Vector3();
|
||||
for (u32 i = 0; i < t_floorManager.floorAmount; i++)
|
||||
{
|
||||
Utils::getMinMax(t_floorManager.floors[i].mesh, min, max);
|
||||
if (result->currentFloor == NULL && this->mesh.position.isOnBox(min, max))
|
||||
{
|
||||
result->currentFloor = &t_floorManager.floors[i];
|
||||
result->currFloorMin.set(min);
|
||||
result->currFloorMax.set(max);
|
||||
}
|
||||
if (result->willCollideFloor == NULL && t_nextPos.collidesBox(min, max))
|
||||
{
|
||||
result->willCollideFloor = &t_floorManager.floors[i];
|
||||
result->willCollideFloorMin.set(min);
|
||||
result->willCollideFloorMax.set(max);
|
||||
}
|
||||
if (result->currentFloor != NULL && result->willCollideFloor != NULL)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -13,8 +13,17 @@
|
||||
|
||||
#include "../managers/floor_manager.hpp"
|
||||
#include "../camera.hpp"
|
||||
#include "./enemy.hpp"
|
||||
#include <modules/pad.hpp>
|
||||
#include <modules/timer.hpp>
|
||||
#include <tamtypes.h>
|
||||
#include <modules/audio.hpp>
|
||||
|
||||
struct FloorsCheck
|
||||
{
|
||||
const Floor *currentFloor, *willCollideFloor;
|
||||
Vector3 currFloorMin, willCollideFloorMin, currFloorMax, willCollideFloorMax;
|
||||
};
|
||||
|
||||
/** Player 3D object class */
|
||||
class Player
|
||||
@@ -22,19 +31,31 @@ class Player
|
||||
|
||||
public:
|
||||
float gravity, velocity, lift;
|
||||
u8 isOnFloor, isCollideFloor, indexOfCurrentFloor;
|
||||
Mesh mesh;
|
||||
Player();
|
||||
s16 indexOfCurrentFloor;
|
||||
Player(Audio *t_audio, TextureRepository *t_texRepo);
|
||||
~Player();
|
||||
|
||||
void update(Pad &pad, Camera &camera, FloorManager &floorManager);
|
||||
void onBeforePlayerFloorMove(Floor *floor, float &newY);
|
||||
void update(const Pad &t_pad, const Camera &t_camera, const FloorManager &t_floorManager, Enemy &enemy);
|
||||
void onBeforePlayerFloorMove(Floor *t_floor, float &t_newY);
|
||||
const inline u32 &getJumpCount() const { return jumpCounter; }
|
||||
const inline u32 &getKilledEnemiesCount() const { return killedEnemies; }
|
||||
inline const Vector3 &getPosition() const { return mesh.position; }
|
||||
|
||||
private:
|
||||
Vector3 playerNextPosition;
|
||||
void getMinMax(Mesh *t_mesh, Vector3 *t_min, Vector3 *t_max);
|
||||
void updatePosition(Pad &pad, Camera &camera, FloorManager &floorManager);
|
||||
void updateGravity(Pad &pad, FloorManager &floorManager);
|
||||
TextureRepository *texRepo;
|
||||
u32 jumpCounter, killedEnemies;
|
||||
Vector3 *getNextPosition(const Pad &t_pad, const Camera &t_camera);
|
||||
FloorsCheck *checkFloors(const FloorManager &t_floorManager, const Vector3 &t_nextPos);
|
||||
u8 isWalkingAnimationSet, isJumpingAnimationSet, isFightingAnimationSet;
|
||||
u8 isFighting, isWalking;
|
||||
Audio *audio;
|
||||
Timer walkTimer, fightTimer;
|
||||
audsrv_adpcm_t *walkAdpcm, *jumpAdpcm, *boomAdpcm;
|
||||
float speed;
|
||||
void getMinMax(const Mesh &t_mesh, Vector3 &t_min, Vector3 &t_max);
|
||||
void updatePosition(const Pad &t_pad, const Camera &t_camera, const FloorManager &t_floorManager, const FloorsCheck &t_floorsCheck, const Vector3 &nextPos, Enemy &enemy);
|
||||
void updateGravity(FloorsCheck *t_floorsCheck);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "ui.hpp"
|
||||
|
||||
#include <utils/debug.hpp>
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
Ui::Ui(TextureRepository *t_texRepo)
|
||||
{
|
||||
PRINT_LOG("Initializing ui");
|
||||
|
||||
isTask1Done = false;
|
||||
isTask2Done = false;
|
||||
|
||||
info.size.set(128.0F, 32.0F);
|
||||
info.position.set(500.0F, 430.0F);
|
||||
|
||||
reward.size.set(128.0F, 128.0F);
|
||||
reward.position.set(500.0F, 280.0F);
|
||||
reward.flipVertically(true);
|
||||
|
||||
task1.size.set(128.0F, 32.0F);
|
||||
task1.position.set(500.0F, 10.0F);
|
||||
|
||||
task2.size.set(128.0F, 32.0F);
|
||||
task2.position.set(500.0F, 50.0F);
|
||||
|
||||
task1Checkbox.size.set(32.0F, 32.0F);
|
||||
task1Checkbox.position.set(460.0F, 10.0F);
|
||||
|
||||
task2Checkbox.size.set(32.0F, 32.0F);
|
||||
task2Checkbox.position.set(460.0F, 50.0F);
|
||||
|
||||
t_texRepo->add("ui/", "reward", BMP)->addLink(reward.getId());
|
||||
t_texRepo->add("ui/", "info-text", PNG)->addLink(info.getId());
|
||||
t_texRepo->add("ui/", "check1-text", PNG)->addLink(task1.getId());
|
||||
t_texRepo->add("ui/", "check2-text", PNG)->addLink(task2.getId());
|
||||
grayCheckboxTex = t_texRepo->add("ui/", "gray-checkmark", PNG);
|
||||
blueCheckboxTex = t_texRepo->add("ui/", "blue-checkmark", PNG);
|
||||
|
||||
grayCheckboxTex->addLink(task1Checkbox.getId());
|
||||
grayCheckboxTex->addLink(task2Checkbox.getId());
|
||||
|
||||
PRINT_LOG("Ui initialized!");
|
||||
}
|
||||
|
||||
Ui::~Ui() {}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
void Ui::update(const Player &player)
|
||||
{
|
||||
if (!isTask1Done && player.getJumpCount() >= 10)
|
||||
{
|
||||
isTask1Done = true;
|
||||
grayCheckboxTex->removeLinkBySprite(task1Checkbox.getId());
|
||||
blueCheckboxTex->addLink(task1Checkbox.getId());
|
||||
}
|
||||
if (!isTask2Done && player.getKilledEnemiesCount() >= 10)
|
||||
{
|
||||
isTask2Done = true;
|
||||
grayCheckboxTex->removeLinkBySprite(task2Checkbox.getId());
|
||||
blueCheckboxTex->addLink(task2Checkbox.getId());
|
||||
}
|
||||
}
|
||||
|
||||
void Ui::render(Renderer *t_renderer)
|
||||
{
|
||||
if (isTask1Done && isTask2Done)
|
||||
t_renderer->draw(reward);
|
||||
t_renderer->draw(info);
|
||||
t_renderer->draw(task1);
|
||||
t_renderer->draw(task2);
|
||||
t_renderer->draw(task1Checkbox);
|
||||
t_renderer->draw(task2Checkbox);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _UI_
|
||||
#define _UI_
|
||||
|
||||
#include <modules/texture_repository.hpp>
|
||||
#include <modules/renderer.hpp>
|
||||
#include "objects/player.hpp"
|
||||
#include <tamtypes.h>
|
||||
|
||||
class Ui
|
||||
{
|
||||
|
||||
public:
|
||||
Ui(TextureRepository *t_texRepo);
|
||||
~Ui();
|
||||
|
||||
void update(const Player &player);
|
||||
void render(Renderer *t_renderer);
|
||||
|
||||
private:
|
||||
u8 isTask1Done, isTask2Done;
|
||||
Sprite task1, task2, task1Checkbox, task2Checkbox, info, reward;
|
||||
Texture *grayCheckboxTex, *blueCheckboxTex;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -32,3 +32,39 @@ float Utils::expoEaseInOut(float t, float b, float c, float d)
|
||||
|
||||
return c / 2 * (-powf(2, -10 * --t) + 2) + b;
|
||||
}
|
||||
|
||||
/** Calculates minimum and maximum X, Y, Z of mesh vertices + current position */
|
||||
void Utils::getMinMax(const Mesh &t_mesh, Vector3 &t_min, Vector3 &t_max)
|
||||
{
|
||||
Vector3 calc = Vector3();
|
||||
u8 isInitialized = 0;
|
||||
const Vector3 *boundingBox = t_mesh.getCurrentBoundingBoxVertices();
|
||||
for (u32 i = 0; i < 8; i++)
|
||||
{
|
||||
calc.set(
|
||||
boundingBox[i].x + t_mesh.position.x,
|
||||
boundingBox[i].y + t_mesh.position.y,
|
||||
boundingBox[i].z + t_mesh.position.z);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,12 +12,15 @@
|
||||
#define _TYRA_UTILS_
|
||||
|
||||
#include <tamtypes.h>
|
||||
#include <models/mesh.hpp>
|
||||
#include <models/math/vector3.hpp>
|
||||
|
||||
class Utils
|
||||
{
|
||||
|
||||
public:
|
||||
static float expoEaseInOut(float t, float b, float c, float d);
|
||||
static void getMinMax(const Mesh &t_mesh, Vector3 &t_min, Vector3 &t_max);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user