diff --git a/CHANGELOG.MD b/CHANGELOG.MD
new file mode 100644
index 0000000..7d58e4d
--- /dev/null
+++ b/CHANGELOG.MD
@@ -0,0 +1,117 @@
+# Changelog
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## [1.31.2] - 2021-02-06
+
+### Added
+- Id to MeshFrame
+- Non textured rendering (RGBA only)
+
+### Changed
+- Moved color from mesh to mesh material.
+- OBJ Loader refactor
+- Logic of loadFrom()
+- Migrated to GCC9 (valid with latest PS2SDK)
+
+### Removed
+- Removed MeshId from TextureLink, TextureRepository
+
+## [1.29.1] - 2020-12-27
+### Added
+- Created libpacket2 in PS2SDK
+- Dolphin sample
+- 2D support (Sprite class)
+- Alpha blending (transparency)
+- PNG support
+- ADPCM support in audio class
+- AudioFinish event in audio class
+- BoundingBox class
+- A lot of useful funcs in Matrix class
+- Mock of file service
+- Array mode to draw() (highly optimized for small meshes)
+- VCLPP - Usage of VU1 Preprocessor
+
+### Changed
+- Project setup (makefile mostly)
+- Readme
+- Switched into libpacket2 in `vifsender` and `gifsender`
+- Timer class refactor
+- Engine base refactor
+- MeshTexture into Texture
+- Refactored floors sample
+- Refactored Audio class
+- Fixed Path 3 lighting
+- Refactored, optimized math classes (vector, matrix..)
+- Cleanup in camera base
+- Refactored Path 3 and Path 1 rendering
+- Synchronization functions (`renderer->waitForRender()`)
+- BMP class refactor
+- Dff Loader refactor
+- Optimized rendering data preparation
+
+### Removed
+- Ari sample
+- VU1 class
+
+## [1.1.0] - 2020-11-03
+### Added
+- A lot of useful functions to Mesh class
+- MeshFrame class
+- MeshMaterial class
+- MeshTexture class
+- TextureLink struct
+- Texture wrapping settings
+- TextureRepository class
+- PRINT_ERR()
+- Ari sample
+
+### Changed
+- Project setup (gitignore etc.)
+- Readme
+- DFF loader refactor
+- OBJ loader refactor
+- MD2 loader refactor
+- 3D data classes refactor (one interface for all)
+- Rendering refactor
+
+### Removed
+- MeshSpec class
+- Texture class
+- Md2Model class
+- ObjModel class
+- DffModel class
+
+## [1.0.0] - 2020-10-28
+### Added
+- Project setup (gitignore etc.)
+- License
+- Readme
+- BMP support
+- DFF support
+- MD2 support
+- OBJ support
+- Animation support
+- Engine base
+- AudioListener class
+- Rendering base
+- Path 1 renderer (VU1)
+- Path 3 renderer (GIF)
+- Math classes (matrix, vector, plane..)
+- Audio support (bg song only)
+- Camera base
+- Base lighting support (bugged) for Path 3
+- Pad support
+- EE Timer
+- Math class
+- String class
+- Mesh class with AABB
+- Makefile
+- Primitive floors sample
+
+[1.31.2]: https://github.com/h4570/tyra/compare/v1.29.1-alpha...v1.31.2-alpha
+[1.29.1]: https://github.com/h4570/tyra/compare/1.1.0...v1.29.1-alpha
+[1.1.0]: https://github.com/h4570/tyra/compare/1.0.0...1.1.0
+[1.0.0]: https://github.com/h4570/tyra/compare/1.0.0
diff --git a/README.MD b/README.MD
index 972e0cf..f3c2777 100644
--- a/README.MD
+++ b/README.MD
@@ -1,19 +1,22 @@
[![Contributors][contributors-shield]][contributors-url]
-[![MIT License][license-shield]][license-url]
-PS2-Scene [](https://discord.gg/7dCr6ThSN5)
+[![MIT License][license-shield]][license-url]
+[](https://discord.gg/NhhTmg3Gm5)
+[](https://discord.gg/7dCr6ThSN5)
-
+
-
Tyra alpha 1.1.0
+ Tyra - alpha 1.31.2
- Open source renderer and game engine for PS2 (PlayStation 2™).
+ Open source game engine for PlayStation 2™
- View Demo (soon) »
+ Dolphin sample »
+
+ Floors sample »
Report Bug
@@ -27,95 +30,79 @@ PS2-Scene [
* [Samples](#samples)
* [About project](#about-project)
- * [Acronyms](#acronyms)
* [Tyra features](#tyra-features)
- * [Built With](#built-with)
+ * [Branches](#branches)
* [Getting Started](#getting-started)
- * [Prerequisites](#prerequisites)
* [Installation](#installation)
+ * [Prerequisites](#prerequisites)
* [Roadmap](#roadmap)
+* [Tyra team](#tyra-team)
* [Contributing](#contributing)
* [License](#license)
-* [Contact](#contact)
+* [Built With](#built-with)
+* [Acronyms](#acronyms)
* [Thanks](#thanks)
## About The Project
-
+
### Samples
+* [Dolphin](https://github.com/h4570/tyra/tree/master/src/samples/dolphin)
* [Floors](https://github.com/h4570/tyra/tree/master/src/samples/floors)
-* [Ari (WIP)](https://github.com/h4570/tyra/tree/master/src/samples/ari)
-
-### Contributors wanted
-#### I will be grateful for any help, Discord: h4570#3402
### About project
-Goal of Tyra project is to provide simple API for PS2 (PlayStation 2™) game creation. So you can just run PS2 emulator, grab your .obj file, and put it into live in a seconds. Project is on early stage, so a lot of stuff is changing from release to release.
+Goal of Tyra project is to provide simple API for PS2 game creation, so you can just run PS2 emulator, grab .obj file, and put it into live in a seconds. Project is on alpha stage, so keep in mind that there are many things to be done and to fix.
YouTube tutorials soon!
-**Why PS2 game dev is so different?** Raw PS2 development can be a big challenge. PS2 it's pretty low-level and there are a lot of stuff that you must do from scratch.
-Tyra takes care for you, and rendering, coprocessors communication and many more low-level stuff is already done.
-
-### Acronyms
-* EE (Emotion Engine) - whole set of processors and subsystems that make up the PlayStation 2
-* GS (Graphic synthesizer) - configurable rasterizer and texture mapper. Has only 2MB~ memory for textures, but for the opposite have very high transfer rate, so you can switch textures in the blink
-* VU0 - programmable (ASM) vector processor that is accessed by inline assembly code injected into C program.
-* VU1 - programmable (ASM) vector processor, which is similar to vertex shader. Accessed via DMA.
-* IOP - I/O processor which enables access to peripheral devices, such the game controller
+**Why Tyra is needed?** Raw PS2 development can be a big challenge. PS2 it's pretty low-level and there are a lot of stuff that you must do from scratch.
+Tyra takes care for you, and rendering, coprocessors communication, synchronization and many more low-level stuff is already done.
### Tyra features
-* VU1 rendering (PATH 1), double-buffered
-* GIF rendering (PATH 3), double-buffered
+* 3D support - VU1 "Path 1 rendering"
+* 2D support - PNG & BMP
* Frustum culling, backface culling
* OpenGL adaptions: Perspective projection, lookAt camera
-* Texture support (.bmp loader)
+* Texture support - .bmp and png
* Mesh loaders: ".obj", ".dff" (RenderWare, GTA:SA) and ".md2" (Quake II)
* Threading support
-* Lighting support (now PATH3 only)
-* Animation support
-* Audio support
+* Animation support for obj and md2
+* Audio support - .wav and .adpcm
* Pad support
-* TODO: physics, ADPCM and many more!
-### Built With
-
-* [PS2SDK](https://github.com/ps2dev/ps2sdk)
+### Branches
+* Master - monthly releases - tested on PS2 & PCSX2.
+* Develop - daily builds - can be unstable.
## Getting Started
-To get a local copy up and running follow these simple steps.
-YouTube tutorials soon!
+### Installation [](https://discord.gg/NhhTmg3Gm5)
+In our Discord channel, there is detailed tutorial which will help you with setting up the all environment - starting from installing dependencies and ending on emulator setup or intellisense.
### Prerequisites
-This is an example of how to list things you need to use the software and how to install them.
+This is an example of how to list things you need to use the software.
* PS2 DEV environment - [PS2DEV](https://github.com/ps2dev/ps2dev)
-* At least #674b6f4 PS2SDK (01.12.2020) - [PS2SDK](https://github.com/ps2dev/ps2sdk)
+* At least #e8e9edb PS2SDK (06.02.2021) - [PS2SDK](https://github.com/ps2dev/ps2sdk)
* PS2 Emulator. For example [PCSX2](https://pcsx2.net/)
-### Installation
-
-1. Clone the repo
-```sh
-git clone https://github.com/h4570/tyra.git
-```
-2. Get into src folder and compile it!
-```sh
-make
-```
-
## Extra info
-* Textures can be saved using GIMP. Just replace red with green color, and when exporting select .bmp, 24bit: RGB888, without saving information about colors
+* BMP loader needs some polishing so be sure that you exporting BMP with 24bit: RGB888 and without information about colors.
* If you want to run .elf in PCSX2, be sure that you have version >=1.6 and **Host access** enabled in PCSX2 configuration file.
-* If you want to use your own .obj file, please check "triangulate faces" in blender. PS2 is supporting only trinagle primitive type.
+* If you want to use your own .obj file, please check "triangulate faces" in blender. PS2 is supporting only triangle primitive type.
## Roadmap
-### Roadmap moved to github kanban:
-[https://github.com/h4570/tyra/projects/1](https://github.com/h4570/tyra/projects/1)
+### Roadmap for next master release:
+[Next release roadmap](https://github.com/h4570/tyra/projects/4)
+## Tyra team
+
+Sandro Sobczyński - sandro.sobczynski@gmail.com
+[![LinkedIn][linkedin-shield]](https://linkedin.com/in/sandro-sobczyński-28820b15a)
+Michał Mostowik - mostek3pl@gmail.com
+[![LinkedIn][linkedin-shield]](https://www.linkedin.com/in/notfoxar)
See the [open issues](https://github.com/h4570/tyra/issues) for a list of proposed features (and known issues).
@@ -133,26 +120,38 @@ Contributions are what make the open source community such an amazing place to b
Distributed under the Apache License 2.0 License. See `LICENSE` for more information.
-## Contact
+## Built With
-Sandro Sobczyński - sandro.sobczynski@gmail.com
-[![LinkedIn][linkedin-shield]][linkedin-url]
+* [PS2SDK](https://github.com/ps2dev/ps2sdk)
+
+### Acronyms
+* EE (Emotion Engine) - whole set of processors and subsystems that make up the PlayStation 2
+* GS (Graphic synthesizer) - configurable rasterizer and texture mapper. Has only 2MB~ memory for textures, but for the opposite have very high transfer rate, so you can switch textures in the blink
+* VU0 - programmable (ASM) vector processor that is accessed by inline assembly code injected into C program.
+* VU1 - programmable (ASM) vector processor, which is similar to vertex shader. Accessed via DMA.
+* IOP - I/O processor which enables access to peripheral devices, such the game controller
## Thanks
Without these guys, everything would be harder:
-* Dr Henry Fortuna - Abertay University (code sources)
-* Lukasz D.K. (huge archive of PS2 stuff)
-* Guilherme Lampert - PlayStation London (code sources)
-* Jesper Svennevid, Daniel Collin - Microcode (openvcl, code samples)
-* Whole PS2SDK/PS2Scene team
+* Dr Henry Fortuna - for code sources
+* Rick Gaiser - for help and new GCC!
+* Lukasz D.K. - for huge archive of PS2 stuff
+* Guilherme Lampert - for code sources
+* Jesper Svennevid, Daniel Collin - for openvcl's code samples
+* Whole PS2DEV team
+* Manieq - for nice splash screens!
* And so many other guys. Thanks!
Project Link: [https://github.com/h4570/tyra](https://github.com/h4570/tyra)
+
+
+
+
+
[contributors-shield]: https://img.shields.io/github/contributors/h4570/tyra.svg?style=flat-square
[contributors-url]: https://github.com/h4570/tyra/graphs/contributors
[linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=flat-square&logo=linkedin&colorB=555
-[linkedin-url]: https://linkedin.com/in/sandro-sobczyński-28820b15a/
[license-shield]: https://img.shields.io/github/license/h4570/tyra.svg?style=flat-square
[license-url]: https://github.com/h4570/tyra/blob/master/LICENSE
diff --git a/src/engine/Makefile b/src/engine/Makefile
index 78c621f..949c572 100644
--- a/src/engine/Makefile
+++ b/src/engine/Makefile
@@ -35,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
diff --git a/src/engine/Makefile.pref b/src/engine/Makefile.pref
index 389166e..24f0306 100644
--- a/src/engine/Makefile.pref
+++ b/src/engine/Makefile.pref
@@ -1,10 +1,11 @@
-EE_LIBS := $(EE_LIBS) -ldraw -lgraph -lmath3d -lpacket -ldma -lpacket2 -lpad -laudsrv -lc -lstdc++ -lpng -lz
+EE_LIBS := $(EE_LIBS) -ldraw -lcdvd -lgraph -lmath3d -lpacket -ldma -lpacket2 -lpad -laudsrv -lc -lstdc++ -lpng -lz
EE_INCS := -I$(TYRA_DIR)/include -I$(PS2SDK)/ports/include $(EE_INCS)
EE_LDFLAGS := -L$(PS2SDK)/ports/lib -L$(TYRA_DIR) $(EE_LDFLAGS)
-EE_CFLAGS := -DHAVE_LIBPNG -DHAVE_ZLIB $(EE_CFLAGS)
-EE_CXXFLAGS := -DHAVE_LIBPNG -DHAVE_ZLIB $(EE_CXXFLAGS)
+EE_CFLAGS := -DHAVE_LIBPNG -D_XCDVD -DHAVE_ZLIB $(EE_CFLAGS)
+EE_CXXFLAGS := -DHAVE_LIBPNG -D_XCDVD -DHAVE_ZLIB $(EE_CXXFLAGS)
EE_DVP = dvp-as
EE_VCL = vcl
+EE_VCLPP = vclpp
LIB_NAME = libtyra.a
include $(PS2SDK)/samples/Makefile.pref
diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp
index 4a604ba..65a111e 100644
--- a/src/engine/engine.cpp
+++ b/src/engine/engine.cpp
@@ -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();
}
diff --git a/src/engine/include/engine.hpp b/src/engine/include/engine.hpp
index 5f10f65..17be5a8 100644
--- a/src/engine/include/engine.hpp
+++ b/src/engine/include/engine.hpp
@@ -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;
diff --git a/src/engine/include/models/bounding_box.hpp b/src/engine/include/models/bounding_box.hpp
index cab4a9b..a2f6c44 100644
--- a/src/engine/include/models/bounding_box.hpp
+++ b/src/engine/include/models/bounding_box.hpp
@@ -91,4 +91,4 @@ private:
BoundingBoxFace _bottomFace;
};
-#endif
\ No newline at end of file
+#endif
diff --git a/src/engine/include/models/math/matrix.hpp b/src/engine/include/models/math/matrix.hpp
index 5e13bd7..46b5140 100644
--- a/src/engine/include/models/math/matrix.hpp
+++ b/src/engine/include/models/math/matrix.hpp
@@ -13,79 +13,174 @@
#include "vector3.hpp"
#include "../screen_settings.hpp"
+#include
-/** 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*(const Matrix &v);
- void operator*=(const 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();
+
+ /**
+ * 1 0 0 0
+ * 0 1 0 0
+ * 0 0 1 0
+ * 0 0 0 1
+ */
inline void unit() { identity(); };
- // Translation
-
- void translate(const Vector3 &t_val);
-
- inline void translation(const Vector3 &t_val)
+ /** Translate matrix. */
+ inline void translate(const Vector3 &t_val)
{
- identity();
- translate(t_val);
- }
-
- // Rotation
-
- void rotateX(const float &t_radians);
- void rotateY(const float &t_radians);
- void rotateZ(const float &t_radians);
-
- inline void rotationX(const float &t_radians)
- {
- identity();
- rotateX(t_radians);
- }
-
- inline void rotationY(const float &t_radians)
- {
- identity();
- rotateY(t_radians);
- }
-
- inline void rotationZ(const float &t_radians)
- {
- identity();
- rotateZ(t_radians);
+ Matrix temp = Matrix(true);
+ temp.translation(t_val);
+ cross(this->data, temp.data, this->data);
}
+ /** Rotate matrix. */
inline void rotate(const Vector3 &t_val)
{
- rotateX(t_val.x);
- rotateY(t_val.y);
- rotateX(t_val.z);
+ 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);
}
- inline void rotation(const Vector3 &t_val)
+ /** Rotate matrix by X. */
+ inline void rotateX(const float &t_radians)
{
- identity();
- rotate(t_val);
+ 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);
+ }
- void setPerspective(ScreenSettings &screen);
+ /** 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
diff --git a/src/engine/include/models/math/vector3.hpp b/src/engine/include/models/math/vector3.hpp
index 641f6b1..53939af 100644
--- a/src/engine/include/models/math/vector3.hpp
+++ b/src/engine/include/models/math/vector3.hpp
@@ -12,6 +12,7 @@
#define _TYRA_VECTOR3_
#include
+#include
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,32 +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*(const float &t);
+ /** Create vector with given vector values. */
+ Vector3(const Vector3 &t_v) { set(t_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);
- Vector3 operator/(float t);
- Vector3 operator-(void);
- static u8 shouldBeBackfaceCulled(const Vector3 *t_cameraPos, const Vector3 *v0, const Vector3 *v1, const Vector3 *v2);
- u8 collidesSquare(const Vector3 &t_min, const Vector3 &t_max) const;
- u8 isOnSquare(const Vector3 &t_min, const Vector3 &t_max) const;
- float length();
- void normalize();
- void setByLerp(const Vector3 &v1, const Vector3 &v2, const float &t_interp, const float &t_scale);
- float innerProduct(Vector3 &v);
+ // ----
+ // 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);
+
+ /** 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;
- const void print() 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
diff --git a/src/engine/include/models/mesh.hpp b/src/engine/include/models/mesh.hpp
index 1f9e7ea..64983fa 100644
--- a/src/engine/include/models/mesh.hpp
+++ b/src/engine/include/models/mesh.hpp
@@ -16,7 +16,6 @@
#include "./texture.hpp"
#include "./mesh_frame.hpp"
#include
-#include
#include
#include
#include "./anim_state.hpp"
@@ -43,7 +42,6 @@ public:
* When true, mesh materials are not drawn when they are outside of view frustum.
*/
u8 shouldBeFrustumCulled;
- color_t color;
clutbuffer_t clut;
lod_t lod;
@@ -176,6 +174,8 @@ public:
void setAnimSpeed(const float &t_value) { animState.speed = t_value; }
+ const u8 &areFramesAllocated() const { return _areFramesAllocated; };
+
/**
* Check if this class loaded mesh data first.
* Meshes which use loadFrom() method have false there.
@@ -207,9 +207,8 @@ private:
AnimState animState;
MeshFrame *frames;
u32 id, framesCount;
- u8 _isMother;
+ u8 _isMother, _areFramesAllocated;
Vector3 calc3Vectors[3];
- void setDefaultColor();
void setDefaultLODAndClut();
};
diff --git a/src/engine/include/models/mesh_frame.hpp b/src/engine/include/models/mesh_frame.hpp
index cd7c299..48cc772 100644
--- a/src/engine/include/models/mesh_frame.hpp
+++ b/src/engine/include/models/mesh_frame.hpp
@@ -35,6 +35,12 @@ public:
// Getters
// ----
+ /**
+ * Auto generated unique Id.
+ * Core role of this variable is to select correct texture to draw
+ */
+ const u32 &getId() const { return id; };
+
const u32 &getVertexCount() const { return vertexCount; };
const u32 &getSTsCount() const { return stsCount; };
const u32 &getNormalsCount() const { return normalsCount; };
@@ -119,12 +125,27 @@ public:
// Other
// ----
+ /**
+ * Check if this object is mother.
+ * Mother = object loaded with loadObj(), loadDff()..
+ * Have all mother data: vertex, st, etc..
+ * Non-mother = object loaded with loadFrom().
+ * Have reference copy to mother data: vertex, st, etc..
+ *
+ * When you will destruct mother object, all vertex, st data will be deleted.
+ * When you will destruct non-mother object, all vertex, st data will be NOT deleted.
+ */
+ const u8 &isMother() const { return _isMother; };
+
const u8 &areSTsAllocated() const { return _areSTsAllocated; };
const u8 &areVerticesAllocated() const { return _areVerticesAllocated; };
const u8 &areNormalsAllocated() const { return _areNormalsAllocated; };
const u8 &areMaterialsAllocated() const { return _areMaterialsAllocated; };
const u8 &isBoundingBoxCalculated() const { return _isBoundingBoxCalculated; };
+ /** Create reference copy (non-mother) */
+ void copyFrom(MeshFrame *t_refCopy);
+
/** Set STs count and allocate memory. */
void allocateSTs(const u32 &t_val);
@@ -146,12 +167,13 @@ public:
private:
BoundingBox *boundingBoxObj;
- u8 _areSTsAllocated,
+ u8 _isMother,
+ _areSTsAllocated,
_areVerticesAllocated,
_areNormalsAllocated,
_areMaterialsAllocated,
_isBoundingBoxCalculated;
- u32 vertexCount, stsCount, normalsCount, materialsCount;
+ u32 vertexCount, stsCount, normalsCount, materialsCount, id;
MeshMaterial *materials;
Point __attribute__((aligned(16))) * sts;
Vector3 __attribute__((aligned(16))) * vertices, *normals;
diff --git a/src/engine/include/models/mesh_material.hpp b/src/engine/include/models/mesh_material.hpp
index 3ba2621..03bbeeb 100644
--- a/src/engine/include/models/mesh_material.hpp
+++ b/src/engine/include/models/mesh_material.hpp
@@ -12,6 +12,7 @@
#define _TYRA_MESH_MATERIAL_
#include
+#include
#include "bounding_box.hpp"
#include "./math/vector3.hpp"
#include "./math/plane.hpp"
@@ -29,6 +30,8 @@ public:
MeshMaterial();
~MeshMaterial();
+ color_t color;
+
// ----
// Getters
// ----
@@ -104,11 +107,43 @@ public:
/** Set material name. */
void setName(char *t_val);
+ /**
+ * Do not call this method unless you know what you do.
+ * Should be called by data loader.
+ */
+ void setSTsPresent(const u8 &b) { _areSTsPresent = b; };
+
+ /**
+ * Do not call this method unless you know what you do.
+ * Should be called by data loader.
+ */
+ void setNormalsPresent(const u8 &b) { _areNormalsPresent = b; };
+
// ----
// Other
// ----
+ const u8 &areSTsPresent() const { return _areSTsPresent; };
+
+ const u8 &areNormalsPresent() const { return _areNormalsPresent; };
+
+ /** Create reference copy (non-mother) */
+ void copyFrom(MeshMaterial *t_refCopy);
+
const u8 &isNameSet() const { return _isNameSet; };
+
+ /**
+ * Check if this object is mother.
+ * Mother = object loaded with loadObj(), loadDff()..
+ * Have all mother data: vertex faces, st faces, etc..
+ * Non-mother = object loaded with loadFrom().
+ * Have reference copy to mother data: vertex faces, st faces, etc..
+ *
+ * When you will destruct mother object, all faces data will be deleted.
+ * When you will destruct non-mother object, all faces data will be NOT deleted.
+ */
+ const u8 &isMother() const { return _isMother; };
+
const u8 &areFacesAllocated() const { return _areFacesAllocated; };
/** Set faces count and allocate memory. */
@@ -125,10 +160,16 @@ public:
u8 isInFrustum(Plane *t_frustumPlanes, const Vector3 &position);
private:
+ void setDefaultColor();
BoundingBox *boundingBoxObj;
u32 facesCount, id;
u32 *vertexFaces, *stFaces, *normalFaces;
- u8 _isNameSet, _areFacesAllocated, _isBoundingBoxCalculated;
+ u8 _isMother,
+ _isNameSet,
+ _areFacesAllocated,
+ _isBoundingBoxCalculated,
+ _areSTsPresent,
+ _areNormalsPresent;
char *name;
};
diff --git a/src/engine/include/models/render_data.hpp b/src/engine/include/models/render_data.hpp
index 4045fd8..f4a89c7 100644
--- a/src/engine/include/models/render_data.hpp
+++ b/src/engine/include/models/render_data.hpp
@@ -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;
diff --git a/src/engine/include/models/texture.hpp b/src/engine/include/models/texture.hpp
index 0b9aaaf..470c0b1 100644
--- a/src/engine/include/models/texture.hpp
+++ b/src/engine/include/models/texture.hpp
@@ -83,21 +83,18 @@ public:
/**
* Returns index of link.
* -1 if not found.
+ * @param t_id
+ * For 3D: Mesh material id.
+ * For 2D: Sprite id.
*/
- const s32 getIndexOfLink(const u32 &t_meshId, const u32 &t_materialId) const
+ const s32 getIndexOfLink(const u32 &t_id) const
{
for (u32 i = 0; i < texLinks.size(); i++)
- if (texLinks[i].materialId == t_materialId && texLinks[i].meshOrSpriteId == t_meshId)
+ if (texLinks[i].id == t_id)
return i;
return -1;
};
- /**
- * Returns index of link.
- * -1 if not found.
- */
- inline const s32 getIndexOfLink(const u32 &t_spriteId) const { return getIndexOfLink(t_spriteId, 0); };
-
// ----
// Setters
// ----
@@ -144,18 +141,15 @@ public:
const u8 &isSizeSet() const { return _isSizeSet; };
- const u8 isLinkedWith(const u32 &t_meshId, const u32 &t_materialId) const
+ /**
+ * Check if texture is linked with Mesh/Sprite.
+ * @param t_id
+ * For 3D: Mesh material id.
+ * For 2D: Sprite id.
+ */
+ const u8 isLinkedWith(const u32 &t_id) const
{
- s32 index = getIndexOfLink(t_meshId, t_materialId);
- if (index != -1)
- return true;
- else
- return false;
- };
-
- const u8 isLinkedWith(const u32 &t_spriteId) const
- {
- s32 index = getIndexOfLink(t_spriteId);
+ s32 index = getIndexOfLink(t_id);
if (index != -1)
return true;
else
@@ -164,18 +158,15 @@ public:
void removeLinkByIndex(const u32 &t_index) { texLinks.erase(texLinks.begin() + t_index); }
- void removeLinkBySprite(const u32 &t_spriteId)
+ /**
+ * Remove texture link with given Mesh/Sprite.
+ * @param t_id
+ * For 3D: Mesh material id.
+ * For 2D: Sprite id.
+ */
+ void removeLinkById(const u32 &t_id)
{
- s32 index = getIndexOfLink(t_spriteId);
- if (index != -1)
- removeLinkByIndex(index);
- else
- PRINT_ERR("Cant remove link, because it was not found!");
- }
-
- void removeLinkByMesh(const u32 &t_meshId, const u32 &t_materialId)
- {
- s32 index = getIndexOfLink(t_meshId, t_materialId);
+ s32 index = getIndexOfLink(t_id);
if (index != -1)
removeLinkByIndex(index);
else
diff --git a/src/engine/include/models/texture_link.hpp b/src/engine/include/models/texture_link.hpp
index 75c24b7..687c9c0 100644
--- a/src/engine/include/models/texture_link.hpp
+++ b/src/engine/include/models/texture_link.hpp
@@ -15,10 +15,11 @@
struct TextureLink
{
- /** Mesh id or sprite id */
- u32 meshOrSpriteId;
- /** Mesh material id or 0 if is sprite */
- u32 materialId;
+ /**
+ * For 3D: Mesh material id.
+ * For 2D: Sprite id.
+ */
+ u32 id;
};
#endif
diff --git a/src/engine/include/modules/audio.hpp b/src/engine/include/modules/audio.hpp
index ea1dfe2..1899cd7 100644
--- a/src/engine/include/modules/audio.hpp
+++ b/src/engine/include/modules/audio.hpp
@@ -126,7 +126,8 @@ public:
private:
u8 songLoaded, volume, realVolume, songPlaying, songInLoop, songFinished;
- std::vector songListeners;
+ u8 hack; // TODO
+ std::vector songListeners;
FILE *wav;
audsrv_fmt_t format;
FileService *fileService;
diff --git a/src/engine/include/modules/camera_base.hpp b/src/engine/include/modules/camera_base.hpp
index 342acc7..b74ff89 100644
--- a/src/engine/include/modules/camera_base.hpp
+++ b/src/engine/include/modules/camera_base.hpp
@@ -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
diff --git a/src/engine/include/modules/gif_sender.hpp b/src/engine/include/modules/gif_sender.hpp
index 0c7646b..baeee9c 100644
--- a/src/engine/include/modules/gif_sender.hpp
+++ b/src/engine/include/modules/gif_sender.hpp
@@ -34,7 +34,7 @@ public:
~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 addObject(RenderData *t_renderData, Mesh &t_mesh, u32 vertexCount, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer, color_t *t_color);
void addClear(zbuffer_t *t_zBuffer, color_t *t_rgb);
void sendPacket();
void sendClear(zbuffer_t *t_zBuffer, color_t *t_rgb);
@@ -54,7 +54,7 @@ private:
float halfScreenW, halfScreenH;
MATRIX localWorld, localScreen, localLight;
- void calc3DObject(Matrix t_perspective, Mesh &t_mesh, u32 vertexCount, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, RenderData *t_renderData, LightBulb *t_bulbs, u16 t_bulbsCount);
+ void calc3DObject(Matrix t_perspective, Mesh &t_mesh, u32 vertexCount, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, RenderData *t_renderData, LightBulb *t_bulbs, u16 t_bulbsCount, color_t *t_color);
void convertCalcs(u32 t_vertCount, VECTOR *t_vertices, VECTOR *t_colors, VECTOR *t_sts, color_t &t_color);
void addCurrentCalcs(u32 &t_vertexCount);
};
diff --git a/src/engine/include/modules/renderer.hpp b/src/engine/include/modules/renderer.hpp
index d2cdb76..9066081 100644
--- a/src/engine/include/modules/renderer.hpp
+++ b/src/engine/include/modules/renderer.hpp
@@ -13,6 +13,8 @@
#include
#include
+#include
+#include
#include
#include "gif_sender.hpp"
#include "vif_sender.hpp"
@@ -39,60 +41,87 @@ 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 many meshes with lighting information.
- * Slowest way of rendering (PATH 3, using EE and GIF).
- * NOTICE: Animation supported, lighting supported
- */
- void drawByPath3(Mesh *t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount);
+ /// --- OBSOLETE
- /**
- * Draw mesh with lighting information.
- * Slowest way of rendering (PATH 3, using EE and GIF).
- * NOTICE: Animation supported, lighting supported
- */
- void drawByPath3(Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount);
+ // /**
+ // * 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
+ // */
+ // void drawByPath3(Mesh *t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount);
- /**
- * Draw many meshes without lighting information.
- * Slowest way of rendering (PATH 3, using EE and GIF).
- * NOTICE: Animation supported, lighting supported
- */
- void drawByPath3(Mesh *t_meshes, u16 t_amount);
+ // /**
+ // * 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
+ // */
+ // void drawByPath3(Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount);
- /**
- * Draw mesh without lighting information.
- * Slowest way of rendering (PATH 3, using EE and GIF).
- * NOTICE: Animation supported, lighting supported
- */
- void drawByPath3(Mesh &t_mesh);
+ // /**
+ // * 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
+ // */
+ // 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
+ // */
+ // void drawByPath3(Mesh &t_mesh);
/// --- Draw: PATH1
/**
- * Draw many meshes with lighting information.
+ * 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.
- * Fastest way of rendering (PATH 1, using VU1).
+ * Draw mesh with lighting information.
+ * Fastest way of rendering (PATH 1, using VU1).
* NOTICE: Animation supported, lighting NOT supported (at this moment)
*/
void draw(Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount);
/**
- * Draw many meshes without lighting information.
- * Fastest way of rendering (PATH 1, using VU1).
+ * 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.
@@ -125,7 +154,7 @@ private:
void flipBuffers();
void beginFrameIfNeeded();
u8 isFrameEmpty;
- Matrix perspective;
+ Matrix perspective, camRotation;
Light light;
RenderData renderData;
TextureRepository textureRepo;
@@ -134,8 +163,8 @@ private:
VifSender *vifSender;
packet2_t *flipPacket;
color_t worldColor;
- void allocateBuffers(float t_screenW, float t_screenH);
- void initDrawingEnv(float t_screenW, float t_screenH);
+ void allocateBuffers(int t_screenW, int t_screenH);
+ void initDrawingEnv();
void setPrim();
};
diff --git a/src/engine/include/modules/texture_repository.hpp b/src/engine/include/modules/texture_repository.hpp
index b3e29ac..67cd672 100644
--- a/src/engine/include/modules/texture_repository.hpp
+++ b/src/engine/include/modules/texture_repository.hpp
@@ -45,23 +45,14 @@ public:
/**
* Returns single texture.
* NULL if not found.
+ * @param t_id
+ * For 3D: Mesh material id.
+ * For 2D: Sprite id.
*/
- Texture *getBySprite(const u32 &t_spriteId)
+ Texture *getBySpriteOrMesh(const u32 &t_id)
{
for (u32 i = 0; i < textures.size(); i++)
- if (textures[i]->isLinkedWith(t_spriteId))
- return textures[i];
- return NULL;
- }
-
- /**
- * Returns single texture.
- * NULL if not found.
- */
- Texture *getByMesh(const u32 &t_meshId, const u32 &t_materialId)
- {
- for (u32 i = 0; i < textures.size(); i++)
- if (textures[i]->isLinkedWith(t_meshId, t_materialId))
+ if (textures[i]->isLinkedWith(t_id))
return textures[i];
return NULL;
}
diff --git a/src/engine/include/modules/vif_sender.hpp b/src/engine/include/modules/vif_sender.hpp
index a3e1e36..65020ab 100644
--- a/src/engine/include/modules/vif_sender.hpp
+++ b/src/engine/include/modules/vif_sender.hpp
@@ -29,18 +29,33 @@ public:
~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 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, color_t *t_color, u8 t_rgbaOnly);
+ 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 isLastRGBAOnly; // 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, color_t *t_color, u8 t_rgbaOnly);
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)));
VECTOR position, rotation;
u32 vertCount;
};
diff --git a/src/engine/include/utils/math.hpp b/src/engine/include/utils/math.hpp
index 3218047..5e97299 100644
--- a/src/engine/include/utils/math.hpp
+++ b/src/engine/include/utils/math.hpp
@@ -14,6 +14,7 @@
#include
#include
#include "../models/math/vector3.hpp"
+#include
class Vector3; // Forward definition
@@ -24,16 +25,15 @@ class Math
{
public:
- 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;
+ constexpr static float HALF_ANG2RAD = 3.14159265358979323846F / 360.0F;
+ constexpr static float ANG2RAD = 3.14159265358979323846F / 180.0F;
+ constexpr static float PI = 3.1415926535897932384626433832795F;
+ constexpr 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; }
diff --git a/src/engine/loaders/dff_loader.cpp b/src/engine/loaders/dff_loader.cpp
index abddbcd..23f73d7 100644
--- a/src/engine/loaders/dff_loader.cpp
+++ b/src/engine/loaders/dff_loader.cpp
@@ -244,6 +244,8 @@ void DffLoader::readGeometryExtension(MeshFrame *o_frame, char **materialNames,
{
u32 facesCount = readDwordFromArrayLE(t_buffer, t_ptrPos);
u32 materialIndex = readDwordFromArrayLE(t_buffer, t_ptrPos);
+ o_frame->getMaterial(i).setSTsPresent(true);
+ o_frame->getMaterial(i).setNormalsPresent(true);
o_frame->getMaterial(i).allocateFaces(facesCount);
o_frame->getMaterial(i).setName(materialNames[materialIndex]);
for (u32 j = 0; j < facesCount; j++)
diff --git a/src/engine/loaders/md2_loader.cpp b/src/engine/loaders/md2_loader.cpp
index d7a8924..d459c00 100644
--- a/src/engine/loaders/md2_loader.cpp
+++ b/src/engine/loaders/md2_loader.cpp
@@ -138,6 +138,8 @@ MeshFrame *MD2Loader::load(u32 &o_framesCount, char *t_subpath, char *t_nameWith
{
for (u32 x = 0; x < framesCount; x++)
{
+ resultFrames[x].getMaterial(0).setSTsPresent(true);
+ resultFrames[x].getMaterial(0).setNormalsPresent(true);
resultFrames[x].getMaterial(0).setVertexFace((i * 3) + j, triangle->index_xyz[j]);
resultFrames[x].getMaterial(0).setSTFace((i * 3) + j, triangle->index_st[j]);
resultFrames[x].getMaterial(0).setNormalFace((i * 3) + j, triangle->index_xyz[j]);
diff --git a/src/engine/loaders/obj_loader.cpp b/src/engine/loaders/obj_loader.cpp
index a200589..7c7662d 100644
--- a/src/engine/loaders/obj_loader.cpp
+++ b/src/engine/loaders/obj_loader.cpp
@@ -36,6 +36,8 @@ void ObjLoader::load(MeshFrame *o_result, char *t_filename, float t_scale, u8 t_
fseek(file, 0, SEEK_SET);
u32 verticesI = 0, cordsI = 0, normalsI = 0, faceI = 0, vertexIndex[3], coordIndex[3], normalIndex[3];
s16 materialsI = -1;
+ Vector3 vector = Vector3();
+ Point point = Point();
while (1)
{
char lineHeader[128]; // read the first word of the line
@@ -44,13 +46,11 @@ void ObjLoader::load(MeshFrame *o_result, char *t_filename, float t_scale, u8 t_
{
if (strcmp(lineHeader, "v") == 0)
{
- Vector3 vector = Vector3();
fscanf(file, "%f %f %f\n", &vector.x, &vector.y, &vector.z);
o_result->setVertex(verticesI++, vector * t_scale);
}
else if (strcmp(lineHeader, "vt") == 0)
{
- Point point = Point();
fscanf(file, "%f %f\n", &point.x, &point.y);
if (t_invertT)
point.y = 1.0F - point.y;
@@ -58,7 +58,6 @@ void ObjLoader::load(MeshFrame *o_result, char *t_filename, float t_scale, u8 t_
}
else if (strcmp(lineHeader, "vn") == 0)
{
- Vector3 vector = Vector3();
fscanf(file, "%f %f %f\n", &vector.x, &vector.y, &vector.z);
o_result->setNormal(normalsI++, vector);
}
@@ -71,32 +70,117 @@ void ObjLoader::load(MeshFrame *o_result, char *t_filename, float t_scale, u8 t_
}
else if (strcmp(lineHeader, "f") == 0)
{
- int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n",
- &vertexIndex[0], &coordIndex[0], &normalIndex[0],
- &vertexIndex[1], &coordIndex[1], &normalIndex[1],
- &vertexIndex[2], &coordIndex[2], &normalIndex[2]);
- if (matches != 9)
- PRINT_ERR(".obj can't be read by this simple parser. Try exporting with other options");
- else
+ int *x = &res; // random assignment, to disable compilation warning
+ fpos_t start;
+ fgetpos(file, &start);
+ int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", x, x, x, x, x, x, x, x, x);
+ fsetpos(file, &start);
+ int newerMatches = 0;
+
+ switch (matches)
+ {
+ /** Vs, VTs and VNs all set */
+ case 9:
+ {
+ fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n",
+ &vertexIndex[0], &coordIndex[0], &normalIndex[0],
+ &vertexIndex[1], &coordIndex[1], &normalIndex[1],
+ &vertexIndex[2], &coordIndex[2], &normalIndex[2]);
+ }
+ break;
+ /** Loaded only two digits (V, VT) succesfuly. Not setting VN. */
+ case 2:
+ {
+ fscanf(file, "%d/%d/ %d/%d/ %d/%d/\n",
+ &vertexIndex[0], &coordIndex[0],
+ &vertexIndex[1], &coordIndex[1],
+ &vertexIndex[2], &coordIndex[2]);
+ }
+ break;
+ /** Only V set. Checking for existance of VT or VN. */
+ case 1:
+ {
+ /** Check for existance of V/// configuration.. */
+ newerMatches = fscanf(file, "%d/// %d/// %d///\n", x, x, x);
+ fsetpos(file, &start);
+ if (newerMatches == 3)
+ {
+ /** Configuration confirmed. */
+ fscanf(file, "%d/// %d/// %d///\n", &vertexIndex[0], &vertexIndex[1], &vertexIndex[2]);
+ }
+ else
+ {
+ /** Failed, checking configuration V//VN */
+ newerMatches = fscanf(file, "%d//%d %d//%d %d//%d", x, x, x, x, x, x);
+ fsetpos(file, &start);
+ if (newerMatches == 6)
+ {
+ /** Configuration confirmed. */
+ newerMatches = fscanf(file, "%d//%d %d//%d %d//%d",
+ &vertexIndex[0], &normalIndex[0],
+ &vertexIndex[1], &normalIndex[1],
+ &vertexIndex[2], &normalIndex[2]);
+ }
+ else
+ {
+ /**Unknown configuration.*/
+ PRINT_ERR("Unknown .obj face for .obj file!");
+ }
+ }
+ break;
+ }
+ default:
+ PRINT_ERR("Unknown faces format in .obj file!");
+ break;
+ }
+
+ if (matches == 9 || matches == 2 || matches == 1)
{
o_result->getMaterial(materialsI).setVertexFace(faceI, vertexIndex[0] - 1);
o_result->getMaterial(materialsI).setVertexFace(faceI + 1, vertexIndex[1] - 1);
o_result->getMaterial(materialsI).setVertexFace(faceI + 2, vertexIndex[2] - 1);
-
+ }
+ if (matches == 9 || matches == 2)
+ {
o_result->getMaterial(materialsI).setSTFace(faceI, coordIndex[0] - 1);
o_result->getMaterial(materialsI).setSTFace(faceI + 1, coordIndex[1] - 1);
o_result->getMaterial(materialsI).setSTFace(faceI + 2, coordIndex[2] - 1);
+ o_result->getMaterial(materialsI).setSTsPresent(true);
+ }
+ if (matches == 9)
+ {
o_result->getMaterial(materialsI).setNormalFace(faceI, normalIndex[0] - 1);
o_result->getMaterial(materialsI).setNormalFace(faceI + 1, normalIndex[1] - 1);
o_result->getMaterial(materialsI).setNormalFace(faceI + 2, normalIndex[2] - 1);
+ o_result->getMaterial(materialsI).setNormalsPresent(true);
faceI += 3;
}
+ else if (matches == 2)
+ {
+ faceI += 2;
+ }
+ else if (matches == 1)
+ {
+ if (newerMatches == 3)
+ {
+ faceI += 1;
+ }
+ else if (newerMatches == 6)
+ {
+ o_result->getMaterial(materialsI).setNormalFace(faceI, normalIndex[0] - 1);
+ o_result->getMaterial(materialsI).setNormalFace(faceI + 1, normalIndex[1] - 1);
+ o_result->getMaterial(materialsI).setNormalFace(faceI + 2, normalIndex[2] - 1);
+ o_result->getMaterial(materialsI).setNormalsPresent(true);
+ faceI += 2;
+ }
+ }
}
}
else
break;
}
+
o_result->calculateBoundingBoxes();
fclose(file);
delete[] path;
diff --git a/src/engine/loaders/png_loader.cpp b/src/engine/loaders/png_loader.cpp
index bc46b9f..402800c 100644
--- a/src/engine/loaders/png_loader.cpp
+++ b/src/engine/loaders/png_loader.cpp
@@ -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);
- png_byte *row_pointers[height];
+ 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];
- for (row = 0; row < height; row++)
- row_pointers[row] = new png_byte[row_bytes];
+ png_read_image(png_ptr, row_pointers);
- png_read_image(png_ptr, row_pointers);
+ u32 x = 0;
- struct pixel
+ for (i = 0; i < height; i++)
+ for (j = 0; j < width; j++)
{
- 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, 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]);
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]);
+ else if (type == TEX_TYPE_RGB)
x += 3;
- }
}
- for (row = 0; row < height; row++)
- delete row_pointers[row];
- }
- else
- {
- printf("This texture depth is not supported yet!\n");
- return;
- }
+ for (row = 0; row < height; row++)
+ 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);
diff --git a/src/engine/models/bounding_box.cpp b/src/engine/models/bounding_box.cpp
index dc90364..2b22fc9 100644
--- a/src/engine/models/bounding_box.cpp
+++ b/src/engine/models/bounding_box.cpp
@@ -46,4 +46,4 @@ BoundingBox::BoundingBox(Vector3 *t_vertices)
BoundingBox::~BoundingBox()
{
-}
\ No newline at end of file
+}
diff --git a/src/engine/models/math/matrix.cpp b/src/engine/models/math/matrix.cpp
index ec927a1..c39ad20 100644
--- a/src/engine/models/math/matrix.cpp
+++ b/src/engine/models/math/matrix.cpp
@@ -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,206 +49,51 @@ 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(
- "vsub.xyzw vf4, vf0, vf0 \n\t"
- "vadd.w vf4, vf4, vf0 \n\t"
- "vmr32.xyzw vf5, vf4 \n\t"
- "vmr32.xyzw vf6, vf5 \n\t"
- "vmr32.xyzw vf7, vf6 \n\t"
- "sqc2 vf4, 0x30(%0) \n\t"
- "sqc2 vf5, 0x20(%0) \n\t"
- "sqc2 vf6, 0x10(%0) \n\t"
- "sqc2 vf7, 0x0(%0) \n\t"
+ "vsub.xyzw $vf4, $vf0, $vf0 \n\t"
+ "vadd.w $vf4, $vf4, $vf0 \n\t"
+ "vmr32.xyzw $vf5, $vf4 \n\t"
+ "vmr32.xyzw $vf6, $vf5 \n\t"
+ "vmr32.xyzw $vf7, $vf6 \n\t"
+ "sqc2 $vf4, 0x30(%0) \n\t"
+ "sqc2 $vf5, 0x20(%0) \n\t"
+ "sqc2 $vf6, 0x10(%0) \n\t"
+ "sqc2 $vf7, 0x0(%0) \n\t"
:
: "r"(this->data));
}
-void Matrix::translate(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::rotateX(const float &t_radians)
-{
- Matrix temp = Matrix();
- temp.identity();
- 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::rotateY(const float &t_radians)
-{
- Matrix temp = Matrix();
- temp.identity();
- 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::rotateZ(const float &t_radians)
-{
- Matrix temp = Matrix();
- temp.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*(const 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;
-}
-
-void Matrix::operator*=(const Matrix &t)
-{
- 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"(this->data), "r"(this->data), "r"(t.data)
- : "memory");
-}
-
-/** 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));
@@ -275,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
@@ -321,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");
+}
diff --git a/src/engine/models/math/vector3.cpp b/src/engine/models/math/vector3.cpp
index 7adafd3..6d71a91 100644
--- a/src/engine/models/math/vector3.cpp
+++ b/src/engine/models/math/vector3.cpp
@@ -9,108 +9,59 @@
*/
#include "../../include/models/math/vector3.hpp"
-
#include "../../include/utils/math.hpp"
-#include
// ----
// 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));
- 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
- "lqc2 vf4, 0x0(%1) \n\t"
- "lqc2 vf5, 0x0(%2) \n\t"
- "vadd.xyz vf6, vf4, vf5 \n\t"
- "sqc2 vf6, 0x0(%0) \n\t"
+ "lqc2 $vf4, 0x0(%1) \n\t"
+ "lqc2 $vf5, 0x0(%2) \n\t"
+ "vadd.xyz $vf6, $vf4, $vf5 \n\t"
+ "sqc2 $vf6, 0x0(%0) \n\t"
:
: "r"(result.xyz), "r"(this->xyz), "r"(v.xyz));
return result;
}
-Vector3 Vector3::operator-(const Vector3 &v)
+Vector3 Vector3::operator-(const Vector3 &v) const
{
Vector3 result;
asm volatile( // VU0 Macro program
- "lqc2 vf4, 0x0(%1) \n\t"
- "lqc2 vf5, 0x0(%2) \n\t"
- "vsub.xyz vf6, vf4, vf5 \n\t"
- "sqc2 vf6, 0x0(%0) \n\t"
+ "lqc2 $vf4, 0x0(%1) \n\t"
+ "lqc2 $vf5, 0x0(%2) \n\t"
+ "vsub.xyz $vf6, $vf4, $vf5 \n\t"
+ "sqc2 $vf6, 0x0(%0) \n\t"
:
: "r"(result.xyz), "r"(this->xyz), "r"(v.xyz));
return result;
}
-Vector3 Vector3::operator-(void)
-{
- Vector3 result;
- result.x = -x;
- result.y = -y;
- result.z = -z;
- return result;
-}
-
-/** Also called "cross product" */
-Vector3 Vector3::operator*(Vector3 &v)
+Vector3 Vector3::operator*(const Vector3 &v) const
{
Vector3 res;
- asm volatile( // VU0 Macro program
- "lqc2 vf4, 0x0(%1) \n\t" // vf4 = this
- "lqc2 vf5, 0x0(%2) \n\t" // vf5 = v
- "vopmula.xyz ACC, vf4, vf5 \n\t"
- "vopmsub.xyz vf8, vf5, vf4 \n\t"
- "vsub.w vf8, vf00, vf00 \n\t"
- "sqc2 vf8, 0x0(%0) \n\t" // vf8 = res
+ asm volatile( // VU0 Macro program
+ "lqc2 $vf4, 0x0(%1) \n\t" // $vf4 = this
+ "lqc2 $vf5, 0x0(%2) \n\t" // $vf5 = v
+ "vopmula.xyz $ACC, $vf4, $vf5 \n\t"
+ "vopmsub.xyz $vf8, $vf5, $vf4 \n\t"
+ "vsub.w $vf8, $vf0, $vf0 \n\t"
+ "sqc2 $vf8, 0x0(%0) \n\t" // $vf8 = res
:
: "r"(res.xyz), "r"(this->xyz), "r"(v.xyz));
// result.x = y * v.z - z * v.y;
@@ -119,33 +70,21 @@ Vector3 Vector3::operator*(Vector3 &v)
return res;
}
-Vector3 Vector3::operator*(const float &t)
+Vector3 Vector3::operator*(const float &t) const
{
Vector3 result;
asm volatile(
- "lqc2 vf4, 0x0(%1) \n\t"
+ "lqc2 $vf4, 0x0(%1) \n\t"
"mfc1 $8, %2 \n\t"
- "qmtc2 $8, vf5 \n\t"
- "vmulx.xyz vf6, vf4, vf5 \n\t"
- "sqc2 vf6, 0x0(%0) \n\t"
+ "qmtc2 $8, $vf5 \n\t"
+ "vmulx.xyz $vf6, $vf4, $vf5 \n\t"
+ "sqc2 $vf6, 0x0(%0) \n\t"
:
: "r"(result.xyz), "r"(this->xyz), "f"(t));
return result;
}
-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));
-}
-
-Vector3 Vector3::operator/(float t)
+Vector3 Vector3::operator/(const float &t) const
{
Vector3 result;
result.x = x / t;
@@ -154,54 +93,78 @@ 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)
{
- register float dot;
- asm volatile(
- "lqc2 vf4, 0x0(%1) \n\t" // vf4 = cameraPos
- "lqc2 vf5, 0x0(%2) \n\t" // vf5 = v0
- "lqc2 vf6, 0x0(%3) \n\t" // vf6 = v1
- "lqc2 vf7, 0x0(%4) \n\t" // vf7 = v2
- "vsub.xyz vf8, vf7, vf5 \n\t" // vf8 = vf7(v2) - vf5(v0)
- "vsub.xyz vf9, vf6, vf5 \n\t" // vf9 = vf6(v1) - vf5(v0)
- "vopmula.xyz ACC, vf8, vf9 \n\t" // vf6 = cross(vf8, vf9)
- "vopmsub.xyz vf6, vf9, vf8 \n\t"
- "vsub.w vf6, vf6, vf6 \n\t"
- "vsub.xyz vf7, vf5, vf4 \n\t" // vf7 = vf5(v0) - vf4(cameraPos)
- "vmul.xyz vf5, vf7, vf6 \n\t" // vf5 = dot(vf7, vf6)
- "vaddy.x vf5, vf5, vf5 \n\t"
- "vaddz.x vf5, vf5, vf5 \n\t"
- "qmfc2 $2, vf5 \n\t" // store result on `dot` variable
- "mtc1 $2, %0 \n\t"
- : "=f"(dot)
- : "r"(t_cameraPos->xyz), "r"(v0->xyz), "r"(v1->xyz), "r"(v2->xyz));
- return dot <= 0.0F;
-}
-
-/** Checks intersection with given square */
-u8 Vector3::collidesSquare(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 is this vector is on given square */
-u8 Vector3::isOnSquare(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;
-}
-
-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"
+ "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"
+ "vaddq.x $vf8, $vf0, $Q \n\t"
+ "qmfc2 $2, $vf8 \n\t"
"mtc1 $2, %0 \n\t"
: "=f"(result)
: "r"(this->xyz));
@@ -212,114 +175,35 @@ float Vector3::length()
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"
+ "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"
+ "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"
+ "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));
- 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"
- :
- : "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));
-}
-
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"
+ "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"
+ "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));
@@ -329,7 +213,42 @@ float Vector3::distanceTo(const Vector3 &v) const
// (this->z - v.z) * (this->z - v.z));
}
-const void Vector3::print() const
+u8 Vector3::shouldBeBackfaceCulled(const Vector3 *t_cameraPos, const Vector3 *t_v0, const Vector3 *t_v1, const Vector3 *t_v2)
{
- printf("Vector3(%f, %f, %f)\n", x, y, z);
+ register float dot;
+ asm volatile(
+ "lqc2 $vf4, 0x0(%1) \n\t" // $vf4 = cameraPos
+ "lqc2 $vf5, 0x0(%2) \n\t" // $vf5 = v0
+ "lqc2 $vf6, 0x0(%3) \n\t" // $vf6 = v1
+ "lqc2 $vf7, 0x0(%4) \n\t" // $vf7 = v2
+ "vsub.xyz $vf8, $vf7, $vf5 \n\t" // $vf8 = $vf7(v2) - $vf5(v0)
+ "vsub.xyz $vf9, $vf6, $vf5 \n\t" // $vf9 = $vf6(v1) - $vf5(v0)
+ "vopmula.xyz $ACC, $vf8, $vf9 \n\t" // $vf6 = cross($vf8, $vf9)
+ "vopmsub.xyz $vf6, $vf9, $vf8 \n\t"
+ "vsub.w $vf6, $vf6, $vf6 \n\t"
+ "vsub.xyz $vf7, $vf5, $vf4 \n\t" // $vf7 = $vf5(v0) - $vf4(cameraPos)
+ "vmul.xyz $vf5, $vf7, $vf6 \n\t" // $vf5 = dot($vf7, $vf6)
+ "vaddy.x $vf5, $vf5, $vf5 \n\t"
+ "vaddz.x $vf5, $vf5, $vf5 \n\t"
+ "qmfc2 $2, $vf5 \n\t" // store result on `dot` variable
+ "mtc1 $2, %0 \n\t"
+ : "=f"(dot)
+ : "r"(t_cameraPos->xyz), "r"(t_v0->xyz), "r"(t_v1->xyz), "r"(t_v2->xyz));
+ return dot <= 0.0F;
+}
+
+void Vector3::setByLerp(const Vector3 &t_v1, const Vector3 &t_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"(&t_v1.xyz), "r"(&t_v2.xyz), "f"(t_interp));
+ operator*=(t_scale);
}
diff --git a/src/engine/models/mesh.cpp b/src/engine/models/mesh.cpp
index 5a47159..e4dd355 100644
--- a/src/engine/models/mesh.cpp
+++ b/src/engine/models/mesh.cpp
@@ -28,6 +28,7 @@ Mesh::Mesh()
shouldBeFrustumCulled = true;
shouldBeBackfaceCulled = false;
shouldBeLighted = false;
+ _areFramesAllocated = false;
_isMother = false;
scale = 1.0F;
framesCount = 0;
@@ -40,13 +41,12 @@ Mesh::Mesh()
animState.isStayFrameSet = false;
animState.nextFrame = 0;
animState.speed = 0.1F;
- setDefaultColor();
setDefaultLODAndClut();
}
Mesh::~Mesh()
{
- if (_isMother)
+ if (_areFramesAllocated)
delete[] frames;
}
@@ -59,6 +59,7 @@ void Mesh::loadObj(char *t_subfolder, char *t_objFile, const float &t_scale, con
ObjLoader loader = ObjLoader();
framesCount = 1;
frames = new MeshFrame[framesCount];
+ _areFramesAllocated = true;
char *part1 = String::createConcatenated(t_subfolder, t_objFile); // "folder/object"
char *finalPath = String::createConcatenated(part1, ".obj"); // "folder/object.obj"
loader.load(&frames[0], finalPath, t_scale, t_invertT);
@@ -78,6 +79,7 @@ void Mesh::loadObj(char *t_subfolder, char *t_objFile, const float &t_scale, con
ObjLoader loader = ObjLoader();
framesCount = t_framesCount;
frames = new MeshFrame[framesCount];
+ _areFramesAllocated = true;
char *part1 = String::createConcatenated(t_subfolder, t_objFile); // "folder/object"
char *part2 = String::createConcatenated(part1, "_"); // "folder/object_"
for (u32 i = 0; i < framesCount; i++)
@@ -105,6 +107,7 @@ void Mesh::loadDff(char *t_subfolder, char *t_dffFile, const float &t_scale, con
char *dffPath = String::createConcatenated(part1, ".dff");
framesCount = 1;
frames = new MeshFrame[1];
+ _areFramesAllocated = true;
loader.load(frames, dffPath, t_scale, t_invertT);
delete[] part1;
delete[] dffPath;
@@ -120,8 +123,11 @@ void Mesh::loadMD2(char *t_subfolder, char *t_md2File, const float &t_scale, con
void Mesh::loadFrom(const Mesh &t_mesh)
{
- frames = t_mesh.frames;
framesCount = t_mesh.framesCount;
+ frames = new MeshFrame[framesCount];
+ _areFramesAllocated = true;
+ for (u32 i = 0; i < framesCount; i++)
+ frames[i].copyFrom(&t_mesh.getFrame(i));
}
void Mesh::playAnimation(const u32 &t_startFrame, const u32 &t_endFrame)
@@ -189,7 +195,7 @@ u32 Mesh::getDrawData(u32 t_materialIndex, VECTOR *o_vertices, VECTOR *o_normals
asm volatile(
// VU0 macro program:
// Load vector with 1.0F values to VF21
- "lqc2 vf21, 0x0(%0) \n\t" // load "one vec"
+ "lqc2 $vf21, 0x0(%0) \n\t" // load "one vec"
:
: "r"(ONE_VEC));
@@ -215,34 +221,34 @@ u32 Mesh::getDrawData(u32 t_materialIndex, VECTOR *o_vertices, VECTOR *o_normals
// Calculate lerp() and store data into calc3Vectors
// Vertex 0
- "lqc2 vf4, 0x0(%3) \n\t" // vf4 = v1
- "lqc2 vf5, 0x0(%6) \n\t" // vf5 = v2
- "mfc1 $10, %9 \n\t" // vf6 = t
- "qmtc2 $10, 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
+ "lqc2 $vf4, 0x0(%3) \n\t" // $vf4 = v1
+ "lqc2 $vf5, 0x0(%6) \n\t" // $vf5 = v2
+ "mfc1 $10, %9 \n\t" // $vf6 = t
+ "qmtc2 $10, $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
// Vertex 1
- "lqc2 vf4, 0x0(%4) \n\t" // vf4 = v1
- "lqc2 vf5, 0x0(%7) \n\t" // vf5 = v2
- "mfc1 $10, %9 \n\t" // vf6 = t
- "qmtc2 $10, 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(%1) \n\t" // v0 = vf9
+ "lqc2 $vf4, 0x0(%4) \n\t" // $vf4 = v1
+ "lqc2 $vf5, 0x0(%7) \n\t" // $vf5 = v2
+ "mfc1 $10, %9 \n\t" // $vf6 = t
+ "qmtc2 $10, $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(%1) \n\t" // v0 = $vf9
// Vertex 2
- "lqc2 vf4, 0x0(%5) \n\t" // vf4 = v1
- "lqc2 vf5, 0x0(%8) \n\t" // vf5 = v2
- "mfc1 $10, %9 \n\t" // vf6 = t
- "qmtc2 $10, 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(%2) \n\t" // v0 = vf9
+ "lqc2 $vf4, 0x0(%5) \n\t" // $vf4 = v1
+ "lqc2 $vf5, 0x0(%8) \n\t" // $vf5 = v2
+ "mfc1 $10, %9 \n\t" // $vf6 = t
+ "qmtc2 $10, $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(%2) \n\t" // v0 = $vf9
:
: "r"(calc3Vectors[0].xyz),
@@ -262,12 +268,12 @@ u32 Mesh::getDrawData(u32 t_materialIndex, VECTOR *o_vertices, VECTOR *o_normals
asm volatile(
// VU0 macro program
// Copy 0,1,2 vertices
- "lqc2 vf1, 0x0(%3) \n\t" // load vert
- "lqc2 vf2, 0x0(%4) \n\t" // load normal
- "lqc2 vf3, 0x0(%5) \n\t" // load st
- "sqc2 vf1, 0x0(%0) \n\t" // store vert
- "sqc2 vf2, 0x0(%1) \n\t" // store normal
- "sqc2 vf3, 0x0(%2) \n\t" // store st
+ "lqc2 $vf1, 0x0(%3) \n\t" // load vert
+ "lqc2 $vf2, 0x0(%4) \n\t" // load normal
+ "lqc2 $vf3, 0x0(%5) \n\t" // load st
+ "sqc2 $vf1, 0x0(%0) \n\t" // store vert
+ "sqc2 $vf2, 0x0(%1) \n\t" // store normal
+ "sqc2 $vf3, 0x0(%2) \n\t" // store st
:
: "r"(calc3Vectors[0].xyz),
"r"(calc3Vectors[1].xyz),
@@ -286,37 +292,37 @@ u32 Mesh::getDrawData(u32 t_materialIndex, VECTOR *o_vertices, VECTOR *o_normals
// Copy data and set vert/normal "w" and st "z"+"w" to 1.0F
// Vertex 0
- "lqc2 vf1, 0x0(%3) \n\t" // load vert
- "lqc2 vf2, 0x0(%4) \n\t" // load normal
- "lqc2 vf3, 0x0(%5) \n\t" // load st
- "vadd.w vf1, vf20, vf21 \n\t" // set vert.w to 1.0F
- "vadd.w vf2, vf20, vf21 \n\t" // set normal.W to 1.0F
- "vadd.zw vf3, vf20, vf21 \n\t" // set st.zw to 1.0F
- "sqc2 vf1, 0x0(%0) \n\t" // store vert
- "sqc2 vf2, 0x0(%1) \n\t" // store normal
- "sqc2 vf3, 0x0(%2) \n\t" // store st
+ "lqc2 $vf1, 0x0(%3) \n\t" // load vert
+ "lqc2 $vf2, 0x0(%4) \n\t" // load normal
+ "lqc2 $vf3, 0x0(%5) \n\t" // load st
+ "vadd.w $vf1, $vf20, $vf21 \n\t" // set vert.w to 1.0F
+ "vadd.w $vf2, $vf20, $vf21 \n\t" // set normal.W to 1.0F
+ "vadd.zw $vf3, $vf20, $vf21 \n\t" // set st.zw to 1.0F
+ "sqc2 $vf1, 0x0(%0) \n\t" // store vert
+ "sqc2 $vf2, 0x0(%1) \n\t" // store normal
+ "sqc2 $vf3, 0x0(%2) \n\t" // store st
// Vertex 1
- "lqc2 vf1, 0x0(%9) \n\t" // load vert
- "lqc2 vf2, 0x0(%10) \n\t" // load normal
- "lqc2 vf3, 0x0(%11) \n\t" // load st
- "vadd.w vf1, vf20, vf21 \n\t" // set vert.w to 1.0F
- "vadd.w vf2, vf20, vf21 \n\t" // set normal.W to 1.0F
- "vadd.zw vf3, vf20, vf21 \n\t" // set st.zw to 1.0F
- "sqc2 vf1, 0x0(%6) \n\t" // store vert
- "sqc2 vf2, 0x0(%7) \n\t" // store normal
- "sqc2 vf3, 0x0(%8) \n\t" // store st
+ "lqc2 $vf1, 0x0(%9) \n\t" // load vert
+ "lqc2 $vf2, 0x0(%10) \n\t" // load normal
+ "lqc2 $vf3, 0x0(%11) \n\t" // load st
+ "vadd.w $vf1, $vf20, $vf21 \n\t" // set vert.w to 1.0F
+ "vadd.w $vf2, $vf20, $vf21 \n\t" // set normal.W to 1.0F
+ "vadd.zw $vf3, $vf20, $vf21 \n\t" // set st.zw to 1.0F
+ "sqc2 $vf1, 0x0(%6) \n\t" // store vert
+ "sqc2 $vf2, 0x0(%7) \n\t" // store normal
+ "sqc2 $vf3, 0x0(%8) \n\t" // store st
// Vertex 2
- "lqc2 vf1, 0x0(%15) \n\t" // load vert
- "lqc2 vf2, 0x0(%16) \n\t" // load normal
- "lqc2 vf3, 0x0(%17) \n\t" // load st
- "vadd.w vf1, vf20, vf21 \n\t" // set vert.w to 1.0F
- "vadd.w vf2, vf20, vf21 \n\t" // set normal.W to 1.0F
- "vadd.zw vf3, vf20, vf21 \n\t" // set st.zw to 1.0F
- "sqc2 vf1, 0x0(%12) \n\t" // store vert
- "sqc2 vf2, 0x0(%13) \n\t" // store normal
- "sqc2 vf3, 0x0(%14) \n\t" // store st
+ "lqc2 $vf1, 0x0(%15) \n\t" // load vert
+ "lqc2 $vf2, 0x0(%16) \n\t" // load normal
+ "lqc2 $vf3, 0x0(%17) \n\t" // load st
+ "vadd.w $vf1, $vf20, $vf21 \n\t" // set vert.w to 1.0F
+ "vadd.w $vf2, $vf20, $vf21 \n\t" // set normal.W to 1.0F
+ "vadd.zw $vf3, $vf20, $vf21 \n\t" // set st.zw to 1.0F
+ "sqc2 $vf1, 0x0(%12) \n\t" // store vert
+ "sqc2 $vf2, 0x0(%13) \n\t" // store normal
+ "sqc2 $vf3, 0x0(%14) \n\t" // store st
:
: "r"(o_vertices[addedFaces]),
@@ -375,16 +381,6 @@ u8 Mesh::isInFrustum(Plane *t_frustumPlanes)
return boxResult;
}
-/** Set's default object color + no transparency */
-void Mesh::setDefaultColor()
-{
- color.r = 0x80;
- color.g = 0x80;
- color.b = 0x80;
- color.a = 0x80;
- color.q = 1.0F;
-}
-
/** Sets texture level of details settings and CLUT settings */
void Mesh::setDefaultLODAndClut()
{
diff --git a/src/engine/models/mesh_frame.cpp b/src/engine/models/mesh_frame.cpp
index 0e224cd..4fc959f 100644
--- a/src/engine/models/mesh_frame.cpp
+++ b/src/engine/models/mesh_frame.cpp
@@ -8,6 +8,7 @@
# Sandro Sobczyński
*/
+#include
#include "../include/models/mesh_frame.hpp"
#include "../include/utils/debug.hpp"
@@ -17,6 +18,7 @@
MeshFrame::MeshFrame()
{
+ id = rand() % 1000000;
vertexCount = 0;
stsCount = 0;
normalsCount = 0;
@@ -25,19 +27,23 @@ MeshFrame::MeshFrame()
_areVerticesAllocated = false;
_areNormalsAllocated = false;
_areMaterialsAllocated = false;
+ _isMother = true;
}
MeshFrame::~MeshFrame()
{
- if (_areSTsAllocated)
- delete[] sts;
- if (_areVerticesAllocated)
- delete[] vertices;
- if (_areNormalsAllocated)
- delete[] normals;
+ if (_isMother)
+ {
+ if (_areSTsAllocated)
+ delete[] sts;
+ if (_areVerticesAllocated)
+ delete[] vertices;
+ if (_areNormalsAllocated)
+ delete[] normals;
+ delete boundingBoxObj;
+ }
if (_areMaterialsAllocated)
delete[] materials;
- delete boundingBoxObj;
}
// ----
@@ -94,14 +100,12 @@ 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!");
- return;
- }
+
for (u32 i = 0; i < materialsCount; i++)
materials->calculateBoundingBox(vertices, vertexCount);
+
float lowX, lowY, lowZ, hiX, hiY, hiZ;
lowX = hiX = vertices[0].x;
lowY = hiY = vertices[0].y;
@@ -124,6 +128,7 @@ void MeshFrame::calculateBoundingBoxes()
hiZ = vertices[i].z;
}
+ Vector3 boundingBox[8];
boundingBox[0].set(lowX, lowY, lowZ);
boundingBox[1].set(lowX, lowY, hiZ);
boundingBox[2].set(lowX, hiY, lowZ);
@@ -135,7 +140,30 @@ void MeshFrame::calculateBoundingBoxes()
boundingBox[7].set(hiX, hiY, hiZ);
_isBoundingBoxCalculated = true;
- //BoundingBox is declared on the heap to prevent any ill-formed default
- //constructor instantiated BoundingBox objects.
+ // BoundingBox is declared on the heap to prevent any ill-formed default
+ // constructor instantiated BoundingBox objects.
boundingBoxObj = new BoundingBox(boundingBox);
}
+
+void MeshFrame::copyFrom(MeshFrame *t_refCopy)
+{
+ vertexCount = t_refCopy->vertexCount;
+ stsCount = t_refCopy->stsCount;
+ normalsCount = t_refCopy->normalsCount;
+ materialsCount = t_refCopy->materialsCount;
+ materials = new MeshMaterial[materialsCount];
+ for (u32 i = 0; i < materialsCount; i++)
+ materials[i].copyFrom(&t_refCopy->materials[i]);
+ _areSTsAllocated = true;
+ _areVerticesAllocated = true;
+ _areNormalsAllocated = true;
+ _areMaterialsAllocated = true;
+ vertices = t_refCopy->vertices;
+ sts = t_refCopy->sts;
+ normals = t_refCopy->normals;
+
+ boundingBoxObj = t_refCopy->boundingBoxObj;
+ _isBoundingBoxCalculated = true;
+
+ _isMother = false;
+}
diff --git a/src/engine/models/mesh_material.cpp b/src/engine/models/mesh_material.cpp
index d6108da..b758840 100644
--- a/src/engine/models/mesh_material.cpp
+++ b/src/engine/models/mesh_material.cpp
@@ -25,18 +25,25 @@ MeshMaterial::MeshMaterial()
_isNameSet = false;
_areFacesAllocated = false;
_isBoundingBoxCalculated = false;
+ _areSTsPresent = false;
+ _areNormalsPresent = false;
+ _isMother = true;
+ setDefaultColor();
}
MeshMaterial::~MeshMaterial()
{
- if (_areFacesAllocated)
+ if (_isMother)
{
- delete[] vertexFaces;
- delete[] stFaces;
- delete[] normalFaces;
+ if (_areFacesAllocated)
+ {
+ delete[] vertexFaces;
+ delete[] stFaces;
+ delete[] normalFaces;
+ }
+ if (_isNameSet)
+ delete[] name;
}
- if (_isNameSet)
- delete[] name;
}
// ----
@@ -102,7 +109,6 @@ 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;
@@ -124,6 +130,8 @@ void MeshMaterial::calculateBoundingBox(Vector3 *t_vertices, u32 t_vertCount)
if (hiZ < t_vertices[vertexFaces[i]].z)
hiZ = t_vertices[vertexFaces[i]].z;
}
+
+ Vector3 boundingBox[8];
boundingBox[0].set(lowX, lowY, lowZ);
boundingBox[1].set(lowX, lowY, hiZ);
boundingBox[2].set(lowX, hiY, lowZ);
@@ -139,3 +147,32 @@ void MeshMaterial::calculateBoundingBox(Vector3 *t_vertices, u32 t_vertCount)
//constructor instantiated BoundingBox objects.
boundingBoxObj = new BoundingBox(boundingBox);
}
+
+void MeshMaterial::copyFrom(MeshMaterial *t_refCopy)
+{
+ _isNameSet = true;
+ name = t_refCopy->name;
+
+ _isBoundingBoxCalculated = true;
+ boundingBoxObj = t_refCopy->boundingBoxObj;
+
+ vertexFaces = t_refCopy->vertexFaces;
+ stFaces = t_refCopy->stFaces;
+ normalFaces = t_refCopy->normalFaces;
+ facesCount = t_refCopy->facesCount;
+ _areSTsPresent = t_refCopy->_areSTsPresent;
+ _areNormalsPresent = t_refCopy->_areNormalsPresent;
+ _areFacesAllocated = true;
+
+ _isMother = false;
+}
+
+/** Set's default object color + no transparency */
+void MeshMaterial::setDefaultColor()
+{
+ color.r = 0x80;
+ color.g = 0x80;
+ color.b = 0x80;
+ color.a = 0x80;
+ color.q = 1.0F;
+}
diff --git a/src/engine/models/texture.cpp b/src/engine/models/texture.cpp
index 8bfb78d..1c247b3 100644
--- a/src/engine/models/texture.cpp
+++ b/src/engine/models/texture.cpp
@@ -82,18 +82,9 @@ void Texture::setWrapSettings(const WrapSettings t_horizontal, const WrapSetting
wrapSettings.vertical = t_vertical;
}
-void Texture::addLink(const u32 &t_meshId, const u32 &t_materialId)
+void Texture::addLink(const u32 &t_id)
{
TextureLink link;
- link.materialId = t_materialId;
- link.meshOrSpriteId = t_meshId;
- texLinks.push_back(link);
-}
-
-void Texture::addLink(const u32 &t_spriteId)
-{
- TextureLink link;
- link.materialId = 0;
- link.meshOrSpriteId = t_spriteId;
+ link.id = t_id;
texLinks.push_back(link);
}
diff --git a/src/engine/modules/audio.cpp b/src/engine/modules/audio.cpp
index 2d7e836..f7b51c0 100644
--- a/src/engine/modules/audio.cpp
+++ b/src/engine/modules/audio.cpp
@@ -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;
@@ -177,6 +178,20 @@ void Audio::startThread(FileService *t_fileService)
/** Main thread loop */
void Audio::threadLoop()
{
+ // ---
+ // TODO - bug here, GCC11 is doing some optimizations and this method probably think that
+ // "songPlaying" is false + on real PS2 I see that program tries to turn on this
+ // method as rarely as possible (slow, flickering sound). On GCC 3.2.3 this one was fine lol!.
+ if (songPlaying) // HACK1 - im not proud of that
+ songPlaying = 1;
+ if (songLoaded)
+ songLoaded = 1;
+ if (hack == 1) // HACK2 - lets give some work to gcc lol
+ hack = 2;
+ else
+ hack = 1;
+ // ---
+
if (!songPlaying || !songLoaded)
return;
if (songFinished)
@@ -186,7 +201,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 +217,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);
diff --git a/src/engine/modules/camera_base.cpp b/src/engine/modules/camera_base.cpp
index 124ee77..8453012 100644
--- a/src/engine/modules/camera_base.cpp
+++ b/src/engine/modules/camera_base.cpp
@@ -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;
diff --git a/src/engine/modules/gif_sender.cpp b/src/engine/modules/gif_sender.cpp
index 08dad58..cf0eac5 100644
--- a/src/engine/modules/gif_sender.cpp
+++ b/src/engine/modules/gif_sender.cpp
@@ -130,22 +130,17 @@ void GifSender::addClear(zbuffer_t *t_zBuffer, color_t *t_rgb)
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
- */
-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)
+/** 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, color_t *t_color)
{
packet2_chain_open_cnt(currentPacket, 0, 0, 0);
packet2_update(currentPacket, draw_texture_sampling(currentPacket->next, 0, &t_mesh.lod));
packet2_update(currentPacket, draw_texturebuffer(currentPacket->next, 0, textureBuffer, &t_mesh.clut));
- packet2_update(currentPacket, draw_prim_start(currentPacket->next, 0, t_renderData->prim, &t_mesh.color));
+ packet2_update(currentPacket, draw_prim_start(currentPacket->next, 0, t_renderData->prim, t_color));
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, t_color);
addCurrentCalcs(vertexCount);
delete[] xyz;
delete[] rgbaq;
@@ -155,12 +150,9 @@ 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)
+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, color_t *t_color)
{
VECTOR *colors = new VECTOR[vertexCount];
VECTOR position, rotation;
@@ -176,7 +168,7 @@ 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)
{
@@ -195,9 +187,9 @@ void GifSender::calc3DObject(Matrix t_perspective, Mesh &t_mesh, u32 vertexCount
for (u32 i = 0; i < vertexCount; i++)
{
// Apply the light value to the colour.
- 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]);
+ colors[i][0] = (t_color->r * lights[i][0]);
+ colors[i][1] = (t_color->g * lights[i][1]);
+ colors[i][2] = (t_color->b * lights[i][2]);
vector_clamp(colors[i], colors[i], 0.00F, 1.99F);
}
@@ -209,14 +201,14 @@ void GifSender::calc3DObject(Matrix t_perspective, Mesh &t_mesh, u32 vertexCount
else
for (u32 i = 0; i < vertexCount; i++)
{
- colors[i][0] = t_mesh.color.r / 128.0F;
- colors[i][1] = t_mesh.color.g / 128.0F;
- colors[i][2] = t_mesh.color.b / 128.0F;
+ colors[i][0] = t_color->r / 128.0F;
+ colors[i][1] = t_color->g / 128.0F;
+ colors[i][2] = t_color->b / 128.0F;
}
calculate_vertices(vertices, vertexCount, vertices, localScreen);
- convertCalcs(vertexCount, vertices, colors, coordinates, t_mesh.color);
+ convertCalcs(vertexCount, vertices, colors, coordinates, *t_color);
delete[] colors;
}
diff --git a/src/engine/modules/renderer.cpp b/src/engine/modules/renderer.cpp
index 02cadff..f554b82 100644
--- a/src/engine/modules/renderer.cpp
+++ b/src/engine/modules/renderer.cpp
@@ -13,8 +13,6 @@
#include
#include
#include
-#include
-#include
#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,23 +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();
worldColor.r = 0x10;
worldColor.g = 0x10;
worldColor.b = 0x10;
- screen = t_screen;
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!");
}
@@ -104,7 +105,7 @@ void Renderer::changeTexture(Texture *t_tex)
void Renderer::draw(Sprite &t_sprite)
{
- Texture *texture = textureRepo.getBySprite(t_sprite.getId());
+ Texture *texture = textureRepo.getBySpriteOrMesh(t_sprite.getId());
texrect_t rect;
float sizeX, sizeY;
if (t_sprite.getMode() == MODE_REPEAT)
@@ -142,7 +143,7 @@ void Renderer::draw(Sprite &t_sprite)
beginFrameIfNeeded();
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();
@@ -151,7 +152,8 @@ void Renderer::draw(Sprite &t_sprite)
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);
@@ -160,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);
@@ -198,106 +200,141 @@ void Renderer::setWorldColor(const color_t &t_rgb)
}
/** Defines and allocates framebuffers and zbuffer */
-void Renderer::allocateBuffers(float t_screenW, float t_screenH)
+void Renderer::allocateBuffers(int t_screenW, int t_screenH)
{
- frameBuffers[0].width = (u16)t_screenW;
- frameBuffers[0].height = (u16)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_24;
- frameBuffers[0].address = graph_vram_allocate((u16)t_screenW, (u16)t_screenH, frameBuffers[0].psm, GRAPH_ALIGN_PAGE);
+ frameBuffers[0].psm = GS_PSM_32;
+ 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_24;
- frameBuffers[1].address = graph_vram_allocate((u16)t_screenW, (u16)t_screenH, frameBuffers[1].psm, GRAPH_ALIGN_PAGE);
+ frameBuffers[1].psm = GS_PSM_32;
+ 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_24;
- zBuffer.address = graph_vram_allocate((u16)t_screenW, (u16)t_screenH, zBuffer.zsm, GRAPH_ALIGN_PAGE);
+ 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
-void Renderer::drawByPath3(Mesh *t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount)
-{
- for (u16 i = 0; i < t_amount; i++)
- drawByPath3(t_meshes[i], t_bulbs, t_bulbsCount);
-}
+// Obsolete
+// void Renderer::drawByPath3(Mesh *t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount)
+// {
+// for (u16 i = 0; i < t_amount; i++)
+// drawByPath3(t_meshes[i], t_bulbs, t_bulbsCount);
+// }
-void Renderer::drawByPath3(Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount)
-{
- beginFrameIfNeeded();
- if (!t_mesh.isDataLoaded())
- PRINT_ERR("Can't draw, because no mesh data was loaded!");
- if (t_mesh.getCurrentAnimationFrame() != t_mesh.getNextAnimationFrame())
- t_mesh.animate();
- for (u32 i = 0; i < t_mesh.getMaterialsCount(); i++)
- {
- if (t_mesh.shouldBeFrustumCulled && !t_mesh.getMaterial(i).isInFrustum(renderData.frustumPlanes, t_mesh.position))
- return;
- Texture *tex = textureRepo.getByMesh(t_mesh.getId(), t_mesh.getMaterial(i).getId());
- changeTexture(tex);
- gifSender->initPacket(context);
- u32 vertCount = t_mesh.getMaterial(i).getFacesCount();
- VECTOR *vertices = new VECTOR[vertCount];
- VECTOR *normals = new VECTOR[vertCount];
- VECTOR *coordinates = new VECTOR[vertCount];
- vertCount = t_mesh.getDrawData(i, vertices, normals, coordinates, *renderData.cameraPosition);
- gifSender->addObject(&renderData, t_mesh, vertCount, vertices, normals, coordinates, t_bulbs, t_bulbsCount, &textureBuffer);
- gifSender->sendPacket();
- delete[] vertices;
- delete[] normals;
- delete[] coordinates;
- }
-}
+// Obsolete
+// void Renderer::drawByPath3(Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount)
+// {
+// beginFrameIfNeeded();
+// if (!t_mesh.isDataLoaded())
+// PRINT_ERR("Can't draw, because no mesh data was loaded!");
+// if (t_mesh.getCurrentAnimationFrame() != t_mesh.getNextAnimationFrame())
+// t_mesh.animate();
+// for (u32 i = 0; i < t_mesh.getMaterialsCount(); i++)
+// {
+// MeshMaterial *material = &t_mesh.getMaterial(i);
+// if (t_mesh.shouldBeFrustumCulled && !material->isInFrustum(renderData.frustumPlanes, t_mesh.position))
+// return;
+// Texture *tex = textureRepo.getBySpriteOrMesh(material->getId());
+// changeTexture(tex);
+// gifSender->initPacket(context);
+// u32 vertCount = material->getFacesCount();
+// VECTOR *vertices = new VECTOR[vertCount];
+// VECTOR *normals = new VECTOR[vertCount];
+// VECTOR *coordinates = new VECTOR[vertCount];
+// vertCount = t_mesh.getDrawData(i, vertices, normals, coordinates, *renderData.cameraPosition);
+// gifSender->addObject(&renderData, t_mesh, vertCount, vertices, normals, coordinates, t_bulbs, t_bulbsCount, &textureBuffer, &material->color);
+// gifSender->sendPacket();
+// delete[] vertices;
+// delete[] normals;
+// delete[] coordinates;
+// }
+// }
-void Renderer::drawByPath3(Mesh *t_meshes, u16 t_amount) { drawByPath3(t_meshes, t_amount, NULL, 0); }
+// Obsolete
+// void Renderer::drawByPath3(Mesh *t_meshes, u16 t_amount) { drawByPath3(t_meshes, t_amount, NULL, 0); }
-void Renderer::drawByPath3(Mesh &t_mesh) { drawByPath3(t_mesh, NULL, 0); }
+// Obsolete
+// 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)
{
- for (u16 i = 0; i < t_amount; i++)
- draw(t_meshes[i], t_bulbs, 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++)
+ 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();
for (u32 i = 0; i < t_mesh.getMaterialsCount(); i++)
{
- if (t_mesh.shouldBeFrustumCulled && !t_mesh.getMaterial(i).isInFrustum(renderData.frustumPlanes, t_mesh.position))
+ MeshMaterial *material = &t_mesh.getMaterial(i);
+ if (t_mesh.shouldBeFrustumCulled && !material->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];
- Texture *tex = textureRepo.getByMesh(t_mesh.getId(), t_mesh.getMaterial(i).getId());
+ u32 vertCount = material->getFacesCount();
+ VECTOR vertices[vertCount] __attribute__((aligned(16)));
+ VECTOR normals[vertCount] __attribute__((aligned(16)));
+ VECTOR coordinates[vertCount] __attribute__((aligned(16)));
+ Texture *tex = textureRepo.getBySpriteOrMesh(material->getId());
changeTexture(tex);
vertCount = t_mesh.getDrawData(i, vertices, normals, coordinates, rotatedCamera);
- vifSender->drawMesh(&renderData, perspective, vertCount, vertices, normals, coordinates, t_mesh, t_bulbs, t_bulbsCount, &textureBuffer);
+ vifSender->drawMesh(&renderData, perspective, vertCount, vertices, normals, coordinates, t_mesh, t_bulbs, t_bulbsCount, &textureBuffer, &material->color, !material->areSTsPresent());
}
}
-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); }
@@ -305,7 +342,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;
}
diff --git a/src/engine/modules/texture_repository.cpp b/src/engine/modules/texture_repository.cpp
index 44112be..2b4f816 100644
--- a/src/engine/modules/texture_repository.cpp
+++ b/src/engine/modules/texture_repository.cpp
@@ -57,7 +57,7 @@ void TextureRepository::addByMesh(char *t_path, Mesh &mesh, TextureFormat t_form
else
pngLoader.load(*texture, t_path, mesh.getMaterial(i).getName(), ".png");
texture->setName(mesh.getMaterial(i).getName());
- texture->addLink(mesh.getId(), mesh.getMaterial(i).getId());
+ texture->addLink(mesh.getMaterial(i).getId());
textures.push_back(texture);
}
}
diff --git a/src/engine/modules/vif_sender.cpp b/src/engine/modules/vif_sender.cpp
index 2ef738a..b078fd9 100644
--- a/src/engine/modules/vif_sender.cpp
+++ b/src/engine/modules/vif_sender.cpp
@@ -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
@@ -31,24 +33,24 @@ extern u32 VU1Draw3D_CodeEnd __attribute__((section(".vudata")));
VifSender::VifSender(Light *t_light)
{
- 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);
}
// ----
@@ -69,27 +71,19 @@ 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);
- MATRIX localWorld, localScreen;
- create_local_world(localWorld, position, rotation);
- create_local_screen(localScreen, localWorld, t_renderData.worldView->data, t_renderData.perspective->data);
- // Small undo, because im testing new matrix funcs, which are DIFFERENT than PS2SDK, so cant be used right now.
- // Matrix viewProj = Matrix();
- // viewProj.rotation(t_rotation); // model matrix
- // viewProj.translate(t_position); // model matrix
- // viewProj *= *t_renderData.worldView * *t_renderData.perspective; // viewproj = model * (view * projection)
- packet2_reset(matricesPacket, false);
- // packet2_utils_vu_add_unpack_data(matricesPacket, 0, &viewProj.data, 8, 0);
- 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)
+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, color_t *t_color, u8 t_rgbaOnly)
{
// we have to split 3D object into small parts, because of small memory of VU1
@@ -103,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, t_color, t_rgbaOnly);
if (endI == vertCount2) // if there are no more vertices to draw, break
{
i = vertCount2;
@@ -119,82 +113,138 @@ 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, color_t *t_color, u8 t_rgbaOnly)
{
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;
+ isLastRGBAOnly = t_rgbaOnly;
+ 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, t_rgbaOnly); // 0 = STQ+RGBA, 1 = RGBA
packet2_utils_gs_add_lod(currPacket, &t_mesh.lod);
- packet2_utils_gs_add_texbuff_clut(currPacket, textureBuffer, &t_mesh.clut);
- packet2_utils_gs_add_prim_giftag(currPacket, t_prim, vertCount, DRAW_STQ2_REGLIST, 3, 0);
-
- 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);
-
- // 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);
- vif_added_bytes += vertCount;
- packet2_utils_vu_add_unpack_data(currPacket, vif_added_bytes, t_coordinates + t_start, vertCount, 1);
- vif_added_bytes += vertCount;
+ packet2_utils_gs_add_texbuff_clut(currPacket, t_texBuff, &t_mesh.clut);
+ if (t_rgbaOnly)
+ packet2_utils_gs_add_prim_giftag(currPacket, t_prim, vertCount, DRAW_RGBAQ_REGLIST, 2, 0);
+ else
+ packet2_utils_gs_add_prim_giftag(currPacket, t_prim, vertCount, DRAW_STQ2_REGLIST, 3, 0);
+ packet2_add_u32(currPacket, t_color->r);
+ packet2_add_u32(currPacket, t_color->g);
+ packet2_add_u32(currPacket, t_color->b);
+ packet2_add_u32(currPacket, t_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);
+ if (!t_rgbaOnly)
+ {
+ vif_added_bytes += vertCount;
+ packet2_utils_vu_add_unpack_data(currPacket, vif_added_bytes, t_coordinates + t_start, vertCount, true);
+ }
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]->getMaterial(0).color.r);
+ packet2_add_u32(currMPacket, t_meshes[i]->getMaterial(0).color.g);
+ packet2_add_u32(currMPacket, t_meshes[i]->getMaterial(0).color.b);
+ packet2_add_u32(currMPacket, t_meshes[i]->getMaterial(0).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, isLastRGBAOnly); // 0 = STQ+RGBA, 1 = RGBA
+ }
+ 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, isLastRGBAOnly); // 0 = STQ+RGBA, 1 = RGBA
+ }
+ 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);
+}
diff --git a/src/engine/utils/math.cpp b/src/engine/utils/math.cpp
index 5c4846e..e9bd11d 100644
--- a/src/engine/utils/math.cpp
+++ b/src/engine/utils/math.cpp
@@ -11,7 +11,6 @@
#include "../include/utils/math.hpp"
#include
-#include
float Math::cos(float x)
{
@@ -72,16 +71,6 @@ float Math::cos(float x)
return r;
}
-float Math::sqrt(float x)
-{
- float r;
- __asm__ volatile(
- "sqrt.s %0, %1 \n\t"
- : "=&f"(r)
- : "f"(x));
- return r;
-}
-
float Math::invSqrt(float x) { return 1.0F / sqrt(x); }
/** Converts Vector3 to PS2SDK's Vector4 */
diff --git a/src/engine/utils/string.cpp b/src/engine/utils/string.cpp
index d928673..60381c3 100644
--- a/src/engine/utils/string.cpp
+++ b/src/engine/utils/string.cpp
@@ -11,6 +11,7 @@
#include "../include/utils/string.hpp"
#include "../include/utils/debug.hpp"
#include
+#define CHAR_BIT 8
char *String::createU32ToString(u32 a)
{
diff --git a/src/engine/vu1_progs/draw3D.vcl b/src/engine/vu1_progs/draw3D.vcl
deleted file mode 100644
index 777d84f..0000000
--- a/src/engine/vu1_progs/draw3D.vcl
+++ /dev/null
@@ -1,154 +0,0 @@
-; ______ ____ ___
-; | \/ ____| |___|
-; | | | \ | |
-;---------------------------
-; Copyright 2020, tyra - https://github.com/h4570/tyra
-; Sandro Sobczyński
-;
-;---------------------------------------------------------------
-; 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
diff --git a/src/engine/vu1_progs/draw3D.vclpp b/src/engine/vu1_progs/draw3D.vclpp
new file mode 100644
index 0000000..7cbe82a
--- /dev/null
+++ b/src/engine/vu1_progs/draw3D.vclpp
@@ -0,0 +1,190 @@
+; ______ ____ ___
+; | \/ ____| |___|
+; | | | \ | |
+;---------------------------
+; Copyright 2020, tyra - https://github.com/h4570/tyra
+; Sandro Sobczyński
+;
+;---------------------------------------------------------------
+; 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
+; - Split this program into two (RBA/STQ), so we can get better performance
+
+#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
+ilw.w rgba_only, 4(double_buffer) ; RGBA (1) or STQ+RGBA (0)
+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, prim_tag_l
+sqi gif_set_tag, (dest_address++) ;
+sqi gif_draw_finish_tag, (dest_address++) ; do draw_finish is needed
+prim_tag_l:
+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 //////////////////
+ vec1:
+ VectorLoad{ vertex, vertex_data, 0 }
+ MatrixXForm{ xformed_vertex, matrix, vertex }
+ VectorClip{ gs_vertex, xformed_vertex }
+ VectorPerspectiveDivide{ xformed_vertex }
+ VectorAddGSScales{ gs_vertex, xformed_vertex, gs_scale }
+
+ ibgtz rgba_only, vec_1_rgba
+
+ vec_1_stq_rgba:
+ VectorLoad{ stq1, stq_data, 0 }
+ VectorTexturePerspectiveCorrection{ pers_stq, stq1 }
+ VectorStore{ pers_stq, dest_address, 0 }
+ VectorStore{ rgba, dest_address, 1 }
+ VectorStore{ gs_vertex, dest_address, 2 }
+ ibeq vi00, vi00, vec2
+
+ vec_1_rgba:
+ VectorStore{ rgba, dest_address, 0 }
+ VectorStore{ gs_vertex, dest_address, 1 }
+
+ ;////////////////////////////////////////////
+
+ ;//////////////// VERTEX 2 //////////////////
+ vec2:
+ VectorLoad{ vertex, vertex_data, 1 }
+ MatrixXForm{ xformed_vertex, matrix, vertex }
+ VectorClip{ gs_vertex, xformed_vertex }
+ VectorPerspectiveDivide{ xformed_vertex }
+ VectorAddGSScales{ gs_vertex, xformed_vertex, gs_scale }
+
+ ibgtz rgba_only, vec_2_rgba
+
+ vec_2_stq_rgba:
+ VectorLoad{ stq2, stq_data, 1 }
+ VectorTexturePerspectiveCorrection{ pers_stq, stq2 }
+ VectorStore{ pers_stq, dest_address, 3 }
+ VectorStore{ rgba, dest_address, 4 }
+ VectorStore{ gs_vertex, dest_address, 5 }
+ ibeq vi00, vi00, vec3
+
+ vec_2_rgba:
+ VectorStore{ rgba, dest_address, 2 }
+ VectorStore{ gs_vertex, dest_address, 3 }
+
+ ;////////////////////////////////////////////
+
+ ;//////////////// VERTEX 3 //////////////////
+ vec3:
+ VectorLoad{ vertex, vertex_data, 2 }
+ MatrixXForm{ xformed_vertex, matrix, vertex }
+ VectorClip{ gs_vertex, xformed_vertex }
+ VectorPerspectiveDivide{ xformed_vertex }
+ VectorAddGSScales{ gs_vertex, xformed_vertex, gs_scale }
+
+ fcand vi01, 0x03FFFF
+ iaddiu new_adc_bit, vi01, 0x7FFF
+ mfir.w gs_vertex, new_adc_bit
+
+ ibgtz rgba_only, vec_3_rgba
+
+ vec_3_stq_rgba:
+ VectorLoad{ stq3, stq_data, 2 }
+ VectorTexturePerspectiveCorrection{ pers_stq, stq3 }
+ VectorStore{ pers_stq, dest_address, 6 }
+ VectorStore{ rgba, dest_address, 7 }
+ VectorStore{ gs_vertex, dest_address, 8 }
+ iaddiu dest_address, dest_address, 9 // Loop control
+ ibeq vi00, vi00, loop_ctrl
+
+ vec_3_rgba:
+ VectorStore{ rgba, dest_address, 4 }
+ VectorStore{ gs_vertex, dest_address, 5 }
+ iaddiu dest_address, dest_address, 6 // Loop control
+
+ ;////////////////////////////////////////////
+
+ ;////////////// LOOP CONTROL ////////////////
+ loop_ctrl:
+ iaddiu vertex_data, vertex_data, 3
+ iaddiu stq_data, stq_data, 3
+
+ 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
\ No newline at end of file
diff --git a/src/engine/vu1_progs/draw3D.vsm b/src/engine/vu1_progs/draw3D.vsm
index f8c1e0e..b1c0afa 100644
--- a/src/engine/vu1_progs/draw3D.vsm
+++ b/src/engine/vu1_progs/draw3D.vsm
@@ -11,63 +11,137 @@
.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 ] 27 [27 0] 27 [__v_draw3D_vcl_4]
+ NOP xtop VI06
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 lq VF01,0(VI00)
+ NOP ilw.x VI01,4(VI06)
+ NOP ilw.y VI08,4(VI06)
+ NOP lq VF03,0(VI06)
+ NOP lq VF04,1(VI06)
+ NOP lq VF08,5(VI06)
+ NOP lq VF10,6(VI06)
+ NOP lq VF05,2(VI06)
+ NOP lq VF06,3(VI06)
+ NOP iaddiu VI04,VI06,0x00000009
+ NOP iadd VI05,VI04,VI08
+ NOP ilw.z VI02,4(VI06)
+ NOP iadd VI07,VI05,VI08
+ NOP loi 0x44fff000
+ NOP ilw.w VI03,4(VI06)
+ NOP lq VF07,7(VI06)
+ NOP sqi VF02,(VI07++)
+ NOP sqi VF08,(VI07++)
+ NOP sqi VF02,(VI07++)
+ NOP lq VF08,8(VI06)
+ NOP iadd VI06,VI05,VI08
+ addi.xy VF09,VF00,I loi 0x492aaaaa
NOP fcset 0
- NOP lq.xyz VF05,0(VI02)
- NOP iadd VI04,VI03,VI07
- NOP iadd VI06,VI04,VI07
- NOP sqi VF06,(VI06++)
- NOP sqi VF09,(VI06++)
- NOP sqi VF06,(VI06++)
- NOP sqi VF08,(VI06++)
- NOP lq VF06,5(VI02)
- NOP iadd VI05,VI04,VI07
- 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
+ NOP iblez VI01,prim_tag_l
+ addi.z VF09,VF00,I sqi VF10,(VI07++)
+; _LNOPT_w=[ normal2 ] 2 [2 0] 2 [__v_draw3D_vcl_5]
+ NOP sqi VF02,(VI07++)
+ NOP sqi VF01,(VI07++)
+prim_tag_l:
+; _LNOPT_w=[ normal2 ] 4 [4 0] 4 [prim_tag_l]
+ NOP iaddiu VI08,VI00,0x00007fff
+ NOP sqi VF07,(VI07++)
+ NOP iaddiu VI08,VI08,0x00000001
+ NOP iaddiu VI09,VI00,0
+triangle_loop:
+; _LNOPT_w=[ normal2 ] 11 [27 0] 27 [triangle_loop]
+ NOP lq VF02,0(VI04)
+ mulax ACC,VF03,VF02x mfir.w VF01,VI08 ; STALL_LATENCY ?3
+ madday ACC,VF04,VF02y NOP
+ maddaz ACC,VF05,VF02z NOP
+ maddw VF02,VF06,VF02w NOP
+ clipw.xyz VF02xyz,VF02w div Q,VF00w,VF02w ; STALL_LATENCY ?3
+ mulq.xyz VF02,VF02,Q waitq ; STALL_LATENCY ?6
+ mulaw.xyz ACC,VF09,VF00w NOP
+ madd.xyz VF02,VF02,VF09 NOP ; STALL_LATENCY ?2
+ NOP ibgtz VI03,vec_1_rgba
+ ftoi4.xyz VF01,VF02 NOP ; STALL_LATENCY ?2
+; _LNOPT_w=[ normal2 ] 5 [9 0] 9 [vec_1_stq_rgba]
+ NOP lq VF02,0(VI05)
+ mulq VF01,VF02,Q sq VF01,2(VI07) ; STALL_LATENCY ?3
+ NOP sq VF08,1(VI07)
+ NOP b vec2
+ NOP sq VF01,0(VI07) ; STALL_LATENCY ?1
+vec_1_rgba:
+; _LNOPT_w=[ normal2 ] 4 [2 0] 4 [vec_1_rgba]
NOP NOP
NOP NOP
+ NOP sq VF08,0(VI07)
+ NOP sq VF01,1(VI07)
+vec2:
+; _LNOPT_w=[ normal2 ] 11 [27 0] 27 [vec2]
+ NOP lq VF02,1(VI04)
+ mulax ACC,VF03,VF02x mfir.w VF01,VI08 ; STALL_LATENCY ?3
+ madday ACC,VF04,VF02y NOP
+ maddaz ACC,VF05,VF02z NOP
+ maddw VF02,VF06,VF02w NOP
+ clipw.xyz VF02xyz,VF02w div Q,VF00w,VF02w ; STALL_LATENCY ?3
+ mulq.xyz VF02,VF02,Q waitq ; STALL_LATENCY ?6
+ mulaw.xyz ACC,VF09,VF00w NOP
+ madd.xyz VF02,VF02,VF09 NOP ; STALL_LATENCY ?2
+ NOP ibgtz VI03,vec_2_rgba
+ ftoi4.xyz VF01,VF02 NOP ; STALL_LATENCY ?2
+; _LNOPT_w=[ normal2 ] 5 [9 0] 9 [vec_2_stq_rgba]
+ NOP lq VF02,1(VI05)
+ mulq VF01,VF02,Q sq VF01,5(VI07) ; STALL_LATENCY ?3
+ NOP sq VF08,4(VI07)
+ NOP b vec3
+ NOP sq VF01,3(VI07) ; STALL_LATENCY ?1
+vec_2_rgba:
+; _LNOPT_w=[ normal2 ] 4 [2 0] 4 [vec_2_rgba]
NOP NOP
NOP NOP
+ NOP sq VF08,2(VI07)
+ NOP sq VF01,3(VI07)
+vec3:
+; _LNOPT_w=[ normal2 ] 13 [27 0] 27 [vec3]
+ NOP lq VF01,2(VI04)
+ mulax ACC,VF03,VF01x NOP ; STALL_LATENCY ?3
+ madday ACC,VF04,VF01y NOP
+ maddaz ACC,VF05,VF01z NOP
+ maddw VF01,VF06,VF01w NOP
+ clipw.xyz VF01xyz,VF01w div Q,VF00w,VF01w ; STALL_LATENCY ?3
+ mulq.xyz VF01,VF01,Q waitq ; STALL_LATENCY ?6
+ mulaw.xyz ACC,VF09,VF00w NOP
+ madd.xyz VF01,VF01,VF09 fcand VI01,262143 ; STALL_LATENCY ?2
+ NOP iaddiu VI01,VI01,0x00007fff
+ NOP mfir.w VF01,VI01
+ NOP ibgtz VI03,vec_3_rgba
+ ftoi4.xyz VF01,VF01 NOP
+; _LNOPT_w=[ normal2 ] 6 [9 0] 9 [vec_3_stq_rgba]
+ NOP lq VF02,2(VI05)
+ mulq VF01,VF02,Q sq VF01,8(VI07) ; STALL_LATENCY ?3
+ NOP sq VF08,7(VI07)
+ NOP iaddiu VI07,VI07,0x00000009
+ NOP b loop_ctrl
+ NOP sq VF01,-3(VI07)
+vec_3_rgba:
+; _LNOPT_w=[ normal2 ] 4 [3 0] 4 [vec_3_rgba]
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]
- NOP xgkick VI05
+ NOP sq VF08,4(VI07)
+ NOP iaddiu VI07,VI07,0x00000006
+ NOP sq VF01,-1(VI07)
+loop_ctrl:
+; _LNOPT_w=[ normal2 ] 4 [4 0] 4 [loop_ctrl]
+ NOP iaddiu VI09,VI09,0x00000001
+ NOP iaddiu VI04,VI04,0x00000003
+ NOP ibne VI09,VI02,triangle_loop
+ NOP iaddiu VI05,VI05,0x00000003
+; _LNOPT_w=[ normal2 ] 3 [1 0] 3 [__v_draw3D_vcl_21]
+ NOP xgkick VI06
NOP[E] NOP
NOP NOP
.align 4
VU1Draw3D_CodeEnd:
-; iCount=47
+; iCount=103
; register stats:
-; 8 VU User integer
-; 10 VU User floating point
+; 10 VU User integer
+; 11 VU User floating point
;-------------------------
;-------------------------
;-------------------------
diff --git a/src/engine/vu1_progs/geometry.inc b/src/engine/vu1_progs/geometry.inc
new file mode 100644
index 0000000..2562412
--- /dev/null
+++ b/src/engine/vu1_progs/geometry.inc
@@ -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
diff --git a/src/engine/vu1_progs/matrix.inc b/src/engine/vu1_progs/matrix.inc
new file mode 100644
index 0000000..47615e5
--- /dev/null
+++ b/src/engine/vu1_progs/matrix.inc
@@ -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
diff --git a/src/engine/vu1_progs/vector.inc b/src/engine/vu1_progs/vector.inc
new file mode 100644
index 0000000..c492916
--- /dev/null
+++ b/src/engine/vu1_progs/vector.inc
@@ -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
diff --git a/src/samples/dolphin/README.MD b/src/samples/dolphin/README.MD
new file mode 100644
index 0000000..884ccc5
--- /dev/null
+++ b/src/samples/dolphin/README.MD
@@ -0,0 +1,20 @@
+## Dolphin sample
+
+### Features
+- Animated character
+- Collectibles and mines
+- Big DFF mesh
+- Background songs
+- Overlay
+- Audio effects (ADPCM)
+- Transparent 2D UI
+- Usage of draw() in array mode (for water tiles, very fast)
+
+### Assets
+[Download](http://apgcglz.cluster028.hosting.ovh.net/tyra/1.31.2/samples/dolphin/assets.zip)
+
+### Screenshot
+
+[![Dolphin screenshot][dolphin-screenshot]](#)
+
+[dolphin-screenshot]: http://apgcglz.cluster028.hosting.ovh.net/tyra/1.31.2/samples/dolphin/dolphin.gif
diff --git a/src/samples/dolphin/camera.cpp b/src/samples/dolphin/camera.cpp
index 5c122f7..69d8669 100755
--- a/src/samples/dolphin/camera.cpp
+++ b/src/samples/dolphin/camera.cpp
@@ -12,14 +12,11 @@
#include
-const float CAMERA_Y = 15.0F;
+const float CAMERA_Y = 25.0F;
-Camera::Camera(ScreenSettings *t_screen) : CameraBase(t_screen, &position, &up)
+Camera::Camera(ScreenSettings *t_screen) : CameraBase(t_screen, &position)
{
verticalLevel = 30.0F;
- up.x = 0.0F;
- up.y = 1.0F;
- up.z = 0.0F;
}
Camera::~Camera() {}
@@ -43,12 +40,7 @@ void Camera::rotate(Pad &t_pad)
horizontalLevel -= 0.08;
else if (t_pad.rJoyH >= 200)
horizontalLevel += 0.08;
- /*
- if (t_pad.rJoyV <= 50 && verticalLevel > 25.0F)
- verticalLevel -= 0.9F;
- else if (t_pad.rJoyV >= 200 && verticalLevel < 80.0F)
- verticalLevel += 0.9F;
- */
+
unitCirclePosition.x = (Math::sin(horizontalLevel) * verticalLevel);
unitCirclePosition.y = CAMERA_Y;
unitCirclePosition.z = (Math::cos(horizontalLevel) * verticalLevel);
@@ -59,15 +51,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;
- }
}
\ No newline at end of file
diff --git a/src/samples/dolphin/camera.hpp b/src/samples/dolphin/camera.hpp
index 7bcbde3..d13d38c 100755
--- a/src/samples/dolphin/camera.hpp
+++ b/src/samples/dolphin/camera.hpp
@@ -22,7 +22,7 @@ class Camera : public CameraBase
{
public:
- Vector3 position,up, unitCirclePosition;
+ Vector3 position, up, unitCirclePosition;
float horizontalLevel, verticalLevel;
Camera(ScreenSettings *t_screen);
@@ -34,7 +34,6 @@ public:
protected:
Vector3 *getPosition() { return &position; };
- Vector3 *getUp() { return &up; };
ScreenSettings screen;
};
diff --git a/src/samples/dolphin/dolphin.cpp b/src/samples/dolphin/dolphin.cpp
index 6471834..fb19346 100755
--- a/src/samples/dolphin/dolphin.cpp
+++ b/src/samples/dolphin/dolphin.cpp
@@ -11,14 +11,12 @@
#include "dolphin.hpp"
#include "utils/math.hpp"
-const u8 WATER_TILE_SCALE = 5;
-const u8 WATER_SIZE = 100;
-
+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;
-float Dolphin::engineFPS = 60.F;
-
Dolphin::Dolphin(Engine *t_engine) : engine(t_engine), camera(&engine->screen)
{
oysters = new Collectible[OYSTERS_COUNT];
@@ -29,12 +27,13 @@ Dolphin::~Dolphin()
{
delete[] oysters;
delete[] mines;
+ delete[] waterDrawList;
}
void Dolphin::onInit()
{
player.init(engine);
- engine->renderer->setCameraDefinitions(&camera.worldView, &camera.position, camera.planes);
+ engine->renderer->setCameraDefinitions(&camera.view, &camera.position, camera.planes);
engine->audio.loadSong("sound/dirediredocks.wav");
engine->audio.playSong();
@@ -73,11 +72,25 @@ void Dolphin::onInit()
printf("Loaded.\n");
printf("Loading water...\n");
- water.loadObj("water/", "water", WATER_TILE_SCALE, false);
- water.position.set(0, WATER_LEVEL, 0);
- texRepo->addByMesh("water/", water, BMP);
- water.shouldBeFrustumCulled = false;
- water.shouldBeBackfaceCulled = false;
+
+ u32 spiralOffset = (u32)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->getBySpriteOrMesh(water[0].getMaterial(0).getId())->addLink(water[i].getMaterial(0).getId());
+ waterDrawList[i] = &water[i];
+ }
printf("Loading seabed...\n");
seabed.loadObj("seabed/", "seabed", 10.0F, false);
@@ -96,7 +109,6 @@ void Dolphin::onInit()
waterbox.position.y = -100.F;
printf("Loading oyster dff\n");
- //oysters[0].loadDff("oyster/", "oyster", 1.F, false);
oysters[0].mesh.loadObj("oyster/", "oyster", 10.F, false);
printf("Loaded.");
oysters[0].mesh.shouldBeBackfaceCulled = false;
@@ -110,14 +122,12 @@ void Dolphin::onInit()
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());
+ texRepo->getBySpriteOrMesh(oysters[0].mesh.getMaterial(0).getId())->addLink(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);
- printf("Loaded.");
mines[0].mesh.shouldBeBackfaceCulled = false;
mines[0].mesh.shouldBeFrustumCulled = false;
mines[0].mesh.position.set(5, -15, 32);
@@ -129,13 +139,13 @@ void Dolphin::onInit()
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());
+ texRepo->getBySpriteOrMesh(mines[0].mesh.getMaterial(0).getId())->addLink(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());
+ // pLifeTex->addLink(lifeSprites[0].getId());
+
for (int i = 0; i < 3; i++)
{
lifeSprites[i].size.set(64.0F, 64.0F);
@@ -164,12 +174,13 @@ void Dolphin::onUpdate()
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.position.x;
- float zDist = player.mesh.position.z - water.position.z;
+ 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)
@@ -177,8 +188,11 @@ void Dolphin::onUpdate()
if (xDist > WATER_SIZE * WATER_TILE_SCALE / 4 ||
zDist > WATER_SIZE * WATER_TILE_SCALE / 4)
{
- water.position.x = (player.mesh.position.x / WATER_SIZE) * WATER_SIZE;
- water.position.z = (player.mesh.position.z / WATER_SIZE) * WATER_SIZE;
+ 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++)
@@ -188,7 +202,7 @@ void Dolphin::onUpdate()
float dist = vecDist.length();
if (dist < 20.F && player.isJumping() && oysters[i].isActive())
{
- printf("Pickup %d Dist %d\n", i, dist);
+ printf("Pickup:%d Dist:%f\n", i, dist);
oysters[i].disappear();
player.setLife(player.getLifes() + 1);
engine->audio.setADPCMVolume(30, 3);
@@ -204,11 +218,11 @@ void Dolphin::onUpdate()
if (dist < 20.F && !mines[i].getExplosionTicks())
{
- printf("Vecdist %f,%f,%f\n", vecDist.x, vecDist.y, vecDist.z);
- printf("Explode %d Dist %d\n", i, dist);
+ 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
+ // 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;
@@ -220,35 +234,34 @@ void Dolphin::onUpdate()
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(water);
+ 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
+ engine->audio.setADPCMVolume(0, 0); // Surface ambient
+ engine->audio.setADPCMVolume(65, 1); // Underwater ambient
}
else
{
@@ -256,3 +269,28 @@ void Dolphin::onUpdate()
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;
+ }
+}
diff --git a/src/samples/dolphin/dolphin.hpp b/src/samples/dolphin/dolphin.hpp
index ad7b3c1..5ee4d05 100755
--- a/src/samples/dolphin/dolphin.hpp
+++ b/src/samples/dolphin/dolphin.hpp
@@ -37,8 +37,15 @@ public:
static float engineFPS;
private:
- /*DO NOT TOUCH ORDER OF DECLARATION!
- GCC BUG CAUSES RENDERING TO FAIL IN ANY OTHER ORDER OF DECLARATION!*/
+ 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;
@@ -49,7 +56,7 @@ private:
Collectible *oysters;
TextureRepository *texRepo;
Sprite waterOverlay;
- Mesh water;
+ Mesh water[WATER_TILES_COUNT];
Mesh waterbox;
Sprite lifeSprites[3];
Sprite gameOver;
diff --git a/src/samples/dolphin/main.cpp b/src/samples/dolphin/main.cpp
index d094a17..fdf11cb 100755
--- a/src/samples/dolphin/main.cpp
+++ b/src/samples/dolphin/main.cpp
@@ -18,4 +18,4 @@ int main()
game.engine->init(&game, 128);
SleepThread();
return 0;
-}
\ No newline at end of file
+}
diff --git a/src/samples/dolphin/objects/collectible.cpp b/src/samples/dolphin/objects/collectible.cpp
index 9cd7d78..0bdd01c 100644
--- a/src/samples/dolphin/objects/collectible.cpp
+++ b/src/samples/dolphin/objects/collectible.cpp
@@ -25,10 +25,6 @@ Collectible::Collectible()
bDisappearing = false;
}
-Collectible::~Collectible()
-{
-}
-
void Collectible::disappear()
{
bDisappearing = true;
diff --git a/src/samples/dolphin/objects/collectible.hpp b/src/samples/dolphin/objects/collectible.hpp
index 32795ea..bac0b37 100644
--- a/src/samples/dolphin/objects/collectible.hpp
+++ b/src/samples/dolphin/objects/collectible.hpp
@@ -21,7 +21,6 @@ public:
float rotation;
Mesh mesh;
Collectible();
- ~Collectible();
void update();
void disappear();
void setActive(const u8 &b) { bActive = b; }
diff --git a/src/samples/dolphin/objects/mine.cpp b/src/samples/dolphin/objects/mine.cpp
index 9a7a19b..a64da3a 100644
--- a/src/samples/dolphin/objects/mine.cpp
+++ b/src/samples/dolphin/objects/mine.cpp
@@ -20,10 +20,6 @@ Mine::Mine()
explosionTicks = 0;
}
-Mine::~Mine()
-{
-}
-
void Mine::update()
{
if (bExploding && explosionTicks < MINE_EXPLOSION_TICKS)
diff --git a/src/samples/dolphin/objects/mine.hpp b/src/samples/dolphin/objects/mine.hpp
index 5dce106..51faa71 100644
--- a/src/samples/dolphin/objects/mine.hpp
+++ b/src/samples/dolphin/objects/mine.hpp
@@ -24,7 +24,6 @@ public:
void explode() { bExploding = true; }
void update();
Mine();
- ~Mine();
const u8 &getExplosionTicks() { return explosionTicks; }
private:
diff --git a/src/samples/dolphin/objects/player.cpp b/src/samples/dolphin/objects/player.cpp
index 84669cc..718f33a 100755
--- a/src/samples/dolphin/objects/player.cpp
+++ b/src/samples/dolphin/objects/player.cpp
@@ -28,10 +28,6 @@ Player::Player()
lifes = 3;
}
-Player::~Player()
-{
-}
-
void Player::init(Engine *t_engine)
{
pEngine = t_engine;
@@ -63,8 +59,7 @@ void Player::update(Pad &t_pad)
if (t_pad.isCrossClicked && mesh.getCurrentAnimationFrame() <= 14 && WATER_LEVEL - 15 < mesh.position.y)
{
- printf("Cross\n");
- mesh.setAnimSpeed(0.8F);
+ mesh.setAnimSpeed(1.0F);
mesh.playAnimation(14, 58, 0);
}
@@ -72,19 +67,10 @@ void Player::update(Pad &t_pad)
bIsJumping = true;
else
bIsJumping = false;
- /*
- if (lift < 0)
- mesh.rotation.y = 1;
- else if (lift > 0)
- mesh.rotation.y = -1;
- else
- mesh.rotation.y = 0;
- */
if (velocity > 0 && mesh.getCurrentAnimationFrame() == 0)
{
mesh.setAnimSpeed(0.05F);
- printf("Swim animation\n");
mesh.playAnimation(1, 14, 0);
}
if (mesh.getCurrentAnimationFrame() == 42)
@@ -101,7 +87,7 @@ void Player::update(Pad &t_pad)
bIsImpactingWater = false;
}
- velocity *= 60.0F / Dolphin::engineFPS; //Moving by deltatime of last frame.
+ 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 +=
diff --git a/src/samples/dolphin/objects/player.hpp b/src/samples/dolphin/objects/player.hpp
index 3aed608..93cde51 100755
--- a/src/samples/dolphin/objects/player.hpp
+++ b/src/samples/dolphin/objects/player.hpp
@@ -25,7 +25,6 @@ public:
float gravity, velocity, lift;
Mesh mesh;
Player();
- ~Player();
void init(Engine *t_engine);
void update(Pad &t_pad);
const u8 &isJumping() { return bIsJumping; }
diff --git a/src/samples/floors/README.MD b/src/samples/floors/README.MD
index 7f8391d..30d0602 100644
--- a/src/samples/floors/README.MD
+++ b/src/samples/floors/README.MD
@@ -1,14 +1,19 @@
## Floors sample
-### Description
-
-Simple demo which shows lighting using PATH3, and player movement and animation.
+### Features
+- Box collision
+- 2 animated characters
+- Texture tricks showcase
+- Background song
+- Audio effects - walking, fighting (ADPCM)
+- Transparent 2D UI
+- Usage of draw() in array mode (for floors, very fast)
### Assets
-[Download](http://apgcglz.cluster028.hosting.ovh.net/tyra/1.1.0/samples/floors/assets.zip)
+[Download](http://apgcglz.cluster028.hosting.ovh.net/tyra/1.31.2/samples/floors/assets.zip)
### Screenshot
[![Floors screenshot][floors-screenshot]](#)
-[floors-screenshot]: http://apgcglz.cluster028.hosting.ovh.net/tyra/1.1.0/samples/floors/floors.gif
+[floors-screenshot]: http://apgcglz.cluster028.hosting.ovh.net/tyra/1.31.2/samples/floors/floors.gif
diff --git a/src/samples/floors/camera.cpp b/src/samples/floors/camera.cpp
index 56c4aa1..e797c0f 100644
--- a/src/samples/floors/camera.cpp
+++ b/src/samples/floors/camera.cpp
@@ -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!");
}
diff --git a/src/samples/floors/camera.hpp b/src/samples/floors/camera.hpp
index 4d6adf8..49735d2 100644
--- a/src/samples/floors/camera.hpp
+++ b/src/samples/floors/camera.hpp
@@ -35,7 +35,6 @@ public:
protected:
Vector3 *getPosition() { return &position; };
- Vector3 *getUp() { return &up; };
ScreenSettings screen;
};
diff --git a/src/samples/floors/floors.cpp b/src/samples/floors/floors.cpp
index 2a55ab1..330c68a 100644
--- a/src/samples/floors/floors.cpp
+++ b/src/samples/floors/floors.cpp
@@ -37,17 +37,17 @@ Floors::~Floors()
void Floors::onInit()
{
+ texRepo = engine->renderer->getTextureRepository();
+ 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.worldView, &camera.unitCirclePosition, camera.planes);
+ 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);
- texRepo = engine->renderer->getTextureRepository();
- enemy = new Enemy(texRepo);
- ui = new Ui(texRepo);
- floorManager = new FloorManager(FLOORS_COUNT, texRepo);
- player = new Player(&engine->audio, texRepo);
}
void Floors::onUpdate()
@@ -60,8 +60,11 @@ void Floors::onUpdate()
player->update(engine->pad, camera, *floorManager, *enemy);
engine->renderer->draw(player->mesh);
engine->renderer->draw(enemy->getMeshes(), enemy->getMeshesCount());
- for (u16 i = 0; i < FLOORS_COUNT; i++)
- engine->renderer->drawByPath3(floorManager->floors[i].mesh, lightManager.bulbs, lightManager.bulbsCount);
+
+ // 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.
}
diff --git a/src/samples/floors/managers/floor_manager.cpp b/src/samples/floors/managers/floor_manager.cpp
index e1b1d09..cc2e0ae 100644
--- a/src/samples/floors/managers/floor_manager.cpp
+++ b/src/samples/floors/managers/floor_manager.cpp
@@ -12,6 +12,7 @@
#include
#include
+#include
// ----
// Constructors/Destructors
@@ -22,17 +23,17 @@
*/
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);
+ int floorSpiralMaxOffset = (int)sqrt(t_floorAmount);
calcSpiral(floorSpiralMaxOffset, floorSpiralMaxOffset);
initFloors();
trick = 0.0F;
- trickMode = 0;
isTimeForChangeTriggerColor = true;
isTimeForChangeDefaultColor = true;
- audioOffset = audioMode = audioTick = 0;
+ audioOffset = audioMode = audioTick = trickMode = 0;
}
FloorManager::~FloorManager()
@@ -85,12 +86,14 @@ void FloorManager::initFloors()
floors[0].mesh.loadObj("meshes/floor/", "floor", 3.0F, false);
floors[0].mesh.shouldBeFrustumCulled = true;
floors[0].mesh.shouldBeLighted = true;
+ 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());
+ texRepo->getBySpriteOrMesh(floors[0].mesh.getMaterial(0).getId())->addLink(floors[i].mesh.getMaterial(0).getId());
+ meshes[i] = &floors[i].mesh;
}
PRINT_LOG("Floors initialized!");
}
@@ -120,18 +123,18 @@ void FloorManager::update(Player &t_player)
for (u16 i = 0; i < floorAmount; i++)
{
floors[i].animate(t_player);
-
+ MeshMaterial *material = &floors[i].mesh.getMaterial(0);
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;
+ material->color.r = trigColor.r;
+ material->color.g = trigColor.g;
+ material->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;
+ material->color.r = defaultColor.r;
+ material->color.g = defaultColor.g;
+ material->color.b = defaultColor.b;
}
}
}
diff --git a/src/samples/floors/managers/floor_manager.hpp b/src/samples/floors/managers/floor_manager.hpp
index 61a64b7..342aefd 100644
--- a/src/samples/floors/managers/floor_manager.hpp
+++ b/src/samples/floors/managers/floor_manager.hpp
@@ -31,8 +31,10 @@ public:
u16 floorAmount;
void update(Player &t_player);
void onAudioTick();
+ Mesh **getMeshes() { return meshes; }
private:
+ Mesh **meshes;
TextureRepository *texRepo;
u8 audioOffset, audioMode;
u32 audioTick;
diff --git a/src/samples/floors/objects/enemy.cpp b/src/samples/floors/objects/enemy.cpp
index 858e79c..2e8aa42 100644
--- a/src/samples/floors/objects/enemy.cpp
+++ b/src/samples/floors/objects/enemy.cpp
@@ -16,6 +16,7 @@
#include
#include
#include
+#include
// ----
// Constructors/Destructors
@@ -26,30 +27,25 @@ 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[0].rotation.x = -1.566F;
- meshes[0].rotation.z = 1.566F;
-
meshes[1].loadMD2("meshes/enemy/", "poss_body", 0.3F, false);
- meshes[1].rotation.x = -1.566F;
- meshes[1].rotation.z = 1.566F;
-
meshes[2].loadMD2("meshes/enemy/", "poss_weapon", 0.3F, false);
- meshes[2].rotation.x = -1.566F;
- meshes[2].rotation.z = 1.566F;
+
+ 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);
- t_texRepo->addByMesh("meshes/enemy/", meshes[0], PNG);
- t_texRepo->addByMesh("meshes/enemy/", meshes[1], PNG);
- t_texRepo->addByMesh("meshes/enemy/", meshes[2], PNG);
-
- meshes[0].playAnimation(1, 6);
- meshes[1].playAnimation(1, 6);
- meshes[2].playAnimation(1, 6);
-
isKilled = true;
PRINT_LOG("Enemy object created!");
diff --git a/src/samples/floors/objects/enemy.hpp b/src/samples/floors/objects/enemy.hpp
index 601a4e9..4ed530a 100644
--- a/src/samples/floors/objects/enemy.hpp
+++ b/src/samples/floors/objects/enemy.hpp
@@ -24,7 +24,7 @@ public:
Enemy(TextureRepository *t_texRepo);
~Enemy();
- inline Mesh *getMeshes() const { return meshes; }
+ inline Mesh **getMeshes() const { return drawMeshes; }
inline u8 getMeshesCount() const { return 3; }
inline Vector3 getPosition() const { return position; }
void setPosition(const Vector3 &t_vec);
@@ -35,6 +35,8 @@ public:
private:
/** 0 - head, 1 - body, 2 - weapon */
Mesh *meshes;
+ /** Only for draw() method. */
+ Mesh **drawMeshes;
const Floor *currentFloor;
Vector3 position, currFloorMin, currFloorMax;
u8 isKilled;
diff --git a/src/samples/floors/objects/player.cpp b/src/samples/floors/objects/player.cpp
index 6d6ae79..738d03a 100644
--- a/src/samples/floors/objects/player.cpp
+++ b/src/samples/floors/objects/player.cpp
@@ -211,13 +211,13 @@ FloorsCheck *Player::checkFloors(const FloorManager &t_floorManager, const Vecto
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.isOnSquare(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.collidesSquare(min, max))
+ if (result->willCollideFloor == NULL && t_nextPos.collidesBox(min, max))
{
result->willCollideFloor = &t_floorManager.floors[i];
result->willCollideFloorMin.set(min);
diff --git a/src/samples/floors/ui.cpp b/src/samples/floors/ui.cpp
index 52c43ff..d398cd9 100644
--- a/src/samples/floors/ui.cpp
+++ b/src/samples/floors/ui.cpp
@@ -66,13 +66,13 @@ void Ui::update(const Player &player)
if (!isTask1Done && player.getJumpCount() >= 10)
{
isTask1Done = true;
- grayCheckboxTex->removeLinkBySprite(task1Checkbox.getId());
+ grayCheckboxTex->removeLinkById(task1Checkbox.getId());
blueCheckboxTex->addLink(task1Checkbox.getId());
}
if (!isTask2Done && player.getKilledEnemiesCount() >= 10)
{
isTask2Done = true;
- grayCheckboxTex->removeLinkBySprite(task2Checkbox.getId());
+ grayCheckboxTex->removeLinkById(task2Checkbox.getId());
blueCheckboxTex->addLink(task2Checkbox.getId());
}
}