Merge pull request #5 from h4570/develop

Updating develop with h4570/tyra develop
This commit is contained in:
Michał Mostowik
2021-04-18 14:32:42 +02:00
committed by GitHub
69 changed files with 2154 additions and 1461 deletions
+117
View File
@@ -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
+62 -63
View File
@@ -1,19 +1,22 @@
[![Contributors][contributors-shield]][contributors-url] [![Contributors][contributors-shield]][contributors-url]
[![MIT License][license-shield]][license-url] [![MIT License][license-shield]][license-url]
PS2-Scene [![Discord](https://img.shields.io/discord/652861436992946216?logo=discord)](https://discord.gg/7dCr6ThSN5) [![Discord](https://img.shields.io/badge/discord-Tyra-brightgreen?logo=discord)](https://discord.gg/NhhTmg3Gm5)
[![Discord](https://img.shields.io/badge/discord-PS2--Scene-brightgreen?logo=discord)](https://discord.gg/7dCr6ThSN5)
<br /> <br />
<p align="center"> <p align="center">
<a href="https://github.com/h4570/tyra"> <a href="https://github.com/h4570/tyra">
<img src="http://allvectorlogo.com/img/2016/05/ps2-logo.png" alt="Logo" width="230" height="125"> <img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/github-splash.png" alt="Logo" width="100%" height="auto">
</a> </a>
<h3 align="center">Tyra alpha 1.1.0</h3> <h3 align="center">Tyra - alpha 1.31.2</h3>
<p align="center"> <p align="center">
Open source renderer and game engine for PS2 (PlayStation 2™). Open source game engine for PlayStation 2™
<br /> <br />
<a href="https://www.youtube.com/"><strong>View Demo (soon) »</strong></a> <a href="https://github.com/h4570/tyra/tree/master/src/samples/dolphin"><strong>Dolphin sample »</strong></a>
&nbsp;
<a href="https://github.com/h4570/tyra/tree/master/src/samples/floors"><strong>Floors sample »</strong></a>
<br /> <br />
<br /> <br />
<a href="https://github.com/h4570/tyra/issues">Report Bug</a> <a href="https://github.com/h4570/tyra/issues">Report Bug</a>
@@ -27,95 +30,79 @@ PS2-Scene [![Discord](https://img.shields.io/discord/652861436992946216?logo=dis
* [About the Project](#about-the-project) * [About the Project](#about-the-project)
* [Samples](#samples) * [Samples](#samples)
* [About project](#about-project) * [About project](#about-project)
* [Acronyms](#acronyms)
* [Tyra features](#tyra-features) * [Tyra features](#tyra-features)
* [Built With](#built-with) * [Branches](#branches)
* [Getting Started](#getting-started) * [Getting Started](#getting-started)
* [Prerequisites](#prerequisites)
* [Installation](#installation) * [Installation](#installation)
* [Prerequisites](#prerequisites)
* [Roadmap](#roadmap) * [Roadmap](#roadmap)
* [Tyra team](#tyra-team)
* [Contributing](#contributing) * [Contributing](#contributing)
* [License](#license) * [License](#license)
* [Contact](#contact) * [Built With](#built-with)
* [Acronyms](#acronyms)
* [Thanks](#thanks) * [Thanks](#thanks)
## About The Project ## About The Project
<img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/1.1.0/tyra.gif" alt="sample" width="600" height="auto"> <img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/1.31.2/tyra.gif" alt="sample" width="600" height="auto">
### Samples ### Samples
* [Dolphin](https://github.com/h4570/tyra/tree/master/src/samples/dolphin)
* [Floors](https://github.com/h4570/tyra/tree/master/src/samples/floors) * [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 ### 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! 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. **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 and many more low-level stuff is already done. Tyra takes care for you, and rendering, coprocessors communication, synchronization 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
### Tyra features ### Tyra features
* VU1 rendering (PATH 1), double-buffered * 3D support - VU1 "Path 1 rendering"
* GIF rendering (PATH 3), double-buffered * 2D support - PNG & BMP
* Frustum culling, backface culling * Frustum culling, backface culling
* OpenGL adaptions: Perspective projection, lookAt camera * 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) * Mesh loaders: ".obj", ".dff" (RenderWare, GTA:SA) and ".md2" (Quake II)
* Threading support * Threading support
* Lighting support (now PATH3 only) * Animation support for obj and md2
* Animation support * Audio support - .wav and .adpcm
* Audio support
* Pad support * Pad support
* TODO: physics, ADPCM and many more!
### Built With ### Branches
* Master - monthly releases - tested on PS2 & PCSX2.
* [PS2SDK](https://github.com/ps2dev/ps2sdk) * Develop - daily builds - can be unstable.
## Getting Started ## Getting Started
To get a local copy up and running follow these simple steps. ### Installation [![Discord](https://img.shields.io/badge/discord-Tyra-brightgreen?logo=discord)](https://discord.gg/NhhTmg3Gm5)
YouTube tutorials soon! 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 ### 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) * 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/) * 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 ## 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 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
### Roadmap moved to github kanban: ### Roadmap for next master release:
[https://github.com/h4570/tyra/projects/1](https://github.com/h4570/tyra/projects/1) [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). 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. Distributed under the Apache License 2.0 License. See `LICENSE` for more information.
## Contact ## Built With
Sandro Sobczyński - sandro.sobczynski@gmail.com * [PS2SDK](https://github.com/ps2dev/ps2sdk)
[![LinkedIn][linkedin-shield]][linkedin-url]
### 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 ## Thanks
Without these guys, everything would be harder: Without these guys, everything would be harder:
* Dr Henry Fortuna - Abertay University (code sources) * Dr Henry Fortuna - for code sources
* Lukasz D.K. (huge archive of PS2 stuff) * Rick Gaiser - for help and new GCC!
* Guilherme Lampert - PlayStation London (code sources) * Lukasz D.K. - for huge archive of PS2 stuff
* Jesper Svennevid, Daniel Collin - Microcode (openvcl, code samples) * Guilherme Lampert - for code sources
* Whole PS2SDK/PS2Scene team * Jesper Svennevid, Daniel Collin - for openvcl's code samples
* Whole PS2DEV team
* Manieq - for nice splash screens!
* And so many other guys. Thanks! * And so many other guys. Thanks!
Project Link: [https://github.com/h4570/tyra](https://github.com/h4570/tyra) Project Link: [https://github.com/h4570/tyra](https://github.com/h4570/tyra)
<br />
<a href="https://github.com/h4570/tyra">
<img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/github-splash2.png" alt="Logo" width="100%" height="auto">
</a>
[contributors-shield]: https://img.shields.io/github/contributors/h4570/tyra.svg?style=flat-square [contributors-shield]: https://img.shields.io/github/contributors/h4570/tyra.svg?style=flat-square
[contributors-url]: https://github.com/h4570/tyra/graphs/contributors [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-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-shield]: https://img.shields.io/github/license/h4570/tyra.svg?style=flat-square
[license-url]: https://github.com/h4570/tyra/blob/master/LICENSE [license-url]: https://github.com/h4570/tyra/blob/master/LICENSE
+4 -2
View File
@@ -35,8 +35,10 @@ all: $(EE_OBJS)
ar rcs $(LIB_NAME) $(EE_OBJS) ar rcs $(LIB_NAME) $(EE_OBJS)
rm -f $(EE_OBJS) rm -f $(EE_OBJS)
# https://github.com/microsoft/wsl/issues/2468#issuecomment-374904520 #%.vcl: %.vclpp
#%.vsm: %.vcl # sudo service binfmt-support start # $(EE_VCLPP) $< $@
#%.vsm: %.vcl
# $(EE_VCL) $< >> $@ # $(EE_VCL) $< >> $@
%.o: %.vsm %.o: %.vsm
+4 -3
View File
@@ -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_INCS := -I$(TYRA_DIR)/include -I$(PS2SDK)/ports/include $(EE_INCS)
EE_LDFLAGS := -L$(PS2SDK)/ports/lib -L$(TYRA_DIR) $(EE_LDFLAGS) EE_LDFLAGS := -L$(PS2SDK)/ports/lib -L$(TYRA_DIR) $(EE_LDFLAGS)
EE_CFLAGS := -DHAVE_LIBPNG -DHAVE_ZLIB $(EE_CFLAGS) EE_CFLAGS := -DHAVE_LIBPNG -D_XCDVD -DHAVE_ZLIB $(EE_CFLAGS)
EE_CXXFLAGS := -DHAVE_LIBPNG -DHAVE_ZLIB $(EE_CXXFLAGS) EE_CXXFLAGS := -DHAVE_LIBPNG -D_XCDVD -DHAVE_ZLIB $(EE_CXXFLAGS)
EE_DVP = dvp-as EE_DVP = dvp-as
EE_VCL = vcl EE_VCL = vcl
EE_VCLPP = vclpp
LIB_NAME = libtyra.a LIB_NAME = libtyra.a
include $(PS2SDK)/samples/Makefile.pref include $(PS2SDK)/samples/Makefile.pref
+5 -4
View File
@@ -41,13 +41,13 @@ Engine::~Engine() {}
void Engine::setDefaultScreen() void Engine::setDefaultScreen()
{ {
screen.projectionScale = 4096.0F;
screen.nearPlaneDist = 2.0F; screen.nearPlaneDist = 2.0F;
screen.farPlaneDist = 2000.0F; screen.farPlaneDist = 2000.0F;
screen.fov = 60.0F; screen.fov = 60.0F;
screen.aspectRatio = 4.0F / 3.0F;
screen.width = 640.0F; screen.width = 640.0F;
screen.height = 480.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) void Engine::init(Game *t_game, u32 t_gifPacketSize)
@@ -77,8 +77,9 @@ void Engine::firePS2()
{ {
SifInitRpc(0); SifInitRpc(0);
srand(time(NULL)); srand(time(NULL));
fileService.startThread(); // fileService.startThread();
audio.startThread(&fileService); // audio.startThread(&fileService);
audio.startThread(NULL);
isInitialized = 0; isInitialized = 0;
mainThreadId = GetThreadId(); mainThreadId = GetThreadId();
} }
+1 -1
View File
@@ -32,7 +32,7 @@ public:
void init(Game *t_game, u32 t_gifPacketSize); void init(Game *t_game, u32 t_gifPacketSize);
void setDefaultScreen(); void setDefaultScreen();
Renderer *renderer; Renderer *renderer;
FileService fileService; // FileService fileService;
Audio audio; Audio audio;
ScreenSettings screen; ScreenSettings screen;
Pad pad; Pad pad;
+1 -1
View File
@@ -91,4 +91,4 @@ private:
BoundingBoxFace _bottomFace; BoundingBoxFace _bottomFace;
}; };
#endif #endif
+145 -50
View File
@@ -13,79 +13,174 @@
#include "vector3.hpp" #include "vector3.hpp"
#include "../screen_settings.hpp" #include "../screen_settings.hpp"
#include <string.h>
/** https://en.wikipedia.org/wiki/Matrix_(mathematics) */ /** 4x4 Matrix class. */
class Matrix class Matrix
{ {
public: 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, // Constructors/Destructors
float m31, float m32, float m33, float m34, // ----
float m41, float m42, float m43, float m44);
Matrix(const Matrix &v); /** Create empty matrix. */
Matrix operator*(const Matrix &v);
void operator*=(const Matrix &v);
Matrix(); Matrix();
~Matrix();
void lookAt(Vector3 &t_up, Vector3 &t_position, Vector3 &t_target); /**
* Create identity/empty matrix.
* @param t_do_identity Identity matrix if true, random matrix values otherwise
*/
Matrix(const u8 &t_do_identity)
{
if (t_do_identity)
identity();
}
/** Init matrix with given values. */
Matrix(const float &m11, const float &m12, const float &m13, const float &m14,
const float &m21, const float &m22, const float &m23, const float &m24,
const float &m31, const float &m32, const float &m33, const float &m34,
const float &m41, const float &m42, const float &m43, const float &m44);
/** Init matrix with other matrix values. */
Matrix(const Matrix &v) { memcpy(data, v.data, 16 * sizeof(float)); }
// ----
// Operators
// ----
Vector3 operator*(const Vector3 &v) const;
Matrix operator*(const Matrix &v) const
{
Matrix result;
cross(result.data, this->data, v.data);
return result;
}
inline void operator*=(const Matrix &v) { cross(this->data, this->data, v.data); }
float &operator[](const u8 &t_index) { return data[t_index]; }
// ----
// Functions
// ----
/**
* 1 0 0 0
* 0 1 0 0
* 0 0 1 0
* 0 0 0 1
*/
void identity(); void identity();
/**
* 1 0 0 0
* 0 1 0 0
* 0 0 1 0
* 0 0 0 1
*/
inline void unit() { identity(); }; inline void unit() { identity(); };
// Translation /** Translate matrix. */
inline void translate(const Vector3 &t_val)
void translate(const Vector3 &t_val);
inline void translation(const Vector3 &t_val)
{ {
identity(); Matrix temp = Matrix(true);
translate(t_val); temp.translation(t_val);
} cross(this->data, temp.data, this->data);
// 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);
} }
/** Rotate matrix. */
inline void rotate(const Vector3 &t_val) inline void rotate(const Vector3 &t_val)
{ {
rotateX(t_val.x); Matrix temp = Matrix(true);
rotateY(t_val.y);
rotateX(t_val.z); 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(); Matrix temp = Matrix(true);
rotate(t_val); 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; 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 #endif
+80 -19
View File
@@ -12,6 +12,7 @@
#define _TYRA_VECTOR3_ #define _TYRA_VECTOR3_
#include <tamtypes.h> #include <tamtypes.h>
#include <stdio.h>
class Math; // Forward definition class Math; // Forward definition
@@ -20,6 +21,7 @@ class Vector3
{ {
public: public:
/** This trick will allow use to use vec.x and vex[0] */
union union
{ {
struct struct
@@ -31,32 +33,91 @@ public:
float xyz[3] __attribute__((__aligned__(16))); 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();
Vector3 operator+(Vector3 v); /** Create vector with given vector values. */
Vector3 operator-(const Vector3 &v); Vector3(const Vector3 &t_v) { set(t_v); }
Vector3 operator*(Vector3 &v);
Vector3 operator*(const float &t); /** 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); 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; // Functions
u8 isOnSquare(const Vector3 &t_min, const Vector3 &t_max) const; // ----
float length();
void normalize(); /** Set vector values via VU0. */
void setByLerp(const Vector3 &v1, const Vector3 &v2, const float &t_interp, const float &t_scale);
float innerProduct(Vector3 &v);
void set(const Vector3 &v); 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 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; 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 #endif
+3 -4
View File
@@ -16,7 +16,6 @@
#include "./texture.hpp" #include "./texture.hpp"
#include "./mesh_frame.hpp" #include "./mesh_frame.hpp"
#include <tamtypes.h> #include <tamtypes.h>
#include <draw_types.h>
#include <draw_buffers.h> #include <draw_buffers.h>
#include <draw_sampling.h> #include <draw_sampling.h>
#include "./anim_state.hpp" #include "./anim_state.hpp"
@@ -43,7 +42,6 @@ public:
* When true, mesh materials are not drawn when they are outside of view frustum. * When true, mesh materials are not drawn when they are outside of view frustum.
*/ */
u8 shouldBeFrustumCulled; u8 shouldBeFrustumCulled;
color_t color;
clutbuffer_t clut; clutbuffer_t clut;
lod_t lod; lod_t lod;
@@ -176,6 +174,8 @@ public:
void setAnimSpeed(const float &t_value) { animState.speed = t_value; } void setAnimSpeed(const float &t_value) { animState.speed = t_value; }
const u8 &areFramesAllocated() const { return _areFramesAllocated; };
/** /**
* Check if this class loaded mesh data first. * Check if this class loaded mesh data first.
* Meshes which use loadFrom() method have false there. * Meshes which use loadFrom() method have false there.
@@ -207,9 +207,8 @@ private:
AnimState animState; AnimState animState;
MeshFrame *frames; MeshFrame *frames;
u32 id, framesCount; u32 id, framesCount;
u8 _isMother; u8 _isMother, _areFramesAllocated;
Vector3 calc3Vectors[3]; Vector3 calc3Vectors[3];
void setDefaultColor();
void setDefaultLODAndClut(); void setDefaultLODAndClut();
}; };
+24 -2
View File
@@ -35,6 +35,12 @@ public:
// Getters // 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 &getVertexCount() const { return vertexCount; };
const u32 &getSTsCount() const { return stsCount; }; const u32 &getSTsCount() const { return stsCount; };
const u32 &getNormalsCount() const { return normalsCount; }; const u32 &getNormalsCount() const { return normalsCount; };
@@ -119,12 +125,27 @@ public:
// Other // 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 &areSTsAllocated() const { return _areSTsAllocated; };
const u8 &areVerticesAllocated() const { return _areVerticesAllocated; }; const u8 &areVerticesAllocated() const { return _areVerticesAllocated; };
const u8 &areNormalsAllocated() const { return _areNormalsAllocated; }; const u8 &areNormalsAllocated() const { return _areNormalsAllocated; };
const u8 &areMaterialsAllocated() const { return _areMaterialsAllocated; }; const u8 &areMaterialsAllocated() const { return _areMaterialsAllocated; };
const u8 &isBoundingBoxCalculated() const { return _isBoundingBoxCalculated; }; const u8 &isBoundingBoxCalculated() const { return _isBoundingBoxCalculated; };
/** Create reference copy (non-mother) */
void copyFrom(MeshFrame *t_refCopy);
/** Set STs count and allocate memory. */ /** Set STs count and allocate memory. */
void allocateSTs(const u32 &t_val); void allocateSTs(const u32 &t_val);
@@ -146,12 +167,13 @@ public:
private: private:
BoundingBox *boundingBoxObj; BoundingBox *boundingBoxObj;
u8 _areSTsAllocated, u8 _isMother,
_areSTsAllocated,
_areVerticesAllocated, _areVerticesAllocated,
_areNormalsAllocated, _areNormalsAllocated,
_areMaterialsAllocated, _areMaterialsAllocated,
_isBoundingBoxCalculated; _isBoundingBoxCalculated;
u32 vertexCount, stsCount, normalsCount, materialsCount; u32 vertexCount, stsCount, normalsCount, materialsCount, id;
MeshMaterial *materials; MeshMaterial *materials;
Point __attribute__((aligned(16))) * sts; Point __attribute__((aligned(16))) * sts;
Vector3 __attribute__((aligned(16))) * vertices, *normals; Vector3 __attribute__((aligned(16))) * vertices, *normals;
+42 -1
View File
@@ -12,6 +12,7 @@
#define _TYRA_MESH_MATERIAL_ #define _TYRA_MESH_MATERIAL_
#include <tamtypes.h> #include <tamtypes.h>
#include <draw_types.h>
#include "bounding_box.hpp" #include "bounding_box.hpp"
#include "./math/vector3.hpp" #include "./math/vector3.hpp"
#include "./math/plane.hpp" #include "./math/plane.hpp"
@@ -29,6 +30,8 @@ public:
MeshMaterial(); MeshMaterial();
~MeshMaterial(); ~MeshMaterial();
color_t color;
// ---- // ----
// Getters // Getters
// ---- // ----
@@ -104,11 +107,43 @@ public:
/** Set material name. */ /** Set material name. */
void setName(char *t_val); 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 // 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; }; 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; }; const u8 &areFacesAllocated() const { return _areFacesAllocated; };
/** Set faces count and allocate memory. */ /** Set faces count and allocate memory. */
@@ -125,10 +160,16 @@ public:
u8 isInFrustum(Plane *t_frustumPlanes, const Vector3 &position); u8 isInFrustum(Plane *t_frustumPlanes, const Vector3 &position);
private: private:
void setDefaultColor();
BoundingBox *boundingBoxObj; BoundingBox *boundingBoxObj;
u32 facesCount, id; u32 facesCount, id;
u32 *vertexFaces, *stFaces, *normalFaces; u32 *vertexFaces, *stFaces, *normalFaces;
u8 _isNameSet, _areFacesAllocated, _isBoundingBoxCalculated; u8 _isMother,
_isNameSet,
_areFacesAllocated,
_isBoundingBoxCalculated,
_areSTsPresent,
_areNormalsPresent;
char *name; char *name;
}; };
+12 -4
View File
@@ -22,10 +22,18 @@ struct RenderData
{ {
LightBulb *bulbs; LightBulb *bulbs;
u16 bulbsCount; u16 bulbsCount;
/** Camera (lookAt) */ /**
Matrix *worldView; * Camera matrix (glLookAt)
/** Perspective projection */ * OpenGL name: View
Matrix *perspective; * Sony name: World view
*/
Matrix *view;
/**
* Projection matrix (glPerspective)
* OpenGL name: Projection
* Sony name: View screen
*/
Matrix *projection;
Vector3 *cameraPosition; Vector3 *cameraPosition;
Plane *frustumPlanes; Plane *frustumPlanes;
prim_t *prim; prim_t *prim;
+21 -30
View File
@@ -83,21 +83,18 @@ public:
/** /**
* Returns index of link. * Returns index of link.
* -1 if not found. * -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++) 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 i;
return -1; 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 // Setters
// ---- // ----
@@ -144,18 +141,15 @@ public:
const u8 &isSizeSet() const { return _isSizeSet; }; 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); s32 index = getIndexOfLink(t_id);
if (index != -1)
return true;
else
return false;
};
const u8 isLinkedWith(const u32 &t_spriteId) const
{
s32 index = getIndexOfLink(t_spriteId);
if (index != -1) if (index != -1)
return true; return true;
else else
@@ -164,18 +158,15 @@ public:
void removeLinkByIndex(const u32 &t_index) { texLinks.erase(texLinks.begin() + t_index); } 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); s32 index = getIndexOfLink(t_id);
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);
if (index != -1) if (index != -1)
removeLinkByIndex(index); removeLinkByIndex(index);
else else
+5 -4
View File
@@ -15,10 +15,11 @@
struct TextureLink struct TextureLink
{ {
/** Mesh id or sprite id */ /**
u32 meshOrSpriteId; * For 3D: Mesh material id.
/** Mesh material id or 0 if is sprite */ * For 2D: Sprite id.
u32 materialId; */
u32 id;
}; };
#endif #endif
+2 -1
View File
@@ -126,7 +126,8 @@ public:
private: private:
u8 songLoaded, volume, realVolume, songPlaying, songInLoop, songFinished; u8 songLoaded, volume, realVolume, songPlaying, songInLoop, songFinished;
std::vector<AudioListenerRef> songListeners; u8 hack; // TODO
std::vector<AudioListenerRef *> songListeners;
FILE *wav; FILE *wav;
audsrv_fmt_t format; audsrv_fmt_t format;
FileService *fileService; FileService *fileService;
+6 -5
View File
@@ -21,7 +21,7 @@ class CameraBase
{ {
public: public:
CameraBase(ScreenSettings *t_screen, Vector3 *t_position, Vector3 *t_up); CameraBase(ScreenSettings *t_screen, Vector3 *t_position);
virtual ~CameraBase(){}; virtual ~CameraBase(){};
/** /**
@@ -31,10 +31,10 @@ public:
Plane planes[6]; Plane planes[6];
/** /**
* Projection matrix * View matrix
* Set by lookAt() method. * Set by lookAt() method.
*/ */
Matrix worldView; Matrix view;
protected: protected:
/** Pointer to screen settings */ /** Pointer to screen settings */
@@ -42,7 +42,7 @@ protected:
/** /**
* Adaption of OpenGL lookAt camera. * Adaption of OpenGL lookAt camera.
* Calculates worldView matrix and update frustum planes * Calculates view matrix and update frustum planes
* Should be called every frame. * Should be called every frame.
*/ */
void lookAt(Vector3 &t_target); void lookAt(Vector3 &t_target);
@@ -56,9 +56,10 @@ protected:
void updatePlanes(Vector3 t_target); void updatePlanes(Vector3 t_target);
private: private:
Vector3 *p_position, *p_up; Vector3 *p_position;
float farPlaneDist, nearPlaneDist, nearHeight, nearWidth, farHeight, farWidth; float farPlaneDist, nearPlaneDist, nearHeight, nearWidth, farHeight, farWidth;
Vector3 ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr; Vector3 ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr;
Vector3 up; // always 0.0F, 1.0F, 0.0F
}; };
#endif #endif
+2 -2
View File
@@ -34,7 +34,7 @@ public:
~GifSender(); ~GifSender();
void initPacket(u8 context); 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 addClear(zbuffer_t *t_zBuffer, color_t *t_rgb);
void sendPacket(); void sendPacket();
void sendClear(zbuffer_t *t_zBuffer, color_t *t_rgb); void sendClear(zbuffer_t *t_zBuffer, color_t *t_rgb);
@@ -54,7 +54,7 @@ private:
float halfScreenW, halfScreenH; float halfScreenW, halfScreenH;
MATRIX localWorld, localScreen, localLight; 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 convertCalcs(u32 t_vertCount, VECTOR *t_vertices, VECTOR *t_colors, VECTOR *t_sts, color_t &t_color);
void addCurrentCalcs(u32 &t_vertexCount); void addCurrentCalcs(u32 &t_vertexCount);
}; };
+64 -35
View File
@@ -13,6 +13,8 @@
#include <draw_buffers.h> #include <draw_buffers.h>
#include <draw_primitives.h> #include <draw_primitives.h>
#include <gs_privileged.h>
#include <draw.h>
#include <packet2.h> #include <packet2.h>
#include "gif_sender.hpp" #include "gif_sender.hpp"
#include "vif_sender.hpp" #include "vif_sender.hpp"
@@ -39,60 +41,87 @@ public:
void enableVSync() { isVSyncEnabled = true; } void enableVSync() { isVSyncEnabled = true; }
void disableVSync() { isVSyncEnabled = false; } 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); void draw(Sprite &t_sprite);
/** /// --- OBSOLETE
* 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 mesh with lighting information. // * WARNING: THIS FUNC CAUSE VISUAL ARTIFACTS!
* Slowest way of rendering (PATH 3, using EE and GIF). // * Draw many meshes with lighting information.
* NOTICE: Animation supported, lighting supported // * 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); // */
// void drawByPath3(Mesh *t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount);
/** // /**
* Draw many meshes without lighting information. // * WARNING: THIS FUNC CAUSE VISUAL ARTIFACTS!
* Slowest way of rendering (PATH 3, using EE and GIF). // * Draw mesh with lighting information.
* NOTICE: Animation supported, lighting supported // * Slowest way of rendering (PATH 3, using EE and GIF).
*/ // * NOTICE: Animation supported, lighting supported
void drawByPath3(Mesh *t_meshes, u16 t_amount); // */
// void drawByPath3(Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount);
/** // /**
* Draw mesh without lighting information. // * WARNING: THIS FUNC CAUSE VISUAL ARTIFACTS!
* Slowest way of rendering (PATH 3, using EE and GIF). // * Draw many meshes without lighting information.
* NOTICE: Animation supported, lighting supported // * Slowest way of rendering (PATH 3, using EE and GIF).
*/ // * NOTICE: Animation supported, lighting supported
void drawByPath3(Mesh &t_mesh); // */
// 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: 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). * Fastest way of rendering (PATH 1, using VU1).
* NOTICE: Animation supported, lighting NOT supported (at this moment) * 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. * Draw mesh with lighting information.
* Fastest way of rendering (PATH 1, using VU1). * Fastest way of rendering (PATH 1, using VU1).
* NOTICE: Animation supported, lighting NOT supported (at this moment) * NOTICE: Animation supported, lighting NOT supported (at this moment)
*/ */
void draw(Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount); void draw(Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount);
/** /**
* Draw many meshes without lighting information. * Draw many meshes without lighting information.
* Fastest way of rendering (PATH 1, using VU1). * 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) * 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. * Draw mesh without lighting information.
@@ -125,7 +154,7 @@ private:
void flipBuffers(); void flipBuffers();
void beginFrameIfNeeded(); void beginFrameIfNeeded();
u8 isFrameEmpty; u8 isFrameEmpty;
Matrix perspective; Matrix perspective, camRotation;
Light light; Light light;
RenderData renderData; RenderData renderData;
TextureRepository textureRepo; TextureRepository textureRepo;
@@ -134,8 +163,8 @@ private:
VifSender *vifSender; VifSender *vifSender;
packet2_t *flipPacket; packet2_t *flipPacket;
color_t worldColor; color_t worldColor;
void allocateBuffers(float t_screenW, float t_screenH); void allocateBuffers(int t_screenW, int t_screenH);
void initDrawingEnv(float t_screenW, float t_screenH); void initDrawingEnv();
void setPrim(); void setPrim();
}; };
@@ -45,23 +45,14 @@ public:
/** /**
* Returns single texture. * Returns single texture.
* NULL if not found. * 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++) for (u32 i = 0; i < textures.size(); i++)
if (textures[i]->isLinkedWith(t_spriteId)) if (textures[i]->isLinkedWith(t_id))
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))
return textures[i]; return textures[i];
return NULL; return NULL;
} }
+20 -5
View File
@@ -29,18 +29,33 @@ public:
~VifSender(); ~VifSender();
// TODO refactor // 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 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 sendMatrices(const RenderData &t_renderData, const Vector3 &t_position, const Vector3 &t_rotation); void calcMatrix(const RenderData &t_renderData, const Vector3 &t_position, const Vector3 &t_rotation);
void drawTheSameWithOtherMatrices(const RenderData &t_renderData, Mesh **t_meshes, const u32 &t_skip, const u32 &t_count);
void enableWait() { isDrawWaitEnabled = true; }
void disableWait() { isDrawWaitEnabled = false; }
private: private:
u32 lastVertCount; // needed for drawTheSameWithOtherMatrices()
u8 isLastRGBAOnly; // needed for drawTheSameWithOtherMatrices()
u8 isDrawWaitEnabled;
Light *light; Light *light;
void uploadMicroProgram(); void uploadMicroProgram();
void setDoubleBuffer(); 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 *textureBuffer); 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 *packets[2] __attribute__((aligned(64)));
packet2_t *currPacket; packet2_t *currPacket;
/**
* OpenGL name: Model
* Sony name: local world
*/
Matrix model;
/**
* OpenGL name: ModelViewProjection
* Sony name: local screen
*/
Matrix modelViewProj;
u8 context; u8 context;
packet2_t *matricesPacket __attribute__((aligned(64)));
VECTOR position, rotation; VECTOR position, rotation;
u32 vertCount; u32 vertCount;
}; };
+5 -5
View File
@@ -14,6 +14,7 @@
#include <tamtypes.h> #include <tamtypes.h>
#include <math3d.h> #include <math3d.h>
#include "../models/math/vector3.hpp" #include "../models/math/vector3.hpp"
#include <fastmath.h>
class Vector3; // Forward definition class Vector3; // Forward definition
@@ -24,16 +25,15 @@ class Math
{ {
public: public:
const static float HALF_ANG2RAD = 3.14159265358979323846F / 360.0F; constexpr static float HALF_ANG2RAD = 3.14159265358979323846F / 360.0F;
const static float ANG2RAD = 3.14159265358979323846F / 180.0F; constexpr static float ANG2RAD = 3.14159265358979323846F / 180.0F;
const static float PI = 3.1415926535897932384626433832795F; constexpr static float PI = 3.1415926535897932384626433832795F;
const static float HALF_PI = 1.5707963267948966192313216916398F; constexpr static float HALF_PI = 1.5707963267948966192313216916398F;
static float cos(float x); static float cos(float x);
static float asin(float x); static float asin(float x);
static float mod(float x, float y); static float mod(float x, float y);
static inline float sin(float x) { return cos(x - HALF_PI); }; static inline float sin(float x) { return cos(x - HALF_PI); };
static inline float tan(float x) { return sin(x) / cos(x); } static inline float tan(float x) { return sin(x) / cos(x); }
static float sqrt(float x);
static float invSqrt(float x); static float invSqrt(float x);
static inline u32 max(u32 a, u32 b) { return (a > b) ? a : b; } static inline u32 max(u32 a, u32 b) { return (a > b) ? a : b; }
static inline s32 max(s32 a, s32 b) { return (a > b) ? a : b; } static inline s32 max(s32 a, s32 b) { return (a > b) ? a : b; }
+2
View File
@@ -244,6 +244,8 @@ void DffLoader::readGeometryExtension(MeshFrame *o_frame, char **materialNames,
{ {
u32 facesCount = readDwordFromArrayLE(t_buffer, t_ptrPos); u32 facesCount = readDwordFromArrayLE(t_buffer, t_ptrPos);
u32 materialIndex = 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).allocateFaces(facesCount);
o_frame->getMaterial(i).setName(materialNames[materialIndex]); o_frame->getMaterial(i).setName(materialNames[materialIndex]);
for (u32 j = 0; j < facesCount; j++) for (u32 j = 0; j < facesCount; j++)
+2
View File
@@ -138,6 +138,8 @@ MeshFrame *MD2Loader::load(u32 &o_framesCount, char *t_subpath, char *t_nameWith
{ {
for (u32 x = 0; x < framesCount; x++) 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).setVertexFace((i * 3) + j, triangle->index_xyz[j]);
resultFrames[x].getMaterial(0).setSTFace((i * 3) + j, triangle->index_st[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]); resultFrames[x].getMaterial(0).setNormalFace((i * 3) + j, triangle->index_xyz[j]);
+95 -11
View File
@@ -36,6 +36,8 @@ void ObjLoader::load(MeshFrame *o_result, char *t_filename, float t_scale, u8 t_
fseek(file, 0, SEEK_SET); fseek(file, 0, SEEK_SET);
u32 verticesI = 0, cordsI = 0, normalsI = 0, faceI = 0, vertexIndex[3], coordIndex[3], normalIndex[3]; u32 verticesI = 0, cordsI = 0, normalsI = 0, faceI = 0, vertexIndex[3], coordIndex[3], normalIndex[3];
s16 materialsI = -1; s16 materialsI = -1;
Vector3 vector = Vector3();
Point point = Point();
while (1) while (1)
{ {
char lineHeader[128]; // read the first word of the line 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) if (strcmp(lineHeader, "v") == 0)
{ {
Vector3 vector = Vector3();
fscanf(file, "%f %f %f\n", &vector.x, &vector.y, &vector.z); fscanf(file, "%f %f %f\n", &vector.x, &vector.y, &vector.z);
o_result->setVertex(verticesI++, vector * t_scale); o_result->setVertex(verticesI++, vector * t_scale);
} }
else if (strcmp(lineHeader, "vt") == 0) else if (strcmp(lineHeader, "vt") == 0)
{ {
Point point = Point();
fscanf(file, "%f %f\n", &point.x, &point.y); fscanf(file, "%f %f\n", &point.x, &point.y);
if (t_invertT) if (t_invertT)
point.y = 1.0F - point.y; 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) else if (strcmp(lineHeader, "vn") == 0)
{ {
Vector3 vector = Vector3();
fscanf(file, "%f %f %f\n", &vector.x, &vector.y, &vector.z); fscanf(file, "%f %f %f\n", &vector.x, &vector.y, &vector.z);
o_result->setNormal(normalsI++, vector); 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) else if (strcmp(lineHeader, "f") == 0)
{ {
int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", int *x = &res; // random assignment, to disable compilation warning
&vertexIndex[0], &coordIndex[0], &normalIndex[0], fpos_t start;
&vertexIndex[1], &coordIndex[1], &normalIndex[1], fgetpos(file, &start);
&vertexIndex[2], &coordIndex[2], &normalIndex[2]); int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", x, x, x, x, x, x, x, x, x);
if (matches != 9) fsetpos(file, &start);
PRINT_ERR(".obj can't be read by this simple parser. Try exporting with other options"); int newerMatches = 0;
else
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, vertexIndex[0] - 1);
o_result->getMaterial(materialsI).setVertexFace(faceI + 1, vertexIndex[1] - 1); o_result->getMaterial(materialsI).setVertexFace(faceI + 1, vertexIndex[1] - 1);
o_result->getMaterial(materialsI).setVertexFace(faceI + 2, vertexIndex[2] - 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, coordIndex[0] - 1);
o_result->getMaterial(materialsI).setSTFace(faceI + 1, coordIndex[1] - 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).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, normalIndex[0] - 1);
o_result->getMaterial(materialsI).setNormalFace(faceI + 1, normalIndex[1] - 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).setNormalFace(faceI + 2, normalIndex[2] - 1);
o_result->getMaterial(materialsI).setNormalsPresent(true);
faceI += 3; 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 else
break; break;
} }
o_result->calculateBoundingBoxes(); o_result->calculateBoundingBoxes();
fclose(file); fclose(file);
delete[] path; delete[] path;
+21 -78
View File
@@ -38,13 +38,11 @@ void PngLoader::load(Texture &o_texture, char *t_subfolder, char *t_name, char *
char *path = String::createConcatenated(path_part2, t_extension); char *path = String::createConcatenated(path_part2, t_extension);
delete[] path_part1; delete[] path_part1;
delete[] path_part2; delete[] path_part2;
FILE *file = fopen(path, "rb"); FILE *file = fopen(path, "rb");
if (file == NULL) if (file == NULL)
{ PRINT_ERR("Failed to open .png file!");
PRINT_ERR("Failed to load .png file!");
return;
}
png_structp png_ptr; png_structp png_ptr;
png_infop info_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); png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL);
if (!png_ptr) if (!png_ptr)
{ PRINT_ERR("PNG struct info init failed(1)!");
printf("PNG Read Struct Init Failed\n");
fclose(file);
return;
}
info_ptr = png_create_info_struct(png_ptr); info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) if (!info_ptr)
{ PRINT_ERR("PNG struct info init failed(2)!");
printf("PNG Info Struct Init Failed\n");
fclose(file);
png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
return;
}
if (setjmp(png_jmpbuf(png_ptr))) if (setjmp(png_jmpbuf(png_ptr)))
{ PRINT_ERR("PNG reader fatal error!");
printf("Got PNG Error!\n");
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
fclose(file);
return;
}
png_init_io(png_ptr, file); 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; type = TEX_TYPE_RGB;
break; break;
default: 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); o_texture.setSize(width, height, type);
printf("PNGLoader - width: %d | height: %d\n", width, height); printf("PNGLoader - width: %d | height: %d\n", width, height);
if (type == TEX_TYPE_RGBA) size_t row_bytes = png_get_rowbytes(png_ptr, info_ptr);
{ png_byte *row_pointers[height];
int row_bytes = png_get_rowbytes(png_ptr, info_ptr); for (row = 0; row < height; row++)
png_byte *row_pointers[height]; row_pointers[row] = new png_byte[row_bytes];
for (row = 0; row < height; row++) png_read_image(png_ptr, row_pointers);
row_pointers[row] = new png_byte[row_bytes];
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; 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]);
u32 x = 0; if (type == TEX_TYPE_RGBA)
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]);
o_texture.setData(x + 3, ((int)row_pointers[i][4 * j + 3] * 128 / 255)); o_texture.setData(x + 3, ((int)row_pointers[i][4 * j + 3] * 128 / 255));
x += 4; x += 4;
} }
} else if (type == TEX_TYPE_RGB)
for (row = 0; row < height; row++)
delete row_pointers[row];
}
else if (type == TEX_TYPE_RGB)
{
int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
png_byte *row_pointers[height];
for (row = 0; row < height; row++)
row_pointers[row] = new png_byte[row_bytes];
png_read_image(png_ptr, row_pointers);
struct pixel3
{
u8 r, g, b;
};
u32 x = 0;
for (i = 0; i < height; i++)
{
for (j = 0; j < width; j++)
{
o_texture.setData(x, row_pointers[i][4 * j]);
o_texture.setData(x + 1, row_pointers[i][4 * j + 1]);
o_texture.setData(x + 2, row_pointers[i][4 * j + 2]);
x += 3; x += 3;
}
} }
for (row = 0; row < height; row++) for (row = 0; row < height; row++)
delete row_pointers[row]; delete[] row_pointers[row];
}
else
{
printf("This texture depth is not supported yet!\n");
return;
}
// Texture->Filter = GS_FILTER_NEAREST;
png_read_end(png_ptr, NULL); png_read_end(png_ptr, NULL);
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+1 -1
View File
@@ -46,4 +46,4 @@ BoundingBox::BoundingBox(Vector3 *t_vertices)
BoundingBox::~BoundingBox() BoundingBox::~BoundingBox()
{ {
} }
+273 -225
View File
@@ -17,11 +17,16 @@
// Constructors/Destructors // Constructors/Destructors
// ---- // ----
/** Create by specifying all points */ Matrix::Matrix()
Matrix::Matrix(float m11, float m12, float m13, float m14, {
float m21, float m22, float m23, float m24, for (u8 i = 0; i < 16; i++)
float m31, float m32, float m33, float m34, data[i] = 0.0F;
float m41, float m42, float m43, float m44) }
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[0] = m11;
data[1] = m12; data[1] = m12;
@@ -44,206 +49,51 @@ Matrix::Matrix(float m11, float m12, float m13, float m14,
data[15] = m44; 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]; float a[4] = {v.x, v.y, v.z, 1.0F};
data[1] = v.data[1]; float res[4];
data[2] = v.data[2]; asm volatile(
data[3] = v.data[3]; "lqc2 $vf4, 0x00(%1) \n\t"
"lqc2 $vf5, 0x10(%1) \n\t"
data[4] = v.data[4]; "lqc2 $vf6, 0x20(%1) \n\t"
data[5] = v.data[5]; "lqc2 $vf7, 0x30(%1) \n\t"
data[6] = v.data[6]; "lqc2 $vf8, 0x00(%2) \n\t"
data[7] = v.data[7]; "vmulax.xyzw $ACC, $vf4, $vf8 \n\t"
"vmadday.xyzw $ACC, $vf5, $vf8 \n\t"
data[8] = v.data[8]; "vmaddaz.xyzw $ACC, $vf6, $vf8 \n\t"
data[9] = v.data[9]; "vmaddw.xyzw $vf9, $vf7, $vf8 \n\t"
data[10] = v.data[10]; "sqc2 $vf9, 0x00(%0) \n\t"
data[11] = v.data[11]; :
: "r"(res), "r"(this->data), "r"(a));
data[12] = v.data[12]; return Vector3(res[0], res[1], res[2]);
data[13] = v.data[13];
data[14] = v.data[14];
data[15] = v.data[15];
} }
// ----
// Functions
// ----
void Matrix::identity() void Matrix::identity()
{ {
asm volatile( asm volatile(
"vsub.xyzw vf4, vf0, vf0 \n\t" "vsub.xyzw $vf4, $vf0, $vf0 \n\t"
"vadd.w vf4, vf4, vf0 \n\t" "vadd.w $vf4, $vf4, $vf0 \n\t"
"vmr32.xyzw vf5, vf4 \n\t" "vmr32.xyzw $vf5, $vf4 \n\t"
"vmr32.xyzw vf6, vf5 \n\t" "vmr32.xyzw $vf6, $vf5 \n\t"
"vmr32.xyzw vf7, vf6 \n\t" "vmr32.xyzw $vf7, $vf6 \n\t"
"sqc2 vf4, 0x30(%0) \n\t" "sqc2 $vf4, 0x30(%0) \n\t"
"sqc2 vf5, 0x20(%0) \n\t" "sqc2 $vf5, 0x20(%0) \n\t"
"sqc2 vf6, 0x10(%0) \n\t" "sqc2 $vf6, 0x10(%0) \n\t"
"sqc2 vf7, 0x0(%0) \n\t" "sqc2 $vf7, 0x0(%0) \n\t"
: :
: "r"(this->data)); : "r"(this->data));
} }
void Matrix::translate(const Vector3 &t_val) void Matrix::setPerspective(const ScreenSettings &t_screen)
{
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)
{ {
float fovYdiv2 = Math::HALF_ANG2RAD * t_screen.fov; float fovYdiv2 = Math::HALF_ANG2RAD * t_screen.fov;
float cotFOV = 1.0F / (Math::sin(fovYdiv2) / Math::cos(fovYdiv2)); 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; this->data[15] = 0.0F;
} }
/** Create a view matrix that transforms coordinates in void Matrix::lookAt(const Vector3 &t_position, const Vector3 &t_target)
* such a way that the user looks at a target vector
* direction from a position vector.
*
* Clone of OpenGL lookAt function
* https://learnopengl.com/Getting-started/Camera
*/
void Matrix::lookAt(Vector3 &t_up, Vector3 &t_position, Vector3 &t_target)
{ {
Vector3 camForward, camUp, camRight; 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; // Vector3 camForward, camUp, camRight;
camForward.normalize(); // Vector3 t_up = Vector3(0.0F, 1.0F, 0.0F);
camRight = t_up * camForward; // camForward = t_position - t_target;
camRight.normalize(); // camForward.normalize();
camUp = camForward * camRight; // camRight = t_up * camForward;
// camRight.normalize();
// camUp = camForward * camRight;
data[0] = camRight.x; // data[0] = camRight.x;
data[4] = camRight.y; // data[4] = camRight.y;
data[8] = camRight.z; // data[8] = camRight.z;
data[12] = -camRight.innerProduct(t_position); // data[12] = -camRight.innerProduct(t_position);
data[1] = camUp.x; // data[1] = camUp.x;
data[5] = camUp.y; // data[5] = camUp.y;
data[9] = camUp.z; // data[9] = camUp.z;
data[13] = -camUp.innerProduct(t_position); // data[13] = -camUp.innerProduct(t_position);
data[2] = camForward.x; // data[2] = camForward.x;
data[6] = camForward.y; // data[6] = camForward.y;
data[10] = camForward.z; // data[10] = camForward.z;
data[14] = -camForward.innerProduct(t_position); // data[14] = -camForward.innerProduct(t_position);
data[3] = 0; // data[3] = 0;
data[7] = 0; // data[7] = 0;
data[11] = 0; // data[11] = 0;
data[15] = 1; // data[15] = 1;
} }
const void Matrix::print() const const void Matrix::print() const
@@ -321,3 +186,186 @@ const void Matrix::print() const
data[8], data[9], data[10], data[11], data[8], data[9], data[10], data[11],
data[12], data[13], data[14], data[15]); 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");
}
+152 -233
View File
@@ -9,108 +9,59 @@
*/ */
#include "../../include/models/math/vector3.hpp" #include "../../include/models/math/vector3.hpp"
#include "../../include/utils/math.hpp" #include "../../include/utils/math.hpp"
#include <stdio.h>
// ---- // ----
// Constructors/Destructors // 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() Vector3::Vector3()
{ {
x = 0; x = 0.0F;
y = 0; y = 0.0F;
z = 0; z = 0.0F;
} }
Vector3::~Vector3() {}
// ---- // ----
// Methods // Operators
// ---- // ----
Vector3 Vector3::operator+(Vector3 v) Vector3 Vector3::operator+(const Vector3 &v) const
{ {
Vector3 result; Vector3 result;
asm volatile( // VU0 Macro program asm volatile( // VU0 Macro program
"lqc2 vf4, 0x0(%1) \n\t" "lqc2 $vf4, 0x0(%1) \n\t"
"lqc2 vf5, 0x0(%2) \n\t" "lqc2 $vf5, 0x0(%2) \n\t"
"vadd.xyz vf6, vf4, vf5 \n\t" "vadd.xyz $vf6, $vf4, $vf5 \n\t"
"sqc2 vf6, 0x0(%0) \n\t" "sqc2 $vf6, 0x0(%0) \n\t"
: :
: "r"(result.xyz), "r"(this->xyz), "r"(v.xyz)); : "r"(result.xyz), "r"(this->xyz), "r"(v.xyz));
return result; return result;
} }
Vector3 Vector3::operator-(const Vector3 &v) Vector3 Vector3::operator-(const Vector3 &v) const
{ {
Vector3 result; Vector3 result;
asm volatile( // VU0 Macro program asm volatile( // VU0 Macro program
"lqc2 vf4, 0x0(%1) \n\t" "lqc2 $vf4, 0x0(%1) \n\t"
"lqc2 vf5, 0x0(%2) \n\t" "lqc2 $vf5, 0x0(%2) \n\t"
"vsub.xyz vf6, vf4, vf5 \n\t" "vsub.xyz $vf6, $vf4, $vf5 \n\t"
"sqc2 vf6, 0x0(%0) \n\t" "sqc2 $vf6, 0x0(%0) \n\t"
: :
: "r"(result.xyz), "r"(this->xyz), "r"(v.xyz)); : "r"(result.xyz), "r"(this->xyz), "r"(v.xyz));
return result; return result;
} }
Vector3 Vector3::operator-(void) Vector3 Vector3::operator*(const Vector3 &v) const
{
Vector3 result;
result.x = -x;
result.y = -y;
result.z = -z;
return result;
}
/** Also called "cross product" */
Vector3 Vector3::operator*(Vector3 &v)
{ {
Vector3 res; Vector3 res;
asm volatile( // VU0 Macro program asm volatile( // VU0 Macro program
"lqc2 vf4, 0x0(%1) \n\t" // vf4 = this "lqc2 $vf4, 0x0(%1) \n\t" // $vf4 = this
"lqc2 vf5, 0x0(%2) \n\t" // vf5 = v "lqc2 $vf5, 0x0(%2) \n\t" // $vf5 = v
"vopmula.xyz ACC, vf4, vf5 \n\t" "vopmula.xyz $ACC, $vf4, $vf5 \n\t"
"vopmsub.xyz vf8, vf5, vf4 \n\t" "vopmsub.xyz $vf8, $vf5, $vf4 \n\t"
"vsub.w vf8, vf00, vf00 \n\t" "vsub.w $vf8, $vf0, $vf0 \n\t"
"sqc2 vf8, 0x0(%0) \n\t" // vf8 = res "sqc2 $vf8, 0x0(%0) \n\t" // $vf8 = res
: :
: "r"(res.xyz), "r"(this->xyz), "r"(v.xyz)); : "r"(res.xyz), "r"(this->xyz), "r"(v.xyz));
// result.x = y * v.z - z * v.y; // result.x = y * v.z - z * v.y;
@@ -119,33 +70,21 @@ Vector3 Vector3::operator*(Vector3 &v)
return res; return res;
} }
Vector3 Vector3::operator*(const float &t) Vector3 Vector3::operator*(const float &t) const
{ {
Vector3 result; Vector3 result;
asm volatile( asm volatile(
"lqc2 vf4, 0x0(%1) \n\t" "lqc2 $vf4, 0x0(%1) \n\t"
"mfc1 $8, %2 \n\t" "mfc1 $8, %2 \n\t"
"qmtc2 $8, vf5 \n\t" "qmtc2 $8, $vf5 \n\t"
"vmulx.xyz vf6, vf4, vf5 \n\t" "vmulx.xyz $vf6, $vf4, $vf5 \n\t"
"sqc2 vf6, 0x0(%0) \n\t" "sqc2 $vf6, 0x0(%0) \n\t"
: :
: "r"(result.xyz), "r"(this->xyz), "f"(t)); : "r"(result.xyz), "r"(this->xyz), "f"(t));
return result; return result;
} }
void Vector3::operator*=(const float &t) Vector3 Vector3::operator/(const float &t) const
{
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 result; Vector3 result;
result.x = x / t; result.x = x / t;
@@ -154,54 +93,78 @@ Vector3 Vector3::operator/(float t)
return result; 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 asm volatile( // VU0 Macro program
"lqc2 vf4, 0x0(%1) \n\t" "lqc2 $vf4, 0x0(%0) \n\t"
"vmul.xyz vf5, vf4, vf4 \n\t" "lqc2 $vf5, 0x0(%1) \n\t"
"vaddy.x vf5, vf5, vf5 \n\t" "vadd.xyz $vf4, $vf4, $vf5 \n\t"
"vaddz.x vf5, vf5, vf5 \n\t" "sqc2 $vf4, 0x0(%0) \n\t"
"vsqrt Q , vf5x \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" "vwaitq \n\t"
"vaddq.x vf8, vf0, Q \n\t" "vaddq.x $vf8, $vf0, $Q \n\t"
"qmfc2 $2, vf8 \n\t" "qmfc2 $2, $vf8 \n\t"
"mtc1 $2, %0 \n\t" "mtc1 $2, %0 \n\t"
: "=f"(result) : "=f"(result)
: "r"(this->xyz)); : "r"(this->xyz));
@@ -212,114 +175,35 @@ float Vector3::length()
void Vector3::normalize() void Vector3::normalize()
{ {
asm volatile( // VU0 Macro program asm volatile( // VU0 Macro program
"lqc2 vf4, 0x0(%0) \n\t" "lqc2 $vf4, 0x0(%0) \n\t"
"vmul.xyz vf5, vf4, vf4 \n\t" "vmul.xyz $vf5, $vf4, $vf4 \n\t"
"vaddy.x vf5, vf5, vf5 \n\t" "vaddy.x $vf5, $vf5, $vf5 \n\t"
"vaddz.x vf5, vf5, vf5 \n\t" "vaddz.x $vf5, $vf5, $vf5 \n\t"
"vrsqrt Q, vf0w, vf5x \n\t" "vrsqrt $Q, $vf0w, $vf5x \n\t"
"vwaitq \n\t" "vwaitq \n\t"
"vsub.xyz vf6, vf0, vf0 \n\t" "vsub.xyz $vf6, $vf0, $vf0 \n\t"
"vaddw.xyz vf6, vf6, vf4 \n\t" "vaddw.xyz $vf6, $vf6, $vf4 \n\t"
"vwaitq \n\t" "vwaitq \n\t"
"vmulq.xyz vf6, vf4, Q \n\t" "vmulq.xyz $vf6, $vf4, $Q \n\t"
"sqc2 vf6, 0x0(%0) \n\t" "sqc2 $vf6, 0x0(%0) \n\t"
: :
: "r"(this->xyz)); : "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 float Vector3::distanceTo(const Vector3 &v) const
{ {
register float result; register float result;
asm volatile( // VU0 Macro program asm volatile( // VU0 Macro program
"lqc2 vf4, 0x0(%1) \n\t" "lqc2 $vf4, 0x0(%1) \n\t"
"lqc2 vf5, 0x0(%2) \n\t" "lqc2 $vf5, 0x0(%2) \n\t"
"vsub.xyz vf6, vf4, vf5 \n\t" "vsub.xyz $vf6, $vf4, $vf5 \n\t"
"vmul.xyz vf7, vf6, vf6 \n\t" "vmul.xyz $vf7, $vf6, $vf6 \n\t"
"vaddy.x vf7, vf7, vf7 \n\t" "vaddy.x $vf7, $vf7, $vf7 \n\t"
"vaddz.x vf7, vf7, vf7 \n\t" "vaddz.x $vf7, $vf7, $vf7 \n\t"
"vsqrt Q , vf7x \n\t" "vsqrt $Q , $vf7x \n\t"
"vwaitq \n\t" "vwaitq \n\t"
"vaddq.x vf8, vf0, Q \n\t" "vaddq.x $vf8, $vf0, $Q \n\t"
"qmfc2 $2, vf8 \n\t" "qmfc2 $2, $vf8 \n\t"
"mtc1 $2, %0 \n\t" "mtc1 $2, %0 \n\t"
: "=f"(result) : "=f"(result)
: "r"(this->xyz), "r"(v.xyz)); : "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)); // (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);
} }
+67 -71
View File
@@ -28,6 +28,7 @@ Mesh::Mesh()
shouldBeFrustumCulled = true; shouldBeFrustumCulled = true;
shouldBeBackfaceCulled = false; shouldBeBackfaceCulled = false;
shouldBeLighted = false; shouldBeLighted = false;
_areFramesAllocated = false;
_isMother = false; _isMother = false;
scale = 1.0F; scale = 1.0F;
framesCount = 0; framesCount = 0;
@@ -40,13 +41,12 @@ Mesh::Mesh()
animState.isStayFrameSet = false; animState.isStayFrameSet = false;
animState.nextFrame = 0; animState.nextFrame = 0;
animState.speed = 0.1F; animState.speed = 0.1F;
setDefaultColor();
setDefaultLODAndClut(); setDefaultLODAndClut();
} }
Mesh::~Mesh() Mesh::~Mesh()
{ {
if (_isMother) if (_areFramesAllocated)
delete[] frames; delete[] frames;
} }
@@ -59,6 +59,7 @@ void Mesh::loadObj(char *t_subfolder, char *t_objFile, const float &t_scale, con
ObjLoader loader = ObjLoader(); ObjLoader loader = ObjLoader();
framesCount = 1; framesCount = 1;
frames = new MeshFrame[framesCount]; frames = new MeshFrame[framesCount];
_areFramesAllocated = true;
char *part1 = String::createConcatenated(t_subfolder, t_objFile); // "folder/object" char *part1 = String::createConcatenated(t_subfolder, t_objFile); // "folder/object"
char *finalPath = String::createConcatenated(part1, ".obj"); // "folder/object.obj" char *finalPath = String::createConcatenated(part1, ".obj"); // "folder/object.obj"
loader.load(&frames[0], finalPath, t_scale, t_invertT); 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(); ObjLoader loader = ObjLoader();
framesCount = t_framesCount; framesCount = t_framesCount;
frames = new MeshFrame[framesCount]; frames = new MeshFrame[framesCount];
_areFramesAllocated = true;
char *part1 = String::createConcatenated(t_subfolder, t_objFile); // "folder/object" char *part1 = String::createConcatenated(t_subfolder, t_objFile); // "folder/object"
char *part2 = String::createConcatenated(part1, "_"); // "folder/object_" char *part2 = String::createConcatenated(part1, "_"); // "folder/object_"
for (u32 i = 0; i < framesCount; i++) 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"); char *dffPath = String::createConcatenated(part1, ".dff");
framesCount = 1; framesCount = 1;
frames = new MeshFrame[1]; frames = new MeshFrame[1];
_areFramesAllocated = true;
loader.load(frames, dffPath, t_scale, t_invertT); loader.load(frames, dffPath, t_scale, t_invertT);
delete[] part1; delete[] part1;
delete[] dffPath; 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) void Mesh::loadFrom(const Mesh &t_mesh)
{ {
frames = t_mesh.frames;
framesCount = t_mesh.framesCount; 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) 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( asm volatile(
// VU0 macro program: // VU0 macro program:
// Load vector with 1.0F values to VF21 // 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)); : "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 // Calculate lerp() and store data into calc3Vectors
// Vertex 0 // Vertex 0
"lqc2 vf4, 0x0(%3) \n\t" // vf4 = v1 "lqc2 $vf4, 0x0(%3) \n\t" // $vf4 = v1
"lqc2 vf5, 0x0(%6) \n\t" // vf5 = v2 "lqc2 $vf5, 0x0(%6) \n\t" // $vf5 = v2
"mfc1 $10, %9 \n\t" // vf6 = t "mfc1 $10, %9 \n\t" // $vf6 = t
"qmtc2 $10, vf6 \n\t" // lerp: "qmtc2 $10, $vf6 \n\t" // lerp:
"vsub.xyz vf7, vf5, vf4 \n\t" // vf7 = v2 - v1 "vsub.xyz $vf7, $vf5, $vf4 \n\t" // $vf7 = v2 - v1
"vmulx.xyz vf8, vf7, vf6 \n\t" // vf8 = vf7 * t "vmulx.xyz $vf8, $vf7, $vf6 \n\t" // $vf8 = $vf7 * t
"vadd.xyz vf9, vf8, vf4 \n\t" // vf9 = vf8 + vf4 "vadd.xyz $vf9, $vf8, $vf4 \n\t" // $vf9 = $vf8 + $vf4
"sqc2 vf9, 0x0(%0) \n\t" // v0 = vf9 "sqc2 $vf9, 0x0(%0) \n\t" // v0 = $vf9
// Vertex 1 // Vertex 1
"lqc2 vf4, 0x0(%4) \n\t" // vf4 = v1 "lqc2 $vf4, 0x0(%4) \n\t" // $vf4 = v1
"lqc2 vf5, 0x0(%7) \n\t" // vf5 = v2 "lqc2 $vf5, 0x0(%7) \n\t" // $vf5 = v2
"mfc1 $10, %9 \n\t" // vf6 = t "mfc1 $10, %9 \n\t" // $vf6 = t
"qmtc2 $10, vf6 \n\t" // lerp: "qmtc2 $10, $vf6 \n\t" // lerp:
"vsub.xyz vf7, vf5, vf4 \n\t" // vf7 = v2 - v1 "vsub.xyz $vf7, $vf5, $vf4 \n\t" // $vf7 = v2 - v1
"vmulx.xyz vf8, vf7, vf6 \n\t" // vf8 = vf7 * t "vmulx.xyz $vf8, $vf7, $vf6 \n\t" // $vf8 = $vf7 * t
"vadd.xyz vf9, vf8, vf4 \n\t" // vf9 = vf8 + vf4 "vadd.xyz $vf9, $vf8, $vf4 \n\t" // $vf9 = $vf8 + $vf4
"sqc2 vf9, 0x0(%1) \n\t" // v0 = vf9 "sqc2 $vf9, 0x0(%1) \n\t" // v0 = $vf9
// Vertex 2 // Vertex 2
"lqc2 vf4, 0x0(%5) \n\t" // vf4 = v1 "lqc2 $vf4, 0x0(%5) \n\t" // $vf4 = v1
"lqc2 vf5, 0x0(%8) \n\t" // vf5 = v2 "lqc2 $vf5, 0x0(%8) \n\t" // $vf5 = v2
"mfc1 $10, %9 \n\t" // vf6 = t "mfc1 $10, %9 \n\t" // $vf6 = t
"qmtc2 $10, vf6 \n\t" // lerp: "qmtc2 $10, $vf6 \n\t" // lerp:
"vsub.xyz vf7, vf5, vf4 \n\t" // vf7 = v2 - v1 "vsub.xyz $vf7, $vf5, $vf4 \n\t" // $vf7 = v2 - v1
"vmulx.xyz vf8, vf7, vf6 \n\t" // vf8 = vf7 * t "vmulx.xyz $vf8, $vf7, $vf6 \n\t" // $vf8 = $vf7 * t
"vadd.xyz vf9, vf8, vf4 \n\t" // vf9 = vf8 + vf4 "vadd.xyz $vf9, $vf8, $vf4 \n\t" // $vf9 = $vf8 + $vf4
"sqc2 vf9, 0x0(%2) \n\t" // v0 = vf9 "sqc2 $vf9, 0x0(%2) \n\t" // v0 = $vf9
: :
: "r"(calc3Vectors[0].xyz), : "r"(calc3Vectors[0].xyz),
@@ -262,12 +268,12 @@ u32 Mesh::getDrawData(u32 t_materialIndex, VECTOR *o_vertices, VECTOR *o_normals
asm volatile( asm volatile(
// VU0 macro program // VU0 macro program
// Copy 0,1,2 vertices // Copy 0,1,2 vertices
"lqc2 vf1, 0x0(%3) \n\t" // load vert "lqc2 $vf1, 0x0(%3) \n\t" // load vert
"lqc2 vf2, 0x0(%4) \n\t" // load normal "lqc2 $vf2, 0x0(%4) \n\t" // load normal
"lqc2 vf3, 0x0(%5) \n\t" // load st "lqc2 $vf3, 0x0(%5) \n\t" // load st
"sqc2 vf1, 0x0(%0) \n\t" // store vert "sqc2 $vf1, 0x0(%0) \n\t" // store vert
"sqc2 vf2, 0x0(%1) \n\t" // store normal "sqc2 $vf2, 0x0(%1) \n\t" // store normal
"sqc2 vf3, 0x0(%2) \n\t" // store st "sqc2 $vf3, 0x0(%2) \n\t" // store st
: :
: "r"(calc3Vectors[0].xyz), : "r"(calc3Vectors[0].xyz),
"r"(calc3Vectors[1].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 // Copy data and set vert/normal "w" and st "z"+"w" to 1.0F
// Vertex 0 // Vertex 0
"lqc2 vf1, 0x0(%3) \n\t" // load vert "lqc2 $vf1, 0x0(%3) \n\t" // load vert
"lqc2 vf2, 0x0(%4) \n\t" // load normal "lqc2 $vf2, 0x0(%4) \n\t" // load normal
"lqc2 vf3, 0x0(%5) \n\t" // load st "lqc2 $vf3, 0x0(%5) \n\t" // load st
"vadd.w vf1, vf20, vf21 \n\t" // set vert.w to 1.0F "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.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 "vadd.zw $vf3, $vf20, $vf21 \n\t" // set st.zw to 1.0F
"sqc2 vf1, 0x0(%0) \n\t" // store vert "sqc2 $vf1, 0x0(%0) \n\t" // store vert
"sqc2 vf2, 0x0(%1) \n\t" // store normal "sqc2 $vf2, 0x0(%1) \n\t" // store normal
"sqc2 vf3, 0x0(%2) \n\t" // store st "sqc2 $vf3, 0x0(%2) \n\t" // store st
// Vertex 1 // Vertex 1
"lqc2 vf1, 0x0(%9) \n\t" // load vert "lqc2 $vf1, 0x0(%9) \n\t" // load vert
"lqc2 vf2, 0x0(%10) \n\t" // load normal "lqc2 $vf2, 0x0(%10) \n\t" // load normal
"lqc2 vf3, 0x0(%11) \n\t" // load st "lqc2 $vf3, 0x0(%11) \n\t" // load st
"vadd.w vf1, vf20, vf21 \n\t" // set vert.w to 1.0F "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.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 "vadd.zw $vf3, $vf20, $vf21 \n\t" // set st.zw to 1.0F
"sqc2 vf1, 0x0(%6) \n\t" // store vert "sqc2 $vf1, 0x0(%6) \n\t" // store vert
"sqc2 vf2, 0x0(%7) \n\t" // store normal "sqc2 $vf2, 0x0(%7) \n\t" // store normal
"sqc2 vf3, 0x0(%8) \n\t" // store st "sqc2 $vf3, 0x0(%8) \n\t" // store st
// Vertex 2 // Vertex 2
"lqc2 vf1, 0x0(%15) \n\t" // load vert "lqc2 $vf1, 0x0(%15) \n\t" // load vert
"lqc2 vf2, 0x0(%16) \n\t" // load normal "lqc2 $vf2, 0x0(%16) \n\t" // load normal
"lqc2 vf3, 0x0(%17) \n\t" // load st "lqc2 $vf3, 0x0(%17) \n\t" // load st
"vadd.w vf1, vf20, vf21 \n\t" // set vert.w to 1.0F "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.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 "vadd.zw $vf3, $vf20, $vf21 \n\t" // set st.zw to 1.0F
"sqc2 vf1, 0x0(%12) \n\t" // store vert "sqc2 $vf1, 0x0(%12) \n\t" // store vert
"sqc2 vf2, 0x0(%13) \n\t" // store normal "sqc2 $vf2, 0x0(%13) \n\t" // store normal
"sqc2 vf3, 0x0(%14) \n\t" // store st "sqc2 $vf3, 0x0(%14) \n\t" // store st
: :
: "r"(o_vertices[addedFaces]), : "r"(o_vertices[addedFaces]),
@@ -375,16 +381,6 @@ u8 Mesh::isInFrustum(Plane *t_frustumPlanes)
return boxResult; 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 */ /** Sets texture level of details settings and CLUT settings */
void Mesh::setDefaultLODAndClut() void Mesh::setDefaultLODAndClut()
{ {
+41 -13
View File
@@ -8,6 +8,7 @@
# Sandro Sobczyński <sandro.sobczynski@gmail.com> # Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/ */
#include <cstdlib>
#include "../include/models/mesh_frame.hpp" #include "../include/models/mesh_frame.hpp"
#include "../include/utils/debug.hpp" #include "../include/utils/debug.hpp"
@@ -17,6 +18,7 @@
MeshFrame::MeshFrame() MeshFrame::MeshFrame()
{ {
id = rand() % 1000000;
vertexCount = 0; vertexCount = 0;
stsCount = 0; stsCount = 0;
normalsCount = 0; normalsCount = 0;
@@ -25,19 +27,23 @@ MeshFrame::MeshFrame()
_areVerticesAllocated = false; _areVerticesAllocated = false;
_areNormalsAllocated = false; _areNormalsAllocated = false;
_areMaterialsAllocated = false; _areMaterialsAllocated = false;
_isMother = true;
} }
MeshFrame::~MeshFrame() MeshFrame::~MeshFrame()
{ {
if (_areSTsAllocated) if (_isMother)
delete[] sts; {
if (_areVerticesAllocated) if (_areSTsAllocated)
delete[] vertices; delete[] sts;
if (_areNormalsAllocated) if (_areVerticesAllocated)
delete[] normals; delete[] vertices;
if (_areNormalsAllocated)
delete[] normals;
delete boundingBoxObj;
}
if (_areMaterialsAllocated) if (_areMaterialsAllocated)
delete[] materials; delete[] materials;
delete boundingBoxObj;
} }
// ---- // ----
@@ -94,14 +100,12 @@ void MeshFrame::allocateMaterials(const u32 &t_val)
void MeshFrame::calculateBoundingBoxes() void MeshFrame::calculateBoundingBoxes()
{ {
Vector3 boundingBox[8];
if (!_areVerticesAllocated) if (!_areVerticesAllocated)
{
PRINT_ERR("Can't calculate bounding box, because vertices were not allocated!"); PRINT_ERR("Can't calculate bounding box, because vertices were not allocated!");
return;
}
for (u32 i = 0; i < materialsCount; i++) for (u32 i = 0; i < materialsCount; i++)
materials->calculateBoundingBox(vertices, vertexCount); materials->calculateBoundingBox(vertices, vertexCount);
float lowX, lowY, lowZ, hiX, hiY, hiZ; float lowX, lowY, lowZ, hiX, hiY, hiZ;
lowX = hiX = vertices[0].x; lowX = hiX = vertices[0].x;
lowY = hiY = vertices[0].y; lowY = hiY = vertices[0].y;
@@ -124,6 +128,7 @@ void MeshFrame::calculateBoundingBoxes()
hiZ = vertices[i].z; hiZ = vertices[i].z;
} }
Vector3 boundingBox[8];
boundingBox[0].set(lowX, lowY, lowZ); boundingBox[0].set(lowX, lowY, lowZ);
boundingBox[1].set(lowX, lowY, hiZ); boundingBox[1].set(lowX, lowY, hiZ);
boundingBox[2].set(lowX, hiY, lowZ); boundingBox[2].set(lowX, hiY, lowZ);
@@ -135,7 +140,30 @@ void MeshFrame::calculateBoundingBoxes()
boundingBox[7].set(hiX, hiY, hiZ); boundingBox[7].set(hiX, hiY, hiZ);
_isBoundingBoxCalculated = true; _isBoundingBoxCalculated = true;
//BoundingBox is declared on the heap to prevent any ill-formed default // BoundingBox is declared on the heap to prevent any ill-formed default
//constructor instantiated BoundingBox objects. // constructor instantiated BoundingBox objects.
boundingBoxObj = new BoundingBox(boundingBox); 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;
}
+44 -7
View File
@@ -25,18 +25,25 @@ MeshMaterial::MeshMaterial()
_isNameSet = false; _isNameSet = false;
_areFacesAllocated = false; _areFacesAllocated = false;
_isBoundingBoxCalculated = false; _isBoundingBoxCalculated = false;
_areSTsPresent = false;
_areNormalsPresent = false;
_isMother = true;
setDefaultColor();
} }
MeshMaterial::~MeshMaterial() MeshMaterial::~MeshMaterial()
{ {
if (_areFacesAllocated) if (_isMother)
{ {
delete[] vertexFaces; if (_areFacesAllocated)
delete[] stFaces; {
delete[] normalFaces; 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) void MeshMaterial::calculateBoundingBox(Vector3 *t_vertices, u32 t_vertCount)
{ {
Vector3 boundingBox[8];
float lowX, lowY, lowZ, hiX, hiY, hiZ; float lowX, lowY, lowZ, hiX, hiY, hiZ;
lowX = hiX = t_vertices[vertexFaces[0]].x; lowX = hiX = t_vertices[vertexFaces[0]].x;
lowY = hiY = t_vertices[vertexFaces[0]].y; 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) if (hiZ < t_vertices[vertexFaces[i]].z)
hiZ = t_vertices[vertexFaces[i]].z; hiZ = t_vertices[vertexFaces[i]].z;
} }
Vector3 boundingBox[8];
boundingBox[0].set(lowX, lowY, lowZ); boundingBox[0].set(lowX, lowY, lowZ);
boundingBox[1].set(lowX, lowY, hiZ); boundingBox[1].set(lowX, lowY, hiZ);
boundingBox[2].set(lowX, hiY, lowZ); boundingBox[2].set(lowX, hiY, lowZ);
@@ -139,3 +147,32 @@ void MeshMaterial::calculateBoundingBox(Vector3 *t_vertices, u32 t_vertCount)
//constructor instantiated BoundingBox objects. //constructor instantiated BoundingBox objects.
boundingBoxObj = new BoundingBox(boundingBox); 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;
}
+2 -11
View File
@@ -82,18 +82,9 @@ void Texture::setWrapSettings(const WrapSettings t_horizontal, const WrapSetting
wrapSettings.vertical = t_vertical; wrapSettings.vertical = t_vertical;
} }
void Texture::addLink(const u32 &t_meshId, const u32 &t_materialId) void Texture::addLink(const u32 &t_id)
{ {
TextureLink link; TextureLink link;
link.materialId = t_materialId; link.id = t_id;
link.meshOrSpriteId = t_meshId;
texLinks.push_back(link);
}
void Texture::addLink(const u32 &t_spriteId)
{
TextureLink link;
link.materialId = 0;
link.meshOrSpriteId = t_spriteId;
texLinks.push_back(link); texLinks.push_back(link);
} }
+23 -8
View File
@@ -89,24 +89,25 @@ void Audio::setSongVolume(const u8 &t_vol)
u32 Audio::addSongListener(AudioListener *t_listener) u32 Audio::addSongListener(AudioListener *t_listener)
{ {
AudioListenerRef ref; AudioListenerRef *ref = new AudioListenerRef;
ref.id = rand() % 1000000; ref->id = rand() % 1000000;
ref.listener = t_listener; ref->listener = t_listener;
songListeners.push_back(ref); songListeners.push_back(ref);
return ref.id; return ref->id;
} }
void Audio::removeSongListener(const u32 &t_id) void Audio::removeSongListener(const u32 &t_id)
{ {
s32 index = -1; s32 index = -1;
for (u32 i = 0; i < songListeners.size(); i++) for (u32 i = 0; i < songListeners.size(); i++)
if (songListeners[i].id == t_id) if (songListeners[i]->id == t_id)
{ {
index = i; index = i;
break; break;
} }
if (index == -1) if (index == -1)
PRINT_ERR("Cant remove listener because given id was not found!"); PRINT_ERR("Cant remove listener because given id was not found!");
delete songListeners[index];
songListeners.erase(songListeners.begin() + 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) void Audio::startThread(FileService *t_fileService)
{ {
PRINT_LOG("Creating audio thread"); PRINT_LOG("Creating audio thread");
fileService = t_fileService; // fileService = t_fileService;
extern void *_gp; extern void *_gp;
thread.func = (void *)Audio::mainThread; thread.func = (void *)Audio::mainThread;
thread.stack = threadStack; thread.stack = threadStack;
@@ -177,6 +178,20 @@ void Audio::startThread(FileService *t_fileService)
/** Main thread loop */ /** Main thread loop */
void Audio::threadLoop() 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) if (!songPlaying || !songLoaded)
return; return;
if (songFinished) if (songFinished)
@@ -186,7 +201,7 @@ void Audio::threadLoop()
{ {
printf("Running again.\n"); printf("Running again.\n");
for (u32 i = 0; i < getSongListenersCount(); i++) for (u32 i = 0; i < getSongListenersCount(); i++)
songListeners[i].listener->onAudioFinish(); songListeners[i]->listener->onAudioFinish();
rewindSongToStart(); rewindSongToStart();
} }
else else
@@ -202,7 +217,7 @@ void Audio::threadLoop()
WaitSema(fillbufferSema); // wait until previous chunk wasn't finished WaitSema(fillbufferSema); // wait until previous chunk wasn't finished
audsrv_play_audio(wavChunk, chunkReadStatus); audsrv_play_audio(wavChunk, chunkReadStatus);
for (u32 i = 0; i < getSongListenersCount(); i++) for (u32 i = 0; i < getSongListenersCount(); i++)
songListeners[i].listener->onAudioTick(); songListeners[i]->listener->onAudioTick();
} }
chunkReadStatus = fread(wavChunk, 1, sizeof(wavChunk), wav); chunkReadStatus = fread(wavChunk, 1, sizeof(wavChunk), wav);
+4 -4
View File
@@ -18,7 +18,7 @@
// Constructors/Destructors // Constructors/Destructors
// ---- // ----
CameraBase::CameraBase(ScreenSettings *t_screen, Vector3 *t_position, Vector3 *t_up) CameraBase::CameraBase(ScreenSettings *t_screen, Vector3 *t_position)
: screen(t_screen) : screen(t_screen)
{ {
PRINT_LOG("Initializing frustum"); PRINT_LOG("Initializing frustum");
@@ -30,7 +30,7 @@ CameraBase::CameraBase(ScreenSettings *t_screen, Vector3 *t_position, Vector3 *t
farHeight = tang * farPlaneDist; farHeight = tang * farPlaneDist;
farWidth = farHeight * screen->aspectRatio; farWidth = farHeight * screen->aspectRatio;
p_position = t_position; p_position = t_position;
p_up = t_up; up.set(0.0F, 1.0F, 0.0F);
PRINT_LOG("CameraBase initialized!"); PRINT_LOG("CameraBase initialized!");
} }
@@ -41,7 +41,7 @@ CameraBase::CameraBase(ScreenSettings *t_screen, Vector3 *t_position, Vector3 *t
void CameraBase::lookAt(Vector3 &t_target) void CameraBase::lookAt(Vector3 &t_target)
{ {
updatePlanes(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) void CameraBase::updatePlanes(Vector3 t_target)
@@ -51,7 +51,7 @@ void CameraBase::updatePlanes(Vector3 t_target)
Z = *p_position - t_target; Z = *p_position - t_target;
Z.normalize(); Z.normalize();
// X axis of camera of given "up" vector and Z axis // X axis of camera of given "up" vector and Z axis
X = *p_up * Z; X = up * Z;
X.normalize(); X.normalize();
// the real "up" vector is the cross product of Z and X // the real "up" vector is the cross product of Z and X
Y = Z * X; Y = Z * X;
+14 -22
View File
@@ -130,22 +130,17 @@ void GifSender::addClear(zbuffer_t *t_zBuffer, color_t *t_rgb)
packet2_chain_close_tag(currentPacket); packet2_chain_close_tag(currentPacket);
} }
/** Adds 3D objects to current packet /** Adds meshes to current packet */
* @param worldView Matrix 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)
* @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)
{ {
packet2_chain_open_cnt(currentPacket, 0, 0, 0); packet2_chain_open_cnt(currentPacket, 0, 0, 0);
packet2_update(currentPacket, draw_texture_sampling(currentPacket->next, 0, &t_mesh.lod)); 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_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]; xyz = new xyz_t[vertexCount];
rgbaq = new color_t[vertexCount]; rgbaq = new color_t[vertexCount];
st = new texel_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); addCurrentCalcs(vertexCount);
delete[] xyz; delete[] xyz;
delete[] rgbaq; 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 /** Calculates 3D object data into xyz, rgbq, st
* After it addCurrentSTQ() can be done * After it addCurrentCalcs() can be done
* @param worldView Matrix
* @param perspective Matrix with .setPerpsective() used [clone of gluPerspective]
* @param mesh 3D object
*/ */
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 *colors = new VECTOR[vertexCount];
VECTOR position, rotation; VECTOR position, rotation;
@@ -176,7 +168,7 @@ void GifSender::calc3DObject(Matrix t_perspective, Mesh &t_mesh, u32 vertexCount
create_local_light(localLight, rotation); create_local_light(localLight, rotation);
// I cant put perspective from renderData here. ee-gcc bug? // 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) 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++) for (u32 i = 0; i < vertexCount; i++)
{ {
// Apply the light value to the colour. // Apply the light value to the colour.
colors[i][0] = (t_mesh.color.r * lights[i][0]); colors[i][0] = (t_color->r * lights[i][0]);
colors[i][1] = (t_mesh.color.g * lights[i][1]); colors[i][1] = (t_color->g * lights[i][1]);
colors[i][2] = (t_mesh.color.b * lights[i][2]); colors[i][2] = (t_color->b * lights[i][2]);
vector_clamp(colors[i], colors[i], 0.00F, 1.99F); 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 else
for (u32 i = 0; i < vertexCount; i++) for (u32 i = 0; i < vertexCount; i++)
{ {
colors[i][0] = t_mesh.color.r / 128.0F; colors[i][0] = t_color->r / 128.0F;
colors[i][1] = t_mesh.color.g / 128.0F; colors[i][1] = t_color->g / 128.0F;
colors[i][2] = t_mesh.color.b / 128.0F; colors[i][2] = t_color->b / 128.0F;
} }
calculate_vertices(vertices, vertexCount, vertices, localScreen); calculate_vertices(vertices, vertexCount, vertices, localScreen);
convertCalcs(vertexCount, vertices, colors, coordinates, t_mesh.color); convertCalcs(vertexCount, vertices, colors, coordinates, *t_color);
delete[] colors; delete[] colors;
} }
+109 -72
View File
@@ -13,8 +13,6 @@
#include <dma.h> #include <dma.h>
#include <graph.h> #include <graph.h>
#include <packet.h> #include <packet.h>
#include <draw.h>
#include <gs_psm.h>
#include "../include/utils/debug.hpp" #include "../include/utils/debug.hpp"
#include "../include/utils/math.hpp" #include "../include/utils/math.hpp"
@@ -22,6 +20,9 @@
// Constructors/Destructors // Constructors/Destructors
// ---- // ----
static const float GS_CENTER = 4096.0F;
static const float SCREEN_CENTER = GS_CENTER / 2.0F;
/** Initialize DMA<->GIF channel /** Initialize DMA<->GIF channel
* Allocate buffers * Allocate buffers
* Initialize screen * Initialize screen
@@ -35,23 +36,23 @@ Renderer::Renderer(u32 t_packetSize, ScreenSettings *t_screen)
PRINT_LOG("Initializing renderer"); PRINT_LOG("Initializing renderer");
dma_channel_initialize(DMA_CHANNEL_GIF, NULL, 0); // Initialize DMA to enable data transfer dma_channel_initialize(DMA_CHANNEL_GIF, NULL, 0); // Initialize DMA to enable data transfer
dma_channel_fast_waits(DMA_CHANNEL_GIF); dma_channel_fast_waits(DMA_CHANNEL_GIF);
screen = t_screen;
context = 0; context = 0;
isTextureVRAMAllocated = false; isTextureVRAMAllocated = false;
isVSyncEnabled = true; isVSyncEnabled = true;
isFrameEmpty = false; isFrameEmpty = false;
lastTextureId = 0; lastTextureId = 0;
flipPacket = packet2_create(4, P2_TYPE_UNCACHED_ACCL, P2_MODE_NORMAL, 0); flipPacket = packet2_create(4, P2_TYPE_UNCACHED_ACCL, P2_MODE_NORMAL, 0);
allocateBuffers(t_screen->width, t_screen->height); allocateBuffers((int)t_screen->width, (int)t_screen->height);
initDrawingEnv(t_screen->width, t_screen->height); initDrawingEnv();
setPrim(); setPrim();
worldColor.r = 0x10; worldColor.r = 0x10;
worldColor.g = 0x10; worldColor.g = 0x10;
worldColor.b = 0x10; worldColor.b = 0x10;
screen = t_screen;
gifSender = new GifSender(t_packetSize, t_screen, &light); gifSender = new GifSender(t_packetSize, t_screen, &light);
vifSender = new VifSender(&light); vifSender = new VifSender(&light);
perspective.setPerspective(*t_screen); perspective.setPerspective(*t_screen);
renderData.perspective = &perspective; renderData.projection = &perspective;
PRINT_LOG("Renderer initialized!"); PRINT_LOG("Renderer initialized!");
} }
@@ -104,7 +105,7 @@ void Renderer::changeTexture(Texture *t_tex)
void Renderer::draw(Sprite &t_sprite) void Renderer::draw(Sprite &t_sprite)
{ {
Texture *texture = textureRepo.getBySprite(t_sprite.getId()); Texture *texture = textureRepo.getBySpriteOrMesh(t_sprite.getId());
texrect_t rect; texrect_t rect;
float sizeX, sizeY; float sizeX, sizeY;
if (t_sprite.getMode() == MODE_REPEAT) if (t_sprite.getMode() == MODE_REPEAT)
@@ -142,7 +143,7 @@ void Renderer::draw(Sprite &t_sprite)
beginFrameIfNeeded(); beginFrameIfNeeded();
changeTexture(texture); changeTexture(texture);
packet2_t *packet2 = packet2_create(12, P2_TYPE_NORMAL, P2_MODE_NORMAL, 0); 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_gif_add_set(packet2, 1);
packet2_utils_gs_add_texbuff_clut(packet2, &textureBuffer, &t_sprite.clut); packet2_utils_gs_add_texbuff_clut(packet2, &textureBuffer, &t_sprite.clut);
draw_enable_blending(); draw_enable_blending();
@@ -151,7 +152,8 @@ void Renderer::draw(Sprite &t_sprite)
draw_primitive_xyoffset( draw_primitive_xyoffset(
packet2->next, packet2->next,
0, 0,
(2048 - (screen->width / 2)), (2048 - (screen->height / 2)))); SCREEN_CENTER - (screen->width / 2.0F),
SCREEN_CENTER - (screen->height / 2.0F)));
draw_disable_blending(); draw_disable_blending();
packet2_update(packet2, draw_finish(packet2->next)); packet2_update(packet2, draw_finish(packet2->next));
dma_channel_wait(DMA_CHANNEL_GIF, 0); dma_channel_wait(DMA_CHANNEL_GIF, 0);
@@ -160,14 +162,14 @@ void Renderer::draw(Sprite &t_sprite)
} }
/** Initializes drawing environment (1st app packet) */ /** Initializes drawing environment (1st app packet) */
void Renderer::initDrawingEnv(float t_screenW, float t_screenH) void Renderer::initDrawingEnv()
{ {
PRINT_LOG("Initializing drawing environment"); 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_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_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)); packet2_update(packet2, draw_finish(packet2->next));
dma_channel_send_packet2(packet2, DMA_CHANNEL_GIF, true); dma_channel_send_packet2(packet2, DMA_CHANNEL_GIF, true);
dma_channel_wait(DMA_CHANNEL_GIF, 0); 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 */ /** 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].width = (unsigned int)t_screenW;
frameBuffers[0].height = (u16)t_screenH; frameBuffers[0].height = (unsigned int)t_screenH;
frameBuffers[0].mask = 0; frameBuffers[0].mask = 0;
frameBuffers[0].psm = GS_PSM_24; frameBuffers[0].psm = GS_PSM_32;
frameBuffers[0].address = graph_vram_allocate((u16)t_screenW, (u16)t_screenH, frameBuffers[0].psm, GRAPH_ALIGN_PAGE); frameBuffers[0].address = graph_vram_allocate(t_screenW, t_screenH, frameBuffers[0].psm, GRAPH_ALIGN_PAGE);
frameBuffers[1].width = (u16)t_screenW; frameBuffers[1].width = (unsigned int)t_screenW;
frameBuffers[1].height = (u16)t_screenH; frameBuffers[1].height = (unsigned int)t_screenH;
frameBuffers[1].mask = 0; frameBuffers[1].mask = 0;
frameBuffers[1].psm = GS_PSM_24; frameBuffers[1].psm = GS_PSM_32;
frameBuffers[1].address = graph_vram_allocate((u16)t_screenW, (u16)t_screenH, frameBuffers[1].psm, GRAPH_ALIGN_PAGE); frameBuffers[1].address = graph_vram_allocate(t_screenW, t_screenH, frameBuffers[1].psm, GRAPH_ALIGN_PAGE);
zBuffer.enable = DRAW_ENABLE; zBuffer.enable = DRAW_ENABLE;
zBuffer.mask = 0; zBuffer.mask = 0;
zBuffer.method = ZTEST_METHOD_GREATER_EQUAL; zBuffer.method = ZTEST_METHOD_GREATER_EQUAL;
zBuffer.zsm = GS_ZBUF_24; 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!"); PRINT_LOG("Framebuffers, zBuffer set and allocated!");
// Initialize the screen and tie the first framebuffer to the read circuits. // 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 /// --- Draw: PATH3
void Renderer::drawByPath3(Mesh *t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 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); // 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) // Obsolete
{ // void Renderer::drawByPath3(Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount)
beginFrameIfNeeded(); // {
if (!t_mesh.isDataLoaded()) // beginFrameIfNeeded();
PRINT_ERR("Can't draw, because no mesh data was loaded!"); // if (!t_mesh.isDataLoaded())
if (t_mesh.getCurrentAnimationFrame() != t_mesh.getNextAnimationFrame()) // PRINT_ERR("Can't draw, because no mesh data was loaded!");
t_mesh.animate(); // if (t_mesh.getCurrentAnimationFrame() != t_mesh.getNextAnimationFrame())
for (u32 i = 0; i < t_mesh.getMaterialsCount(); i++) // 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; // MeshMaterial *material = &t_mesh.getMaterial(i);
Texture *tex = textureRepo.getByMesh(t_mesh.getId(), t_mesh.getMaterial(i).getId()); // if (t_mesh.shouldBeFrustumCulled && !material->isInFrustum(renderData.frustumPlanes, t_mesh.position))
changeTexture(tex); // return;
gifSender->initPacket(context); // Texture *tex = textureRepo.getBySpriteOrMesh(material->getId());
u32 vertCount = t_mesh.getMaterial(i).getFacesCount(); // changeTexture(tex);
VECTOR *vertices = new VECTOR[vertCount]; // gifSender->initPacket(context);
VECTOR *normals = new VECTOR[vertCount]; // u32 vertCount = material->getFacesCount();
VECTOR *coordinates = new VECTOR[vertCount]; // VECTOR *vertices = new VECTOR[vertCount];
vertCount = t_mesh.getDrawData(i, vertices, normals, coordinates, *renderData.cameraPosition); // VECTOR *normals = new VECTOR[vertCount];
gifSender->addObject(&renderData, t_mesh, vertCount, vertices, normals, coordinates, t_bulbs, t_bulbsCount, &textureBuffer); // VECTOR *coordinates = new VECTOR[vertCount];
gifSender->sendPacket(); // vertCount = t_mesh.getDrawData(i, vertices, normals, coordinates, *renderData.cameraPosition);
delete[] vertices; // gifSender->addObject(&renderData, t_mesh, vertCount, vertices, normals, coordinates, t_bulbs, t_bulbsCount, &textureBuffer, &material->color);
delete[] normals; // gifSender->sendPacket();
delete[] coordinates; // 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 /// --- 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++) beginFrameIfNeeded();
draw(t_meshes[i], t_bulbs, t_bulbsCount); 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) void Renderer::draw(Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount)
{ {
beginFrameIfNeeded(); beginFrameIfNeeded();
vifSender->sendMatrices(renderData, t_mesh.position, t_mesh.rotation); vifSender->calcMatrix(renderData, t_mesh.position, t_mesh.rotation);
if (!t_mesh.isDataLoaded()) if (!t_mesh.isDataLoaded())
PRINT_ERR("Can't draw, because no mesh data was loaded!"); PRINT_ERR("Can't draw, because no mesh data was loaded!");
Vector3 rotatedCamera = Vector3(*renderData.cameraPosition); camRotation.identity();
rotatedCamera.rotate(t_mesh.rotation, true); camRotation.rotate(-t_mesh.rotation);
Vector3 rotatedCamera = Vector3(camRotation * *renderData.cameraPosition);
if (t_mesh.getCurrentAnimationFrame() != t_mesh.getNextAnimationFrame()) if (t_mesh.getCurrentAnimationFrame() != t_mesh.getNextAnimationFrame())
t_mesh.animate(); t_mesh.animate();
for (u32 i = 0; i < t_mesh.getMaterialsCount(); i++) 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; return;
u32 vertCount = t_mesh.getMaterial(i).getFacesCount(); u32 vertCount = material->getFacesCount();
VECTOR __attribute__((aligned(16))) vertices[vertCount]; VECTOR vertices[vertCount] __attribute__((aligned(16)));
VECTOR __attribute__((aligned(16))) normals[vertCount]; VECTOR normals[vertCount] __attribute__((aligned(16)));
VECTOR __attribute__((aligned(16))) coordinates[vertCount]; VECTOR coordinates[vertCount] __attribute__((aligned(16)));
Texture *tex = textureRepo.getByMesh(t_mesh.getId(), t_mesh.getMaterial(i).getId()); Texture *tex = textureRepo.getBySpriteOrMesh(material->getId());
changeTexture(tex); changeTexture(tex);
vertCount = t_mesh.getDrawData(i, vertices, normals, coordinates, rotatedCamera); 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); } 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) 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.cameraPosition = t_cameraPos;
renderData.frustumPlanes = t_planes; renderData.frustumPlanes = t_planes;
} }
+1 -1
View File
@@ -57,7 +57,7 @@ void TextureRepository::addByMesh(char *t_path, Mesh &mesh, TextureFormat t_form
else else
pngLoader.load(*texture, t_path, mesh.getMaterial(i).getName(), ".png"); pngLoader.load(*texture, t_path, mesh.getMaterial(i).getName(), ".png");
texture->setName(mesh.getMaterial(i).getName()); texture->setName(mesh.getMaterial(i).getName());
texture->addLink(mesh.getId(), mesh.getMaterial(i).getId()); texture->addLink(mesh.getMaterial(i).getId());
textures.push_back(texture); textures.push_back(texture);
} }
} }
+143 -93
View File
@@ -17,8 +17,10 @@
#include "../include/utils/debug.hpp" #include "../include/utils/debug.hpp"
const u32 VU1_PACKAGE_VERTS_PER_BUFF = 96; // Remember to modify buffer size in vu1 also 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_PACKAGES_PER_PACKET = 9;
const u32 VU1_PACKET_SIZE = 128; 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 // Constructors/Destructors
@@ -31,24 +33,24 @@ extern u32 VU1Draw3D_CodeEnd __attribute__((section(".vudata")));
VifSender::VifSender(Light *t_light) VifSender::VifSender(Light *t_light)
{ {
light = t_light;
PRINT_LOG("Initializing VifSender"); 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_initialize(DMA_CHANNEL_VIF1, NULL, 0);
dma_channel_fast_waits(DMA_CHANNEL_VIF1); dma_channel_fast_waits(DMA_CHANNEL_VIF1);
uploadMicroProgram(); uploadMicroProgram();
packets[0] = packet2_create(VU1_PACKET_SIZE, P2_TYPE_NORMAL, P2_MODE_CHAIN, true); 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); 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; context = 0;
setDoubleBuffer(); setDoubleBufferAddStaticData();
PRINT_LOG("VifSender initialized!");
} }
VifSender::~VifSender() VifSender::~VifSender()
{ {
packet2_free(packets[0]); packet2_free(packets[0]);
packet2_free(packets[1]); packet2_free(packets[1]);
packet2_free(matricesPacket);
} }
// ---- // ----
@@ -69,27 +71,19 @@ void VifSender::uploadMicroProgram()
packet2_free(packet2); 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); model.identity();
vec3ToNative(rotation, t_rotation, 1.0F); model.rotate(t_rotation);
MATRIX localWorld, localScreen; model.translate(t_position);
create_local_world(localWorld, position, rotation);
create_local_screen(localScreen, localWorld, t_renderData.worldView->data, t_renderData.perspective->data); modelViewProj.identity();
// Small undo, because im testing new matrix funcs, which are DIFFERENT than PS2SDK, so cant be used right now. modelViewProj = model * modelViewProj;
// Matrix viewProj = Matrix(); modelViewProj = *t_renderData.view * modelViewProj;
// viewProj.rotation(t_rotation); // model matrix modelViewProj = *t_renderData.projection * modelViewProj;
// 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);
} }
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 // 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; i -= 3;
const u32 endI = i + (VU1_PACKAGE_VERTS_PER_BUFF - 1) > vertCount2 ? vertCount2 : i + (VU1_PACKAGE_VERTS_PER_BUFF - 1); 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 if (endI == vertCount2) // if there are no more vertices to draw, break
{ {
i = vertCount2; 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_t *settings = packet2_create(10, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
packet2_utils_vu_add_double_buffer(settings, 8, 496); 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); 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); dma_channel_wait(DMA_CHANNEL_VIF1, 0);
packet2_free(settings); packet2_free(settings);
} }
/** Draw using PATH1 */ /** 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; const u32 vertCount = t_end - t_start;
u32 vif_added_bytes = 0; lastVertCount = vertCount;
packet2_utils_vu_open_unpack(currPacket, 0, 1); isLastRGBAOnly = t_rgbaOnly;
// TODO get this via screensettings packet2_utils_vu_open_unpack(currPacket, 0, true);
packet2_add_float(currPacket, 2048.0F); // scale packet2_add_data(currPacket, modelViewProj.data, 4);
packet2_add_float(currPacket, 2048.0F); // scale packet2_add_u32(currPacket, t_addDrawWait); // Draw finish?
packet2_add_float(currPacket, ((float)0xFFFFFF) / 32.0F); // scale packet2_add_u32(currPacket, vertCount); // Vertex count
packet2_add_u32(currPacket, vertCount); // vertex count packet2_add_u32(currPacket, vertCount / 3); // Triangles count
packet2_utils_gif_add_set(currPacket, 1); packet2_add_u32(currPacket, t_rgbaOnly); // 0 = STQ+RGBA, 1 = RGBA
packet2_utils_gs_add_lod(currPacket, &t_mesh.lod); packet2_utils_gs_add_lod(currPacket, &t_mesh.lod);
packet2_utils_gs_add_texbuff_clut(currPacket, textureBuffer, &t_mesh.clut); packet2_utils_gs_add_texbuff_clut(currPacket, t_texBuff, &t_mesh.clut);
packet2_utils_gs_add_prim_giftag(currPacket, t_prim, vertCount, DRAW_STQ2_REGLIST, 3, 0); if (t_rgbaOnly)
packet2_utils_gs_add_prim_giftag(currPacket, t_prim, vertCount, DRAW_RGBAQ_REGLIST, 2, 0);
packet2_add_u32(currPacket, t_mesh.color.r); else
packet2_add_u32(currPacket, t_mesh.color.g); packet2_utils_gs_add_prim_giftag(currPacket, t_prim, vertCount, DRAW_STQ2_REGLIST, 3, 0);
packet2_add_u32(currPacket, t_mesh.color.b); packet2_add_u32(currPacket, t_color->r);
packet2_add_u32(currPacket, t_mesh.color.a); packet2_add_u32(currPacket, t_color->g);
packet2_add_u32(currPacket, t_color->b);
// Clipping tests start packet2_add_u32(currPacket, t_color->a);
u32 vif_added_bytes = packet2_utils_vu_close_unpack(currPacket);
// // const float minZ = 1; packet2_utils_vu_add_unpack_data(currPacket, vif_added_bytes, t_vertices + t_start, vertCount, true);
// // const float maxZ = 65535; if (!t_rgbaOnly)
// // const int iGuardDimXY = 2048; {
vif_added_bytes += vertCount;
// // vu1.addFloat(1.0F); // f_TODO clipping maybe there is problem? packet2_utils_vu_add_unpack_data(currPacket, vif_added_bytes, t_coordinates + t_start, vertCount, true);
// // 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_vu_add_start_program(currPacket, 0); 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);
}
-11
View File
@@ -11,7 +11,6 @@
#include "../include/utils/math.hpp" #include "../include/utils/math.hpp"
#include <math.h> #include <math.h>
#include <fastmath.h>
float Math::cos(float x) float Math::cos(float x)
{ {
@@ -72,16 +71,6 @@ float Math::cos(float x)
return r; 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); } float Math::invSqrt(float x) { return 1.0F / sqrt(x); }
/** Converts Vector3 to PS2SDK's Vector4 */ /** Converts Vector3 to PS2SDK's Vector4 */
+1
View File
@@ -11,6 +11,7 @@
#include "../include/utils/string.hpp" #include "../include/utils/string.hpp"
#include "../include/utils/debug.hpp" #include "../include/utils/debug.hpp"
#include <stdio.h> #include <stdio.h>
#define CHAR_BIT 8
char *String::createU32ToString(u32 a) char *String::createU32ToString(u32 a)
{ {
-154
View File
@@ -1,154 +0,0 @@
; ______ ____ ___
; | \/ ____| |___|
; | | | \ | |
;---------------------------
; Copyright 2020, tyra - https://github.com/h4570/tyra
; Sandro Sobczyński <sandro.sobczynski@gmail.com>
;
;---------------------------------------------------------------
; draw3D.vcl |
;---------------------------------------------------------------
; A VU1 microprogram to draw 3D object using XYZ2, RGBAQ and ST|
; This program uses double buffering (xtop) |
; |
; Many thanks to: |
; - Dr Henry Fortuna |
; - Jesper Svennevid, Daniel Collin |
; - Guilherme Lampert |
;---------------------------------------------------------------
; TODO
; - Fix vertex clipping (is clipping visible triangles :/)
; - Move lerp() from EE to VU1 (performance)
; - Add dynamic lighting (feature)
; - Add --cont + MSCNT instead of alltime MSCAL (performance)
.syntax new
.name VU1Draw3D
.vu
.init_vf_all
.init_vi_all
--enter
--endenter
;//////////// --- Load data 1 --- /////////////
; Updated once per frame
lq matrixRow0, 0(vi00) ; load view-projection matrix
lq matrixRow1, 1(vi00)
lq matrixRow2, 2(vi00)
lq matrixRow3, 3(vi00)
;/////////////////////////////////////////////
fcset 0x000000 ; VCL won't let us use CLIP without first zeroing
; the clip flags
;//////////// --- Load data 2 --- /////////////
; Updated dynamically
xtop iBase
lq.xyz scale, 0(iBase) ; load program params
; float : X, Y, Z - scale vector that we will use to scale the verts after projecting them.
; float : W - vert count.
lq gifSetTag, 1(iBase) ; GIF tag - set
lq texGifTag1, 2(iBase) ; GIF tag - texture LOD
lq texGifTag2, 3(iBase) ; GIF tag - texture buffer & CLUT
lq primTag, 4(iBase) ; GIF tag - tell GS how many data we will send
lq rgba, 5(iBase) ; RGBA
;lq clipScale, 6(iBase) ; TODO clipping tests
; u32 : R, G, B, A (0-128)
iaddiu vertexData, iBase, 7 ; pointer to vertex data
ilw.w vertCount, 0(iBase) ; load vert count from scale vector
iadd stqData, vertexData, vertCount ; pointer to stq
iadd kickAddress, stqData, vertCount ; pointer for XGKICK
iadd destAddress, stqData, vertCount ; helper pointer for data inserting
;////////////////////////////////////////////
;/////////// --- Store tags --- /////////////
sqi gifSetTag, (destAddress++) ;
sqi texGifTag1, (destAddress++) ; texture LOD tag
sqi gifSetTag, (destAddress++) ;
sqi texGifTag2, (destAddress++) ; texture buffer & CLUT tag
sqi primTag, (destAddress++) ; prim + tell gs how many data will be
;////////////////////////////////////////////
;/////////////// --- Loop --- ///////////////
iadd vertexCounter, iBase, vertCount ; loop vertCount times
vertexLoop:
;////////// --- Load loop data --- //////////
lq vertex, 0(vertexData) ; load xyz
; float : X, Y, Z
; any32 : _ = 0
lq stq, 0(stqData) ; load stq
; float : S, T
; any32 : Q = 1 ; 1, because we will mul this by 1/vert[w] and this
; will be our q for texture perspective correction
; any32 : _ = 0
;////////////////////////////////////////////
;////////////// --- Vertex --- //////////////
mul acc, matrixRow0, vertex[x] ; transform each vertex by the matrix
madd acc, matrixRow1, vertex[y]
madd acc, matrixRow2, vertex[z]
madd vertex, matrixRow3, vertex[w]
;add.z acc, vf0, clipScale[w] ; TODO clipping maybe this?
;madd.z clipVec, clipScale, vertex
;mul.xy clipVec, clipScale, vertex
;mul.w clipVec, vf0, vertex[z]
;mul.xyz clipVec, vertex, clipScale ; TODO clipping maybe this?
clipw.xyz vertex, vertex ; Dr. Fortuna: This instruction checks if the vertex is outside
; the viewing frustum. If it is, then the appropriate
; clipping flags are set
fcand VI01, 0x3FFFF ; Bitwise AND the clipping flags with 0x3FFFF, this makes
; sure that we get the clipping judgement for the last three
; verts (i.e. that make up the triangle we are about to draw)
iaddiu iADC, VI01, 0x7FFF ; Add 0x7FFF. If any of the clipping flags were set this will
; cause the triangle not to be drawn (any values above 0x8000
; that are stored in the w component of XYZ2 will set the ADC
; bit, which tells the GS not to perform a drawing kick on this
; triangle.
;ilw.w iNoDraw, UVStart(Counter) ; Load the iNoDraw flag. If true we should set the ADC bit so the vert isn't drawn
;iadd iADC, iADC, iNoDraw ; TODO clipping maybe this?
isw.w iADC, 2(destAddress)
div q, vf00[w], vertex[w] ; perspective divide (1/vert[w]):
mul.xyz vertex, vertex, q
mula.xyz acc, scale, vf00[w] ; scale to GS screen space
madd.xyz vertex, vertex, scale ; multiply and add the scales -> vert = vert * scale + scale
ftoi4.xyz vertex, vertex ; convert vertex to 12:4 fixed point format
;////////////////////////////////////////////
;//////////////// --- ST --- ////////////////
mulq modStq, stq, q
;////////////////////////////////////////////
;//////////// --- Store data --- ////////////
sq modStq, 0(destAddress) ; STQ
sq rgba, 1(destAddress) ; RGBA ; q is grabbed from stq
sq.xyz vertex, 2(destAddress) ; XYZ2
;////////////////////////////////////////////
iaddiu vertexData, vertexData, 1
iaddiu stqData, stqData, 1
iaddiu destAddress, destAddress, 3
iaddi vertexCounter, vertexCounter, -1 ; decrement the loop counter
ibne vertexCounter, iBase, vertexLoop ; and repeat if needed
;////////////////////////////////////////////
--barrier
xgkick kickAddress ; dispatch to the GS rasterizer.
--exit
--endexit
+190
View File
@@ -0,0 +1,190 @@
; ______ ____ ___
; | \/ ____| |___|
; | | | \ | |
;---------------------------
; Copyright 2020, tyra - https://github.com/h4570/tyra
; Sandro Sobczyński <sandro.sobczynski@gmail.com>
;
;---------------------------------------------------------------
; draw3D.vcl |
;---------------------------------------------------------------
; First tyra VU1 microprogram. |
; Features: |
; - Draw triangles (no strip) with STQ (textures) and 1 RGBA. |
; This program uses double buffering (xtop) |
; |
; I want to say thank you to: |
; - Dr Henry Fortuna - for teaching how things work |
; - Jesper Svennevid, Daniel Collin - for openvcl samples |
; - Guilherme Lampert - for VU1 idea for PS2 Quake and vclpp |
; - Tyler Daniel - for PS2GL source code for PS2 Linux |
;---------------------------------------------------------------
; TODO
; - Add dynamic lighting (feature)
; - Add --cont + MSCNT instead of alltime MSCAL
; - 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
+119 -45
View File
@@ -11,63 +11,137 @@
.global VU1Draw3D_CodeEnd .global VU1Draw3D_CodeEnd
VU1Draw3D_CodeStart: VU1Draw3D_CodeStart:
__v_draw3D_vcl_4: __v_draw3D_vcl_4:
; _LNOPT_w=[ normal2 ] 23 [23 0] 23 [__v_draw3D_vcl_4] ; _LNOPT_w=[ normal2 ] 27 [27 0] 27 [__v_draw3D_vcl_4]
NOP lq VF01,0(VI00) NOP xtop VI06
NOP xtop VI02
NOP lq VF02,1(VI00) NOP lq VF02,1(VI00)
NOP lq VF06,1(VI02) NOP lq VF01,0(VI00)
NOP lq VF09,2(VI02) NOP ilw.x VI01,4(VI06)
NOP lq VF08,3(VI02) NOP ilw.y VI08,4(VI06)
NOP lq VF07,4(VI02) NOP lq VF03,0(VI06)
NOP lq VF03,2(VI00) NOP lq VF04,1(VI06)
NOP iaddiu VI03,VI02,0x00000007 NOP lq VF08,5(VI06)
NOP ilw.w VI07,0(VI02) NOP lq VF10,6(VI06)
NOP lq VF04,3(VI00) 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 fcset 0
NOP lq.xyz VF05,0(VI02) NOP iblez VI01,prim_tag_l
NOP iadd VI04,VI03,VI07 addi.z VF09,VF00,I sqi VF10,(VI07++)
NOP iadd VI06,VI04,VI07 ; _LNOPT_w=[ normal2 ] 2 [2 0] 2 [__v_draw3D_vcl_5]
NOP sqi VF06,(VI06++) NOP sqi VF02,(VI07++)
NOP sqi VF09,(VI06++) NOP sqi VF01,(VI07++)
NOP sqi VF06,(VI06++) prim_tag_l:
NOP sqi VF08,(VI06++) ; _LNOPT_w=[ normal2 ] 4 [4 0] 4 [prim_tag_l]
NOP lq VF06,5(VI02) NOP iaddiu VI08,VI00,0x00007fff
NOP iadd VI05,VI04,VI07 NOP sqi VF07,(VI07++)
NOP sqi VF07,(VI06++) NOP iaddiu VI08,VI08,0x00000001
NOP iadd VI07,VI02,VI07 NOP iaddiu VI09,VI00,0
vertexLoop: triangle_loop:
; _LNOPT_w=[ normal2 ] 21 [31 14] 31 [vertexLoop] ; _LNOPT_w=[ normal2 ] 11 [27 0] 27 [triangle_loop]
NOP lq VF07,0(VI03) NOP lq VF02,0(VI04)
mulax ACC,VF01,VF07x sq VF06,1(VI06) ; STALL_LATENCY ?3 mulax ACC,VF03,VF02x mfir.w VF01,VI08 ; STALL_LATENCY ?3
madday ACC,VF02,VF07y lq VF08,0(VI04) madday ACC,VF04,VF02y NOP
maddaz ACC,VF03,VF07z iaddiu VI06,VI06,0x00000003 maddaz ACC,VF05,VF02z NOP
maddw VF07,VF04,VF07w NOP maddw VF02,VF06,VF02w NOP
clipw.xyz VF07xyz,VF07w div Q,VF00w,VF07w ; STALL_LATENCY ?3 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 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 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
NOP NOP NOP sq VF08,4(VI07)
mulq.xyz VF07,VF07,Q fcand VI01,262143 NOP iaddiu VI07,VI07,0x00000006
mulaw.xyz ACC,VF05,VF00w iaddiu VI03,VI03,0x00000001 NOP sq VF01,-1(VI07)
madd.xyz VF07,VF07,VF05 iaddiu VI04,VI04,0x00000001 ; STALL_LATENCY ?2 loop_ctrl:
mulq VF08,VF08,Q isubiu VI07,VI07,1 ; _LNOPT_w=[ normal2 ] 4 [4 0] 4 [loop_ctrl]
ftoi4.xyz VF07,VF07 iaddiu VI01,VI01,0x00007fff ; STALL_LATENCY ?2 NOP iaddiu VI09,VI09,0x00000001
NOP isw.w VI01,-1(VI06) NOP iaddiu VI04,VI04,0x00000003
NOP sq VF08,-3(VI06) NOP ibne VI09,VI02,triangle_loop
NOP ibne VI07,VI02,vertexLoop NOP iaddiu VI05,VI05,0x00000003
NOP sq.xyz VF07,-1(VI06) ; _LNOPT_w=[ normal2 ] 3 [1 0] 3 [__v_draw3D_vcl_21]
; _LNOPT_w=[ normal2 ] 3 [1 0] 3 [__v_draw3D_vcl_7] NOP xgkick VI06
NOP xgkick VI05
NOP[E] NOP NOP[E] NOP
NOP NOP NOP NOP
.align 4 .align 4
VU1Draw3D_CodeEnd: VU1Draw3D_CodeEnd:
; iCount=47 ; iCount=103
; register stats: ; register stats:
; 8 VU User integer ; 10 VU User integer
; 10 VU User floating point ; 11 VU User floating point
;------------------------- ;-------------------------
;------------------------- ;-------------------------
;------------------------- ;-------------------------
+7
View File
@@ -0,0 +1,7 @@
; Load GS offsets to center xformed vertex in gs coord space and color clamping constant
#macro LoadScaleConstant: gs_scale
loi 2047.5
addi.xy gs_scale, vf00, i
loi 699050.625000 // ((float)0xFFFFFF) / 24.0F
addi.z gs_scale, vf00, i
#endmacro
+13
View File
@@ -0,0 +1,13 @@
#macro MatrixLoad: matrix, offset, vumem
lq matrix[0], offset+0(vumem)
lq matrix[1], offset+1(vumem)
lq matrix[2], offset+2(vumem)
lq matrix[3], offset+3(vumem)
#endmacro
#macro MatrixXForm: output_vertex, matrix, input_vertex
mul acc, matrix[0], input_vertex[x]
madd acc, matrix[1], input_vertex[y]
madd acc, matrix[2], input_vertex[z]
madd output_vertex, matrix[3], input_vertex[w]
#endmacro
+27
View File
@@ -0,0 +1,27 @@
#macro VectorPerspectiveDivide: vertex
div q, vf00[w], vertex[w]
mulq.xyz vertex, vertex, q
#endmacro
#macro VectorAddGSScales: output_vertex, input_vertex, gs_scale
mula.xyz acc, gs_scale, vf00[w]
madd.xyz output_vertex, input_vertex, gs_scale
ftoi4.xyz output_vertex, output_vertex
#endmacro
#macro VectorTexturePerspectiveCorrection: output_vertex, input_vertex
mulq output_vertex, input_vertex, q
#endmacro
#macro VectorStore: vertex, vumem, num
sq vertex, num(vumem)
#endmacro
#macro VectorClip: output_vertex, input_vertex
clipw.xyz input_vertex, input_vertex
mfir.w output_vertex, adc_bit
#endmacro
#macro VectorLoad: output_vertex, vumem, offset
lq output_vertex, offset(vumem)
#endmacro
+20
View File
@@ -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
+3 -22
View File
@@ -12,14 +12,11 @@
#include <utils/math.hpp> #include <utils/math.hpp>
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; verticalLevel = 30.0F;
up.x = 0.0F;
up.y = 1.0F;
up.z = 0.0F;
} }
Camera::~Camera() {} Camera::~Camera() {}
@@ -43,12 +40,7 @@ void Camera::rotate(Pad &t_pad)
horizontalLevel -= 0.08; horizontalLevel -= 0.08;
else if (t_pad.rJoyH >= 200) else if (t_pad.rJoyH >= 200)
horizontalLevel += 0.08; 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.x = (Math::sin(horizontalLevel) * verticalLevel);
unitCirclePosition.y = CAMERA_Y; unitCirclePosition.y = CAMERA_Y;
unitCirclePosition.z = (Math::cos(horizontalLevel) * verticalLevel); 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.x = unitCirclePosition.x + t_mesh.position.x;
position.y = unitCirclePosition.y + t_mesh.position.y; position.y = unitCirclePosition.y + t_mesh.position.y;
position.z = unitCirclePosition.z + t_mesh.position.z; position.z = unitCirclePosition.z + t_mesh.position.z;
if (position.x > (-0.04F * verticalLevel) &&
position.x < 0.0F &&
position.z > (0.998F * verticalLevel))
{
// TODO
// position.x = 0.0F;
// position.y = 0.0F;
// position.z = 0.0F;
// horizontalLevel = 0.0F;
}
} }
+1 -2
View File
@@ -22,7 +22,7 @@ class Camera : public CameraBase
{ {
public: public:
Vector3 position,up, unitCirclePosition; Vector3 position, up, unitCirclePosition;
float horizontalLevel, verticalLevel; float horizontalLevel, verticalLevel;
Camera(ScreenSettings *t_screen); Camera(ScreenSettings *t_screen);
@@ -34,7 +34,6 @@ public:
protected: protected:
Vector3 *getPosition() { return &position; }; Vector3 *getPosition() { return &position; };
Vector3 *getUp() { return &up; };
ScreenSettings screen; ScreenSettings screen;
}; };
+78 -40
View File
@@ -11,14 +11,12 @@
#include "dolphin.hpp" #include "dolphin.hpp"
#include "utils/math.hpp" #include "utils/math.hpp"
const u8 WATER_TILE_SCALE = 5; float Dolphin::engineFPS = 60.0F;
const u8 WATER_SIZE = 100; const float WATER_TILE_SCALE = 6.0F;
const u8 WATER_SIZE = 4;
const u8 MINES_COUNT = 15; const u8 MINES_COUNT = 15;
const u8 OYSTERS_COUNT = 5; const u8 OYSTERS_COUNT = 5;
float Dolphin::engineFPS = 60.F;
Dolphin::Dolphin(Engine *t_engine) : engine(t_engine), camera(&engine->screen) Dolphin::Dolphin(Engine *t_engine) : engine(t_engine), camera(&engine->screen)
{ {
oysters = new Collectible[OYSTERS_COUNT]; oysters = new Collectible[OYSTERS_COUNT];
@@ -29,12 +27,13 @@ Dolphin::~Dolphin()
{ {
delete[] oysters; delete[] oysters;
delete[] mines; delete[] mines;
delete[] waterDrawList;
} }
void Dolphin::onInit() void Dolphin::onInit()
{ {
player.init(engine); 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.loadSong("sound/dirediredocks.wav");
engine->audio.playSong(); engine->audio.playSong();
@@ -73,11 +72,25 @@ void Dolphin::onInit()
printf("Loaded.\n"); printf("Loaded.\n");
printf("Loading water...\n"); printf("Loading water...\n");
water.loadObj("water/", "water", WATER_TILE_SCALE, false);
water.position.set(0, WATER_LEVEL, 0); u32 spiralOffset = (u32)sqrt(WATER_TILES_COUNT);
texRepo->addByMesh("water/", water, BMP); waterDrawList = new Mesh *[WATER_TILES_COUNT];
water.shouldBeFrustumCulled = false; calcSpiral(spiralOffset, spiralOffset);
water.shouldBeBackfaceCulled = false; 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"); printf("Loading seabed...\n");
seabed.loadObj("seabed/", "seabed", 10.0F, false); seabed.loadObj("seabed/", "seabed", 10.0F, false);
@@ -96,7 +109,6 @@ void Dolphin::onInit()
waterbox.position.y = -100.F; waterbox.position.y = -100.F;
printf("Loading oyster dff\n"); printf("Loading oyster dff\n");
//oysters[0].loadDff("oyster/", "oyster", 1.F, false);
oysters[0].mesh.loadObj("oyster/", "oyster", 10.F, false); oysters[0].mesh.loadObj("oyster/", "oyster", 10.F, false);
printf("Loaded."); printf("Loaded.");
oysters[0].mesh.shouldBeBackfaceCulled = false; oysters[0].mesh.shouldBeBackfaceCulled = false;
@@ -110,14 +122,12 @@ void Dolphin::onInit()
oysters[i].mesh.loadFrom(oysters[0].mesh); oysters[i].mesh.loadFrom(oysters[0].mesh);
oysters[i].mesh.shouldBeBackfaceCulled = false; oysters[i].mesh.shouldBeBackfaceCulled = false;
oysters[i].mesh.shouldBeFrustumCulled = false; oysters[i].mesh.shouldBeFrustumCulled = false;
texRepo->getByMesh(oysters[0].mesh.getId(), oysters[0].mesh.getMaterial(0).getId()) texRepo->getBySpriteOrMesh(oysters[0].mesh.getMaterial(0).getId())->addLink(oysters[i].mesh.getMaterial(0).getId());
->addLink(oysters[i].mesh.getId(), oysters[i].mesh.getMaterial(0).getId());
oysters[i].mesh.position.set(i * -100, 5.0F, i * -100); oysters[i].mesh.position.set(i * -100, 5.0F, i * -100);
} }
printf("Loading mine .obj\n"); printf("Loading mine .obj\n");
mines[0].mesh.loadObj("mine/", "mine", 10.F, false); mines[0].mesh.loadObj("mine/", "mine", 10.F, false);
printf("Loaded.");
mines[0].mesh.shouldBeBackfaceCulled = false; mines[0].mesh.shouldBeBackfaceCulled = false;
mines[0].mesh.shouldBeFrustumCulled = false; mines[0].mesh.shouldBeFrustumCulled = false;
mines[0].mesh.position.set(5, -15, 32); 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.loadFrom(mines[0].mesh);
mines[i].mesh.shouldBeBackfaceCulled = false; mines[i].mesh.shouldBeBackfaceCulled = false;
mines[i].mesh.shouldBeFrustumCulled = false; mines[i].mesh.shouldBeFrustumCulled = false;
texRepo->getByMesh(mines[0].mesh.getId(), mines[0].mesh.getMaterial(0).getId()) texRepo->getBySpriteOrMesh(mines[0].mesh.getMaterial(0).getId())->addLink(mines[i].mesh.getMaterial(0).getId());
->addLink(mines[i].mesh.getId(), mines[i].mesh.getMaterial(0).getId());
mines[i].mesh.position.set(i * -10, 0.0F, i * -68); mines[i].mesh.position.set(i * -10, 0.0F, i * -68);
} }
Texture *pLifeTex = texRepo->add("2d/", "life", PNG); Texture *pLifeTex = texRepo->add("2d/", "life", PNG);
//pLifeTex->addLink(lifeSprites[0].getId()); // pLifeTex->addLink(lifeSprites[0].getId());
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
{ {
lifeSprites[i].size.set(64.0F, 64.0F); lifeSprites[i].size.set(64.0F, 64.0F);
@@ -164,12 +174,13 @@ void Dolphin::onUpdate()
engine->renderer->draw(gameOver); engine->renderer->draw(gameOver);
return; 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; Dolphin::engineFPS = engine->fps;
float zDist = player.mesh.position.z - water.position.z; // 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) if (xDist < 0)
xDist *= -1; xDist *= -1;
if (zDist < 0) if (zDist < 0)
@@ -177,8 +188,11 @@ void Dolphin::onUpdate()
if (xDist > WATER_SIZE * WATER_TILE_SCALE / 4 || if (xDist > WATER_SIZE * WATER_TILE_SCALE / 4 ||
zDist > WATER_SIZE * WATER_TILE_SCALE / 4) zDist > WATER_SIZE * WATER_TILE_SCALE / 4)
{ {
water.position.x = (player.mesh.position.x / WATER_SIZE) * WATER_SIZE; for (size_t i = 0; i < WATER_TILES_COUNT; i++)
water.position.z = (player.mesh.position.z / WATER_SIZE) * WATER_SIZE; {
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++) for (int i = 0; i < OYSTERS_COUNT; i++)
@@ -188,7 +202,7 @@ void Dolphin::onUpdate()
float dist = vecDist.length(); float dist = vecDist.length();
if (dist < 20.F && player.isJumping() && oysters[i].isActive()) 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(); oysters[i].disappear();
player.setLife(player.getLifes() + 1); player.setLife(player.getLifes() + 1);
engine->audio.setADPCMVolume(30, 3); engine->audio.setADPCMVolume(30, 3);
@@ -204,11 +218,11 @@ void Dolphin::onUpdate()
if (dist < 20.F && !mines[i].getExplosionTicks()) if (dist < 20.F && !mines[i].getExplosionTicks())
{ {
printf("Vecdist %f,%f,%f\n", vecDist.x, vecDist.y, vecDist.z); printf("Vecdist: %f,%f,%f\n", vecDist.x, vecDist.y, vecDist.z);
printf("Explode %d Dist %d\n", i, dist); printf("Explode:%d Dist:%f\n", i, dist);
mines[i].explode(); mines[i].explode();
player.setLife(player.getLifes() - 1); 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.setADPCMVolume(65, Mine::lastSoundBuffer);
engine->audio.playADPCM(boomSound, Mine::lastSoundBuffer); engine->audio.playADPCM(boomSound, Mine::lastSoundBuffer);
Mine::lastSoundBuffer = Mine::lastSoundBuffer == 4 ? 5 : 4; Mine::lastSoundBuffer = Mine::lastSoundBuffer == 4 ? 5 : 4;
@@ -220,35 +234,34 @@ void Dolphin::onUpdate()
player.update(engine->pad); player.update(engine->pad);
camera.update(engine->pad, player.mesh); camera.update(engine->pad, player.mesh);
skybox.position.set(player.mesh.position.x, +200.0F, player.mesh.position.z); 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); waterbox.position.set(player.mesh.position.x, -260.0F, player.mesh.position.z);
engine->renderer->draw(island); engine->renderer->draw(island);
engine->renderer->draw(water); engine->renderer->draw(waterDrawList, WATER_TILES_COUNT);
engine->renderer->draw(skybox); engine->renderer->draw(skybox);
engine->renderer->draw(waterbox); engine->renderer->draw(waterbox);
engine->renderer->draw(seabed); engine->renderer->draw(seabed);
for (u8 i = 0; i < OYSTERS_COUNT; i++) for (u8 i = 0; i < OYSTERS_COUNT; i++)
{
if (oysters[i].isActive()) if (oysters[i].isActive())
{
engine->renderer->draw(oysters[i].mesh); engine->renderer->draw(oysters[i].mesh);
}
}
for (u8 i = 0; i < MINES_COUNT; i++) for (u8 i = 0; i < MINES_COUNT; i++)
{
if (mines[i].getExplosionTicks() < MINE_EXPLOSION_TICKS) if (mines[i].getExplosionTicks() < MINE_EXPLOSION_TICKS)
engine->renderer->draw(mines[i].mesh); engine->renderer->draw(mines[i].mesh);
}
for (u8 i = 0; i < player.getLifes(); i++) for (u8 i = 0; i < player.getLifes(); i++)
{
engine->renderer->draw(lifeSprites[i]); engine->renderer->draw(lifeSprites[i]);
}
engine->renderer->draw(player.mesh); engine->renderer->draw(player.mesh);
if (camera.position.y < WATER_LEVEL) if (camera.position.y < WATER_LEVEL)
{ {
engine->renderer->draw(waterOverlay); engine->renderer->draw(waterOverlay);
engine->audio.setADPCMVolume(0, 0); //Surface ambient engine->audio.setADPCMVolume(0, 0); // Surface ambient
engine->audio.setADPCMVolume(65, 1); //Underwater ambient engine->audio.setADPCMVolume(65, 1); // Underwater ambient
} }
else else
{ {
@@ -256,3 +269,28 @@ void Dolphin::onUpdate()
engine->audio.setADPCMVolume(0, 1); //Underwater ambient engine->audio.setADPCMVolume(0, 1); //Underwater ambient
} }
} }
void Dolphin::calcSpiral(int X, int Y)
{
int x, y, dx;
x = y = dx = 0;
int dy = -1;
int t = X > Y ? X : Y;
int maxI = t * t;
for (int i = 0; i < maxI; i++)
{
if ((-X / 2 <= x) && (x <= X / 2) && (-Y / 2 <= y) && (y <= Y / 2))
{
spirals[i].x = x;
spirals[i].y = y;
}
if ((x == y) || ((x < 0) && (x == -y)) || ((x > 0) && (x == 1 - y)))
{
t = dx;
dx = -dy;
dy = t;
}
x += dx;
y += dy;
}
}
+10 -3
View File
@@ -37,8 +37,15 @@ public:
static float engineFPS; static float engineFPS;
private: private:
/*DO NOT TOUCH ORDER OF DECLARATION! void calcSpiral(int X, int Y);
GCC BUG CAUSES RENDERING TO FAIL IN ANY OTHER ORDER OF DECLARATION!*/ 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 seabed;
Mesh island; Mesh island;
Mesh skybox; Mesh skybox;
@@ -49,7 +56,7 @@ private:
Collectible *oysters; Collectible *oysters;
TextureRepository *texRepo; TextureRepository *texRepo;
Sprite waterOverlay; Sprite waterOverlay;
Mesh water; Mesh water[WATER_TILES_COUNT];
Mesh waterbox; Mesh waterbox;
Sprite lifeSprites[3]; Sprite lifeSprites[3];
Sprite gameOver; Sprite gameOver;
+1 -1
View File
@@ -18,4 +18,4 @@ int main()
game.engine->init(&game, 128); game.engine->init(&game, 128);
SleepThread(); SleepThread();
return 0; return 0;
} }
@@ -25,10 +25,6 @@ Collectible::Collectible()
bDisappearing = false; bDisappearing = false;
} }
Collectible::~Collectible()
{
}
void Collectible::disappear() void Collectible::disappear()
{ {
bDisappearing = true; bDisappearing = true;
@@ -21,7 +21,6 @@ public:
float rotation; float rotation;
Mesh mesh; Mesh mesh;
Collectible(); Collectible();
~Collectible();
void update(); void update();
void disappear(); void disappear();
void setActive(const u8 &b) { bActive = b; } void setActive(const u8 &b) { bActive = b; }
-4
View File
@@ -20,10 +20,6 @@ Mine::Mine()
explosionTicks = 0; explosionTicks = 0;
} }
Mine::~Mine()
{
}
void Mine::update() void Mine::update()
{ {
if (bExploding && explosionTicks < MINE_EXPLOSION_TICKS) if (bExploding && explosionTicks < MINE_EXPLOSION_TICKS)
-1
View File
@@ -24,7 +24,6 @@ public:
void explode() { bExploding = true; } void explode() { bExploding = true; }
void update(); void update();
Mine(); Mine();
~Mine();
const u8 &getExplosionTicks() { return explosionTicks; } const u8 &getExplosionTicks() { return explosionTicks; }
private: private:
+2 -16
View File
@@ -28,10 +28,6 @@ Player::Player()
lifes = 3; lifes = 3;
} }
Player::~Player()
{
}
void Player::init(Engine *t_engine) void Player::init(Engine *t_engine)
{ {
pEngine = 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) if (t_pad.isCrossClicked && mesh.getCurrentAnimationFrame() <= 14 && WATER_LEVEL - 15 < mesh.position.y)
{ {
printf("Cross\n"); mesh.setAnimSpeed(1.0F);
mesh.setAnimSpeed(0.8F);
mesh.playAnimation(14, 58, 0); mesh.playAnimation(14, 58, 0);
} }
@@ -72,19 +67,10 @@ void Player::update(Pad &t_pad)
bIsJumping = true; bIsJumping = true;
else else
bIsJumping = false; 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) if (velocity > 0 && mesh.getCurrentAnimationFrame() == 0)
{ {
mesh.setAnimSpeed(0.05F); mesh.setAnimSpeed(0.05F);
printf("Swim animation\n");
mesh.playAnimation(1, 14, 0); mesh.playAnimation(1, 14, 0);
} }
if (mesh.getCurrentAnimationFrame() == 42) if (mesh.getCurrentAnimationFrame() == 42)
@@ -101,7 +87,7 @@ void Player::update(Pad &t_pad)
bIsImpactingWater = false; 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 += mesh.position.z +=
Math::cos(mesh.rotation.z) * velocity * (bIsJumping + 1); Math::cos(mesh.rotation.z) * velocity * (bIsJumping + 1);
mesh.position.x += mesh.position.x +=
-1
View File
@@ -25,7 +25,6 @@ public:
float gravity, velocity, lift; float gravity, velocity, lift;
Mesh mesh; Mesh mesh;
Player(); Player();
~Player();
void init(Engine *t_engine); void init(Engine *t_engine);
void update(Pad &t_pad); void update(Pad &t_pad);
const u8 &isJumping() { return bIsJumping; } const u8 &isJumping() { return bIsJumping; }
+10 -5
View File
@@ -1,14 +1,19 @@
## Floors sample ## Floors sample
### Description ### Features
- Box collision
Simple demo which shows lighting using PATH3, and player movement and animation. - 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 ### 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 ### Screenshot
[![Floors screenshot][floors-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
+1 -4
View File
@@ -19,13 +19,10 @@ const float CAMERA_Y = 30.0F;
// Constructors/Destructors // 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"); PRINT_LOG("Initializing camera");
verticalLevel = 80.0F; verticalLevel = 80.0F;
up.x = 0.0F;
up.y = 1.0F;
up.z = 0.0F;
PRINT_LOG("Camera initialized!"); PRINT_LOG("Camera initialized!");
} }
-1
View File
@@ -35,7 +35,6 @@ public:
protected: protected:
Vector3 *getPosition() { return &position; }; Vector3 *getPosition() { return &position; };
Vector3 *getUp() { return &up; };
ScreenSettings screen; ScreenSettings screen;
}; };
+11 -8
View File
@@ -37,17 +37,17 @@ Floors::~Floors()
void Floors::onInit() 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(); 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.addSongListener(this);
engine->audio.loadSong("sounds/mafikizolo-loot.wav"); engine->audio.loadSong("sounds/mafikizolo-loot.wav");
engine->audio.playSong(); engine->audio.playSong();
engine->audio.setSongVolume(80); 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() void Floors::onUpdate()
@@ -60,8 +60,11 @@ void Floors::onUpdate()
player->update(engine->pad, camera, *floorManager, *enemy); player->update(engine->pad, camera, *floorManager, *enemy);
engine->renderer->draw(player->mesh); engine->renderer->draw(player->mesh);
engine->renderer->draw(enemy->getMeshes(), enemy->getMeshesCount()); 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. ui->render(engine->renderer); // 2D rendering ist LAST step, because layers gonna play there.
} }
+15 -12
View File
@@ -12,6 +12,7 @@
#include <utils/math.hpp> #include <utils/math.hpp>
#include <utils/debug.hpp> #include <utils/debug.hpp>
#include <stdlib.h>
// ---- // ----
// Constructors/Destructors // Constructors/Destructors
@@ -22,17 +23,17 @@
*/ */
FloorManager::FloorManager(int t_floorAmount, TextureRepository *t_texRepo) FloorManager::FloorManager(int t_floorAmount, TextureRepository *t_texRepo)
{ {
meshes = new Mesh *[t_floorAmount];
texRepo = t_texRepo; texRepo = t_texRepo;
floorAmount = t_floorAmount; floorAmount = t_floorAmount;
spirals = new Point[t_floorAmount]; spirals = new Point[t_floorAmount];
int floorSpiralMaxOffset = (int)Math::sqrt(t_floorAmount); int floorSpiralMaxOffset = (int)sqrt(t_floorAmount);
calcSpiral(floorSpiralMaxOffset, floorSpiralMaxOffset); calcSpiral(floorSpiralMaxOffset, floorSpiralMaxOffset);
initFloors(); initFloors();
trick = 0.0F; trick = 0.0F;
trickMode = 0;
isTimeForChangeTriggerColor = true; isTimeForChangeTriggerColor = true;
isTimeForChangeDefaultColor = true; isTimeForChangeDefaultColor = true;
audioOffset = audioMode = audioTick = 0; audioOffset = audioMode = audioTick = trickMode = 0;
} }
FloorManager::~FloorManager() FloorManager::~FloorManager()
@@ -85,12 +86,14 @@ void FloorManager::initFloors()
floors[0].mesh.loadObj("meshes/floor/", "floor", 3.0F, false); floors[0].mesh.loadObj("meshes/floor/", "floor", 3.0F, false);
floors[0].mesh.shouldBeFrustumCulled = true; floors[0].mesh.shouldBeFrustumCulled = true;
floors[0].mesh.shouldBeLighted = true; floors[0].mesh.shouldBeLighted = true;
meshes[0] = &floors[0].mesh;
texRepo->addByMesh("meshes/floor/", floors[0].mesh, BMP); texRepo->addByMesh("meshes/floor/", floors[0].mesh, BMP);
for (u16 i = 1; i < floorAmount; i++) for (u16 i = 1; i < floorAmount; i++)
{ {
floors[i].mesh.shouldBeFrustumCulled = true;
floors[i].init(floors[0].mesh, spirals[i], i); floors[i].init(floors[0].mesh, spirals[i], i);
texRepo->getByMesh(floors[0].mesh.getId(), floors[0].mesh.getMaterial(0).getId()) texRepo->getBySpriteOrMesh(floors[0].mesh.getMaterial(0).getId())->addLink(floors[i].mesh.getMaterial(0).getId());
->addLink(floors[i].mesh.getId(), floors[i].mesh.getMaterial(0).getId()); meshes[i] = &floors[i].mesh;
} }
PRINT_LOG("Floors initialized!"); PRINT_LOG("Floors initialized!");
} }
@@ -120,18 +123,18 @@ void FloorManager::update(Player &t_player)
for (u16 i = 0; i < floorAmount; i++) for (u16 i = 0; i < floorAmount; i++)
{ {
floors[i].animate(t_player); floors[i].animate(t_player);
MeshMaterial *material = &floors[i].mesh.getMaterial(0);
if (floors[i].isByAudioTriggered) if (floors[i].isByAudioTriggered)
{ {
floors[i].mesh.color.r = trigColor.r; material->color.r = trigColor.r;
floors[i].mesh.color.g = trigColor.g; material->color.g = trigColor.g;
floors[i].mesh.color.b = trigColor.b; material->color.b = trigColor.b;
} }
else else
{ {
floors[i].mesh.color.r = defaultColor.r; material->color.r = defaultColor.r;
floors[i].mesh.color.g = defaultColor.g; material->color.g = defaultColor.g;
floors[i].mesh.color.b = defaultColor.b; material->color.b = defaultColor.b;
} }
} }
} }
@@ -31,8 +31,10 @@ public:
u16 floorAmount; u16 floorAmount;
void update(Player &t_player); void update(Player &t_player);
void onAudioTick(); void onAudioTick();
Mesh **getMeshes() { return meshes; }
private: private:
Mesh **meshes;
TextureRepository *texRepo; TextureRepository *texRepo;
u8 audioOffset, audioMode; u8 audioOffset, audioMode;
u32 audioTick; u32 audioTick;
+12 -16
View File
@@ -16,6 +16,7 @@
#include <modules/gif_sender.hpp> #include <modules/gif_sender.hpp>
#include <utils/debug.hpp> #include <utils/debug.hpp>
#include <utils/math.hpp> #include <utils/math.hpp>
#include <stdlib.h>
// ---- // ----
// Constructors/Destructors // Constructors/Destructors
@@ -26,30 +27,25 @@ Enemy::Enemy(TextureRepository *t_texRepo)
PRINT_LOG("Creating enemy object"); PRINT_LOG("Creating enemy object");
meshes = new Mesh[getMeshesCount()]; meshes = new Mesh[getMeshesCount()];
drawMeshes = new Mesh *[getMeshesCount()];
meshes[0].loadMD2("meshes/enemy/", "poss_head", 0.3F, false); 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].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].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); Vector3 initPos = Vector3(0.00F, 40.00F, 0.00F);
setPosition(initPos); 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; isKilled = true;
PRINT_LOG("Enemy object created!"); PRINT_LOG("Enemy object created!");
+3 -1
View File
@@ -24,7 +24,7 @@ public:
Enemy(TextureRepository *t_texRepo); Enemy(TextureRepository *t_texRepo);
~Enemy(); ~Enemy();
inline Mesh *getMeshes() const { return meshes; } inline Mesh **getMeshes() const { return drawMeshes; }
inline u8 getMeshesCount() const { return 3; } inline u8 getMeshesCount() const { return 3; }
inline Vector3 getPosition() const { return position; } inline Vector3 getPosition() const { return position; }
void setPosition(const Vector3 &t_vec); void setPosition(const Vector3 &t_vec);
@@ -35,6 +35,8 @@ public:
private: private:
/** 0 - head, 1 - body, 2 - weapon */ /** 0 - head, 1 - body, 2 - weapon */
Mesh *meshes; Mesh *meshes;
/** Only for draw() method. */
Mesh **drawMeshes;
const Floor *currentFloor; const Floor *currentFloor;
Vector3 position, currFloorMin, currFloorMax; Vector3 position, currFloorMin, currFloorMax;
u8 isKilled; u8 isKilled;
+2 -2
View File
@@ -211,13 +211,13 @@ FloorsCheck *Player::checkFloors(const FloorManager &t_floorManager, const Vecto
for (u32 i = 0; i < t_floorManager.floorAmount; i++) for (u32 i = 0; i < t_floorManager.floorAmount; i++)
{ {
Utils::getMinMax(t_floorManager.floors[i].mesh, min, max); 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->currentFloor = &t_floorManager.floors[i];
result->currFloorMin.set(min); result->currFloorMin.set(min);
result->currFloorMax.set(max); 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->willCollideFloor = &t_floorManager.floors[i];
result->willCollideFloorMin.set(min); result->willCollideFloorMin.set(min);
+2 -2
View File
@@ -66,13 +66,13 @@ void Ui::update(const Player &player)
if (!isTask1Done && player.getJumpCount() >= 10) if (!isTask1Done && player.getJumpCount() >= 10)
{ {
isTask1Done = true; isTask1Done = true;
grayCheckboxTex->removeLinkBySprite(task1Checkbox.getId()); grayCheckboxTex->removeLinkById(task1Checkbox.getId());
blueCheckboxTex->addLink(task1Checkbox.getId()); blueCheckboxTex->addLink(task1Checkbox.getId());
} }
if (!isTask2Done && player.getKilledEnemiesCount() >= 10) if (!isTask2Done && player.getKilledEnemiesCount() >= 10)
{ {
isTask2Done = true; isTask2Done = true;
grayCheckboxTex->removeLinkBySprite(task2Checkbox.getId()); grayCheckboxTex->removeLinkById(task2Checkbox.getId());
blueCheckboxTex->addLink(task2Checkbox.getId()); blueCheckboxTex->addLink(task2Checkbox.getId());
} }
} }