Merge pull request #82 from h4570/develop

Monthly release
This commit is contained in:
Sandro Sobczyński
2020-12-27 20:03:09 +01:00
committed by GitHub
80 changed files with 3099 additions and 1514 deletions
+5 -2
View File
@@ -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
+1
View File
@@ -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
+6 -5
View File
@@ -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);
+1 -1
View File
@@ -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
+1 -1
View File
@@ -17,7 +17,7 @@
struct LightBulb
{
Vector3 position;
u16 intensity;
u8 intensity;
};
#endif
+158 -13
View File
@@ -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
+82 -20
View File
@@ -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
+6 -3
View File
@@ -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
+11 -5
View File
@@ -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,
+11 -5
View File
@@ -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;
+12 -4
View File
@@ -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;
+13
View File
@@ -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();
+12 -11
View File
@@ -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;
};
+3 -2
View File
@@ -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;
+6 -5
View File
@@ -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
+5 -3
View File
@@ -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;
+6 -2
View File
@@ -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
+47 -7
View File
@@ -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();
};
+2 -1
View File
@@ -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:
+21 -6
View File
@@ -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;
};
+11 -1
View File
@@ -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();
+11 -68
View File
@@ -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);
+49
View File
@@ -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
View File
@@ -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
View File
@@ -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);
}
+1 -1
View File
@@ -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;
+7
View File
@@ -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 -3
View File
@@ -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);
}
+1
View File
@@ -24,6 +24,7 @@ Sprite::Sprite()
_flipH = false;
_flipV = false;
scale = 1.0F;
mode = MODE_REPEAT;
setDefaultColor();
setDefaultLODAndClut();
}
+9 -8
View File
@@ -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);
+4 -4
View File
@@ -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;
+15 -23
View File
@@ -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);
}
+29 -22
View File
@@ -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
View File
@@ -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);
}
}
+6 -18
View File
@@ -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()
+134 -80
View File
@@ -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);
}
+84
View File
@@ -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;
}
-154
View File
@@ -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
+153
View File
@@ -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
View File
@@ -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
;-------------------------
;-------------------------
;-------------------------
+7
View File
@@ -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
+13
View File
@@ -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
+27
View File
@@ -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
-19
View File
@@ -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
-137
View File
@@ -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;
}
}
-50
View File
@@ -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
-44
View File
@@ -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
// ----
-65
View File
@@ -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
+4 -2
View File
@@ -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
+12 -40
View File
@@ -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;
}
}
+2 -4
View File
@@ -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;
};
+299
View File
@@ -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;
}
}
+69
View File
@@ -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
+4 -3
View File
@@ -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
+30
View File
@@ -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++;
}
}
+34
View File
@@ -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
+98
View File
@@ -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;
}
+43
View File
@@ -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
+2
View File
@@ -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
+3 -17
View File
@@ -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;
}
}
-1
View File
@@ -35,7 +35,6 @@ public:
protected:
Vector3 *getPosition() { return &position; };
Vector3 *getUp() { return &up; };
ScreenSettings screen;
};
+48 -23
View File
@@ -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;
+8 -2
View File
@@ -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
+82 -15
View File
@@ -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;
}
}
+11 -2
View File
@@ -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;
}
}
+98
View File
@@ -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);
}
+46
View File
@@ -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
+7 -7
View File
@@ -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;
}
+1 -1
View File
@@ -23,7 +23,7 @@ class Floor
public:
u16 animTimer;
u8 animDirection, initOffset, isByAudioTriggered;
s16 animDirection, initOffset, isByAudioTriggered;
Mesh mesh;
Floor();
+171 -124
View File
@@ -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;
}
+29 -8
View File
@@ -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
+89
View File
@@ -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);
}
+35
View File
@@ -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
+36
View File
@@ -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;
}
}
+3
View File
@@ -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