Compare commits
327 Commits
1.1.0
...
v1.36.3-alpha
| Author | SHA1 | Date | |
|---|---|---|---|
| c7f210706d | |||
| 3a06ac548d | |||
| 8225abf328 | |||
| 2e23914c17 | |||
| e7c2f8a7c7 | |||
| 756fb216a4 | |||
| de4ce28839 | |||
| ed59d6b254 | |||
| 3fe9715958 | |||
| cba177f2db | |||
| 781c97eb73 | |||
| 5245ba3f55 | |||
| f0b5d25a27 | |||
| 5f22c02d2e | |||
| d63bd6cb0e | |||
| 921f34eb4c | |||
| 385e553e5a | |||
| e4230f1b62 | |||
| 94a353cdb8 | |||
| 8a162be036 | |||
| 1d273de455 | |||
| eecfc0b6c2 | |||
| 7ff8153086 | |||
| 9cb52ff620 | |||
| 3023bb7501 | |||
| 762e7eada2 | |||
| 70ea8e47ba | |||
| dd8499abad | |||
| 0816f522bb | |||
| fafc66d35c | |||
| d8458b98e0 | |||
| d0d7ed85e5 | |||
| a80f62e843 | |||
| 8b0233a45d | |||
| 10b275055c | |||
| 164d9f558c | |||
| 247e71a407 | |||
| ea49543542 | |||
| 20de0dc17d | |||
| 1090801f4e | |||
| 7b43c0c90f | |||
| b0ae873a88 | |||
| 7b3a28065b | |||
| 589b3b03a4 | |||
| 611d4f76be | |||
| bf0c65a14c | |||
| ab0c999117 | |||
| 28599512e4 | |||
| db6c84ba11 | |||
| b0c94a1602 | |||
| f34284591f | |||
| 7203f6f5c4 | |||
| 94f6e9fbf2 | |||
| 18ba08dc7a | |||
| 9dd69317e3 | |||
| 24509f7f20 | |||
| 9268628ccd | |||
| 4160bddc4b | |||
| e022fcdafe | |||
| 444990a262 | |||
| b749a80a25 | |||
| e43fae88e8 | |||
| 11717f42eb | |||
| 142bf60a6d | |||
| 9efd8ab3e1 | |||
| 7b2e411a13 | |||
| 8bd5476d61 | |||
| 4146df48a9 | |||
| 35fc8aea73 | |||
| c0bb78f1c9 | |||
| e5c2aa1548 | |||
| c72393b236 | |||
| a973c47321 | |||
| bc41afdf89 | |||
| 67bbe2e674 | |||
| 69b3621215 | |||
| b053504623 | |||
| ad43a4bfd3 | |||
| 1b6e1e94ee | |||
| 6e09741d19 | |||
| 152bc7d6cf | |||
| 25255c1c22 | |||
| afa98e8bdf | |||
| 55bc876dfb | |||
| 6432fc183e | |||
| a971309e2d | |||
| b94fa40eac | |||
| c1ed10eb3b | |||
| 07ba692009 | |||
| 64a2ccd6f3 | |||
| ea0d47e09c | |||
| 913f52ec6f | |||
| 55f476e9ed | |||
| 1d7730504b | |||
| c7fe915174 | |||
| 92d5ad7ad0 | |||
| e987089df0 | |||
| 89295ff27a | |||
| d0c2dfcaa3 | |||
| 7f9f86d7c3 | |||
| 91772a905c | |||
| 8a8d453ee0 | |||
| 8406dcee72 | |||
| 4c8ead755b | |||
| aeb25ad398 | |||
| d60d42cac6 | |||
| c0ece7206c | |||
| 096f2490ec | |||
| b4fe16dccc | |||
| 469ef48051 | |||
| 91934df5e8 | |||
| e39c8c5de8 | |||
| 8589a298da | |||
| 5a932b35ca | |||
| 7dd8947612 | |||
| 4b2deb8b39 | |||
| e0ad58f72f | |||
| f95e805d33 | |||
| b935d4da13 | |||
| f6cbac7c20 | |||
| 3af3576203 | |||
| ae3dd737e5 | |||
| 23ea1a28f6 | |||
| 115dac21bc | |||
| f8f91c6b49 | |||
| 8137bd56d8 | |||
| cf07cf78c8 | |||
| 13f6a2ecb7 | |||
| 9e1a9e8b3c | |||
| 5c232aebce | |||
| 586fe136ea | |||
| 02d7916925 | |||
| 1cc1e62ed6 | |||
| 1765885bec | |||
| d835f83e51 | |||
| 974138d64e | |||
| ae15906c99 | |||
| 71ce30a8fc | |||
| 55d8e445db | |||
| 11a4e2ee76 | |||
| 596bf2d89a | |||
| 53c134b0d5 | |||
| 9b2d39505b | |||
| 44776f7aba | |||
| bb0ec257b2 | |||
| a8a649d723 | |||
| 73a3d1d7e5 | |||
| dfee1ab25f | |||
| fcf03b27fa | |||
| b8d31fc1cc | |||
| 249c2431a2 | |||
| 2d1d36ddcc | |||
| bd11955fd4 | |||
| 3c827a407b | |||
| 607c2abc0c | |||
| 49713dc145 | |||
| 18db9875ad | |||
| 37703e69d0 | |||
| d4f2a1e1a2 | |||
| 91e8f791b0 | |||
| 12ef639516 | |||
| 552f2c6e4a | |||
| ea6d5215d1 | |||
| 4a1bca12aa | |||
| 0156d4444f | |||
| 623576a387 | |||
| 3f4d2c5521 | |||
| 206ccdf415 | |||
| 7025f5371b | |||
| 2455ce82dd | |||
| 2ce2e76663 | |||
| f4e699025a | |||
| b050e4643b | |||
| e38f569bc4 | |||
| 3dd51607f0 | |||
| b7618c014a | |||
| 8256efa7c8 | |||
| ac36012545 | |||
| 968718a549 | |||
| 24bab8464a | |||
| 4bee938106 | |||
| 86c48eeca4 | |||
| 97151ffc78 | |||
| bc44f598c1 | |||
| 5129d53b27 | |||
| 1539aa4108 | |||
| 083c041973 | |||
| 0c0512b37f | |||
| e7aa4d13cc | |||
| 1c9351e5e9 | |||
| f86a1bf190 | |||
| 36a637e5e6 | |||
| c4fc52b043 | |||
| 70efbcad46 | |||
| db635c09ea | |||
| edf5bd1e55 | |||
| f4421b659d | |||
| a017c3a3b6 | |||
| 220caba84a | |||
| 921b482e61 | |||
| 45edf7aedb | |||
| d9b5f8a4aa | |||
| 4557485cab | |||
| 582b42c29e | |||
| 6e1c94a112 | |||
| 62cff819ff | |||
| 729bcff954 | |||
| 8a0f5f7b84 | |||
| 5787b6a920 | |||
| 6d9b93998a | |||
| 96fe7c380e | |||
| 11a92c32ee | |||
| 87ae4b0507 | |||
| ad855a13d2 | |||
| 14b688c6cb | |||
| 0474fc07a5 | |||
| e00e677d1e | |||
| 3284c5a598 | |||
| dd49fc165e | |||
| 83dce5cb92 | |||
| 32422b87eb | |||
| 6292c27c50 | |||
| 4b158781af | |||
| cad2623649 | |||
| d94f51623c | |||
| 18f3398687 | |||
| 1c3edb3887 | |||
| 5fb6858678 | |||
| 8a1bc254c5 | |||
| 0423e484a5 | |||
| ed6c20e5df | |||
| f95794c181 | |||
| 9f4f6f4b18 | |||
| fbbb41580c | |||
| d15cdecd97 | |||
| 8b9ea4696e | |||
| 9fb2cb385a | |||
| 97c9a5cd90 | |||
| f080a97dc5 | |||
| 55cee63ace | |||
| 69d4cf81ec | |||
| bcad6f7941 | |||
| 94e4f8ea3a | |||
| d0017f26f1 | |||
| 9a94d93747 | |||
| 67a10cb724 | |||
| b8552330bd | |||
| 20b14a5168 | |||
| c0ab97585c | |||
| d61396866d | |||
| b547de9cbb | |||
| a05b4fbd0f | |||
| 3e385f7c84 | |||
| fd29a11579 | |||
| 82361e4619 | |||
| b48d342adf | |||
| d22d125afa | |||
| 513ae84577 | |||
| db23acddd7 | |||
| 17ef6b9fbc | |||
| e5eb57e587 | |||
| f45f5c39c7 | |||
| bae834e599 | |||
| 72266d0c25 | |||
| a6f8bb9b36 | |||
| 940271fe8c | |||
| 7e676916a0 | |||
| d58163d75b | |||
| 56e1d7d5d8 | |||
| 945aeb1bec | |||
| c662307942 | |||
| 389a5ee608 | |||
| ade89bbdd1 | |||
| ca7846f60b | |||
| 510199164c | |||
| 3841487388 | |||
| 51702d5ef7 | |||
| 6f1d0e2e33 | |||
| eed34a17bc | |||
| 2fad5f67f1 | |||
| 7d2f354085 | |||
| 7233e6a4f4 | |||
| 94db15da9b | |||
| d1f16cf9b3 | |||
| 25b5fb4295 | |||
| 3cbea1877a | |||
| e9febb5d8d | |||
| 756f69d160 | |||
| 1e4022171d | |||
| 66f67b0d22 | |||
| 82cab6f78b | |||
| 5e811b78cd | |||
| 3d755e9983 | |||
| 6b821afd86 | |||
| 8a3485e671 | |||
| 33d7f9648d | |||
| 2b42bc53cb | |||
| 4112e6d327 | |||
| d2ce2eb7b2 | |||
| 00c171d6b9 | |||
| 7e442bcf5c | |||
| c1ad6effbd | |||
| 6c82beb383 | |||
| fb0df1537e | |||
| c6af82943a | |||
| f3a1bcb47d | |||
| ac7a04b669 | |||
| a3a6150ecb | |||
| 3b5fb1b670 | |||
| 3dc304b829 | |||
| b11df0262e | |||
| eba254f13b | |||
| 3fdbda4a4a | |||
| 1868b714bc | |||
| bfd75003a4 | |||
| 1757ef67dc | |||
| efe34c677d | |||
| d2013d4467 | |||
| b48fa16274 | |||
| 1f11c9f8e5 | |||
| ef16f1dbe2 | |||
| aa6b2d314b | |||
| 4d53c6c5fe | |||
| 02560f2d6f | |||
| 5399b1744f | |||
| 52518540f3 | |||
| 9e3ed74b45 |
@@ -0,0 +1,60 @@
|
|||||||
|
# Based on https://github.com/ps2dev/gsKit/blob/master/.github/workflows/compilation.yml
|
||||||
|
# Thanks fjtrujy!
|
||||||
|
|
||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
repository_dispatch:
|
||||||
|
types: [run_build]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container: ps2dev/ps2sdk-ports:latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
apk add build-base git
|
||||||
|
|
||||||
|
- name: Compile engine
|
||||||
|
working-directory: ./src/engine
|
||||||
|
env:
|
||||||
|
ZLIB: ${PS2SDK}/ports
|
||||||
|
LIBTIFF: ${PS2SDK}/ports
|
||||||
|
LIBJPEG: ${PS2SDK}/ports
|
||||||
|
LIBPNG: ${PS2SDK}/ports
|
||||||
|
TYRA: ${GITHUB_WORKSPACE}
|
||||||
|
run: |
|
||||||
|
make
|
||||||
|
|
||||||
|
- name: Compile unit test project
|
||||||
|
working-directory: ./src/unit_tests/
|
||||||
|
env:
|
||||||
|
TYRA: ${GITHUB_WORKSPACE}
|
||||||
|
run: |
|
||||||
|
make
|
||||||
|
|
||||||
|
- name: Compile cube project
|
||||||
|
working-directory: ./src/samples/cube/
|
||||||
|
env:
|
||||||
|
TYRA: ${GITHUB_WORKSPACE}
|
||||||
|
run: |
|
||||||
|
make
|
||||||
|
|
||||||
|
- name: Compile floors project
|
||||||
|
working-directory: ./src/samples/floors/
|
||||||
|
env:
|
||||||
|
TYRA: ${GITHUB_WORKSPACE}
|
||||||
|
run: |
|
||||||
|
make
|
||||||
|
|
||||||
|
- name: Compile dolphin project
|
||||||
|
working-directory: ./src/samples/dolphin/
|
||||||
|
env:
|
||||||
|
TYRA: ${GITHUB_WORKSPACE}
|
||||||
|
run: |
|
||||||
|
make
|
||||||
+1
-7
@@ -1,11 +1,5 @@
|
|||||||
.vscode/
|
.vscode/
|
||||||
|
.idea/
|
||||||
*.[Bb][Mm][Pp]
|
|
||||||
*.[Oo][Bb][Jj]
|
|
||||||
*.[Ww][Aa][Vv]
|
|
||||||
*.[Dd][Ff][Ff]
|
|
||||||
*.[Ii][Rr][Xx]
|
|
||||||
*.[Mm][Dd]2
|
|
||||||
|
|
||||||
# ---
|
# ---
|
||||||
|
|
||||||
|
|||||||
+134
@@ -0,0 +1,134 @@
|
|||||||
|
# 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.36.3] - 2021-05-28
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Unit test project
|
||||||
|
- Assert
|
||||||
|
- CI via Github workflows
|
||||||
|
- Install tutorial as separated .MD file
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Improved BMP loader.
|
||||||
|
- All PRINT_LOG and PRINT_ERR to consoleLog() and assertMsg()
|
||||||
|
- Refactored makefiles
|
||||||
|
- **CHANGED ENV VARIABLES!**
|
||||||
|
- Install tutorial
|
||||||
|
- Readme
|
||||||
|
|
||||||
|
## [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.36.3]: https://github.com/h4570/tyra/compare/v1.31.2-alpha...v1.36.3-alpha
|
||||||
|
[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
|
||||||
@@ -1,122 +1,133 @@
|
|||||||
[![Contributors][contributors-shield]][contributors-url]
|
[![Contributors][contributors-shield]][contributors-url]
|
||||||
[![MIT License][license-shield]][license-url]
|
[![MIT License][license-shield]][license-url]
|
||||||
|
[](https://discord.gg/NhhTmg3Gm5)
|
||||||
|
[](https://discord.gg/7dCr6ThSN5)
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/ps2-tyra/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.36.3</h3>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
First 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>
|
||||||
|
|
||||||
|
<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/ps2-tyra/tyra/issues">Report Bug</a>
|
<a href="https://github.com/h4570/tyra/issues">Report Bug</a>
|
||||||
·
|
·
|
||||||
<a href="https://github.com/ps2-tyra/tyra/issues">Request Feature</a>
|
<a href="https://github.com/h4570/tyra/issues">Request Feature</a>
|
||||||
</p>
|
</p>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
[](https://github.com/h4570/tyra/stargazers)
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
* [About the Project](#about-the-project)
|
* [About the Project](#about-the-project)
|
||||||
* [Samples](#samples)
|
* [Samples](#samples)
|
||||||
* [About project](#about-project)
|
* [Description](#description)
|
||||||
* [Acronyms](#acronyms)
|
* [Features](#features)
|
||||||
* [Tyra features](#tyra-features)
|
* [Branches](#branches)
|
||||||
* [Built With](#built-with)
|
|
||||||
* [Getting Started](#getting-started)
|
* [Getting Started](#getting-started)
|
||||||
* [Prerequisites](#prerequisites)
|
|
||||||
* [Installation](#installation)
|
* [Installation](#installation)
|
||||||
|
* [Prerequisites](#prerequisites)
|
||||||
* [Roadmap](#roadmap)
|
* [Roadmap](#roadmap)
|
||||||
* [Contributing](#contributing)
|
* [Contributing](#contributing)
|
||||||
* [License](#license)
|
* [License](#license)
|
||||||
* [Contact](#contact)
|
* [Built With](#built-with)
|
||||||
|
* [Acronyms](#acronyms)
|
||||||
* [Thanks](#thanks)
|
* [Thanks](#thanks)
|
||||||
|
|
||||||
## About The Project
|
<br />
|
||||||
|
|
||||||
<img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/1.1.0/tyra.gif" alt="sample" width="600" height="auto">
|
## About the Project
|
||||||
|
|
||||||
|
<img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/tyra.gif" alt="Sample code" width="600" height="auto">
|
||||||
|
<img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/dolphin.gif " alt="Sample game" width="500" height="auto">
|
||||||
|
|
||||||
### Samples
|
### Samples
|
||||||
* [Floors](https://github.com/ps2-tyra/tyra/tree/master/src/samples/floors)
|
* [Dolphin](https://github.com/h4570/tyra/tree/master/src/samples/dolphin)
|
||||||
* [Ari (WIP)](https://github.com/ps2-tyra/tyra/tree/master/src/samples/ari)
|
* [Floors](https://github.com/h4570/tyra/tree/master/src/samples/floors)
|
||||||
|
* [Cube](https://github.com/h4570/tyra/tree/master/src/samples/cube)
|
||||||
|
|
||||||
### Contributors wanted
|
### Description
|
||||||
#### I will be grateful for any help, Discord: Sandro#3402
|
Tyra is a project that aims to facilitate the development of PlayStation 2 games. The goal is simple API which will allow you to develop some nice small homebrew games in a short period of time. Finally, (thanks to PS2DEV team) Tyra supports C++20, so we are free from the 2003's GCC which only supported C++98.
|
||||||
|
**Project is on alpha stage, so keep in mind that there are many things to be done and to fix.**
|
||||||
|
Unfortunately there are not many people, which want's to help with this project. **If you want to be a volunteer**, but don't have too much knowledge in this field, write to me on Discord, **I will be happy to help.**
|
||||||
|
|
||||||
### About project
|
When project will be on beta stage, we plan to create some YouTube tutorials :)
|
||||||
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.
|
|
||||||
|
|
||||||
YouTube tutorials soon!
|
**Why was this project created?**
|
||||||
|
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.
|
||||||
|
For example, if you want to render something using only PS2DEV you must:
|
||||||
|
- Create VU1 micro-program
|
||||||
|
- Load micro-program and send it to VU1
|
||||||
|
- Create parser for your 3D file
|
||||||
|
- Create parser for texture file
|
||||||
|
- Calculate lights, shadows, MVP matrices (3D->2D)..
|
||||||
|
- Clip triangles ([sic!](https://github.com/h4570/tyra/issues/14))
|
||||||
|
- Prepare DMA packets for coprocessors communication
|
||||||
|
- Setup rasterizer (GS)
|
||||||
|
- Send texture to GS
|
||||||
|
- Send packets
|
||||||
|
- Synchronize all
|
||||||
|
|
||||||
**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.
|
but with Tyra you can do it with methods like `loadObj()` and `draw()` 😁.
|
||||||
Tyra takes care for you, and rendering, coprocessors communication and many more low-level stuff is already done.
|
|
||||||
|
|
||||||
### Acronyms
|
### Features
|
||||||
* EE (Emotion Engine) - whole set of processors and subsystems that make up the PlayStation 2
|
* 3D support - VU1 "Path 1 rendering"
|
||||||
* 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
|
* 2D support - PNG & BMP
|
||||||
* 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
|
|
||||||
* VU1 rendering (PATH 1), double-buffered
|
|
||||||
* GIF rendering (PATH 3), double-buffered
|
|
||||||
* 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.
|
||||||
|
* Develop - daily builds - can be unstable.
|
||||||
|
|
||||||
* [PS2SDK](https://github.com/ps2dev/ps2sdk)
|
<br />
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
To get a local copy up and running follow these simple steps.
|
### Installation
|
||||||
YouTube tutorials soon!
|
Step by step [tutorial here](https://github.com/h4570/tyra/tree/develop/docs)
|
||||||
|
If you need any support, feel free to ask questions on discord:
|
||||||
|
[](https://discord.gg/NhhTmg3Gm5)
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
This is an example of how to list things you need to use the software and how to install them.
|
|
||||||
* PS2 DEV environment - [PS2DEV](https://github.com/ps2dev/ps2dev)
|
* PS2 DEV environment - [PS2DEV](https://github.com/ps2dev/ps2dev)
|
||||||
* At least #1a4587d PS2SDK - [PS2SDK](https://github.com/ps2dev/ps2sdk)
|
* At least #58ffb33 PS2SDK (28.05.2021) - [PS2SDK](https://github.com/ps2dev/ps2sdk)
|
||||||
* PS2 Emulator. For example [PCSX2](https://pcsx2.net/)
|
* PS2 Emulator. For example [PCSX2](https://pcsx2.net/)
|
||||||
|
|
||||||
### Installation
|
<br />
|
||||||
|
|
||||||
1. Clone the repo
|
|
||||||
```sh
|
|
||||||
git clone https://github.com/ps2-tyra/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
|
* If you want to use your own .obj file, please check "triangulate faces" in blender.
|
||||||
* If you want to run .elf in PCSX2, be sure that you have version >=1.6 and **Host access** enabled in PCSX2 configuration file.
|
PS2 is supporting only triangle primitive type.
|
||||||
* If you want to use your own .obj file, please check "triangulate faces" in blender. PS2 is supporting only trinagle primitive type.
|
|
||||||
|
<br />
|
||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
|
|
||||||
### Roadmap moved to github kanban:
|
### Roadmap for next master release:
|
||||||
[https://github.com/ps2-tyra/tyra/projects/1](https://github.com/ps2-tyra/tyra/projects/1)
|
[Next release roadmap](https://github.com/h4570/tyra/projects/4)
|
||||||
|
|
||||||
|
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/ps2-tyra/tyra/issues) for a list of proposed features (and known issues).
|
<br />
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
@@ -128,30 +139,52 @@ Contributions are what make the open source community such an amazing place to b
|
|||||||
4. Push to the Branch (`git push origin feature/amazing-feature`)
|
4. Push to the Branch (`git push origin feature/amazing-feature`)
|
||||||
5. Open a Pull Request
|
5. Open a Pull Request
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
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
|
<br />
|
||||||
|
|
||||||
Sandro Sobczyński - sandro.sobczynski@gmail.com
|
## Built With
|
||||||
[![LinkedIn][linkedin-shield]][linkedin-url]
|
|
||||||
|
* [PS2DEV](https://github.com/ps2dev/ps2dev)
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## 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
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
## 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, fjtrujy - 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/ps2-tyra/tyra](https://github.com/ps2-tyra/tyra)
|
Project Link: [https://github.com/h4570/tyra](https://github.com/h4570/tyra)
|
||||||
|
Sandro Sobczyński - sandro.sobczynski@gmail.com
|
||||||
|
[![LinkedIn][linkedin-shield]](https://linkedin.com/in/sandro-sobczyński-28820b15a)
|
||||||
|
|
||||||
[contributors-shield]: https://img.shields.io/github/contributors/ps2-tyra/tyra.svg?style=flat-square
|
<br />
|
||||||
[contributors-url]: https://github.com/ps2-tyra/tyra/graphs/contributors
|
<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-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/ps2-tyra/tyra.svg?style=flat-square
|
[license-url]: https://github.com/h4570/tyra/blob/master/LICENSE
|
||||||
[license-url]: https://github.com/ps2-tyra/tyra/blob/master/LICENSE
|
|
||||||
|
|||||||
+210
@@ -0,0 +1,210 @@
|
|||||||
|
# Installation tutorial
|
||||||
|
|
||||||
|
This tutorial will show you, how to:
|
||||||
|
- Setup your WSL machine for PS2DEV
|
||||||
|
- Install entire PS2DEV+Tyra environment
|
||||||
|
- Setup VSCode with Intelisense
|
||||||
|
- Setup PCSX2
|
||||||
|
|
||||||
|
So let's get started!
|
||||||
|
|
||||||
|
---
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
## VSCode and WSL
|
||||||
|
- Install VSCode from
|
||||||
|
https://code.visualstudio.com/
|
||||||
|
- Install WSL
|
||||||
|
https://docs.microsoft.com/en-us/windows/wsl/install-win10
|
||||||
|
`Info: Please choose Ubuntu-20.04`
|
||||||
|
- Set root as default WSL user.
|
||||||
|
Open `cmd.exe` and type:
|
||||||
|
`ubuntu2004 config --default-user root`
|
||||||
|
|
||||||
|
---
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
## Ubuntu configuration and PS2DEV+Tyra
|
||||||
|
- Open WSL terminal (Windows search -> wsl)
|
||||||
|
`Info: Be sure that are you logged as a root!`
|
||||||
|
- Type these commands
|
||||||
|
```
|
||||||
|
apt-get update && apt-get upgrade -y
|
||||||
|
apt-get install -y build-essential make texinfo cmake bison flex gettext libgmp3-dev libmpfr-dev libmpc-dev libz-dev wget patch
|
||||||
|
```
|
||||||
|
- Configure git (replace your name and email)
|
||||||
|
```
|
||||||
|
git config --global user.email "your@email.com"
|
||||||
|
git config --global user.name "Your Name"
|
||||||
|
```
|
||||||
|
- Create directories
|
||||||
|
```
|
||||||
|
mkdir /ps2dev
|
||||||
|
mkdir /ps2dev/built
|
||||||
|
mkdir /ps2dev/source
|
||||||
|
mkdir /repos
|
||||||
|
mkdir /repos/tyra
|
||||||
|
```
|
||||||
|
- Clone repos
|
||||||
|
```
|
||||||
|
git clone https://github.com/ps2dev/ps2dev.git /ps2dev/source/
|
||||||
|
git clone https://github.com/h4570/tyra.git /repos/tyra/
|
||||||
|
```
|
||||||
|
- Open bashrc via `nano ~/.bashrc` and add these lines at the end of file. Be sure that they are 1:1, so don't add additional spaces!
|
||||||
|
```
|
||||||
|
export PS2DEV=/ps2dev/built
|
||||||
|
export PS2SDK=$PS2DEV/ps2sdk
|
||||||
|
export GSKIT=$PS2DEV/gsKit
|
||||||
|
export PATH=$PATH:$PS2DEV/bin:$PS2DEV/ee/bin:$PS2DEV/iop/bin:$PS2DEV/dvp/bin:$PS2SDK/bin
|
||||||
|
export PS2HOSTNAME=192.168.0.200
|
||||||
|
export TYRA=/repos/tyra
|
||||||
|
export WSL_MAKE_WINDOWS=\\\\\\\\wsl\$\$\\\\Ubuntu-20.04
|
||||||
|
export WSL_LINUX_PCSX2=/mnt/c/Program\\\ Files\\\ \\\(x86\\\)/PCSX2
|
||||||
|
```
|
||||||
|
- Refresh env variables via -> `. ~/.bashrc`
|
||||||
|
- Close wsl terminal
|
||||||
|
|
||||||
|
---
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
## Mapping WSL directories to your Windows machine
|
||||||
|
- Open cmd and type `wsl.exe --list`
|
||||||
|
`Info: Remember your distribution name from this list. My is "Ubuntu-20.04"`
|
||||||
|
- Click at the windows logo on your keyboard, type "This PC" and open
|
||||||
|
- At the upper menu click "Map disk drive"
|
||||||
|
`Info: Replace my name with your WSL name!`
|
||||||
|
- Folder: \\\\wsl$\\Ubuntu-20.04
|
||||||
|
- Click OK
|
||||||
|
|
||||||
|
`Info: You will have now new disk on your PC, this is the WSL filesystem.`
|
||||||
|
|
||||||
|
---
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
## Configuring VSCode
|
||||||
|
- Open VSCode
|
||||||
|
- Install extension "Remote - WSL"
|
||||||
|
- Install extension "C/C++"
|
||||||
|
- Restart VSCode if required
|
||||||
|
- VSCode: Click on "File" -> "Open folder in WSL"
|
||||||
|
- Open "repos/tyra"
|
||||||
|
- VSCode: Click on "Terminal" -> "New terminal"
|
||||||
|
|
||||||
|
`Info: New terminal should appear. This is the same WSL terminal :)`
|
||||||
|
|
||||||
|
---
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
## PS2DEV installation
|
||||||
|
- In VSCode's WSL terminal type:
|
||||||
|
```
|
||||||
|
cd /ps2dev/source
|
||||||
|
./build-all.sh
|
||||||
|
```
|
||||||
|
`Info: This can take some time...`
|
||||||
|
- And open again .bashrc via `nano ~/.bashrc` and add these lines at the end of file.
|
||||||
|
```
|
||||||
|
export ZLIB=${PS2SDK}/ports
|
||||||
|
export LIBTIFF=${PS2SDK}/ports
|
||||||
|
export LIBJPEG=${PS2SDK}/ports
|
||||||
|
export LIBPNG=${PS2SDK}/ports
|
||||||
|
```
|
||||||
|
- Refresh env variables via `. ~/.bashrc`
|
||||||
|
|
||||||
|
### !!! Please don't forgot to remove/refresh these 4 exports when you will want to update PS2DEV (./build-all.sh), because there is circular dependency between these libs and gsKit which is included in PS2DEV !!!
|
||||||
|
|
||||||
|
---
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
## Build Tyra
|
||||||
|
- Go to one of the samples via `cd /repos/tyra/src/samples/floors`
|
||||||
|
- Build debug version: `make rebuild-dbg-engine`
|
||||||
|
`Info: If you want to build final version in future, type make rebuild-engine `
|
||||||
|
|
||||||
|
---
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
## Install & configure PCSX2
|
||||||
|
- Download & install PCSX2 from (1.6+ version)
|
||||||
|
https://pcsx2.net/
|
||||||
|
- Extract bios files from
|
||||||
|
https://romsmania.cc/bios/pcsx2-playstation-2-bios-3
|
||||||
|
to
|
||||||
|
`C:\Users%USERNAME%\Documents\PCSX2\bios`
|
||||||
|
- Close `PCSX2` if you have opened!
|
||||||
|
- Open `C:\Users\hasto\Documents\PCSX2\inis\PCSX2_vm.ini` in notepad
|
||||||
|
```
|
||||||
|
HostFs=enabled
|
||||||
|
```
|
||||||
|
- Open PCSX2 and map pad to your keyboard, for example:
|
||||||
|
```
|
||||||
|
WASD = Left joy
|
||||||
|
Arrows = Right joy
|
||||||
|
Space = X
|
||||||
|
Circle = C
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
## Run one of the samples
|
||||||
|
|
||||||
|
- Add assets for "floors" sample
|
||||||
|
- Download assets from
|
||||||
|
https://github.com/h4570/tyra/tree/master/src/samples/floors
|
||||||
|
- Windows: Open your WSL folder (This PC -> WSL folder)
|
||||||
|
- Extract assets to /repos/tyra/src/samples/floors/bin/ (create bin folder if not exists)
|
||||||
|
- Compile sample via `make`
|
||||||
|
`Info: Elf file should be produced in /bin`
|
||||||
|
- Run sample in PSX2 via `make run-pcsx2`
|
||||||
|
|
||||||
|
---
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
## How to code?
|
||||||
|
Do some changes in your sample and just type `make clean all run-pcsx2` in your sample folder.
|
||||||
|
You can create your own sample, by just copying cube folder.
|
||||||
|
|
||||||
|
---
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
## Setup Intelisense
|
||||||
|
|
||||||
|
- Download
|
||||||
|
http://apgcglz.cluster028.hosting.ovh.net/tyra/intellisense.zip
|
||||||
|
- Unpack `.vscode` folder to WSL's `/repos/tyra/`
|
||||||
|
`Info: This configuration is set for cube sample, but you can change it in tasks.json file`
|
||||||
|
|
||||||
|
---
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
## Advanced: Compiling VU1 programs
|
||||||
|
`Info: Based on https://github.com/microsoft/wsl/issues/2468#issuecomment-374904520`
|
||||||
|
- Download VCL
|
||||||
|
http://lukasz.dk/files/vcl.1.4.beta7.x86.tgz
|
||||||
|
- Rename `vcl_14beta7_x86` binary to `vcl`
|
||||||
|
- Put `vcl` to WSL's `/usr/bin`
|
||||||
|
```
|
||||||
|
apt-get install qemu qemu-user-static binfmt-support
|
||||||
|
update-binfmts --install i386 /usr/bin/qemu-i386-static --magic '\x7fELF\x01\x01\x01\x03\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x03\x00\x01\x00\x00\x00' --mask '\xff\xff\xff\xff\xff\xff\xff\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xf8\xff\xff\xff\xff\xff\xff\xff'
|
||||||
|
dpkg --add-architecture i386
|
||||||
|
apt-get update
|
||||||
|
apt-get install libstdc++5:i386
|
||||||
|
chmod 755 /usr/bin/vcl
|
||||||
|
```
|
||||||
|
`Info: In Ubuntu 18.04 I was obligated to install lib32ncurses5 also`
|
||||||
|
- Add this line to `~/.bashrc`
|
||||||
|
```
|
||||||
|
service binfmt-support start &>/dev/null
|
||||||
|
```
|
||||||
|
- Uncomment `.vsm`/`.vcl` recipe from Tyra's engine `Makefile`
|
||||||
|
- Download & install VCL preprocessor
|
||||||
|
```
|
||||||
|
mkdir temp && cd temp
|
||||||
|
git clone https://github.com/glampert/vclpp .
|
||||||
|
make
|
||||||
|
cp vclpp /usr/bin/
|
||||||
|
chmod 755 /usr/bin/vclpp
|
||||||
|
cd .. && rm -rf ./temp
|
||||||
|
```
|
||||||
|
- Uncomment `.vclpp`/`.vcl` recipe from Tyra's engine `Makefile`
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
TYRA_DIR = ./
|
||||||
|
|
||||||
|
EE_OBJS = \
|
||||||
|
models/math/matrix.o \
|
||||||
|
models/math/plane.o \
|
||||||
|
models/math/point.o \
|
||||||
|
models/math/vector3.o \
|
||||||
|
models/mesh_frame.o \
|
||||||
|
models/bounding_box.o \
|
||||||
|
models/mesh_material.o \
|
||||||
|
models/mesh.o \
|
||||||
|
models/sprite.o \
|
||||||
|
models/texture.o \
|
||||||
|
modules/audio.o \
|
||||||
|
modules/camera_base.o \
|
||||||
|
modules/file_service.o \
|
||||||
|
modules/gif_sender.o \
|
||||||
|
modules/light.o \
|
||||||
|
modules/pad.o \
|
||||||
|
modules/renderer.o \
|
||||||
|
modules/texture_repository.o \
|
||||||
|
modules/timer.o \
|
||||||
|
modules/vif_sender.o \
|
||||||
|
utils/math.o \
|
||||||
|
utils/string.o \
|
||||||
|
loaders/bmp_loader.o \
|
||||||
|
loaders/dff_loader.o \
|
||||||
|
loaders/md2_loader.o \
|
||||||
|
loaders/obj_loader.o \
|
||||||
|
loaders/png_loader.o \
|
||||||
|
vu1_progs/draw3D.o \
|
||||||
|
engine.o
|
||||||
|
|
||||||
|
all: $(EE_OBJS)
|
||||||
|
ar rcs $(LIB_NAME) $(EE_OBJS)
|
||||||
|
rm -f $(EE_OBJS)
|
||||||
|
|
||||||
|
# %.vcl: %.vclpp
|
||||||
|
# $(EE_VCLPP) $< $@
|
||||||
|
|
||||||
|
# %.vsm: %.vcl
|
||||||
|
# $(EE_VCL) $< >> $@
|
||||||
|
|
||||||
|
%.o: %.vsm
|
||||||
|
$(EE_DVP) $< -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(EE_OBJS)
|
||||||
|
rm -f $(LIB_NAME)
|
||||||
|
|
||||||
|
include Makefile.pref
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
EE_LIBS := $(EE_LIBS) -ldraw -lcdvd -lgraph -lmath3d -lpacket -ldma -lpacket2 -lpad -laudsrv -lc -lstdc++ -lpng -lz
|
||||||
|
EE_INCS := -I$(TYRA)/src/engine/include -I$(PS2SDK)/ports/include $(EE_INCS)
|
||||||
|
EE_LDFLAGS := -L$(PS2SDK)/ports/lib -L$(TYRA)/src/engine $(EE_LDFLAGS)
|
||||||
|
EE_CXXFLAGS := -DHAVE_LIBJPEG -DHAVE_LIBTIFF -DHAVE_LIBPNG -DHAVE_ZLIB -D_XCDVD $(EE_CXXFLAGS)
|
||||||
|
EE_DVP = dvp-as
|
||||||
|
EE_VCL = vcl
|
||||||
|
EE_VCLPP = vclpp
|
||||||
|
LIB_NAME = libtyra.a
|
||||||
|
|
||||||
|
include $(PS2SDK)/samples/Makefile.pref
|
||||||
|
include $(PS2SDK)/samples/Makefile.eeglobal
|
||||||
+29
-37
@@ -15,28 +15,22 @@
|
|||||||
#include <sifrpc.h>
|
#include <sifrpc.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
#include "include/modules/vu1.hpp"
|
|
||||||
#include "include/utils/debug.hpp"
|
#include "include/utils/debug.hpp"
|
||||||
|
|
||||||
// VU1 micro program
|
|
||||||
extern u32 VU1Draw3D_CodeStart __attribute__((section(".vudata")));
|
|
||||||
extern u32 VU1Draw3D_CodeEnd __attribute__((section(".vudata")));
|
|
||||||
//
|
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
// Constructors/Destructors
|
// Constructors/Destructors
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
Engine::Engine()
|
Engine::Engine()
|
||||||
{
|
{
|
||||||
SifInitRpc(0);
|
setDefaultScreen();
|
||||||
srand(time(NULL));
|
firePS2();
|
||||||
VU1::uploadProgram(0, &VU1Draw3D_CodeStart, &VU1Draw3D_CodeEnd);
|
}
|
||||||
audio.startThread();
|
|
||||||
isInitialized = 0;
|
Engine::Engine(const ScreenSettings &t_screen)
|
||||||
isScreenInitialized = 0;
|
{
|
||||||
mainThreadId = GetThreadId();
|
screen = t_screen;
|
||||||
|
firePS2();
|
||||||
}
|
}
|
||||||
|
|
||||||
Engine::~Engine() {}
|
Engine::~Engine() {}
|
||||||
@@ -45,38 +39,25 @@ Engine::~Engine() {}
|
|||||||
// Methods
|
// Methods
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
void Engine::setScreen(ScreenSettings &t_settings)
|
|
||||||
{
|
|
||||||
screen = t_settings;
|
|
||||||
isScreenInitialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
||||||
isScreenInitialized = true;
|
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)
|
||||||
{
|
{
|
||||||
if (!isScreenInitialized)
|
assertMsg(!isInitialized, "Engine was already initialized!");
|
||||||
PRINT_ERR("Cant init because screen was not set!");
|
game = t_game;
|
||||||
else if (isInitialized)
|
renderer = new Renderer(t_gifPacketSize, &screen);
|
||||||
PRINT_ERR("Already initialized!");
|
isInitialized = true;
|
||||||
else
|
game->onInit();
|
||||||
{
|
gameLoop();
|
||||||
game = t_game;
|
|
||||||
renderer = new Renderer(t_gifPacketSize, &screen);
|
|
||||||
isInitialized = true;
|
|
||||||
game->onInit();
|
|
||||||
gameLoop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Do not call this method. This is used in gameLoop() to maintain multithreading */
|
/** Do not call this method. This is used in gameLoop() to maintain multithreading */
|
||||||
@@ -88,6 +69,17 @@ void Engine::wakeup(s32 t_alarmId, u16 t_time, void *t_common)
|
|||||||
ExitHandler();
|
ExitHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Engine::firePS2()
|
||||||
|
{
|
||||||
|
SifInitRpc(0);
|
||||||
|
srand(time(NULL));
|
||||||
|
// fileService.startThread();
|
||||||
|
// audio.startThread(&fileService);
|
||||||
|
audio.startThread(NULL);
|
||||||
|
isInitialized = 0;
|
||||||
|
mainThreadId = GetThreadId();
|
||||||
|
}
|
||||||
|
|
||||||
void Engine::gameLoop()
|
void Engine::gameLoop()
|
||||||
{
|
{
|
||||||
for (;;)
|
for (;;)
|
||||||
@@ -99,10 +91,10 @@ void Engine::gameLoop()
|
|||||||
fps = timer.getFPS();
|
fps = timer.getFPS();
|
||||||
fpsDelayer = 0;
|
fpsDelayer = 0;
|
||||||
}
|
}
|
||||||
timer.primeTimer();
|
timer.prime();
|
||||||
renderer->endFrame(fps);
|
renderer->endFrame(fps);
|
||||||
/** -6~ FPS */
|
/** -6~ FPS */
|
||||||
SetAlarm(fps > 49.0F ? 24 : 48, &Engine::wakeup, &mainThreadId);
|
SetAlarm(150, &Engine::wakeup, &mainThreadId);
|
||||||
SleepThread();
|
SleepThread();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,33 +19,34 @@
|
|||||||
#include "modules/timer.hpp"
|
#include "modules/timer.hpp"
|
||||||
#include "modules/pad.hpp"
|
#include "modules/pad.hpp"
|
||||||
#include "modules/audio.hpp"
|
#include "modules/audio.hpp"
|
||||||
|
#include "modules/file_service.hpp"
|
||||||
|
|
||||||
class Engine
|
class Engine
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Engine(const ScreenSettings &screen);
|
||||||
Engine();
|
Engine();
|
||||||
~Engine();
|
~Engine();
|
||||||
|
|
||||||
void init(Game *t_game, u32 t_gifPacketSize);
|
void init(Game *t_game, u32 t_gifPacketSize);
|
||||||
void setDefaultScreen();
|
void setDefaultScreen();
|
||||||
void setScreen(ScreenSettings &t_settings);
|
|
||||||
Renderer *renderer;
|
Renderer *renderer;
|
||||||
|
// FileService fileService;
|
||||||
Audio audio;
|
Audio audio;
|
||||||
ScreenSettings screen;
|
ScreenSettings screen;
|
||||||
Pad pad;
|
Pad pad;
|
||||||
float fps;
|
float fps;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void firePS2();
|
||||||
u8 fpsDelayer;
|
u8 fpsDelayer;
|
||||||
Timer timer;
|
Timer timer;
|
||||||
u8 isInitialized, isScreenInitialized;
|
u8 isInitialized;
|
||||||
void gameLoop();
|
void gameLoop();
|
||||||
Game *game;
|
Game *game;
|
||||||
s32 mainThreadId;
|
s32 mainThreadId;
|
||||||
static void wakeup(s32 t_alarmId, u16 t_time, void *t_common);
|
static void wakeup(s32 t_alarmId, u16 t_time, void *t_common);
|
||||||
|
|
||||||
// ThreadManager threadManager;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <tamtypes.h>
|
#include <tamtypes.h>
|
||||||
#include "../models/mesh_texture.hpp"
|
#include "../models/texture.hpp"
|
||||||
|
|
||||||
/** Class responsible for loading images in bmp format */
|
/** Class responsible for loading images in bmp format */
|
||||||
class BmpLoader
|
class BmpLoader
|
||||||
@@ -23,7 +23,7 @@ public:
|
|||||||
BmpLoader();
|
BmpLoader();
|
||||||
~BmpLoader();
|
~BmpLoader();
|
||||||
|
|
||||||
void load(MeshTexture &o_texture, char *t_subfolder, char *t_name, char *t_extension);
|
void load(Texture &o_texture, char *t_subfolder, char *t_name, char *t_extension);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ public:
|
|||||||
DffLoader();
|
DffLoader();
|
||||||
~DffLoader();
|
~DffLoader();
|
||||||
|
|
||||||
|
// void im_not_used_anywhere(MeshFrame *o_result, char *t_fileName, float t_scale, u8 t_invertT);
|
||||||
void load(MeshFrame *o_result, char *t_fileName, float t_scale, u8 t_invertT);
|
void load(MeshFrame *o_result, char *t_fileName, float t_scale, u8 t_invertT);
|
||||||
void serialize(MeshFrame *o_result, u8 t_invertT, u8 *t_data, float t_scale);
|
void serialize(MeshFrame *o_result, u8 t_invertT, u8 *t_data, float t_scale);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TYRA_PNG_LOADER_
|
||||||
|
#define _TYRA_BMP_LOADER_
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <tamtypes.h>
|
||||||
|
#include "../models/texture.hpp"
|
||||||
|
|
||||||
|
/** Class responsible for loading images in bmp format */
|
||||||
|
class PngLoader
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
PngLoader();
|
||||||
|
~PngLoader();
|
||||||
|
|
||||||
|
void load(Texture &o_texture, char *t_subfolder, char *t_name, char *t_extension);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -17,6 +17,7 @@ class AudioListener
|
|||||||
public:
|
public:
|
||||||
virtual ~AudioListener(){};
|
virtual ~AudioListener(){};
|
||||||
virtual void onAudioTick() = 0;
|
virtual void onAudioTick() = 0;
|
||||||
|
virtual void onAudioFinish() = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Michał Mostowik <mostek3pl@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TYRA_BOUNDING_BOX_
|
||||||
|
#define _TYRA_BOUNDING_BOX_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <tamtypes.h>
|
||||||
|
#include "math/point.hpp"
|
||||||
|
#include "math/vector3.hpp"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Struct containing face data used in
|
||||||
|
* bounding box class.
|
||||||
|
*/
|
||||||
|
struct BoundingBoxFace
|
||||||
|
{
|
||||||
|
BoundingBoxFace(){
|
||||||
|
|
||||||
|
};
|
||||||
|
BoundingBoxFace(const Vector3 &t_minCorner, const Vector3 &t_maxCorner, float t_axisPos)
|
||||||
|
{
|
||||||
|
minCorner = t_minCorner;
|
||||||
|
maxCorner = t_maxCorner;
|
||||||
|
axisPosition = t_axisPos;
|
||||||
|
}
|
||||||
|
/** Position of the face on it's respective axis. */
|
||||||
|
float axisPosition;
|
||||||
|
/** Corner of the face with lower coordinates */
|
||||||
|
Vector3 minCorner;
|
||||||
|
/** Corner of the face with higher coordinates */
|
||||||
|
Vector3 maxCorner;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class containing bounding box data
|
||||||
|
* which can be used for collision detection.
|
||||||
|
*/
|
||||||
|
class BoundingBox
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BoundingBox(Vector3 *t_vertices);
|
||||||
|
~BoundingBox();
|
||||||
|
const float &getHeight() { return _height; };
|
||||||
|
const float &getDepth() { return _depth; };
|
||||||
|
const float &getWidth() { return _width; };
|
||||||
|
/** @returns the vector directly in middle of the bounding box. */
|
||||||
|
const Vector3 &getCenter() { return _centerVector; };
|
||||||
|
/** @returns the front face (further on z-axis) */
|
||||||
|
const BoundingBoxFace &getFrontFace() { return _frontFace; };
|
||||||
|
/** @returns the back face (nearer on z-axis) */
|
||||||
|
const BoundingBoxFace &getBackFace() { return _backFace; };
|
||||||
|
/** @returns the left face (further on x-axis) */
|
||||||
|
const BoundingBoxFace &getLeftFace() { return _leftFace; };
|
||||||
|
/** @returns the right face (nearer on x-axis) */
|
||||||
|
const BoundingBoxFace &getRightFace() { return _rightFace; };
|
||||||
|
/** @returns the top face (further on y-axis) */
|
||||||
|
const BoundingBoxFace &getTopFace() { return _topFace; };
|
||||||
|
/** @returns the bottom face (nearer on y-axis) */
|
||||||
|
const BoundingBoxFace &getBottomFace() { return _bottomFace; };
|
||||||
|
/**
|
||||||
|
* @returns bounding box raw vertices array.
|
||||||
|
* Total length: 8
|
||||||
|
*/
|
||||||
|
const Vector3 &getVertex(const u8 &i) { return _vertices[i]; };
|
||||||
|
/** @returns single vertex from raw vertices array.*/
|
||||||
|
Vector3 *getVertices() { return _vertices; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
Vector3 _vertices[8];
|
||||||
|
float _height, _depth, _width;
|
||||||
|
Vector3 _centerVector;
|
||||||
|
/** Front face (further on z-axis) */
|
||||||
|
BoundingBoxFace _frontFace;
|
||||||
|
/** Back face (nearer on z-axis) */
|
||||||
|
BoundingBoxFace _backFace;
|
||||||
|
/** Left face (nearer on x-axis) */
|
||||||
|
BoundingBoxFace _leftFace;
|
||||||
|
/** Right face (further on x-axis) */
|
||||||
|
BoundingBoxFace _rightFace;
|
||||||
|
/** Top face (further on y-axis) */
|
||||||
|
BoundingBoxFace _topFace;
|
||||||
|
/** Bottom face (nearer on y-axis) */
|
||||||
|
BoundingBoxFace _bottomFace;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
struct LightBulb
|
struct LightBulb
|
||||||
{
|
{
|
||||||
Vector3 position;
|
Vector3 position;
|
||||||
u16 intensity;
|
u8 intensity;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -13,29 +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*(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();
|
||||||
void makeZRotation(float t_radians);
|
|
||||||
void translate(float t_x, float t_y, float t_z);
|
/**
|
||||||
void setPerspective(ScreenSettings &screen);
|
* 1 0 0 0
|
||||||
void print();
|
* 0 1 0 0
|
||||||
|
* 0 0 1 0
|
||||||
|
* 0 0 0 1
|
||||||
|
*/
|
||||||
|
inline void unit() { identity(); };
|
||||||
|
|
||||||
|
/** Translate matrix. */
|
||||||
|
inline void translate(const Vector3 &t_val)
|
||||||
|
{
|
||||||
|
Matrix temp = Matrix(true);
|
||||||
|
temp.translation(t_val);
|
||||||
|
cross(this->data, temp.data, this->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Rotate matrix. */
|
||||||
|
inline void rotate(const Vector3 &t_val)
|
||||||
|
{
|
||||||
|
Matrix temp = Matrix(true);
|
||||||
|
|
||||||
|
temp.rotationZ(t_val.z);
|
||||||
|
cross(this->data, temp.data, this->data);
|
||||||
|
|
||||||
|
temp.identity();
|
||||||
|
temp.rotationY(t_val.y);
|
||||||
|
cross(this->data, temp.data, this->data);
|
||||||
|
|
||||||
|
temp.identity();
|
||||||
|
temp.rotationX(t_val.x);
|
||||||
|
cross(this->data, temp.data, this->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Rotate matrix by X. */
|
||||||
|
inline void rotateX(const float &t_radians)
|
||||||
|
{
|
||||||
|
Matrix temp = Matrix(true);
|
||||||
|
temp.rotationX(t_radians);
|
||||||
|
cross(this->data, temp.data, this->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Rotate matrix by Y. */
|
||||||
|
inline void rotateY(const float &t_radians)
|
||||||
|
{
|
||||||
|
Matrix temp = Matrix(true);
|
||||||
|
temp.rotationY(t_radians);
|
||||||
|
cross(this->data, temp.data, this->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Rotate matrix by Z. */
|
||||||
|
inline void rotateZ(const float &t_radians)
|
||||||
|
{
|
||||||
|
Matrix temp = Matrix(true);
|
||||||
|
temp.rotationZ(t_radians);
|
||||||
|
cross(this->data, temp.data, this->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Rotate matrix by angle. */
|
||||||
|
void rotateByAngle(const float &t_angle, const Vector3 &t_axis)
|
||||||
|
{
|
||||||
|
Matrix temp;
|
||||||
|
temp.rotationByAngle(t_angle, t_axis);
|
||||||
|
cross(this->data, temp.data, this->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Scale matrix. */
|
||||||
|
void scale(const Vector3 &t_val)
|
||||||
|
{
|
||||||
|
Matrix temp = Matrix(true);
|
||||||
|
temp.setScale(t_val);
|
||||||
|
cross(this->data, temp.data, this->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create perspective projection matrix.
|
||||||
|
*
|
||||||
|
* Complies with OpenGL standard (gluPerspective).
|
||||||
|
* @see https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml
|
||||||
|
* @param screen Screen settings
|
||||||
|
*/
|
||||||
|
void setPerspective(const ScreenSettings &screen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a view matrix that transforms coordinates in
|
||||||
|
* such a way that the user looks at a target vector
|
||||||
|
* direction from a position vector.
|
||||||
|
*
|
||||||
|
* Complies with OpenGL standard (glLookAt).
|
||||||
|
* @see https://learnopengl.com/Getting-started/Camera
|
||||||
|
*/
|
||||||
|
void lookAt(const Vector3 &t_position, const Vector3 &t_target);
|
||||||
|
|
||||||
|
/** Print matrix (printf). */
|
||||||
|
const void print() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void rotationX(const float &t_radians);
|
||||||
|
void rotationY(const float &t_radians);
|
||||||
|
void rotationZ(const float &t_radians);
|
||||||
|
void rotationByAngle(const float &t_angle, const Vector3 &t_axis);
|
||||||
|
void translation(const Vector3 &t_val);
|
||||||
|
void setScale(const Vector3 &t_val);
|
||||||
|
void setCamera(const float t_pos[4], const float t_vz[4], const float t_vy[4]);
|
||||||
|
void cross(float res[16], const float a[16], const float b[16]) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public:
|
|||||||
|
|
||||||
void update(Vector3 &a, Vector3 &b, Vector3 &c);
|
void update(Vector3 &a, Vector3 &b, Vector3 &c);
|
||||||
inline float distanceTo(Vector3 &t_vec) { return this->distance + this->normal.innerProduct(t_vec); }
|
inline float distanceTo(Vector3 &t_vec) { return this->distance + this->normal.innerProduct(t_vec); }
|
||||||
void print();
|
const void print() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -32,8 +32,9 @@ public:
|
|||||||
~Point();
|
~Point();
|
||||||
|
|
||||||
void set(const float &t_x, const float &t_y);
|
void set(const float &t_x, const float &t_y);
|
||||||
|
void rotate(const float &t_angle, const float &t_x, const float &t_y);
|
||||||
void set(const Point &v);
|
void set(const Point &v);
|
||||||
void print();
|
const void print() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -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,30 +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*(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);
|
/** Create vector with given values. */
|
||||||
u8 collidesSquare(Vector3 &t_min, Vector3 &t_max);
|
Vector3(const float &t_x, const float &t_y, const float &t_z) { set(t_x, t_y, t_z); }
|
||||||
u8 isOnSquare(Vector3 &t_min, Vector3 &t_max);
|
|
||||||
float length();
|
// ----
|
||||||
void normalize();
|
// Operators
|
||||||
void setByLerp(const Vector3 &v1, const Vector3 &v2, const float &t_interp, const float &t_scale);
|
// ----
|
||||||
float innerProduct(Vector3 &v);
|
|
||||||
|
Vector3 operator+(const Vector3 &v) const;
|
||||||
|
Vector3 operator-(const Vector3 &v) const;
|
||||||
|
/** Also called "cross product" */
|
||||||
|
Vector3 operator*(const Vector3 &v) const;
|
||||||
|
Vector3 operator*(const float &t) const;
|
||||||
|
Vector3 operator/(const float &t) const;
|
||||||
|
Vector3 operator-(void) const { return Vector3(-x, -y, -z); }
|
||||||
|
void operator+=(const Vector3 &t);
|
||||||
|
void operator*=(const float &t);
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Functions
|
||||||
|
// ----
|
||||||
|
|
||||||
|
/** Set vector values via VU0. */
|
||||||
void set(const Vector3 &v);
|
void set(const Vector3 &v);
|
||||||
void set(const float &x, const float &y, const float &z);
|
|
||||||
void copy(Vector3 &v);
|
/** Set vector values. */
|
||||||
float distanceTo(Vector3 &v);
|
void set(const float &t_x, const float &t_y, const float &t_z);
|
||||||
void print();
|
|
||||||
|
/** Also called dot3. */
|
||||||
|
float innerProduct(const Vector3 &v) const;
|
||||||
|
|
||||||
|
/** Get vector length */
|
||||||
|
float length() const;
|
||||||
|
|
||||||
|
/** Normalize vector. */
|
||||||
|
void normalize();
|
||||||
|
|
||||||
|
/** Returns distance between two vectors */
|
||||||
|
float distanceTo(const Vector3 &v) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks intersection with given box
|
||||||
|
* @param t_min Opposite min vertex (ex. near, left, down vertex of bounding box)
|
||||||
|
* @param t_max Opposite max vertex (ex. far, right, up vertex of bounding box)
|
||||||
|
*/
|
||||||
|
u8 collidesBox(const Vector3 &t_min, const Vector3 &t_max) const
|
||||||
|
{
|
||||||
|
return ((this->x <= t_max.x && this->x >= t_min.x) && (this->y < t_max.y && this->y >= t_min.y) && (this->z <= t_max.z && this->z >= t_min.z)) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this vector is on given box (this->y >= box.y)
|
||||||
|
* @param t_min Opposite min vertex (ex. near, left, down vertex of bounding box)
|
||||||
|
* @param t_max Opposite max vertex (ex. far, right, up vertex of bounding box)
|
||||||
|
*/
|
||||||
|
u8 isOnBox(const Vector3 &t_min, const Vector3 &t_max) const
|
||||||
|
{
|
||||||
|
return ((this->x <= t_max.x && this->x >= t_min.x) && (this->y >= t_max.y) && (this->z <= t_max.z && this->z >= t_min.z)) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check if given triangle should be backface culled. */
|
||||||
|
static u8 shouldBeBackfaceCulled(const Vector3 *t_cameraPos, const Vector3 *t_v0, const Vector3 *t_v1, const Vector3 *t_v2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set by linear interpolation between two vertices (animation).
|
||||||
|
* @param t_v1 Before vertex
|
||||||
|
* @param t_v2 After vertex
|
||||||
|
* @param t_interp State of interpolation
|
||||||
|
* @param t_scale Scale
|
||||||
|
*/
|
||||||
|
void setByLerp(const Vector3 &t_v1, const Vector3 &t_v2, const float &t_interp, const float &t_scale);
|
||||||
|
|
||||||
|
const void print() const
|
||||||
|
{
|
||||||
|
printf("Vector3(%f, %f, %f)\n", x, y, z);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -13,15 +13,17 @@
|
|||||||
|
|
||||||
#include "math/vector3.hpp"
|
#include "math/vector3.hpp"
|
||||||
#include "math/plane.hpp"
|
#include "math/plane.hpp"
|
||||||
#include "./mesh_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"
|
||||||
|
|
||||||
/** Class which have common types for all 3D objects */
|
/**
|
||||||
|
* Class which have contain 3D object data.
|
||||||
|
* External data can be loaded via loadXXX() methods.
|
||||||
|
*/
|
||||||
class Mesh
|
class Mesh
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -31,8 +33,15 @@ public:
|
|||||||
|
|
||||||
Vector3 position, rotation;
|
Vector3 position, rotation;
|
||||||
float scale;
|
float scale;
|
||||||
u8 shouldBeLighted, shouldBeBackfaceCulled, shouldBeFrustumCulled;
|
u8 shouldBeLighted;
|
||||||
color_t color;
|
/**
|
||||||
|
* When true, invisible triangles of mesh materials are not drawn.
|
||||||
|
*/
|
||||||
|
u8 shouldBeBackfaceCulled;
|
||||||
|
/**
|
||||||
|
* When true, mesh materials are not drawn when they are outside of view frustum.
|
||||||
|
*/
|
||||||
|
u8 shouldBeFrustumCulled;
|
||||||
clutbuffer_t clut;
|
clutbuffer_t clut;
|
||||||
lod_t lod;
|
lod_t lod;
|
||||||
|
|
||||||
@@ -51,7 +60,7 @@ public:
|
|||||||
/** Returns material, which is a mesh "subgroup". */
|
/** Returns material, which is a mesh "subgroup". */
|
||||||
MeshMaterial &getMaterial(const u32 &i) const { return frames[0].getMaterial(i); };
|
MeshMaterial &getMaterial(const u32 &i) const { return frames[0].getMaterial(i); };
|
||||||
|
|
||||||
/** Auto count of frames. Static object (not animated) will have only 1 frame. */
|
/** Count of frames. Static object (not animated) will have only 1 frame. */
|
||||||
const u32 &getFramesCount() const { return framesCount; };
|
const u32 &getFramesCount() const { return framesCount; };
|
||||||
|
|
||||||
/** Count of vertices. */
|
/** Count of vertices. */
|
||||||
@@ -83,10 +92,13 @@ public:
|
|||||||
* Returns bounding vertex of current frame.
|
* Returns bounding vertex of current frame.
|
||||||
* @param i 0-7. Because, bounding box have 8 corners
|
* @param i 0-7. Because, bounding box have 8 corners
|
||||||
*/
|
*/
|
||||||
Vector3 &getCurrentBoundingBoxVertex(const u8 &i) { return frames[animState.currentFrame].getBoundingBoxVertex(i); };
|
const Vector3 &getCurrentBoundingBoxVertex(const u8 &i) { return frames[animState.currentFrame].getBoundingBoxVertex(i); };
|
||||||
|
|
||||||
/** Returns bounding box of current frame. Size: 8 */
|
/** @returns bounding box vertex array of current frame. Size: 8 */
|
||||||
Vector3 *getCurrentBoundingBox() const { return frames[animState.currentFrame].getBoundingBox(); };
|
const Vector3 *getCurrentBoundingBoxVertices() const { return frames[animState.currentFrame].getBoundingBoxVertices(); };
|
||||||
|
|
||||||
|
/** @returns bounding box object of current frame. */
|
||||||
|
const BoundingBox *getCurrentBoundingBox() const { return frames[animState.currentFrame].getBoundingBox(); };
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
// Setters
|
// Setters
|
||||||
@@ -97,7 +109,7 @@ public:
|
|||||||
// ----
|
// ----
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load mesh data from .obj files. Animation not supported.
|
* Load mesh data from .obj files. Animation supported.
|
||||||
* Be aware that texture names will be grabbed from material name.
|
* Be aware that texture names will be grabbed from material name.
|
||||||
* So no .mtl file is needed. Please check if material names in .obj file
|
* So no .mtl file is needed. Please check if material names in .obj file
|
||||||
* are equal to texture file names.
|
* are equal to texture file names.
|
||||||
@@ -113,7 +125,7 @@ public:
|
|||||||
void loadObj(char *t_subfolder, char *t_objFile, const float &t_scale, const u32 &t_framesCount, const u8 &t_invertT);
|
void loadObj(char *t_subfolder, char *t_objFile, const float &t_scale, const u32 &t_framesCount, const u8 &t_invertT);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load mesh data from .obj file. Animation supported.
|
* Load mesh data from .obj file. Animation not supported.
|
||||||
* Be aware that texture names will be grabbed from material name.
|
* Be aware that texture names will be grabbed from material name.
|
||||||
* So no .mtl file is needed. Please check if material names in .obj file
|
* So no .mtl file is needed. Please check if material names in .obj file
|
||||||
* are equal to texture file names.
|
* are equal to texture file names.
|
||||||
@@ -162,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.
|
||||||
@@ -193,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();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <tamtypes.h>
|
#include <tamtypes.h>
|
||||||
|
#include "bounding_box.hpp"
|
||||||
#include "math/point.hpp"
|
#include "math/point.hpp"
|
||||||
#include "math/vector3.hpp"
|
#include "math/vector3.hpp"
|
||||||
#include "./mesh_material.hpp"
|
#include "./mesh_material.hpp"
|
||||||
@@ -34,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; };
|
||||||
@@ -76,16 +83,21 @@ public:
|
|||||||
MeshMaterial *getMaterials() const { return materials; };
|
MeshMaterial *getMaterials() const { return materials; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns bounding box (AABB).
|
* @returns bounding box (AABB).
|
||||||
* Total length: 8
|
* Total length: 8
|
||||||
*/
|
*/
|
||||||
Vector3 *getBoundingBox() { return boundingBox; };
|
Vector3 *getBoundingBoxVertices() { return boundingBoxObj->getVertices(); };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns bounding box (AABB) vertex.
|
* @returns bounding box (AABB) vertex.
|
||||||
* Total length: 8
|
* Total length: 8
|
||||||
*/
|
*/
|
||||||
Vector3 &getBoundingBoxVertex(const u8 &i) { return boundingBox[i]; };
|
const Vector3 &getBoundingBoxVertex(const u8 &i) { return boundingBoxObj->getVertex(i); };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns bounding box (AABB) object pointer.
|
||||||
|
*/
|
||||||
|
BoundingBox *getBoundingBox() { return boundingBoxObj; };
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
// Setters
|
// Setters
|
||||||
@@ -113,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);
|
||||||
|
|
||||||
@@ -139,18 +166,17 @@ public:
|
|||||||
void calculateBoundingBoxes();
|
void calculateBoundingBoxes();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector3 boundingBox[8];
|
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 *sts __attribute__((aligned(16)));
|
Point __attribute__((aligned(16))) * sts;
|
||||||
Vector3
|
Vector3 __attribute__((aligned(16))) * vertices, *normals;
|
||||||
*vertices __attribute__((aligned(16))),
|
|
||||||
*normals __attribute__((aligned(16)));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -12,10 +12,13 @@
|
|||||||
#define _TYRA_MESH_MATERIAL_
|
#define _TYRA_MESH_MATERIAL_
|
||||||
|
|
||||||
#include <tamtypes.h>
|
#include <tamtypes.h>
|
||||||
|
#include <draw_types.h>
|
||||||
|
#include "bounding_box.hpp"
|
||||||
#include "./math/vector3.hpp"
|
#include "./math/vector3.hpp"
|
||||||
#include "./math/plane.hpp"
|
#include "./math/plane.hpp"
|
||||||
|
|
||||||
/** Class which contains draw instructions for part mesh of mesh.
|
/**
|
||||||
|
* Class which contains draw instructions for part of mesh.
|
||||||
* Mesh can have many materials.
|
* Mesh can have many materials.
|
||||||
* For example, car mesh can have three materials:
|
* For example, car mesh can have three materials:
|
||||||
* body, tires and windows.
|
* body, tires and windows.
|
||||||
@@ -27,6 +30,8 @@ public:
|
|||||||
MeshMaterial();
|
MeshMaterial();
|
||||||
~MeshMaterial();
|
~MeshMaterial();
|
||||||
|
|
||||||
|
color_t color;
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
// Getters
|
// Getters
|
||||||
// ----
|
// ----
|
||||||
@@ -61,16 +66,21 @@ public:
|
|||||||
u32 *getNormalFaces() const { return normalFaces; };
|
u32 *getNormalFaces() const { return normalFaces; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns bounding box (AABB).
|
* @returns bounding box (AABB).
|
||||||
* Total length: 8
|
* Total length: 8
|
||||||
*/
|
*/
|
||||||
Vector3 *getBoundingBox() { return boundingBox; };
|
Vector3 *getBoundingBoxVertices() { return boundingBoxObj->getVertices(); };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns bounding box (AABB) vertex.
|
* @returns bounding box (AABB) vertex.
|
||||||
* Total length: 8
|
* Total length: 8
|
||||||
*/
|
*/
|
||||||
Vector3 &getBoundingBoxVertex(const u8 &i) { return boundingBox[i]; };
|
const Vector3 &getBoundingBoxVertex(const u8 &i) { return boundingBoxObj->getVertex(i); };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns bounding box (AABB) object pointer.
|
||||||
|
*/
|
||||||
|
BoundingBox *getBoundingBox() { return boundingBoxObj; };
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
// Setters
|
// Setters
|
||||||
@@ -97,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. */
|
||||||
@@ -118,10 +160,16 @@ public:
|
|||||||
u8 isInFrustum(Plane *t_frustumPlanes, const Vector3 &position);
|
u8 isInFrustum(Plane *t_frustumPlanes, const Vector3 &position);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector3 boundingBox[8];
|
void setDefaultColor();
|
||||||
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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,7 +21,6 @@ struct ScreenSettings
|
|||||||
float aspectRatio;
|
float aspectRatio;
|
||||||
float nearPlaneDist;
|
float nearPlaneDist;
|
||||||
float farPlaneDist;
|
float farPlaneDist;
|
||||||
/** change it to 4096.0F to check out frustum culling! 😎 */
|
|
||||||
float projectionScale;
|
float projectionScale;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TYRA_SPRITE_
|
||||||
|
#define _TYRA_SPRITE_
|
||||||
|
|
||||||
|
#include <models/math/point.hpp>
|
||||||
|
#include <draw_types.h>
|
||||||
|
#include <draw_buffers.h>
|
||||||
|
|
||||||
|
enum SpriteMode
|
||||||
|
{
|
||||||
|
MODE_STRETCH,
|
||||||
|
MODE_REPEAT
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class which have contain 2D image data.
|
||||||
|
*/
|
||||||
|
class Sprite
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
Sprite();
|
||||||
|
~Sprite();
|
||||||
|
|
||||||
|
Point position, size;
|
||||||
|
float scale;
|
||||||
|
color_t color;
|
||||||
|
clutbuffer_t clut;
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Getters
|
||||||
|
// ----
|
||||||
|
|
||||||
|
/** Auto generated unique Id. */
|
||||||
|
inline const u32 &getId() const { return id; };
|
||||||
|
|
||||||
|
/** Get sprite drawing mode. */
|
||||||
|
inline const SpriteMode &getMode() const { return mode; };
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Setters
|
||||||
|
// ----
|
||||||
|
|
||||||
|
/** Set sprite drawing mode. */
|
||||||
|
void setMode(const SpriteMode &t_val) { mode = t_val; }
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Other
|
||||||
|
// ----
|
||||||
|
|
||||||
|
/** Flip texture horizontally. */
|
||||||
|
inline void flipHorizontally(const u8 &t_set) { _flipH = t_set; };
|
||||||
|
|
||||||
|
/** Flip texture vertically. */
|
||||||
|
inline void flipVertically(const u8 &t_set) { _flipV = t_set; };
|
||||||
|
|
||||||
|
/** Check if texture is vertically flipped. */
|
||||||
|
inline const u8 &isFlippedVertically() const { return _flipV; };
|
||||||
|
|
||||||
|
/** Check if texture is horizontally flipped. */
|
||||||
|
inline const u8 &isFlippedHorizontally() const { return _flipH; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
u32 id;
|
||||||
|
SpriteMode mode;
|
||||||
|
u8 _isSizeSet, _flipH, _flipV;
|
||||||
|
void setDefaultColor();
|
||||||
|
void setDefaultLODAndClut();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
+61
-34
@@ -8,8 +8,8 @@
|
|||||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TYRA_MESH_TEXTURE_
|
#ifndef _TYRA_TEXTURE_
|
||||||
#define _TYRA_MESH_TEXTURE_
|
#define _TYRA_TEXTURE_
|
||||||
|
|
||||||
#include <tamtypes.h>
|
#include <tamtypes.h>
|
||||||
#include <draw_sampling.h>
|
#include <draw_sampling.h>
|
||||||
@@ -17,18 +17,25 @@
|
|||||||
#include "./texture_link.hpp"
|
#include "./texture_link.hpp"
|
||||||
#include "../include/utils/debug.hpp"
|
#include "../include/utils/debug.hpp"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <gs_psm.h>
|
||||||
|
|
||||||
|
enum TextureType
|
||||||
|
{
|
||||||
|
TEX_TYPE_RGB = GS_PSM_24, // BMP
|
||||||
|
TEX_TYPE_RGBA = GS_PSM_32 // PNG
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class which contains texture data.
|
* Class which contains texture data.
|
||||||
* Textures are paired with meshes via addUsage(),
|
* Textures are paired with meshes/sprites via addLink() and
|
||||||
* removeUsage() functions which use meshId and materialId.
|
* removeLink() functions which use meshId/spriteId and materialId (for mesh).
|
||||||
*/
|
*/
|
||||||
class MeshTexture
|
class Texture
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MeshTexture();
|
Texture();
|
||||||
~MeshTexture();
|
~Texture();
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
// Getters
|
// Getters
|
||||||
@@ -40,45 +47,50 @@ public:
|
|||||||
* again texture in renderer, when last sent texture id
|
* again texture in renderer, when last sent texture id
|
||||||
* by renderer will be equal to this id.
|
* by renderer will be equal to this id.
|
||||||
*/
|
*/
|
||||||
const u32 &getId() const { return id; };
|
inline const u32 getId() const { return id; };
|
||||||
|
|
||||||
const u8 &getWidth() const { return width; };
|
inline const u16 getWidth() const { return width; };
|
||||||
|
|
||||||
const u8 &getHeight() const { return height; };
|
inline const u16 getHeight() const { return height; };
|
||||||
|
|
||||||
u32 getTextureLinksCount() const { return static_cast<u32>(texLinks.size()); };
|
inline const TextureType getType() const { return _type; };
|
||||||
|
|
||||||
texwrap_t *getWrapSettings() { return &wrapSettings; };
|
inline u32 getTextureLinksCount() const { return static_cast<u32>(texLinks.size()); };
|
||||||
|
|
||||||
|
inline texwrap_t *getWrapSettings() { return &wrapSettings; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns always width * width * 3.
|
* Returns always width * width * 3/4.
|
||||||
* 3 because of RGB
|
* 3 for RGB, 4 for RGBA.
|
||||||
*/
|
*/
|
||||||
u32 getDataSize() const { return width * height * 3; };
|
inline u32 getDataSize() const { return _type == TEX_TYPE_RGB ? width * height * 3 : width * height * 4; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Texture data, used by renderer.
|
* Texture data, used by renderer.
|
||||||
* Array of size getDataSize().
|
* Array of size getDataSize().
|
||||||
*/
|
*/
|
||||||
unsigned char *getData() const { return data; };
|
inline unsigned char *getData() const { return data; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get texture name.
|
* Get texture name.
|
||||||
* For "textures/abc.bmp" result will be: "abc"
|
* For "textures/abc.bmp" result will be: "abc"
|
||||||
*/
|
*/
|
||||||
char *getName() const { return name; };
|
inline char *getName() const { return name; };
|
||||||
|
|
||||||
/** Array of texture links. Size of getTextureLinksCount() */
|
/** Array of texture links. Size of getTextureLinksCount() */
|
||||||
const std::vector<TextureLink> &getTextureLinks() const { return texLinks; };
|
inline const std::vector<TextureLink> &getTextureLinks() const { return texLinks; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns index of link.
|
* 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].meshId == t_meshId)
|
if (texLinks[i].id == t_id)
|
||||||
return i;
|
return i;
|
||||||
return -1;
|
return -1;
|
||||||
};
|
};
|
||||||
@@ -92,7 +104,7 @@ public:
|
|||||||
* Do not call this method unless you know what you do.
|
* Do not call this method unless you know what you do.
|
||||||
* Should be called by data loader.
|
* Should be called by data loader.
|
||||||
*/
|
*/
|
||||||
void setSize(const u8 &t_width, const u8 &t_height);
|
void setSize(const u8 &t_width, const u8 &t_height, const TextureType &t_type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do not call this method unless you know what you do.
|
* Do not call this method unless you know what you do.
|
||||||
@@ -101,8 +113,8 @@ public:
|
|||||||
void setHeight(const u8 &t_val) { height = t_val; }
|
void setHeight(const u8 &t_val) { height = t_val; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set texture name.
|
* Do not call this method unless you know what you do.
|
||||||
* Should be the file name without extension
|
* Should be called by data loader.
|
||||||
*/
|
*/
|
||||||
void setData(const u32 &t_index, const unsigned char &t_val) { data[t_index] = t_val; }
|
void setData(const u32 &t_index, const unsigned char &t_val) { data[t_index] = t_val; }
|
||||||
|
|
||||||
@@ -119,40 +131,55 @@ public:
|
|||||||
// Other
|
// Other
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
/** Assign texture to mesh and mesh material */
|
/** Assign texture to mesh and mesh material. */
|
||||||
void addLink(const u32 &t_meshId, const u32 &t_materialId);
|
void addLink(const u32 &t_meshId, const u32 &t_materialId);
|
||||||
|
|
||||||
|
/** Assign texture to sprite. */
|
||||||
|
void addLink(const u32 &t_spriteId);
|
||||||
|
|
||||||
const u8 &isNameSet() const { return _isNameSet; };
|
const u8 &isNameSet() const { return _isNameSet; };
|
||||||
|
|
||||||
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)
|
if (index != -1)
|
||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
void removeLink(const u32 &t_index) { texLinks.erase(texLinks.begin() + t_index); }
|
void removeLinkByIndex(const u32 &t_index) { texLinks.erase(texLinks.begin() + t_index); }
|
||||||
|
|
||||||
void removeLink(const u32 &t_meshId, const u32 &t_materialId)
|
/**
|
||||||
|
* 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_meshId, t_materialId);
|
s32 index = getIndexOfLink(t_id);
|
||||||
if (index != -1)
|
assertMsg(index != -1, "Cant remove link, because it was not found!");
|
||||||
removeLink(index);
|
removeLinkByIndex(index);
|
||||||
else
|
|
||||||
PRINT_ERR("Cant remove link, because it was not found!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setDefaultWrapSettings();
|
void setDefaultWrapSettings();
|
||||||
texwrap_t wrapSettings;
|
texwrap_t wrapSettings;
|
||||||
char *name;
|
char *name;
|
||||||
|
TextureType _type;
|
||||||
std::vector<TextureLink> texLinks;
|
std::vector<TextureLink> texLinks;
|
||||||
u32 id;
|
u32 id;
|
||||||
u8 width, height, _isNameSet, _isSizeSet;
|
u16 width, height;
|
||||||
|
u8 _isNameSet, _isSizeSet;
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -15,7 +15,11 @@
|
|||||||
|
|
||||||
struct TextureLink
|
struct TextureLink
|
||||||
{
|
{
|
||||||
u32 meshId, materialId;
|
/**
|
||||||
|
* For 3D: Mesh material id.
|
||||||
|
* For 2D: Sprite id.
|
||||||
|
*/
|
||||||
|
u32 id;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -11,56 +11,147 @@
|
|||||||
#ifndef _TYRA_AUDIO_
|
#ifndef _TYRA_AUDIO_
|
||||||
#define _TYRA_AUDIO_
|
#define _TYRA_AUDIO_
|
||||||
|
|
||||||
|
#include "../models/audio_listener.hpp"
|
||||||
|
#include "./file_service.hpp"
|
||||||
#include <tamtypes.h>
|
#include <tamtypes.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <audsrv.h>
|
#include <audsrv.h>
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include "../models/audio_listener.hpp"
|
#include <vector>
|
||||||
|
|
||||||
#define STACK_SIZE 8 * 1024
|
struct AudioListenerRef
|
||||||
|
{
|
||||||
|
AudioListener *listener;
|
||||||
|
u32 id;
|
||||||
|
};
|
||||||
|
|
||||||
/** Class responsible for audio playing */
|
/**
|
||||||
|
* Class responsible for audio playing.
|
||||||
|
* There are two main features:
|
||||||
|
* - WAV song (background music)
|
||||||
|
* - ADPCM samples
|
||||||
|
*/
|
||||||
class Audio
|
class Audio
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/** Constructor is called by the engine. */
|
||||||
Audio();
|
Audio();
|
||||||
~Audio();
|
~Audio();
|
||||||
|
|
||||||
u8 isTrackDone;
|
// Song
|
||||||
ee_sema_t sema;
|
|
||||||
int fillbufferSema;
|
|
||||||
|
|
||||||
void init(u32 t_listenersAmount);
|
/**
|
||||||
void play();
|
* Load 24bit 22050Hz Stereo WAV.
|
||||||
void stop();
|
* Can be used multiple times for song switching.
|
||||||
void loadSong(char *t_filename);
|
* @param t_path Example: "song.wav" or "folder/song.wav"
|
||||||
void unloadSong();
|
*/
|
||||||
void setVolume(u8 t_volume);
|
void loadSong(char *t_path);
|
||||||
void addListener(AudioListener *t_listener);
|
|
||||||
void startThread();
|
void playSong();
|
||||||
|
|
||||||
|
void stopSong();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set song volume.
|
||||||
|
* @param t_vol Value 0-100
|
||||||
|
*/
|
||||||
|
void setSongVolume(const u8 &t_vol);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If you want to synchronize some actions with
|
||||||
|
* background song, add audio listener.
|
||||||
|
* @returns Listener id.
|
||||||
|
*/
|
||||||
|
u32 addSongListener(AudioListener *t_listener);
|
||||||
|
|
||||||
|
/** Remove song listener. */
|
||||||
|
void removeSongListener(const u32 &t_id);
|
||||||
|
|
||||||
|
const u8 &isSongPlaying() const { return songPlaying; }
|
||||||
|
|
||||||
|
const u8 &isSongLoaded() const { return songLoaded; }
|
||||||
|
|
||||||
|
const u8 &isSongInLoop() const { return songInLoop; }
|
||||||
|
|
||||||
|
u32 getSongListenersCount() const { return songListeners.size(); }
|
||||||
|
|
||||||
|
const u8 &getVolume() const { return volume; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set song loop/noloop.
|
||||||
|
* @param t_set false - noloop, true - loop
|
||||||
|
*/
|
||||||
|
void setSongLoop(const u8 &t_set) { songInLoop = t_set; }
|
||||||
|
|
||||||
|
// ADPCM
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load ADPCM sample. ADPCM sample is an output from
|
||||||
|
* "adpenc" tool, shipped with PS2SDK.
|
||||||
|
* @param t_path Example: "hit.adpcm" or "folder/jump.adpcm"
|
||||||
|
*/
|
||||||
|
audsrv_adpcm_t *loadADPCM(char *t_path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Play ADPCM sample.
|
||||||
|
* ADPCM sample can't be stopped.
|
||||||
|
* @param t_adpcm ADPCM data, created by loadADPCM();
|
||||||
|
*/
|
||||||
|
void playADPCM(audsrv_adpcm_t *t_adpcm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Play ADPCM sample.
|
||||||
|
* ADPCM sample can't be stopped.
|
||||||
|
* @param t_adpcm ADPCM data, created by loadADPCM();
|
||||||
|
* @param t_ch Channel (0-23). Type -1 for use any free channel.
|
||||||
|
*/
|
||||||
|
void playADPCM(audsrv_adpcm_t *t_adpcm, const s8 &t_ch);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set ADPCM volume.
|
||||||
|
* @param t_vol Value 0-100
|
||||||
|
* @param t_ch Channel (0-23)
|
||||||
|
*/
|
||||||
|
void setADPCMVolume(u8 t_vol, const s8 &t_ch) { audsrv_adpcm_set_volume(t_ch, t_vol); }
|
||||||
|
|
||||||
|
// Other
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start audio thread.
|
||||||
|
* Do not call this method unless you know what you do.
|
||||||
|
* Should be called by engine.
|
||||||
|
*/
|
||||||
|
void startThread(FileService *t_fileService);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void work();
|
u8 songLoaded, volume, realVolume, songPlaying, songInLoop, songFinished;
|
||||||
static void audioThread();
|
u8 hack; // TODO
|
||||||
u8 isInitialized, shouldPlay, songLoaded, isVolumeSet;
|
std::vector<AudioListenerRef *> songListeners;
|
||||||
|
FILE *wav;
|
||||||
|
audsrv_fmt_t format;
|
||||||
|
FileService *fileService;
|
||||||
|
|
||||||
ee_thread_t audioThreadAttr;
|
char wavChunk[2 * 1024] __attribute__((aligned(16)));
|
||||||
u8 audioThreadStack[STACK_SIZE] ALIGNED(16);
|
s32 chunkReadStatus;
|
||||||
int audioThreadId;
|
|
||||||
|
u8 threadStack[8 * 1024] __attribute__((aligned(16)));
|
||||||
|
u32 getThreadStackSize() { return 8 * 1024; }
|
||||||
|
u32 getSongBufferSize() { return 4 * 1024; }
|
||||||
|
ee_thread_t thread;
|
||||||
|
int threadId;
|
||||||
|
ee_sema_t sema;
|
||||||
|
s32 fillbufferSema;
|
||||||
|
|
||||||
|
void setSongFormat();
|
||||||
|
void unloadSong();
|
||||||
|
void rewindSongToStart();
|
||||||
|
|
||||||
AudioListener **listeners;
|
|
||||||
u32 listenersAmount;
|
|
||||||
u32 addedListeners;
|
|
||||||
void initSema();
|
void initSema();
|
||||||
void loadModules();
|
void loadModules();
|
||||||
void initAUDSRV();
|
void initAUDSRV();
|
||||||
|
void threadLoop();
|
||||||
int ret, played;
|
static void mainThread();
|
||||||
char chunk[2048];
|
|
||||||
FILE *wav;
|
|
||||||
audsrv_fmt_t format;
|
|
||||||
static int fillbuffer(void *arg);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -21,21 +21,45 @@ class CameraBase
|
|||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CameraBase(ScreenSettings *t_screen, Vector3 *t_position, Vector3 *t_up, Vector3 *t_unitCirclePosition);
|
CameraBase(ScreenSettings *t_screen, Vector3 *t_position);
|
||||||
virtual ~CameraBase(){};
|
virtual ~CameraBase(){};
|
||||||
|
|
||||||
void setScreen();
|
/**
|
||||||
void updatePlanes(Vector3 t_target);
|
* Frustum planes.
|
||||||
|
* Set by lookAt() method.
|
||||||
|
*/
|
||||||
Plane planes[6];
|
Plane planes[6];
|
||||||
Matrix worldView;
|
|
||||||
|
/**
|
||||||
|
* View matrix
|
||||||
|
* Set by lookAt() method.
|
||||||
|
*/
|
||||||
|
Matrix view;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
/** Pointer to screen settings */
|
||||||
ScreenSettings *screen;
|
ScreenSettings *screen;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adaption of OpenGL lookAt camera.
|
||||||
|
* Calculates view matrix and update frustum planes
|
||||||
|
* Should be called every frame.
|
||||||
|
*/
|
||||||
|
void lookAt(Vector3 &t_target);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not call this method unless you know what you do.
|
||||||
|
* Called via lookAt().
|
||||||
|
* Calculate and update frustum planes.
|
||||||
|
* http://www.lighthouse3d.com/tutorials/view-frustum-culling/geometric-approach-extracting-the-planes/
|
||||||
|
*/
|
||||||
|
void updatePlanes(Vector3 t_target);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector3 *position2, *up2, *unitCirclePosition2;
|
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
|
||||||
|
|||||||
@@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TYRA_FILE_SERVICE_
|
||||||
|
#define _TYRA_FILE_SERVICE_
|
||||||
|
|
||||||
|
#include <tamtypes.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <kernel.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
enum FileServiceTaskType
|
||||||
|
{
|
||||||
|
ReadChunk = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FileServiceTask
|
||||||
|
{
|
||||||
|
FileServiceTaskType type;
|
||||||
|
|
||||||
|
u32 id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by types:
|
||||||
|
* - ReadChunk
|
||||||
|
*/
|
||||||
|
FILE *file;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by types:
|
||||||
|
* - ReadChunk
|
||||||
|
*/
|
||||||
|
s32 readStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by types:
|
||||||
|
* - ReadChunk
|
||||||
|
*/
|
||||||
|
void *destination;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by types:
|
||||||
|
* - ReadChunk
|
||||||
|
*/
|
||||||
|
u32 size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by types:
|
||||||
|
* - ReadChunk
|
||||||
|
*/
|
||||||
|
u32 n;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Class responsible for background, non-blocking file loading playing. */
|
||||||
|
class FileService
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Constructor is called by the engine. */
|
||||||
|
FileService();
|
||||||
|
~FileService();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add task to read next chunk. ( fread() )
|
||||||
|
* @returns Task id
|
||||||
|
*/
|
||||||
|
u32 addReadChunk(FILE *t_file, void *t_destination, const u32 &t_size, const u32 &t_n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if given task was done.
|
||||||
|
* When task is done, this method will return read status.
|
||||||
|
* After this, task is removed from file service, so this method
|
||||||
|
* will return something once per task.
|
||||||
|
* @returns Read status (ex. result of fread()). -2137 if task is not done.
|
||||||
|
*/
|
||||||
|
s32 isTaskDone(const u32 &t_taskId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start file service thread.
|
||||||
|
* Do not call this method unless you know what you do.
|
||||||
|
* Should be called by engine.
|
||||||
|
*/
|
||||||
|
void startThread();
|
||||||
|
|
||||||
|
std::vector<FileServiceTask> tasks;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/** Remove task by index */
|
||||||
|
void removeByIndex(const u32 &t_index) { tasks.erase(tasks.begin() + t_index); }
|
||||||
|
|
||||||
|
/** Remove task by id */
|
||||||
|
const void removeById(const u32 &t_taskId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get index of task.
|
||||||
|
* @returns Index of task. -1 if not found.
|
||||||
|
*/
|
||||||
|
const s32 getIndexOf(const u32 &t_taskId);
|
||||||
|
|
||||||
|
u8 threadStack[8 * 1024] __attribute__((aligned(16)));
|
||||||
|
u32 getThreadStackSize() { return 8 * 1024; }
|
||||||
|
ee_thread_t thread;
|
||||||
|
int threadId;
|
||||||
|
void threadLoop();
|
||||||
|
static void mainThread();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -16,45 +16,45 @@
|
|||||||
#include <draw_types.h>
|
#include <draw_types.h>
|
||||||
#include <draw_primitives.h>
|
#include <draw_primitives.h>
|
||||||
#include <math3d.h>
|
#include <math3d.h>
|
||||||
#include <packet.h>
|
#include <packet2.h>
|
||||||
|
#include "./light.hpp"
|
||||||
#include "../models/mesh.hpp"
|
#include "../models/mesh.hpp"
|
||||||
#include "../models/math/matrix.hpp"
|
#include "../models/math/matrix.hpp"
|
||||||
#include "../models/screen_settings.hpp"
|
#include "../models/screen_settings.hpp"
|
||||||
#include "../models/light_bulb.hpp"
|
#include "../models/light_bulb.hpp"
|
||||||
#include "../models/render_data.hpp"
|
#include "../models/render_data.hpp"
|
||||||
#include "../models/mesh_texture.hpp"
|
#include "../models/texture.hpp"
|
||||||
|
|
||||||
/** Class responsible for sending data packets via GIF (PATH3) */
|
/** Class responsible for sending data packets via GIF (PATH3) */
|
||||||
class GifSender
|
class GifSender
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GifSender(u32 t_packetSize, ScreenSettings *t_screen);
|
GifSender(u32 t_packetSize, ScreenSettings *t_screen, Light *t_light);
|
||||||
~GifSender();
|
~GifSender();
|
||||||
|
|
||||||
void initPacket(u8 context);
|
void initPacket(u8 context);
|
||||||
void addObject(RenderData *t_renderData, Mesh *t_objects3D, 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);
|
void addClear(zbuffer_t *t_zBuffer, color_t *t_rgb);
|
||||||
void sendPacket();
|
void sendPacket();
|
||||||
void sendClear(zbuffer_t *t_zBuffer);
|
void sendClear(zbuffer_t *t_zBuffer, color_t *t_rgb);
|
||||||
static void sendTexture(MeshTexture &texture, texbuffer_t *t_texBuffer);
|
static void sendTexture(Texture &texture, texbuffer_t *t_texBuffer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Light *light;
|
||||||
xyz_t *xyz;
|
xyz_t *xyz;
|
||||||
color_t *rgbaq;
|
color_t *rgbaq;
|
||||||
texel_t *st;
|
texel_t *st;
|
||||||
u8 isAnyObjectAdded;
|
u8 isAnyObjectAdded;
|
||||||
ScreenSettings *screen;
|
ScreenSettings *screen;
|
||||||
u64 *dw;
|
packet2_t *packets[2];
|
||||||
qword_t *q, *dmatag;
|
packet2_t *currentPacket;
|
||||||
packet_t *packets[2];
|
|
||||||
packet_t *currentPacket;
|
|
||||||
u8 packetsCount;
|
u8 packetsCount;
|
||||||
int packetSize;
|
int packetSize;
|
||||||
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);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -23,10 +23,14 @@ public:
|
|||||||
Light();
|
Light();
|
||||||
~Light();
|
~Light();
|
||||||
|
|
||||||
static u16 getLightsCount(u32 t_bulbsCount);
|
u16 getLightsCount(u32 t_bulbsCount);
|
||||||
static void calculateLight(VECTOR *t_lightDirections, VECTOR *t_lightColors, int *t_lightTypes, LightBulb *t_bulbs, u32 t_bulbsCount, Vector3 t_objPosition);
|
|
||||||
|
/** Values from 0.0000F to 1.0000F */
|
||||||
|
void setAmbientLight(const Vector3 &t_rgb);
|
||||||
|
void calculateLight(VECTOR *t_lightDirections, VECTOR *t_lightColors, int *t_lightTypes, LightBulb *t_bulbs, u32 t_lightsCount, Vector3 t_objPosition);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Vector3 ambientLight;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -13,10 +13,14 @@
|
|||||||
|
|
||||||
#include <draw_buffers.h>
|
#include <draw_buffers.h>
|
||||||
#include <draw_primitives.h>
|
#include <draw_primitives.h>
|
||||||
#include <packet.h>
|
#include <gs_privileged.h>
|
||||||
|
#include <draw.h>
|
||||||
|
#include <packet2.h>
|
||||||
#include "gif_sender.hpp"
|
#include "gif_sender.hpp"
|
||||||
#include "vif_sender.hpp"
|
#include "vif_sender.hpp"
|
||||||
|
#include "light.hpp"
|
||||||
#include "../models/math/plane.hpp"
|
#include "../models/math/plane.hpp"
|
||||||
|
#include "../models/sprite.hpp"
|
||||||
#include "../models/screen_settings.hpp"
|
#include "../models/screen_settings.hpp"
|
||||||
#include "../models/render_data.hpp"
|
#include "../models/render_data.hpp"
|
||||||
#include "./texture_repository.hpp"
|
#include "./texture_repository.hpp"
|
||||||
@@ -30,52 +34,137 @@ public:
|
|||||||
~Renderer();
|
~Renderer();
|
||||||
|
|
||||||
framebuffer_t frameBuffers[2];
|
framebuffer_t frameBuffers[2];
|
||||||
u8 context;
|
u8 context; // TODO
|
||||||
zbuffer_t zBuffer;
|
zbuffer_t zBuffer;
|
||||||
prim_t prim;
|
prim_t prim;
|
||||||
|
|
||||||
/** PATH3 Many + lighting */
|
void enableVSync() { isVSyncEnabled = true; }
|
||||||
void drawByPath3(Mesh **t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount);
|
void disableVSync() { isVSyncEnabled = false; }
|
||||||
/** PATH3 Single + lighting */
|
|
||||||
void drawByPath3(Mesh *t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount);
|
|
||||||
/** PATH3 Many */
|
|
||||||
void drawByPath3(Mesh **t_meshes, u16 t_amount);
|
|
||||||
/** PATH3 Single */
|
|
||||||
void drawByPath3(Mesh *t_mesh);
|
|
||||||
|
|
||||||
/** PATH1 Many + lighting */
|
/** 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);
|
||||||
|
|
||||||
|
/// --- OBSOLETE
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * WARNING: THIS FUNC CAUSE VISUAL ARTIFACTS!
|
||||||
|
// * Draw many meshes with lighting information.
|
||||||
|
// * Slowest way of rendering (PATH 3, using EE and GIF).
|
||||||
|
// * NOTICE: Animation supported, lighting supported
|
||||||
|
// */
|
||||||
|
// void drawByPath3(Mesh *t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount);
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * WARNING: THIS FUNC CAUSE VISUAL ARTIFACTS!
|
||||||
|
// * Draw mesh with lighting information.
|
||||||
|
// * Slowest way of rendering (PATH 3, using EE and GIF).
|
||||||
|
// * NOTICE: Animation supported, lighting supported
|
||||||
|
// */
|
||||||
|
// void drawByPath3(Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount);
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * WARNING: THIS FUNC CAUSE VISUAL ARTIFACTS!
|
||||||
|
// * Draw many meshes without lighting information.
|
||||||
|
// * Slowest way of rendering (PATH 3, using EE and GIF).
|
||||||
|
// * NOTICE: Animation supported, lighting supported
|
||||||
|
// */
|
||||||
|
// void drawByPath3(Mesh *t_meshes, u16 t_amount);
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * WARNING: THIS FUNC CAUSE VISUAL ARTIFACTS!
|
||||||
|
// * Draw mesh without lighting information.
|
||||||
|
// * Slowest way of rendering (PATH 3, using EE and GIF).
|
||||||
|
// * NOTICE: Animation supported, lighting supported
|
||||||
|
// */
|
||||||
|
// void drawByPath3(Mesh &t_mesh);
|
||||||
|
|
||||||
|
/// --- Draw: PATH1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw many meshes with lighting information.
|
||||||
|
* Draw in array mode, can be A LOT faster than for looping!
|
||||||
|
* Fastest way of rendering (PATH 1, using VU1).
|
||||||
|
* NOTICE: Animation supported, lighting NOT supported (at this moment)
|
||||||
|
*/
|
||||||
void draw(Mesh **t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount);
|
void draw(Mesh **t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount);
|
||||||
/** PATH1 Single + lighting */
|
|
||||||
void draw(Mesh *t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount);
|
/**
|
||||||
/** PATH1 Many */
|
* Draw mesh with lighting information.
|
||||||
|
* Fastest way of rendering (PATH 1, using VU1).
|
||||||
|
* NOTICE: Animation supported, lighting NOT supported (at this moment)
|
||||||
|
*/
|
||||||
|
void draw(Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw many meshes without lighting information.
|
||||||
|
* Draw in array mode, can be A LOT faster than for looping!
|
||||||
|
* Fastest way of rendering (PATH 1, using VU1).
|
||||||
|
* NOTICE: Animation supported, lighting NOT supported (at this moment)
|
||||||
|
*/
|
||||||
void draw(Mesh **t_meshes, u16 t_amount);
|
void draw(Mesh **t_meshes, u16 t_amount);
|
||||||
/** PATH1 Single */
|
|
||||||
void draw(Mesh *t_mesh);
|
/**
|
||||||
|
* Draw mesh without lighting information.
|
||||||
|
* Fastest way of rendering (PATH 1, using VU1).
|
||||||
|
* NOTICE: Animation supported, lighting NOT supported (at this moment)
|
||||||
|
*/
|
||||||
|
void draw(Mesh &t_mesh);
|
||||||
|
|
||||||
void setCameraDefinitions(Matrix *t_worldView, Vector3 *t_cameraPos, Plane *t_planes);
|
void setCameraDefinitions(Matrix *t_worldView, Vector3 *t_cameraPos, Plane *t_planes);
|
||||||
|
|
||||||
|
void setWorldColor(const color_t &t_rgb);
|
||||||
|
|
||||||
void endFrame(float fps);
|
void endFrame(float fps);
|
||||||
|
|
||||||
TextureRepository *getTextureRepository() { return &textureRepo; };
|
void setAmbientLight(const Vector3 &t_rgb) { light.setAmbientLight(t_rgb); }
|
||||||
|
|
||||||
|
TextureRepository *getTextureRepository()
|
||||||
|
{
|
||||||
|
return &textureRepo;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void changeTexture(Mesh *t_mesh, u32 t_materialId);
|
// We have some GCC bug here. Just try to reorder declarations. For example move worldColor up - game will crash.
|
||||||
|
void changeTexture(Texture *t_tex);
|
||||||
u32 lastTextureId;
|
u32 lastTextureId;
|
||||||
texbuffer_t textureBuffer;
|
texbuffer_t textureBuffer;
|
||||||
u8 isTextureVRAMAllocated;
|
u8 isTextureVRAMAllocated, isVSyncEnabled;
|
||||||
void allocateTextureBuffer(u16 t_width, u16 t_height);
|
void allocateTextureBuffer(Texture *t_texture);
|
||||||
void deallocateTextureBuffer();
|
void deallocateTextureBuffer();
|
||||||
void flipBuffers();
|
void flipBuffers();
|
||||||
void beginFrameIfNeeded();
|
void beginFrameIfNeeded();
|
||||||
u8 isFrameEmpty;
|
u8 isFrameEmpty;
|
||||||
Matrix perspective;
|
Matrix perspective, camRotation;
|
||||||
|
Light light;
|
||||||
RenderData renderData;
|
RenderData renderData;
|
||||||
TextureRepository textureRepo;
|
TextureRepository textureRepo;
|
||||||
|
ScreenSettings *screen;
|
||||||
GifSender *gifSender;
|
GifSender *gifSender;
|
||||||
VifSender *vifSender;
|
VifSender *vifSender;
|
||||||
packet_t *flipPacket;
|
packet2_t *flipPacket;
|
||||||
void allocateBuffers(float t_screenW, float t_screenH);
|
color_t worldColor;
|
||||||
void initDrawingEnv(float t_screenW, float t_screenH);
|
void allocateBuffers(int t_screenW, int t_screenH);
|
||||||
|
void initDrawingEnv();
|
||||||
void setPrim();
|
void setPrim();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,13 @@
|
|||||||
#include "../models/mesh.hpp"
|
#include "../models/mesh.hpp"
|
||||||
#include "../models/mesh_frame.hpp"
|
#include "../models/mesh_frame.hpp"
|
||||||
#include "../loaders/bmp_loader.hpp"
|
#include "../loaders/bmp_loader.hpp"
|
||||||
|
#include "../loaders/png_loader.hpp"
|
||||||
|
|
||||||
|
enum TextureFormat
|
||||||
|
{
|
||||||
|
BMP,
|
||||||
|
PNG
|
||||||
|
};
|
||||||
|
|
||||||
/** Class responsible for intializing draw env, textures and buffers */
|
/** Class responsible for intializing draw env, textures and buffers */
|
||||||
class TextureRepository
|
class TextureRepository
|
||||||
@@ -31,18 +38,21 @@ public:
|
|||||||
// ----
|
// ----
|
||||||
|
|
||||||
/** Returns all repository textures. */
|
/** Returns all repository textures. */
|
||||||
std::vector<MeshTexture *> *getAll() { return &textures; }
|
std::vector<Texture *> *getAll() { return &textures; }
|
||||||
|
|
||||||
u32 getTexturesCount() const { return static_cast<u32>(textures.size()); };
|
u32 getTexturesCount() const { return static_cast<u32>(textures.size()); };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
*/
|
*/
|
||||||
MeshTexture *getByMesh(const u32 &t_meshId, const u32 &t_materialId)
|
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_meshId, t_materialId))
|
if (textures[i]->isLinkedWith(t_id))
|
||||||
return textures[i];
|
return textures[i];
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -51,7 +61,7 @@ public:
|
|||||||
* Returns single texture.
|
* Returns single texture.
|
||||||
* NULL if not found.
|
* NULL if not found.
|
||||||
*/
|
*/
|
||||||
MeshTexture *getByTextureId(const u32 &t_id) const
|
Texture *getByTextureId(const u32 &t_id) const
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < textures.size(); i++)
|
for (u32 i = 0; i < textures.size(); i++)
|
||||||
if (t_id == textures[i]->getId())
|
if (t_id == textures[i]->getId())
|
||||||
@@ -79,20 +89,22 @@ public:
|
|||||||
// Other
|
// Other
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
/** Add unlinked texture.
|
/**
|
||||||
* NOTICE: BMP (RGB 888 24bit, without color information) is suppored only!
|
* Add unlinked texture.
|
||||||
* @param t_subfolder Relative path. Ex.: "textures/"
|
* @param t_subfolder Relative path. Ex.: "textures/"
|
||||||
* @param t_name Filename without extension. Ex.: "water"
|
* @param t_name Filename without extension. Ex.: "water"
|
||||||
*
|
* @param t_format if you want to use BMP, be sure that you have
|
||||||
|
* BMP with RGB 888 24bit, without color information.
|
||||||
*/
|
*/
|
||||||
MeshTexture *add(char *t_subfolder, char *t_name);
|
Texture *add(char *t_subfolder, char *t_name, TextureFormat t_format);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add linked textures in given subpath for mesh material names.
|
* Add linked textures in given subpath for mesh material names.
|
||||||
* NOTICE: BMP (RGB 888 24bit, without color information) is suppored only!
|
* @param t_path Relative path where textures should be searched.
|
||||||
* @param t_path Relative path where textures should be searched
|
* @param t_format if you want to use BMP, be sure that you have
|
||||||
|
* BMP with RGB 888 24bit, without color information.
|
||||||
*/
|
*/
|
||||||
void addByMesh(char *t_path, Mesh &mesh);
|
void addByMesh(char *t_path, Mesh &mesh, TextureFormat t_format);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove texture from repository.
|
* Remove texture from repository.
|
||||||
@@ -107,15 +119,14 @@ public:
|
|||||||
const void removeById(const u32 &t_texId)
|
const void removeById(const u32 &t_texId)
|
||||||
{
|
{
|
||||||
s32 index = getIndexOf(t_texId);
|
s32 index = getIndexOf(t_texId);
|
||||||
if (index != -1)
|
assertMsg(index != -1, "Cant remove texture, because it was not found!");
|
||||||
removeByIndex(index);
|
removeByIndex(index);
|
||||||
else
|
|
||||||
PRINT_ERR("Cant remove texture, because it was not found!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<MeshTexture *> textures;
|
std::vector<Texture *> textures;
|
||||||
BmpLoader loader;
|
BmpLoader bmpLoader;
|
||||||
|
PngLoader pngLoader;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#define _TYRA_TIMER_
|
#define _TYRA_TIMER_
|
||||||
|
|
||||||
#include <tamtypes.h>
|
#include <tamtypes.h>
|
||||||
|
#include <timer.h>
|
||||||
|
|
||||||
/** Class responsible for fps counting */
|
/** Class responsible for fps counting */
|
||||||
class Timer
|
class Timer
|
||||||
@@ -22,7 +23,7 @@ public:
|
|||||||
~Timer();
|
~Timer();
|
||||||
|
|
||||||
u32 getTimeDelta();
|
u32 getTimeDelta();
|
||||||
void primeTimer();
|
inline void prime() { lastTime = *T3_COUNT; }
|
||||||
float getFPS();
|
float getFPS();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -12,29 +12,50 @@
|
|||||||
#define _TYRA_VIF_SENDER_
|
#define _TYRA_VIF_SENDER_
|
||||||
|
|
||||||
#include <tamtypes.h>
|
#include <tamtypes.h>
|
||||||
|
#include <packet2_utils.h>
|
||||||
#include "../models/render_data.hpp"
|
#include "../models/render_data.hpp"
|
||||||
|
#include "./light.hpp"
|
||||||
#include "../models/light_bulb.hpp"
|
#include "../models/light_bulb.hpp"
|
||||||
#include "../models/mesh.hpp"
|
#include "../models/mesh.hpp"
|
||||||
#include "../models/math/matrix.hpp"
|
#include "../models/math/matrix.hpp"
|
||||||
#include "../models/math/vector3.hpp"
|
#include "../models/math/vector3.hpp"
|
||||||
#include "vu1.hpp"
|
|
||||||
|
|
||||||
/** Class responsible for sending 3D objects via VIF (PATH 1) */
|
/** Class responsible for sending 3D objects via VIF (PATH 1) */
|
||||||
class VifSender
|
class VifSender
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VifSender();
|
VifSender(Light *t_light);
|
||||||
~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:
|
||||||
void drawVertices(Mesh *t_mesh, u32 t_start, u32 t_end, VECTOR *t_vertices, VECTOR *t_coordinates, prim_t *t_prim, texbuffer_t *textureBuffer);
|
u32 lastVertCount; // needed for drawTheSameWithOtherMatrices()
|
||||||
VU1 vu1; // TODO
|
u8 isLastRGBAOnly; // needed for drawTheSameWithOtherMatrices()
|
||||||
MATRIX localWorld, localScreen;
|
u8 isDrawWaitEnabled;
|
||||||
|
Light *light;
|
||||||
|
void uploadMicroProgram();
|
||||||
|
void setDoubleBufferAddStaticData();
|
||||||
|
void drawVertices(Mesh &t_mesh, u32 t_start, u32 t_end, VECTOR *t_vertices, VECTOR *t_coordinates, prim_t *t_prim, texbuffer_t *t_textureBuffer, u8 t_addDrawWait, color_t *t_color, u8 t_rgbaOnly);
|
||||||
|
packet2_t *packets[2] __attribute__((aligned(64)));
|
||||||
|
packet2_t *currPacket;
|
||||||
|
/**
|
||||||
|
* OpenGL name: Model
|
||||||
|
* Sony name: local world
|
||||||
|
*/
|
||||||
|
Matrix model;
|
||||||
|
/**
|
||||||
|
* OpenGL name: ModelViewProjection
|
||||||
|
* Sony name: local screen
|
||||||
|
*/
|
||||||
|
Matrix modelViewProj;
|
||||||
|
u8 context;
|
||||||
VECTOR position, rotation;
|
VECTOR position, rotation;
|
||||||
u32 vertCount;
|
u32 vertCount;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,98 +0,0 @@
|
|||||||
/*
|
|
||||||
# ______ ____ ___
|
|
||||||
# | \/ ____| |___|
|
|
||||||
# | | | \ | |
|
|
||||||
#-----------------------------------------------------------------------
|
|
||||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
|
||||||
# Licenced under Apache License 2.0
|
|
||||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _TYRA_VU1_
|
|
||||||
#define _TYRA_VU1_
|
|
||||||
|
|
||||||
#include "../models/math/matrix.hpp"
|
|
||||||
#include <draw_buffers.h>
|
|
||||||
#include <tamtypes.h>
|
|
||||||
#include <draw_primitives.h>
|
|
||||||
#include <packet.h>
|
|
||||||
#include <math3d.h>
|
|
||||||
|
|
||||||
const u32 VIF_BUFFER_SIZE = 48 * 1024;
|
|
||||||
|
|
||||||
typedef struct VU1BuildList
|
|
||||||
{
|
|
||||||
u8 isBuilding;
|
|
||||||
void *offset;
|
|
||||||
void *kickBuffer;
|
|
||||||
u32 dmaSize;
|
|
||||||
u32 dmaSizeAll;
|
|
||||||
u32 dmaDestination;
|
|
||||||
} VU1BuildList;
|
|
||||||
|
|
||||||
/** Class responsible for managing VU1 micro programs */
|
|
||||||
class VU1
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
VU1();
|
|
||||||
~VU1();
|
|
||||||
|
|
||||||
static void uploadProgram(int t_dest, u32 *t_start, u32 *t_end);
|
|
||||||
void createList();
|
|
||||||
void sendSingleRefList(int t_destAddress, void *t_data, int t_quadSize);
|
|
||||||
void addListBeginning();
|
|
||||||
void continueList();
|
|
||||||
void addReferenceList(u32 t_offset, void *t_data, u32 t_size, u8 t_useTops);
|
|
||||||
void addFloat(float v);
|
|
||||||
void add32(u32 v);
|
|
||||||
void add64(u64 v);
|
|
||||||
void add128(u64 v1, u64 v2);
|
|
||||||
void addListEnding();
|
|
||||||
void addStartProgram();
|
|
||||||
void addContinueProgram();
|
|
||||||
void sendList();
|
|
||||||
void addDoubleBufferSetting();
|
|
||||||
void addFlush();
|
|
||||||
|
|
||||||
private:
|
|
||||||
u8 isDoubleBufferSet;
|
|
||||||
void checkDataAlignment(void *data);
|
|
||||||
VU1BuildList buildList;
|
|
||||||
char dmaBuffer1[VIF_BUFFER_SIZE] __attribute__((aligned(16)));
|
|
||||||
char dmaBuffer2[VIF_BUFFER_SIZE] __attribute__((aligned(16)));
|
|
||||||
void *currentBuffer;
|
|
||||||
u32 switchBuffer;
|
|
||||||
static u32 countProgramSize(u32 *t_start, u32 *t_end);
|
|
||||||
void checkList();
|
|
||||||
inline s32 AddUnpack(int format, int addr, int num, int usetops = 0, int nosign = 1, int masking = 0)
|
|
||||||
{
|
|
||||||
return (s32)((0x60 << 24) + (format << 24) + (masking << 28) + (usetops << 15) +
|
|
||||||
(nosign << 14) + (num << 16) + addr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#define DMA_REF_TAG(ADDR, COUNT) ((((unsigned long)ADDR) << 32) | (0x3 << 28) | COUNT)
|
|
||||||
#define DMA_CNT_TAG(COUNT) (((unsigned long)(0x1) << 28) | COUNT)
|
|
||||||
#define DMA_END_TAG(COUNT) (((unsigned long)(0x7) << 28) | COUNT)
|
|
||||||
#define VIF_NOP 0x00
|
|
||||||
#define VIF_STCYL 0x01
|
|
||||||
#define VIF_OFFSET 0x02
|
|
||||||
#define VIF_BASE 0x03
|
|
||||||
#define VIF_FLUSH 0x11
|
|
||||||
#define VIF_MSCAL 0x14
|
|
||||||
#define VIF_MSCNT 0x17
|
|
||||||
#define VIF_MPG 0x4A
|
|
||||||
#define V4_32 0xC
|
|
||||||
#define VIF_UNPACK 0x60
|
|
||||||
#define U128(n) ((u128)(n))
|
|
||||||
#define VIF_UNPACK_V4_32 (VIF_UNPACK | V4_32)
|
|
||||||
#define VIF_CODE(CMD, NUM, IMMEDIATE) ((((unsigned int)(CMD)) << 24) | \
|
|
||||||
(((unsigned int)(NUM)) << 16) | \
|
|
||||||
((unsigned int)(IMMEDIATE)))
|
|
||||||
#define GS_PRIM(PRIM, IIP, TME, FGE, ABE, AA1, FST, CTXT, FIX) U128((FIX << 10) | (CTXT << 9) | (FST << 8) | (AA1 << 7) | (ABE << 6) | (FGE << 5) | (TME << 4) | (IIP << 3) | (PRIM))
|
|
||||||
#define GS_GIFTAG(NLOOP, EOP, PRE, PRIM, FLG, NREG) (((u64)(NREG) << 60) | ((u64)(FLG) << 58) | ((u64)(PRIM) << 47) | ((u64)(PRE) << 46) | (EOP << 15) | (NLOOP << 0))
|
|
||||||
#define VU1_DMA_CHAN_TIMEOUT -1
|
|
||||||
#define GS_GIFTAG_PACKED 0
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -11,14 +11,16 @@
|
|||||||
#ifndef _TYRA_DEBUG_
|
#ifndef _TYRA_DEBUG_
|
||||||
#define _TYRA_DEBUG_
|
#define _TYRA_DEBUG_
|
||||||
|
|
||||||
#include <tamtypes.h>
|
#ifdef NDEBUG
|
||||||
#include <math3d.h>
|
#define consoleLog(message) ((void)0)
|
||||||
#include <stdio.h>
|
#define assertMsg(condition, message) ((void)0)
|
||||||
|
|
||||||
|
#else // IF Debug
|
||||||
|
#include <stdio.h>
|
||||||
class Debug
|
class Debug
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void errTrap(char *t_text, char *t_file)
|
static void trap(const char *t_text, const char *t_file)
|
||||||
{
|
{
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("====================================\n");
|
printf("====================================\n");
|
||||||
@@ -29,8 +31,10 @@ public:
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
#define consoleLog(message) printf("LOG: " message " (" __FILE__ ")\n")
|
||||||
|
#define assertMsg(condition, message) \
|
||||||
|
if (!(condition)) \
|
||||||
|
Debug::trap(message, __FILE__)
|
||||||
|
#endif // NDEBUG
|
||||||
|
|
||||||
#define PRINT_LOG(TEXT) printf("LOG: " TEXT " (" __FILE__ ")\n")
|
#endif // _TYRA_DEBUG_
|
||||||
#define PRINT_ERR(TEXT) Debug::errTrap(TEXT, __FILE__)
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -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,13 +25,22 @@ class Math
|
|||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const static float HALF_ANG2RAD = 3.14159265358979323846 / 360.0;
|
constexpr static float HALF_ANG2RAD = 3.14159265358979323846F / 360.0F;
|
||||||
const static float PI = 3.1415926535897932384626433832795F;
|
constexpr static float ANG2RAD = 3.14159265358979323846F / 180.0F;
|
||||||
const static float HALF_PI = 1.5707963267948966192313216916398F;
|
constexpr static float PI = 3.1415926535897932384626433832795F;
|
||||||
|
constexpr static float HALF_PI = 1.5707963267948966192313216916398F;
|
||||||
static float cos(float x);
|
static float cos(float x);
|
||||||
|
static float asin(float x);
|
||||||
|
static float mod(float x, float y);
|
||||||
static inline float sin(float x) { return cos(x - HALF_PI); };
|
static inline float sin(float x) { return cos(x - HALF_PI); };
|
||||||
static float sqrt(float x);
|
static inline float tan(float x) { return sin(x) / cos(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 s32 max(s32 a, s32 b) { return (a > b) ? a : b; }
|
||||||
|
static inline float max(float a, float b) { return (a > b) ? a : b; }
|
||||||
|
static inline u32 min(u32 a, u32 b) { return (a < b) ? a : b; }
|
||||||
|
static inline s32 min(s32 a, s32 b) { return (a < b) ? a : b; }
|
||||||
|
static inline float min(float a, float b) { return (a < b) ? a : b; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Math();
|
Math();
|
||||||
|
|||||||
@@ -17,12 +17,12 @@ class String
|
|||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static char *createU32ToString(u32 a);
|
static char *createU32ToString(const u32 a);
|
||||||
static char *createWithLeadingZeros(char *a);
|
static char *createWithLeadingZeros(const char *a);
|
||||||
static char *createCopy(char *source);
|
static char *createCopy(const char *source);
|
||||||
static u32 getLength(char *a);
|
static u32 getLength(const char *a);
|
||||||
static char *createConcatenated(char *a, char *b);
|
static char *createConcatenated(const char *a, const char *b);
|
||||||
static char *createWithoutExtension(char *source);
|
static char *createWithoutExtension(const char *source);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -30,52 +30,49 @@ BmpLoader::~BmpLoader() {}
|
|||||||
* @param t_name Without extension. Example "skyfall2"
|
* @param t_name Without extension. Example "skyfall2"
|
||||||
* @param t_extension With dot and extension. Example ".BMP"
|
* @param t_extension With dot and extension. Example ".BMP"
|
||||||
*/
|
*/
|
||||||
void BmpLoader::load(MeshTexture &o_texture, char *t_subfolder, char *t_name, char *t_extension)
|
void BmpLoader::load(Texture &o_texture, char *t_subfolder, char *t_name, char *t_extension)
|
||||||
{
|
{
|
||||||
char *t_path_part = String::createConcatenated(t_subfolder, t_name);
|
char *path_part1 = String::createConcatenated(t_subfolder, t_name);
|
||||||
char *t_path = String::createConcatenated(t_path_part, t_extension);
|
char *path_part2 = String::createConcatenated("host:", path_part1);
|
||||||
delete[] t_path_part;
|
char *path = String::createConcatenated(path_part2, t_extension);
|
||||||
FILE *file = fopen(t_path, "rb");
|
delete[] path_part1;
|
||||||
|
delete[] path_part2;
|
||||||
if (file == NULL)
|
FILE *file = fopen(path, "rb");
|
||||||
{
|
assertMsg(file != NULL, "Failed to load .bmp file!");
|
||||||
PRINT_ERR("Failed to load .bmp file!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char header[54];
|
unsigned char header[54];
|
||||||
fread(header, sizeof(unsigned char), 54, file);
|
fread(header, sizeof(unsigned char), 54, file);
|
||||||
|
|
||||||
u32 width = *(u32 *)&header[18];
|
u32 width = (u32)header[18];
|
||||||
u32 height = *(u32 *)&header[22];
|
u32 height = (u32)header[22];
|
||||||
o_texture.setSize(width, height);
|
u32 bits = (u32)header[28];
|
||||||
printf("BMPLoader - width: %d | height: %d\n", width, height);
|
u32 dataOffset = (u32)header[10];
|
||||||
if (width > 128 || height > 128)
|
|
||||||
PRINT_ERR("Given texture is big for PS2. Please strict to 128x128 max");
|
assertMsg(bits == 24, "Invalid bits per pixel in .bmp file - expected 24!");
|
||||||
|
|
||||||
|
o_texture.setSize(width, height, TEX_TYPE_RGB);
|
||||||
|
printf("BMPLoader - width: %d | height: %d | bits: %d\n", width, height, bits);
|
||||||
|
|
||||||
u64 rowPadded = (width * 3 + 3) & (~3);
|
u64 rowPadded = (width * 3 + 3) & (~3);
|
||||||
|
|
||||||
unsigned char *data = new unsigned char[rowPadded];
|
unsigned char row[rowPadded];
|
||||||
unsigned char tmp;
|
|
||||||
|
//Offset file stream to raster data
|
||||||
|
fseek(file, dataOffset, SEEK_SET);
|
||||||
|
|
||||||
u32 x = 0;
|
u32 x = 0;
|
||||||
for (u32 i = 0; i < height; i++)
|
for (u32 i = 0; i < height; i++)
|
||||||
{
|
{
|
||||||
fread(data, sizeof(unsigned char), rowPadded, file);
|
fread(&row, sizeof(unsigned char), rowPadded, file);
|
||||||
for (u32 j = 0; j < width * 3; j += 3)
|
for (u32 j = 0; j < width * 3; j += 3)
|
||||||
{
|
{
|
||||||
// Convert (B, G, R) to (R, G, B)
|
// Convert (B, G, R) to (R, G, B)
|
||||||
tmp = data[j];
|
o_texture.setData(x, row[j + 2]);
|
||||||
data[j] = data[j + 2];
|
o_texture.setData(x + 1, row[j + 1]);
|
||||||
data[j + 2] = tmp;
|
o_texture.setData(x + 2, row[j]);
|
||||||
|
|
||||||
o_texture.setData(x, data[j]);
|
|
||||||
o_texture.setData(x + 1, data[j + 1]);
|
|
||||||
o_texture.setData(x + 2, data[j + 2]);
|
|
||||||
x += 3;
|
x += 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete[] t_path;
|
delete[] path;
|
||||||
delete[] data;
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,10 +36,10 @@ DffLoader::~DffLoader() {}
|
|||||||
|
|
||||||
void DffLoader::load(MeshFrame *o_result, char *t_filename, float t_scale, u8 t_invertT)
|
void DffLoader::load(MeshFrame *o_result, char *t_filename, float t_scale, u8 t_invertT)
|
||||||
{
|
{
|
||||||
PRINT_LOG("Loading dff file");
|
consoleLog("Loading dff file");
|
||||||
FILE *file = fopen(t_filename, "rb");
|
char *path = String::createConcatenated("host:", t_filename);
|
||||||
if (file == NULL)
|
FILE *file = fopen(path, "rb");
|
||||||
PRINT_ERR("Failed to load .obj file!");
|
assertMsg(file != NULL, "Failed to load .dff file!");
|
||||||
fseek(file, 0L, SEEK_END);
|
fseek(file, 0L, SEEK_END);
|
||||||
long fileSize = ftell(file);
|
long fileSize = ftell(file);
|
||||||
u8 data[fileSize];
|
u8 data[fileSize];
|
||||||
@@ -48,9 +48,29 @@ void DffLoader::load(MeshFrame *o_result, char *t_filename, float t_scale, u8 t_
|
|||||||
fclose(file);
|
fclose(file);
|
||||||
serialize(o_result, t_invertT, data, t_scale);
|
serialize(o_result, t_invertT, data, t_scale);
|
||||||
o_result->calculateBoundingBoxes();
|
o_result->calculateBoundingBoxes();
|
||||||
PRINT_LOG("Dff file loaded!");
|
delete[] path;
|
||||||
|
consoleLog("Dff file loaded!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// void DffLoader::im_not_used_anywhere(MeshFrame *o_result, char *t_filename, float t_scale, u8 t_invertT)
|
||||||
|
// {
|
||||||
|
// PRINT_LOG("Loading dff file");
|
||||||
|
// char *path = String::createConcatenated("host:", t_filename);
|
||||||
|
// FILE *file = fopen(path, "rb");
|
||||||
|
// if (file == NULL)
|
||||||
|
// PRINT_ERR("Failed to load .dff file!");
|
||||||
|
// fseek(file, 0L, SEEK_END);
|
||||||
|
// long fileSize = ftell(file);
|
||||||
|
// u8 data[fileSize];
|
||||||
|
// rewind(file);
|
||||||
|
// fread(&data, sizeof(u8), fileSize, file);
|
||||||
|
// fclose(file);
|
||||||
|
// serialize(o_result, t_invertT, data, t_scale);
|
||||||
|
// o_result->calculateBoundingBoxes();
|
||||||
|
// delete[] path;
|
||||||
|
// PRINT_LOG("Dff file loaded!");
|
||||||
|
// }
|
||||||
|
|
||||||
void DffLoader::serialize(MeshFrame *o_result, u8 t_invertT, u8 *t_data, float t_scale)
|
void DffLoader::serialize(MeshFrame *o_result, u8 t_invertT, u8 *t_data, float t_scale)
|
||||||
{
|
{
|
||||||
u32 ptrPos = 0;
|
u32 ptrPos = 0;
|
||||||
@@ -223,14 +243,17 @@ 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++)
|
||||||
{
|
{
|
||||||
u32 vertex1 = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
u32 vertex1 = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||||
o_frame->getMaterial(i).setVertexFace(j, vertex1);
|
// Inverted insertind due to backface culling
|
||||||
o_frame->getMaterial(i).setNormalFace(j, vertex1);
|
o_frame->getMaterial(i).setVertexFace(facesCount - 1 - j, vertex1);
|
||||||
o_frame->getMaterial(i).setSTFace(j, vertex1);
|
o_frame->getMaterial(i).setNormalFace(facesCount - 1 - j, vertex1);
|
||||||
|
o_frame->getMaterial(i).setSTFace(facesCount - 1 - j, vertex1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,27 +44,20 @@ int MEM_fread(char *buf, size_t size, size_t n, const FILE *f)
|
|||||||
*/
|
*/
|
||||||
MeshFrame *MD2Loader::load(u32 &o_framesCount, char *t_subpath, char *t_nameWithoutExtension, float t_scale, u8 t_invertT)
|
MeshFrame *MD2Loader::load(u32 &o_framesCount, char *t_subpath, char *t_nameWithoutExtension, float t_scale, u8 t_invertT)
|
||||||
{
|
{
|
||||||
PRINT_LOG("Loading new MD2 file");
|
consoleLog("Loading new MD2 file");
|
||||||
char *part1 = String::createConcatenated(t_subpath, t_nameWithoutExtension);
|
char *part1 = String::createConcatenated(t_subpath, t_nameWithoutExtension);
|
||||||
char *finalPath = String::createConcatenated(part1, ".md2"); // "folder/object.md2"
|
char *part2 = String::createConcatenated("host:", part1);
|
||||||
|
char *finalPath = String::createConcatenated(part2, ".md2"); // "folder/object.md2"
|
||||||
delete[] part1;
|
delete[] part1;
|
||||||
|
delete[] part2;
|
||||||
md2_t header;
|
md2_t header;
|
||||||
|
|
||||||
FILE *file = fopen(finalPath, "rb");
|
FILE *file = fopen(finalPath, "rb");
|
||||||
|
assertMsg(file != NULL, "Failed to load .md2 file!");
|
||||||
if (file == NULL)
|
|
||||||
{
|
|
||||||
PRINT_ERR("Failed to load .md2 file!");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
fread((char *)&header, sizeof(md2_t), 1, file);
|
fread((char *)&header, sizeof(md2_t), 1, file);
|
||||||
|
|
||||||
if ((header.ident != MD2_IDENT) && (header.version != MD2_VERSION))
|
assertMsg((header.ident == MD2_IDENT) && (header.version == MD2_VERSION), "This MD2 file was not in correct format!");
|
||||||
{
|
|
||||||
PRINT_ERR("This MD2 file was not in correct format!");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 framesCount = header.num_frames;
|
u32 framesCount = header.num_frames;
|
||||||
u32 vertexCount = header.num_xyz;
|
u32 vertexCount = header.num_xyz;
|
||||||
@@ -85,7 +78,7 @@ MeshFrame *MD2Loader::load(u32 &o_framesCount, char *t_subpath, char *t_nameWith
|
|||||||
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
|
||||||
MeshFrame *resultFrames = new MeshFrame[26];
|
MeshFrame *resultFrames = new MeshFrame[framesCount];
|
||||||
|
|
||||||
frame_t *frame;
|
frame_t *frame;
|
||||||
Vector3 tempVec = Vector3();
|
Vector3 tempVec = Vector3();
|
||||||
@@ -136,6 +129,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]);
|
||||||
@@ -143,7 +138,7 @@ MeshFrame *MD2Loader::load(u32 &o_framesCount, char *t_subpath, char *t_nameWith
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PRINT_LOG("MD2 file loaded!");
|
consoleLog("MD2 file loaded!");
|
||||||
delete[] finalPath;
|
delete[] finalPath;
|
||||||
o_framesCount = framesCount;
|
o_framesCount = framesCount;
|
||||||
for (u32 i = 0; i < framesCount; i++)
|
for (u32 i = 0; i < framesCount; i++)
|
||||||
|
|||||||
@@ -28,13 +28,15 @@ ObjLoader::~ObjLoader() {}
|
|||||||
|
|
||||||
void ObjLoader::load(MeshFrame *o_result, char *t_filename, float t_scale, u8 t_invertT)
|
void ObjLoader::load(MeshFrame *o_result, char *t_filename, float t_scale, u8 t_invertT)
|
||||||
{
|
{
|
||||||
FILE *file = fopen(t_filename, "rb");
|
char *path = String::createConcatenated("host:", t_filename);
|
||||||
if (file == NULL)
|
FILE *file = fopen(path, "rb");
|
||||||
PRINT_ERR("Failed to load .obj file!");
|
assertMsg(file != NULL, "Failed to load .obj file!");
|
||||||
allocateObjMemory(file, o_result);
|
allocateObjMemory(file, o_result);
|
||||||
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
|
||||||
@@ -43,13 +45,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;
|
||||||
@@ -57,7 +57,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);
|
||||||
}
|
}
|
||||||
@@ -70,34 +69,115 @@ 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 3:
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
assertMsg(newerMatches == 6, "Unknown .obj face for .obj file!");
|
||||||
|
/** Configuration confirmed. */
|
||||||
|
newerMatches = fscanf(file, "%d//%d %d//%d %d//%d",
|
||||||
|
&vertexIndex[0], &normalIndex[0],
|
||||||
|
&vertexIndex[1], &normalIndex[1],
|
||||||
|
&vertexIndex[2], &normalIndex[2]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
assertMsg(true == false, "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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Calculate how many vertices(v), coordinates(vt), normals(vn) and faces(f) have .obj file */
|
/** Calculate how many vertices(v), coordinates(vt), normals(vn) and faces(f) have .obj file */
|
||||||
@@ -145,7 +225,10 @@ void ObjLoader::allocateObjMemory(FILE *t_file, MeshFrame *o_result)
|
|||||||
if (strcmp(lineHeader, "usemtl") == 0)
|
if (strcmp(lineHeader, "usemtl") == 0)
|
||||||
{
|
{
|
||||||
if (currentMatI >= 0) // Skip -1
|
if (currentMatI >= 0) // Skip -1
|
||||||
|
{
|
||||||
o_result->getMaterial(currentMatI).allocateFaces(facesCounter);
|
o_result->getMaterial(currentMatI).allocateFaces(facesCounter);
|
||||||
|
facesCounter = 0;
|
||||||
|
}
|
||||||
currentMatI++;
|
currentMatI++;
|
||||||
}
|
}
|
||||||
else if (strcmp(lineHeader, "f") == 0)
|
else if (strcmp(lineHeader, "f") == 0)
|
||||||
|
|||||||
@@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../include/loaders/png_loader.hpp"
|
||||||
|
|
||||||
|
#include "../include/utils/debug.hpp"
|
||||||
|
#include "../include/utils/string.hpp"
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <png.h>
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Constructors/Destructors
|
||||||
|
// ----
|
||||||
|
|
||||||
|
PngLoader::PngLoader() {}
|
||||||
|
|
||||||
|
PngLoader::~PngLoader() {}
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Methods
|
||||||
|
// ----
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param t_name Without extension. Example "skyfall2"
|
||||||
|
* @param t_extension With dot and extension. Example ".png"
|
||||||
|
*/
|
||||||
|
void PngLoader::load(Texture &o_texture, char *t_subfolder, char *t_name, char *t_extension)
|
||||||
|
{
|
||||||
|
char *path_part1 = String::createConcatenated(t_subfolder, t_name);
|
||||||
|
char *path_part2 = String::createConcatenated("host:", path_part1);
|
||||||
|
char *path = String::createConcatenated(path_part2, t_extension);
|
||||||
|
delete[] path_part1;
|
||||||
|
delete[] path_part2;
|
||||||
|
|
||||||
|
FILE *file = fopen(path, "rb");
|
||||||
|
assertMsg(file != NULL, "Failed to open .png file!");
|
||||||
|
|
||||||
|
png_structp png_ptr;
|
||||||
|
png_infop info_ptr;
|
||||||
|
png_uint_32 width, height;
|
||||||
|
|
||||||
|
u32 sig_read = 0, row = 0, i = 0, j = 0;
|
||||||
|
int bit_depth, color_type, interlace_type;
|
||||||
|
|
||||||
|
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||||
|
assertMsg(png_ptr, "PNG read struct init failed!");
|
||||||
|
info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
assertMsg(info_ptr, "PNG info struct init failed!");
|
||||||
|
assertMsg(!setjmp(png_jmpbuf(png_ptr)), "PNG reader fatal error!");
|
||||||
|
|
||||||
|
png_init_io(png_ptr, file);
|
||||||
|
png_set_sig_bytes(png_ptr, sig_read);
|
||||||
|
png_read_info(png_ptr, info_ptr);
|
||||||
|
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL);
|
||||||
|
png_set_strip_16(png_ptr);
|
||||||
|
|
||||||
|
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
||||||
|
png_set_expand(png_ptr);
|
||||||
|
|
||||||
|
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
|
||||||
|
png_set_expand(png_ptr);
|
||||||
|
|
||||||
|
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
|
||||||
|
png_set_tRNS_to_alpha(png_ptr);
|
||||||
|
|
||||||
|
png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
|
||||||
|
|
||||||
|
png_read_update_info(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
png_byte pngType = png_get_color_type(png_ptr, info_ptr);
|
||||||
|
TextureType type;
|
||||||
|
switch (pngType)
|
||||||
|
{
|
||||||
|
case PNG_COLOR_TYPE_RGB_ALPHA:
|
||||||
|
type = TEX_TYPE_RGBA;
|
||||||
|
break;
|
||||||
|
case PNG_COLOR_TYPE_RGB:
|
||||||
|
type = TEX_TYPE_RGB;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assertMsg(true == false, "This png format is not supported! RGB/RGBA only.");
|
||||||
|
}
|
||||||
|
|
||||||
|
o_texture.setSize(width, height, type);
|
||||||
|
printf("PNGLoader - width: %d | height: %d\n", width, height);
|
||||||
|
|
||||||
|
size_t row_bytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||||
|
png_byte *row_pointers[height];
|
||||||
|
for (row = 0; row < height; row++)
|
||||||
|
row_pointers[row] = new png_byte[row_bytes];
|
||||||
|
|
||||||
|
png_read_image(png_ptr, row_pointers);
|
||||||
|
|
||||||
|
u32 x = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < height; i++)
|
||||||
|
for (j = 0; j < width; j++)
|
||||||
|
{
|
||||||
|
o_texture.setData(x, row_pointers[i][4 * j]);
|
||||||
|
o_texture.setData(x + 1, row_pointers[i][4 * j + 1]);
|
||||||
|
o_texture.setData(x + 2, row_pointers[i][4 * j + 2]);
|
||||||
|
if (type == TEX_TYPE_RGBA)
|
||||||
|
{
|
||||||
|
o_texture.setData(x + 3, ((int)row_pointers[i][4 * j + 3] * 128 / 255));
|
||||||
|
x += 4;
|
||||||
|
}
|
||||||
|
else if (type == TEX_TYPE_RGB)
|
||||||
|
x += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (row = 0; row < height; row++)
|
||||||
|
delete[] row_pointers[row];
|
||||||
|
|
||||||
|
png_read_end(png_ptr, NULL);
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
||||||
|
|
||||||
|
delete[] path;
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Michał Mostowik <mostek3pl@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../include/models/bounding_box.hpp"
|
||||||
|
#include "../include/utils/debug.hpp"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a BoundingBox class
|
||||||
|
* Allows for user friendly access to bounding box data.
|
||||||
|
* @param t_vertices Array of 8 Vector3 elements.
|
||||||
|
*/
|
||||||
|
BoundingBox::BoundingBox(Vector3 *t_vertices)
|
||||||
|
{
|
||||||
|
//Perform a deep copy of vertex array parameter
|
||||||
|
memcpy(_vertices, t_vertices, 8 * sizeof(Vector3));
|
||||||
|
|
||||||
|
//This might be shortened with Vector3 operator overloading, but current
|
||||||
|
//implementation is more human readable.
|
||||||
|
_height = _vertices[0].y - _vertices[2].y;
|
||||||
|
_width = _vertices[0].x - _vertices[4].x;
|
||||||
|
_depth = _vertices[0].z - _vertices[1].z;
|
||||||
|
|
||||||
|
_centerVector = _vertices[0];
|
||||||
|
_centerVector.x += (_width / 2);
|
||||||
|
_centerVector.y += (_height / 2);
|
||||||
|
_centerVector.z += (_depth / 2);
|
||||||
|
|
||||||
|
//Z-Axis faces
|
||||||
|
_frontFace = BoundingBoxFace(_vertices[1], _vertices[7], _vertices[1].z);
|
||||||
|
_backFace = BoundingBoxFace(_vertices[0], _vertices[6], _vertices[0].z);
|
||||||
|
//X-Axis faces
|
||||||
|
_leftFace = BoundingBoxFace(_vertices[0], _vertices[3], _vertices[0].x);
|
||||||
|
_rightFace = BoundingBoxFace(_vertices[4], _vertices[7], _vertices[4].x);
|
||||||
|
//Y-Axis faces
|
||||||
|
_topFace = BoundingBoxFace(_vertices[2], _vertices[7], _vertices[2].y);
|
||||||
|
_bottomFace = BoundingBoxFace(_vertices[0], _vertices[5], _vertices[0].y);
|
||||||
|
}
|
||||||
|
|
||||||
|
BoundingBox::~BoundingBox()
|
||||||
|
{
|
||||||
|
}
|
||||||
+276
-168
@@ -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,151 +49,56 @@ 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(float x, float y, float z)
|
void Matrix::setPerspective(const ScreenSettings &t_screen)
|
||||||
{
|
|
||||||
this->identity();
|
|
||||||
this->data[(3 << 2) + 0] = x; // 3,0
|
|
||||||
this->data[(3 << 2) + 1] = y; // 3,1
|
|
||||||
this->data[(3 << 2) + 2] = z; // 3,2
|
|
||||||
}
|
|
||||||
|
|
||||||
void Matrix::makeZRotation(float t_radians)
|
|
||||||
{
|
|
||||||
this->identity();
|
|
||||||
float c = Math::cos(t_radians);
|
|
||||||
float s = Math::sin(t_radians);
|
|
||||||
this->data[0] = c; // 0,0
|
|
||||||
this->data[1] = s; // 0,1
|
|
||||||
this->data[4] = -s; // 1,0
|
|
||||||
this->data[5] = c; // 1,1
|
|
||||||
}
|
|
||||||
|
|
||||||
Matrix Matrix::operator*(Matrix &t)
|
|
||||||
{
|
|
||||||
Matrix result;
|
|
||||||
asm volatile(
|
|
||||||
"lqc2 vf1, 0x00(%1) \n\t"
|
|
||||||
"lqc2 vf2, 0x10(%1) \n\t"
|
|
||||||
"lqc2 vf3, 0x20(%1) \n\t"
|
|
||||||
"lqc2 vf4, 0x30(%1) \n\t"
|
|
||||||
"lqc2 vf5, 0x00(%2) \n\t"
|
|
||||||
"lqc2 vf6, 0x10(%2) \n\t"
|
|
||||||
"lqc2 vf7, 0x20(%2) \n\t"
|
|
||||||
"lqc2 vf8, 0x30(%2) \n\t"
|
|
||||||
"vmulax.xyzw ACC, vf5, vf1 \n\t"
|
|
||||||
"vmadday.xyzw ACC, vf6, vf1 \n\t"
|
|
||||||
"vmaddaz.xyzw ACC, vf7, vf1 \n\t"
|
|
||||||
"vmaddw.xyzw vf1, vf8, vf1 \n\t"
|
|
||||||
"vmulax.xyzw ACC, vf5, vf2 \n\t"
|
|
||||||
"vmadday.xyzw ACC, vf6, vf2 \n\t"
|
|
||||||
"vmaddaz.xyzw ACC, vf7, vf2 \n\t"
|
|
||||||
"vmaddw.xyzw vf2, vf8, vf2 \n\t"
|
|
||||||
"vmulax.xyzw ACC, vf5, vf3 \n\t"
|
|
||||||
"vmadday.xyzw ACC, vf6, vf3 \n\t"
|
|
||||||
"vmaddaz.xyzw ACC, vf7, vf3 \n\t"
|
|
||||||
"vmaddw.xyzw vf3, vf8, vf3 \n\t"
|
|
||||||
"vmulax.xyzw ACC, vf5, vf4 \n\t"
|
|
||||||
"vmadday.xyzw ACC, vf6, vf4 \n\t"
|
|
||||||
"vmaddaz.xyzw ACC, vf7, vf4 \n\t"
|
|
||||||
"vmaddw.xyzw vf4, vf8, vf4 \n\t"
|
|
||||||
"sqc2 vf1, 0x00(%0) \n\t"
|
|
||||||
"sqc2 vf2, 0x10(%0) \n\t"
|
|
||||||
"sqc2 vf3, 0x20(%0) \n\t"
|
|
||||||
"sqc2 vf4, 0x30(%0) \n\t"
|
|
||||||
:
|
|
||||||
: "r"(result.data), "r"(this->data), "r"(t.data)
|
|
||||||
: "memory");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Create empty matrix */
|
|
||||||
Matrix::Matrix()
|
|
||||||
{
|
|
||||||
data[0] = 0.0F;
|
|
||||||
data[1] = 0.0F;
|
|
||||||
data[2] = 0.0F;
|
|
||||||
data[3] = 0.0F;
|
|
||||||
|
|
||||||
data[4] = 0.0F;
|
|
||||||
data[5] = 0.0F;
|
|
||||||
data[6] = 0.0F;
|
|
||||||
data[7] = 0.0F;
|
|
||||||
|
|
||||||
data[8] = 0.0F;
|
|
||||||
data[9] = 0.0F;
|
|
||||||
data[10] = 0.0F;
|
|
||||||
data[11] = 0.0F;
|
|
||||||
|
|
||||||
data[12] = 0.0F;
|
|
||||||
data[13] = 0.0F;
|
|
||||||
data[14] = 0.0F;
|
|
||||||
data[15] = 0.0F;
|
|
||||||
}
|
|
||||||
|
|
||||||
Matrix::~Matrix() {}
|
|
||||||
|
|
||||||
// ----
|
|
||||||
// Methods
|
|
||||||
// ----
|
|
||||||
|
|
||||||
/** Set up a perspective projection matrix
|
|
||||||
*
|
|
||||||
* Clone of gluPerspective()
|
|
||||||
* https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml
|
|
||||||
* @param fov (FOV in radians)/2
|
|
||||||
* @param aspect Aspect ratio
|
|
||||||
* @param scrW Half of screen width
|
|
||||||
* @param scrH Half of screen height
|
|
||||||
* @param zNear Distance to near plane
|
|
||||||
* @param zFar Distance to far plane
|
|
||||||
* @param projScale Projection scale
|
|
||||||
*/
|
|
||||||
void Matrix::setPerspective(ScreenSettings &t_screen)
|
|
||||||
{
|
{
|
||||||
float fovYdiv2 = Math::HALF_ANG2RAD * t_screen.fov;
|
float 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));
|
||||||
float w = cotFOV * (t_screen.width / 4096.0F) / t_screen.aspectRatio;
|
float w = cotFOV * (t_screen.width / t_screen.projectionScale) / t_screen.aspectRatio;
|
||||||
float h = cotFOV * (t_screen.height / 4096.0F);
|
float h = cotFOV * (t_screen.height / t_screen.projectionScale);
|
||||||
|
|
||||||
this->data[0] = w;
|
this->data[0] = w;
|
||||||
this->data[1] = 0.0F;
|
this->data[1] = 0.0F;
|
||||||
@@ -215,45 +125,60 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Matrix::print()
|
const void Matrix::print() const
|
||||||
{
|
{
|
||||||
printf("MATRIX(\n%f, %f, %f, %f\n%f, %f, %f, %f\n%f, %f, %f, %f\n%f, %f, %f, %f\n)\n",
|
printf("MATRIX(\n%f, %f, %f, %f\n%f, %f, %f, %f\n%f, %f, %f, %f\n%f, %f, %f, %f\n)\n",
|
||||||
data[0], data[1], data[2], data[3],
|
data[0], data[1], data[2], data[3],
|
||||||
@@ -261,3 +186,186 @@ void Matrix::print()
|
|||||||
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");
|
||||||
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ void Plane::update(Vector3 &a, Vector3 &b, Vector3 &c)
|
|||||||
this->distance = -this->normal.innerProduct(b);
|
this->distance = -this->normal.innerProduct(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plane::print()
|
const void Plane::print() const
|
||||||
{
|
{
|
||||||
printf("Plane(Vector3(%f, %f, %f), %f)\n", this->normal.x, this->normal.y, this->normal.z, this->distance);
|
printf("Plane(Vector3(%f, %f, %f), %f)\n", this->normal.x, this->normal.y, this->normal.z, this->distance);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../../include/models/math/point.hpp"
|
#include "../../include/models/math/point.hpp"
|
||||||
|
#include "../../include/utils/math.hpp"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
@@ -55,7 +56,22 @@ void Point::set(const Point &v)
|
|||||||
y = v.y;
|
y = v.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Point::print()
|
void Point::rotate(const float &t_angle, const float &t_x, const float &t_y)
|
||||||
|
{
|
||||||
|
float s = Math::sin(t_angle);
|
||||||
|
float c = Math::cos(t_angle);
|
||||||
|
|
||||||
|
x -= t_x;
|
||||||
|
y -= t_y;
|
||||||
|
|
||||||
|
float xnew = x * c - y * s;
|
||||||
|
float ynew = x * s + y * c;
|
||||||
|
|
||||||
|
x = xnew + t_x;
|
||||||
|
y = ynew + t_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
const void Point::print() const
|
||||||
{
|
{
|
||||||
printf("Point(%f, %f)\n", x, y);
|
printf("Point(%f, %f)\n", x, y);
|
||||||
}
|
}
|
||||||
|
|||||||
+158
-205
@@ -9,121 +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)
|
|
||||||
: "$8");
|
|
||||||
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"
|
||||||
"vmulz.y vf6, vf4, vf5 \n\t" // vf6.y = vf4.y * vf5.z
|
"vopmsub.xyz $vf8, $vf5, $vf4 \n\t"
|
||||||
"vmuly.z vf6, vf4, vf5 \n\t"
|
"vsub.w $vf8, $vf0, $vf0 \n\t"
|
||||||
"vsubz.y vf6, vf6, vf6 \n\t" // vf6.y = vf4.y - vf4.z
|
"sqc2 $vf8, 0x0(%0) \n\t" // $vf8 = res
|
||||||
"vaddy.x vf8, vf0, vf6 \n\t" // res.x = vf4.y * vf5.z - vf4.z * vf5.y
|
|
||||||
|
|
||||||
"vmulx.z vf6, vf4, vf5 \n\t"
|
|
||||||
"vmulz.x vf6, vf4, vf5 \n\t"
|
|
||||||
"vsubx.z vf6, vf6, vf6 \n\t"
|
|
||||||
"vaddz.y vf8, vf0, vf6 \n\t" // res.y = vf4.z * vf5.x - vf4.x * vf5.z
|
|
||||||
|
|
||||||
"vmuly.x vf6, vf4, vf5 \n\t"
|
|
||||||
"vmulx.y vf6, vf4, vf5 \n\t"
|
|
||||||
"vsuby.x vf6, vf6, vf6 \n\t"
|
|
||||||
"vaddx.z vf8, vf0, vf6 \n\t" // res.z = vf4.x * vf5.y - vf4.y * vf5.x
|
|
||||||
"sqc2 vf8, 0x0(%0) \n\t"
|
|
||||||
:
|
:
|
||||||
: "r"(res.xyz), "r"(this->xyz), "r"(v.xyz));
|
: "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;
|
||||||
@@ -132,22 +70,21 @@ Vector3 Vector3::operator*(Vector3 &v)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 Vector3::operator*(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));
|
||||||
: "$8");
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 Vector3::operator/(float t)
|
Vector3 Vector3::operator/(const float &t) const
|
||||||
{
|
{
|
||||||
Vector3 result;
|
Vector3 result;
|
||||||
result.x = x / t;
|
result.x = x / t;
|
||||||
@@ -156,58 +93,81 @@ 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)
|
|
||||||
: "$2");
|
|
||||||
return dot <= 0.0F;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Checks intersection with given square */
|
|
||||||
u8 Vector3::collidesSquare(Vector3 &t_min, Vector3 &t_max)
|
|
||||||
{
|
|
||||||
return ((this->x <= t_max.x && this->x >= t_min.x) && (this->y < t_max.y && this->y >= t_min.y) && (this->z <= t_max.z && this->z >= t_min.z)) ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Checks is this vector is on given square */
|
|
||||||
u8 Vector3::isOnSquare(Vector3 &t_min, Vector3 &t_max)
|
|
||||||
{
|
|
||||||
return ((this->x <= t_max.x && this->x >= t_min.x) && (this->y >= t_max.y) && (this->z <= t_max.z && this->z >= t_min.z)) ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
float Vector3::length()
|
|
||||||
{
|
|
||||||
register float result;
|
|
||||||
asm volatile( // VU0 Macro program
|
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"
|
:
|
||||||
"vaddq.x vf8, vf0, Q \n\t"
|
: "r"(this->xyz), "r"(t.xyz));
|
||||||
"qmfc2 $2, vf8 \n\t"
|
}
|
||||||
|
|
||||||
|
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"
|
"mtc1 $2, %0 \n\t"
|
||||||
: "=f"(result)
|
: "=f"(result)
|
||||||
: "r"(this->xyz)
|
: "r"(this->xyz), "r"(v.xyz));
|
||||||
: "$2");
|
return result;
|
||||||
|
// return (x * v.x + y * v.y + z * v.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
float Vector3::length() const
|
||||||
|
{
|
||||||
|
float result;
|
||||||
|
asm volatile( // VU0 Macro program
|
||||||
|
"lqc2 $vf4, 0x0(%1) \n\t"
|
||||||
|
"vmul.xyz $vf5, $vf4, $vf4 \n\t"
|
||||||
|
"vaddy.x $vf5, $vf5, $vf5 \n\t"
|
||||||
|
"vaddz.x $vf5, $vf5, $vf5 \n\t"
|
||||||
|
"vsqrt $Q , $vf5x \n\t"
|
||||||
|
"vwaitq \n\t"
|
||||||
|
"vaddq.x $vf8, $vf0, $Q \n\t"
|
||||||
|
"qmfc2 $2, $vf8 \n\t"
|
||||||
|
"mtc1 $2, %0 \n\t"
|
||||||
|
: "=f"(result)
|
||||||
|
: "r"(this->xyz));
|
||||||
return result;
|
return result;
|
||||||
// return Math::sqrt(x * x + y * y + z * z);
|
// return Math::sqrt(x * x + y * y + z * z);
|
||||||
}
|
}
|
||||||
@@ -215,87 +175,80 @@ 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"
|
||||||
"vsub.xyz vf6, vf0, vf0 \n\t"
|
|
||||||
"vaddw.xyz vf6, vf6, vf4 \n\t"
|
|
||||||
"vwaitq \n\t"
|
"vwaitq \n\t"
|
||||||
"vmulq.xyz vf6, vf4, Q \n\t"
|
"vsub.xyz $vf6, $vf0, $vf0 \n\t"
|
||||||
"sqc2 vf6, 0x0(%0) \n\t"
|
"vaddw.xyz $vf6, $vf6, $vf4 \n\t"
|
||||||
|
"vwaitq \n\t"
|
||||||
|
"vmulq.xyz $vf6, $vf4, $Q \n\t"
|
||||||
|
"sqc2 $vf6, 0x0(%0) \n\t"
|
||||||
:
|
:
|
||||||
: "r"(this->xyz));
|
: "r"(this->xyz));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Also called dot3 */
|
float Vector3::distanceTo(const Vector3 &v) const
|
||||||
float Vector3::innerProduct(Vector3 &v)
|
|
||||||
{
|
{
|
||||||
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"
|
||||||
"vmul.xyz vf6, vf4, vf5 \n\t"
|
"vsub.xyz $vf6, $vf4, $vf5 \n\t"
|
||||||
"vaddy.x vf6, vf6, vf6 \n\t"
|
"vmul.xyz $vf7, $vf6, $vf6 \n\t"
|
||||||
"vaddz.x vf6, vf6, vf6 \n\t"
|
"vaddy.x $vf7, $vf7, $vf7 \n\t"
|
||||||
"qmfc2 $2, vf6 \n\t"
|
"vaddz.x $vf7, $vf7, $vf7 \n\t"
|
||||||
|
"vsqrt $Q , $vf7x \n\t"
|
||||||
|
"vwaitq \n\t"
|
||||||
|
"vaddq.x $vf8, $vf0, $Q \n\t"
|
||||||
|
"qmfc2 $2, $vf8 \n\t"
|
||||||
"mtc1 $2, %0 \n\t"
|
"mtc1 $2, %0 \n\t"
|
||||||
: "=f"(result)
|
: "=f"(result)
|
||||||
: "r"(this->xyz), "r"(v.xyz)
|
: "r"(this->xyz), "r"(v.xyz));
|
||||||
: "$2");
|
|
||||||
return result;
|
return result;
|
||||||
// return (x * v.x + y * v.y + z * v.z);
|
// return Math::sqrt((this->x - v.x) * (this->x - v.x) +
|
||||||
|
// (this->y - v.y) * (this->y - v.y) +
|
||||||
|
// (this->z - v.z) * (this->z - v.z));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vector3::set(const float &x, const float &y, const float &z)
|
u8 Vector3::shouldBeBackfaceCulled(const Vector3 *t_cameraPos, const Vector3 *t_v0, const Vector3 *t_v1, const Vector3 *t_v2)
|
||||||
{
|
{
|
||||||
this->x = x;
|
register float dot;
|
||||||
this->y = y;
|
asm volatile(
|
||||||
this->z = z;
|
"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::set(const Vector3 &v)
|
void Vector3::setByLerp(const Vector3 &t_v1, const Vector3 &t_v2, const float &t_interp, const float &t_scale)
|
||||||
{
|
{
|
||||||
this->x = v.x;
|
asm volatile(
|
||||||
this->y = v.y;
|
"lqc2 $vf4, 0x0(%1) \n\t" // $vf4 = v1
|
||||||
this->z = v.z;
|
"lqc2 $vf5, 0x0(%2) \n\t" // $vf5 = v2
|
||||||
}
|
"mfc1 $8, %3 \n\t" // $vf6 = t
|
||||||
|
"qmtc2 $8, $vf6 \n\t" // lerp:
|
||||||
void Vector3::copy(Vector3 &v)
|
"vsub.xyz $vf7, $vf5, $vf4 \n\t" // $vf7 = v2 - v1
|
||||||
{
|
"vmulx.xyz $vf8, $vf7, $vf6 \n\t" // $vf8 = $vf7 * t
|
||||||
asm volatile( // VU0 Macro program
|
"vadd.xyz $vf9, $vf8, $vf4 \n\t" // $vf9 = $vf8 + $vf4
|
||||||
"lq $6, 0x0(%1) \n\t"
|
"sqc2 $vf9, 0x0(%0) \n\t" // v0 = $vf9
|
||||||
"sq $6, 0x0(%0) \n\t"
|
|
||||||
:
|
:
|
||||||
: "r"(v.xyz), "r"(this->xyz)
|
: "r"(&this->xyz), "r"(&t_v1.xyz), "r"(&t_v2.xyz), "f"(t_interp));
|
||||||
: "$6");
|
operator*=(t_scale);
|
||||||
}
|
|
||||||
|
|
||||||
float Vector3::distanceTo(Vector3 &v)
|
|
||||||
{
|
|
||||||
register float result;
|
|
||||||
asm volatile( // VU0 Macro program
|
|
||||||
"lqc2 vf4, 0x0(%1) \n\t"
|
|
||||||
"lqc2 vf5, 0x0(%2) \n\t"
|
|
||||||
"vsub.xyz vf6, vf4, vf5 \n\t"
|
|
||||||
"vmul.xyz vf7, vf6, vf6 \n\t"
|
|
||||||
"vaddy.x vf7, vf7, vf7 \n\t"
|
|
||||||
"vaddz.x vf7, vf7, vf7 \n\t"
|
|
||||||
"vsqrt Q , vf7x \n\t"
|
|
||||||
"vaddq.x vf8, vf0, Q \n\t"
|
|
||||||
"qmfc2 $2, vf8 \n\t"
|
|
||||||
"mtc1 $2, %0 \n\t"
|
|
||||||
: "=f"(result)
|
|
||||||
: "r"(this->xyz), "r"(v.xyz)
|
|
||||||
: "$2");
|
|
||||||
return result;
|
|
||||||
// return Math::sqrt((this->x - another.x) * (this->x - another.x) +
|
|
||||||
// (this->y - another.y) * (this->y - another.y) +
|
|
||||||
// (this->z - another.z) * (this->z - another.z));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vector3::print()
|
|
||||||
{
|
|
||||||
printf("Vector3(%f, %f, %f)\n", x, y, z);
|
|
||||||
}
|
}
|
||||||
|
|||||||
+168
-80
@@ -13,7 +13,7 @@
|
|||||||
#include "../include/loaders/md2_loader.hpp"
|
#include "../include/loaders/md2_loader.hpp"
|
||||||
#include "../include/loaders/dff_loader.hpp"
|
#include "../include/loaders/dff_loader.hpp"
|
||||||
#include "../include/loaders/bmp_loader.hpp"
|
#include "../include/loaders/bmp_loader.hpp"
|
||||||
#include "../include/models/mesh_texture.hpp"
|
#include "../include/models/texture.hpp"
|
||||||
#include "../include/utils/debug.hpp"
|
#include "../include/utils/debug.hpp"
|
||||||
#include "../include/utils/string.hpp"
|
#include "../include/utils/string.hpp"
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
@@ -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);
|
||||||
@@ -69,15 +70,15 @@ void Mesh::loadObj(char *t_subfolder, char *t_objFile, const float &t_scale, con
|
|||||||
|
|
||||||
void Mesh::loadObj(char *t_subfolder, char *t_objFile, const float &t_scale, const u32 &t_framesCount, const u8 &t_invertT)
|
void Mesh::loadObj(char *t_subfolder, char *t_objFile, const float &t_scale, const u32 &t_framesCount, const u8 &t_invertT)
|
||||||
{
|
{
|
||||||
if (t_framesCount == 0)
|
assertMsg(t_framesCount != 0, "Frames count cannot be 0!");
|
||||||
PRINT_ERR("Frames count cannot be 0!");
|
if (t_framesCount == 1)
|
||||||
else if (t_framesCount == 1)
|
|
||||||
loadObj(t_subfolder, t_objFile, t_scale, t_invertT);
|
loadObj(t_subfolder, t_objFile, t_scale, t_invertT);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
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 +106,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,45 +122,36 @@ 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)
|
||||||
{
|
{
|
||||||
if (framesCount > 1)
|
assertMsg(framesCount > 0, "Cant play animation, because no mesh data was loaded!");
|
||||||
{
|
assertMsg(framesCount != 1, "Cant play animation, because this mesh have only one frame.");
|
||||||
if (t_endFrame >= framesCount)
|
assertMsg(t_endFrame < framesCount, "End frame value is too high. Valid range: (0, getFramesCount()-1)");
|
||||||
PRINT_ERR("End frame value is too high. Valid range: (0, getFramesCount()-1)");
|
animState.startFrame = t_startFrame;
|
||||||
animState.startFrame = t_startFrame;
|
animState.endFrame = t_endFrame;
|
||||||
animState.endFrame = t_endFrame;
|
if (animState.currentFrame == t_startFrame)
|
||||||
if (animState.currentFrame == t_startFrame)
|
animState.nextFrame = t_endFrame;
|
||||||
animState.nextFrame = t_endFrame;
|
else
|
||||||
else
|
animState.nextFrame = t_startFrame;
|
||||||
animState.nextFrame = t_startFrame;
|
|
||||||
}
|
|
||||||
else if (framesCount == 0)
|
|
||||||
PRINT_ERR("Cant play animation, because no mesh data was loaded!");
|
|
||||||
else if (framesCount == 1)
|
|
||||||
PRINT_ERR("Cant play animation, because this mesh have only one frame.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mesh::playAnimation(const u32 &t_startFrame, const u32 &t_endFrame, const u32 &t_stayFrame)
|
void Mesh::playAnimation(const u32 &t_startFrame, const u32 &t_endFrame, const u32 &t_stayFrame)
|
||||||
{
|
{
|
||||||
if (framesCount > 1)
|
assertMsg(framesCount > 0, "Cant play animation, because no mesh data was loaded!");
|
||||||
{
|
assertMsg(framesCount != 1, "Cant play animation, because this mesh have only one frame.");
|
||||||
if (t_endFrame >= framesCount)
|
assertMsg(t_endFrame < framesCount, "End frame value is too high. Valid range: (0, getFramesCount()-1)");
|
||||||
PRINT_ERR("End frame value is too high. Valid range: (0, getFramesCount()-1)");
|
animState.startFrame = t_startFrame;
|
||||||
animState.startFrame = t_startFrame;
|
animState.endFrame = t_endFrame;
|
||||||
animState.endFrame = t_endFrame;
|
animState.isStayFrameSet = true;
|
||||||
animState.isStayFrameSet = true;
|
animState.stayFrame = t_stayFrame;
|
||||||
animState.stayFrame = t_stayFrame;
|
animState.nextFrame = t_startFrame;
|
||||||
animState.nextFrame = t_startFrame;
|
|
||||||
}
|
|
||||||
else if (framesCount == 0)
|
|
||||||
PRINT_ERR("Cant play animation, because no mesh data was loaded!");
|
|
||||||
else if (framesCount == 1)
|
|
||||||
PRINT_ERR("Cant play animation, because this mesh have only one frame.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mesh::animate()
|
void Mesh::animate()
|
||||||
@@ -185,55 +178,160 @@ void Mesh::animate()
|
|||||||
|
|
||||||
u32 Mesh::getDrawData(u32 t_materialIndex, VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, Vector3 &t_cameraPos)
|
u32 Mesh::getDrawData(u32 t_materialIndex, VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, Vector3 &t_cameraPos)
|
||||||
{
|
{
|
||||||
|
VECTOR ONE_VEC = {1.0F, 1.0F, 1.0F, 1.0F};
|
||||||
|
asm volatile(
|
||||||
|
// VU0 macro program:
|
||||||
|
// Load vector with 1.0F values to VF21
|
||||||
|
"lqc2 $vf21, 0x0(%0) \n\t" // load "one vec"
|
||||||
|
:
|
||||||
|
: "r"(ONE_VEC));
|
||||||
|
|
||||||
u32 addedFaces = 0;
|
u32 addedFaces = 0;
|
||||||
#define CURR_FRAME frames[animState.currentFrame]
|
#define CURR_FRAME frames[animState.currentFrame]
|
||||||
#define NEXT_FRAME frames[animState.nextFrame]
|
#define NEXT_FRAME frames[animState.nextFrame]
|
||||||
|
|
||||||
MeshMaterial *material = &CURR_FRAME.getMaterial(t_materialIndex); // cache
|
MeshMaterial *material = &CURR_FRAME.getMaterial(t_materialIndex); // cache
|
||||||
|
u32 *vertFaces = material->getVertexFaces(); // cache
|
||||||
|
u32 *normalFaces = material->getNormalFaces(); // cache
|
||||||
|
u32 *stFaces = material->getSTFaces(); // cache
|
||||||
Vector3 *verts = CURR_FRAME.getVertices(); // cache
|
Vector3 *verts = CURR_FRAME.getVertices(); // cache
|
||||||
Vector3 *nextVerts = NEXT_FRAME.getVertices(); // cache
|
Vector3 *nextVerts = NEXT_FRAME.getVertices(); // cache
|
||||||
Point *sts = CURR_FRAME.getSTs(); // cache
|
Point *sts = CURR_FRAME.getSTs(); // cache
|
||||||
Vector3 *normals = CURR_FRAME.getNormals(); // cache
|
Vector3 *normals = CURR_FRAME.getNormals(); // cache
|
||||||
#define CURR_VERT verts[material->getVertexFace(matI + vertI)]
|
|
||||||
#define CURR_ST sts[material->getSTFace(matI + vertI)]
|
|
||||||
#define CURR_NORMAL normals[material->getNormalFace(matI + vertI)]
|
|
||||||
#define NEXT_VERT nextVerts[material->getVertexFace(matI + vertI)]
|
|
||||||
|
|
||||||
for (u32 matI = 0; matI < material->getFacesCount(); matI += 3)
|
for (u32 faceI = 0; faceI < material->getFacesCount(); faceI += 3)
|
||||||
{
|
{
|
||||||
for (u32 vertI = 0; vertI < 3; vertI++)
|
if (animState.currentFrame != animState.nextFrame)
|
||||||
if (animState.currentFrame != animState.nextFrame)
|
{
|
||||||
calc3Vectors[vertI].setByLerp(CURR_VERT, NEXT_VERT, animState.interpolation, scale);
|
asm volatile(
|
||||||
|
// VU0 macro program:
|
||||||
|
// Calculate lerp() and store data into calc3Vectors
|
||||||
|
|
||||||
|
// Vertex 0
|
||||||
|
"lqc2 $vf4, 0x0(%3) \n\t" // $vf4 = v1
|
||||||
|
"lqc2 $vf5, 0x0(%6) \n\t" // $vf5 = v2
|
||||||
|
"mfc1 $10, %9 \n\t" // $vf6 = t
|
||||||
|
"qmtc2 $10, $vf6 \n\t" // lerp:
|
||||||
|
"vsub.xyz $vf7, $vf5, $vf4 \n\t" // $vf7 = v2 - v1
|
||||||
|
"vmulx.xyz $vf8, $vf7, $vf6 \n\t" // $vf8 = $vf7 * t
|
||||||
|
"vadd.xyz $vf9, $vf8, $vf4 \n\t" // $vf9 = $vf8 + $vf4
|
||||||
|
"sqc2 $vf9, 0x0(%0) \n\t" // v0 = $vf9
|
||||||
|
|
||||||
|
// Vertex 1
|
||||||
|
"lqc2 $vf4, 0x0(%4) \n\t" // $vf4 = v1
|
||||||
|
"lqc2 $vf5, 0x0(%7) \n\t" // $vf5 = v2
|
||||||
|
"mfc1 $10, %9 \n\t" // $vf6 = t
|
||||||
|
"qmtc2 $10, $vf6 \n\t" // lerp:
|
||||||
|
"vsub.xyz $vf7, $vf5, $vf4 \n\t" // $vf7 = v2 - v1
|
||||||
|
"vmulx.xyz $vf8, $vf7, $vf6 \n\t" // $vf8 = $vf7 * t
|
||||||
|
"vadd.xyz $vf9, $vf8, $vf4 \n\t" // $vf9 = $vf8 + $vf4
|
||||||
|
"sqc2 $vf9, 0x0(%1) \n\t" // v0 = $vf9
|
||||||
|
|
||||||
|
// Vertex 2
|
||||||
|
"lqc2 $vf4, 0x0(%5) \n\t" // $vf4 = v1
|
||||||
|
"lqc2 $vf5, 0x0(%8) \n\t" // $vf5 = v2
|
||||||
|
"mfc1 $10, %9 \n\t" // $vf6 = t
|
||||||
|
"qmtc2 $10, $vf6 \n\t" // lerp:
|
||||||
|
"vsub.xyz $vf7, $vf5, $vf4 \n\t" // $vf7 = v2 - v1
|
||||||
|
"vmulx.xyz $vf8, $vf7, $vf6 \n\t" // $vf8 = $vf7 * t
|
||||||
|
"vadd.xyz $vf9, $vf8, $vf4 \n\t" // $vf9 = $vf8 + $vf4
|
||||||
|
"sqc2 $vf9, 0x0(%2) \n\t" // v0 = $vf9
|
||||||
|
|
||||||
|
:
|
||||||
|
: "r"(calc3Vectors[0].xyz),
|
||||||
|
"r"(calc3Vectors[1].xyz),
|
||||||
|
"r"(calc3Vectors[2].xyz),
|
||||||
|
"r"(verts[vertFaces[faceI]].xyz),
|
||||||
|
"r"(verts[vertFaces[faceI + 1]].xyz),
|
||||||
|
"r"(verts[vertFaces[faceI + 2]].xyz),
|
||||||
|
"r"(nextVerts[vertFaces[faceI]].xyz),
|
||||||
|
"r"(nextVerts[vertFaces[faceI + 1]].xyz),
|
||||||
|
"r"(nextVerts[vertFaces[faceI + 2]].xyz),
|
||||||
|
"f"(animState.interpolation)
|
||||||
|
: "$10");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
asm volatile(
|
||||||
|
// VU0 macro program
|
||||||
|
// Copy 0,1,2 vertices
|
||||||
|
"lqc2 $vf1, 0x0(%3) \n\t" // load vert
|
||||||
|
"lqc2 $vf2, 0x0(%4) \n\t" // load normal
|
||||||
|
"lqc2 $vf3, 0x0(%5) \n\t" // load st
|
||||||
|
"sqc2 $vf1, 0x0(%0) \n\t" // store vert
|
||||||
|
"sqc2 $vf2, 0x0(%1) \n\t" // store normal
|
||||||
|
"sqc2 $vf3, 0x0(%2) \n\t" // store st
|
||||||
|
:
|
||||||
|
: "r"(calc3Vectors[0].xyz),
|
||||||
|
"r"(calc3Vectors[1].xyz),
|
||||||
|
"r"(calc3Vectors[2].xyz),
|
||||||
|
"r"(verts[vertFaces[faceI]].xyz),
|
||||||
|
"r"(verts[vertFaces[faceI + 1]].xyz),
|
||||||
|
"r"(verts[vertFaces[faceI + 2]].xyz));
|
||||||
|
}
|
||||||
|
|
||||||
if (!shouldBeBackfaceCulled ||
|
if (!shouldBeBackfaceCulled ||
|
||||||
Vector3::shouldBeBackfaceCulled(&t_cameraPos, &calc3Vectors[0], &calc3Vectors[1], &calc3Vectors[2]))
|
!Vector3::shouldBeBackfaceCulled(&t_cameraPos, &calc3Vectors[2], &calc3Vectors[1], &calc3Vectors[0]))
|
||||||
|
{
|
||||||
|
|
||||||
for (u32 vertI = 0; vertI < 3; vertI++)
|
asm volatile(
|
||||||
{
|
// VU0 macro program:
|
||||||
|
// Copy data and set vert/normal "w" and st "z"+"w" to 1.0F
|
||||||
|
|
||||||
if (animState.currentFrame == animState.nextFrame)
|
// Vertex 0
|
||||||
{
|
"lqc2 $vf1, 0x0(%3) \n\t" // load vert
|
||||||
o_vertices[addedFaces][0] = CURR_VERT.x;
|
"lqc2 $vf2, 0x0(%4) \n\t" // load normal
|
||||||
o_vertices[addedFaces][1] = CURR_VERT.y;
|
"lqc2 $vf3, 0x0(%5) \n\t" // load st
|
||||||
o_vertices[addedFaces][2] = CURR_VERT.z;
|
"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
|
||||||
else
|
"vadd.zw $vf3, $vf20, $vf21 \n\t" // set st.zw to 1.0F
|
||||||
{
|
"sqc2 $vf1, 0x0(%0) \n\t" // store vert
|
||||||
o_vertices[addedFaces][0] = calc3Vectors[vertI].x;
|
"sqc2 $vf2, 0x0(%1) \n\t" // store normal
|
||||||
o_vertices[addedFaces][1] = calc3Vectors[vertI].y;
|
"sqc2 $vf3, 0x0(%2) \n\t" // store st
|
||||||
o_vertices[addedFaces][2] = calc3Vectors[vertI].z;
|
|
||||||
}
|
|
||||||
o_vertices[addedFaces][3] = 1.0F;
|
|
||||||
|
|
||||||
o_normals[addedFaces][0] = CURR_NORMAL.x;
|
// Vertex 1
|
||||||
o_normals[addedFaces][1] = CURR_NORMAL.y;
|
"lqc2 $vf1, 0x0(%9) \n\t" // load vert
|
||||||
o_normals[addedFaces][2] = CURR_NORMAL.z;
|
"lqc2 $vf2, 0x0(%10) \n\t" // load normal
|
||||||
o_normals[addedFaces][3] = 1.0F;
|
"lqc2 $vf3, 0x0(%11) \n\t" // load st
|
||||||
|
"vadd.w $vf1, $vf20, $vf21 \n\t" // set vert.w to 1.0F
|
||||||
|
"vadd.w $vf2, $vf20, $vf21 \n\t" // set normal.W to 1.0F
|
||||||
|
"vadd.zw $vf3, $vf20, $vf21 \n\t" // set st.zw to 1.0F
|
||||||
|
"sqc2 $vf1, 0x0(%6) \n\t" // store vert
|
||||||
|
"sqc2 $vf2, 0x0(%7) \n\t" // store normal
|
||||||
|
"sqc2 $vf3, 0x0(%8) \n\t" // store st
|
||||||
|
|
||||||
o_coordinates[addedFaces][0] = CURR_ST.x;
|
// Vertex 2
|
||||||
o_coordinates[addedFaces][1] = CURR_ST.y;
|
"lqc2 $vf1, 0x0(%15) \n\t" // load vert
|
||||||
o_coordinates[addedFaces][2] = 1.0F;
|
"lqc2 $vf2, 0x0(%16) \n\t" // load normal
|
||||||
o_coordinates[addedFaces++][3] = 1.0F;
|
"lqc2 $vf3, 0x0(%17) \n\t" // load st
|
||||||
}
|
"vadd.w $vf1, $vf20, $vf21 \n\t" // set vert.w to 1.0F
|
||||||
|
"vadd.w $vf2, $vf20, $vf21 \n\t" // set normal.W to 1.0F
|
||||||
|
"vadd.zw $vf3, $vf20, $vf21 \n\t" // set st.zw to 1.0F
|
||||||
|
"sqc2 $vf1, 0x0(%12) \n\t" // store vert
|
||||||
|
"sqc2 $vf2, 0x0(%13) \n\t" // store normal
|
||||||
|
"sqc2 $vf3, 0x0(%14) \n\t" // store st
|
||||||
|
|
||||||
|
:
|
||||||
|
: "r"(o_vertices[addedFaces]),
|
||||||
|
"r"(o_normals[addedFaces]),
|
||||||
|
"r"(o_coordinates[addedFaces]),
|
||||||
|
"r"(calc3Vectors[0].xyz),
|
||||||
|
"r"(normals[normalFaces[faceI]].xyz),
|
||||||
|
"r"(sts[stFaces[faceI]].xy),
|
||||||
|
"r"(o_vertices[addedFaces + 1]),
|
||||||
|
"r"(o_normals[addedFaces + 1]),
|
||||||
|
"r"(o_coordinates[addedFaces + 1]),
|
||||||
|
"r"(calc3Vectors[1].xyz),
|
||||||
|
"r"(normals[normalFaces[faceI + 1]].xyz),
|
||||||
|
"r"(sts[stFaces[faceI + 1]].xy),
|
||||||
|
"r"(o_vertices[addedFaces + 2]),
|
||||||
|
"r"(o_normals[addedFaces + 2]),
|
||||||
|
"r"(o_coordinates[addedFaces + 2]),
|
||||||
|
"r"(calc3Vectors[2].xyz),
|
||||||
|
"r"(normals[normalFaces[faceI + 2]].xyz),
|
||||||
|
"r"(sts[stFaces[faceI + 2]].xy));
|
||||||
|
addedFaces += 3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return addedFaces;
|
return addedFaces;
|
||||||
}
|
}
|
||||||
@@ -242,7 +340,7 @@ u8 Mesh::isInFrustum(Plane *t_frustumPlanes)
|
|||||||
{
|
{
|
||||||
Vector3 boxCalcTemp;
|
Vector3 boxCalcTemp;
|
||||||
u8 boxResult = 1, boxIn = 0, boxOut = 0;
|
u8 boxResult = 1, boxIn = 0, boxOut = 0;
|
||||||
Vector3 *currentBoundingBox = getCurrentBoundingBox();
|
const Vector3 *currentBoundingBox = getCurrentBoundingBoxVertices();
|
||||||
for (int i = 0; i < 6; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
boxOut = 0;
|
boxOut = 0;
|
||||||
@@ -270,16 +368,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()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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,16 +27,21 @@ 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;
|
||||||
}
|
}
|
||||||
@@ -45,11 +52,7 @@ MeshFrame::~MeshFrame()
|
|||||||
|
|
||||||
void MeshFrame::allocateSTs(const u32 &t_val)
|
void MeshFrame::allocateSTs(const u32 &t_val)
|
||||||
{
|
{
|
||||||
if (_areSTsAllocated)
|
assertMsg(!_areSTsAllocated, "Can't allocate STs, because were already set!");
|
||||||
{
|
|
||||||
PRINT_ERR("Can't allocate STs, because were already set!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
stsCount = t_val;
|
stsCount = t_val;
|
||||||
sts = new Point[t_val];
|
sts = new Point[t_val];
|
||||||
_areSTsAllocated = true;
|
_areSTsAllocated = true;
|
||||||
@@ -57,11 +60,7 @@ void MeshFrame::allocateSTs(const u32 &t_val)
|
|||||||
|
|
||||||
void MeshFrame::allocateVertices(const u32 &t_val)
|
void MeshFrame::allocateVertices(const u32 &t_val)
|
||||||
{
|
{
|
||||||
if (_areVerticesAllocated)
|
assertMsg(!_areVerticesAllocated, "Can't allocate vertices, because were already set!");
|
||||||
{
|
|
||||||
PRINT_ERR("Can't allocate vertices, because were already set!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
vertexCount = t_val;
|
vertexCount = t_val;
|
||||||
vertices = new Vector3[t_val];
|
vertices = new Vector3[t_val];
|
||||||
_areVerticesAllocated = true;
|
_areVerticesAllocated = true;
|
||||||
@@ -69,11 +68,7 @@ void MeshFrame::allocateVertices(const u32 &t_val)
|
|||||||
|
|
||||||
void MeshFrame::allocateNormals(const u32 &t_val)
|
void MeshFrame::allocateNormals(const u32 &t_val)
|
||||||
{
|
{
|
||||||
if (_areNormalsAllocated)
|
assertMsg(!_areNormalsAllocated, "Can't allocate normals, because were already set!");
|
||||||
{
|
|
||||||
PRINT_ERR("Can't allocate normals, because were already set!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
normalsCount = t_val;
|
normalsCount = t_val;
|
||||||
normals = new Vector3[t_val];
|
normals = new Vector3[t_val];
|
||||||
_areNormalsAllocated = true;
|
_areNormalsAllocated = true;
|
||||||
@@ -81,11 +76,7 @@ void MeshFrame::allocateNormals(const u32 &t_val)
|
|||||||
|
|
||||||
void MeshFrame::allocateMaterials(const u32 &t_val)
|
void MeshFrame::allocateMaterials(const u32 &t_val)
|
||||||
{
|
{
|
||||||
if (_areMaterialsAllocated)
|
assertMsg(!_areMaterialsAllocated, "Can't allocate materials, because were already set!");
|
||||||
{
|
|
||||||
PRINT_ERR("Can't allocate materials, because were already set!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
materialsCount = t_val;
|
materialsCount = t_val;
|
||||||
materials = new MeshMaterial[t_val];
|
materials = new MeshMaterial[t_val];
|
||||||
_areMaterialsAllocated = true;
|
_areMaterialsAllocated = true;
|
||||||
@@ -93,13 +84,10 @@ void MeshFrame::allocateMaterials(const u32 &t_val)
|
|||||||
|
|
||||||
void MeshFrame::calculateBoundingBoxes()
|
void MeshFrame::calculateBoundingBoxes()
|
||||||
{
|
{
|
||||||
if (!_areVerticesAllocated)
|
assertMsg(_areVerticesAllocated, "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;
|
||||||
@@ -121,6 +109,8 @@ void MeshFrame::calculateBoundingBoxes()
|
|||||||
if (hiZ < vertices[i].z)
|
if (hiZ < vertices[i].z)
|
||||||
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);
|
||||||
@@ -131,4 +121,31 @@ void MeshFrame::calculateBoundingBoxes()
|
|||||||
boundingBox[6].set(hiX, hiY, lowZ);
|
boundingBox[6].set(hiX, hiY, lowZ);
|
||||||
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
|
||||||
|
// constructor instantiated BoundingBox objects.
|
||||||
|
boundingBoxObj = new BoundingBox(boundingBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshFrame::copyFrom(MeshFrame *t_refCopy)
|
||||||
|
{
|
||||||
|
vertexCount = t_refCopy->vertexCount;
|
||||||
|
stsCount = t_refCopy->stsCount;
|
||||||
|
normalsCount = t_refCopy->normalsCount;
|
||||||
|
materialsCount = t_refCopy->materialsCount;
|
||||||
|
materials = new MeshMaterial[materialsCount];
|
||||||
|
for (u32 i = 0; i < materialsCount; i++)
|
||||||
|
materials[i].copyFrom(&t_refCopy->materials[i]);
|
||||||
|
_areSTsAllocated = true;
|
||||||
|
_areVerticesAllocated = true;
|
||||||
|
_areNormalsAllocated = true;
|
||||||
|
_areMaterialsAllocated = true;
|
||||||
|
vertices = t_refCopy->vertices;
|
||||||
|
sts = t_refCopy->sts;
|
||||||
|
normals = t_refCopy->normals;
|
||||||
|
|
||||||
|
boundingBoxObj = t_refCopy->boundingBoxObj;
|
||||||
|
_isBoundingBoxCalculated = true;
|
||||||
|
|
||||||
|
_isMother = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../include/models/mesh_material.hpp"
|
#include "../include/models/mesh_material.hpp"
|
||||||
|
#include "../include/models/bounding_box.hpp"
|
||||||
#include "../include/utils/debug.hpp"
|
#include "../include/utils/debug.hpp"
|
||||||
#include "../include/utils/string.hpp"
|
#include "../include/utils/string.hpp"
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
@@ -24,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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
@@ -44,11 +52,7 @@ MeshMaterial::~MeshMaterial()
|
|||||||
|
|
||||||
void MeshMaterial::allocateFaces(const u32 &t_val)
|
void MeshMaterial::allocateFaces(const u32 &t_val)
|
||||||
{
|
{
|
||||||
if (_areFacesAllocated)
|
assertMsg(!_areFacesAllocated, "Can't allocate faces, because were already set!");
|
||||||
{
|
|
||||||
PRINT_ERR("Can't allocate faces, because were already set!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
facesCount = t_val;
|
facesCount = t_val;
|
||||||
stFaces = new u32[t_val];
|
stFaces = new u32[t_val];
|
||||||
normalFaces = new u32[t_val];
|
normalFaces = new u32[t_val];
|
||||||
@@ -58,11 +62,7 @@ void MeshMaterial::allocateFaces(const u32 &t_val)
|
|||||||
|
|
||||||
void MeshMaterial::setName(char *t_val)
|
void MeshMaterial::setName(char *t_val)
|
||||||
{
|
{
|
||||||
if (_isNameSet)
|
assertMsg(!_isNameSet, "Can't set name, because was already set!");
|
||||||
{
|
|
||||||
PRINT_ERR("Can't set name, because was already set!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
name = String::createCopy(t_val);
|
name = String::createCopy(t_val);
|
||||||
_isNameSet = true;
|
_isNameSet = true;
|
||||||
}
|
}
|
||||||
@@ -71,19 +71,20 @@ u8 MeshMaterial::isInFrustum(Plane *t_frustumPlanes, const Vector3 &position)
|
|||||||
{
|
{
|
||||||
Vector3 boxCalcTemp;
|
Vector3 boxCalcTemp;
|
||||||
u8 boxResult = 1, boxIn = 0, boxOut = 0;
|
u8 boxResult = 1, boxIn = 0, boxOut = 0;
|
||||||
for (int i = 0; i < 6; i++)
|
|
||||||
|
for (u8 i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
boxOut = 0;
|
boxOut = 0;
|
||||||
boxIn = 0;
|
boxIn = 0;
|
||||||
// for each corner of the box do ...
|
// for each corner of the box do ...
|
||||||
// get out of the cycle as soon as a box as corners
|
// get out of the cycle as soon as a box as corners
|
||||||
// both inside and out of the frustum
|
// both inside and out of the frustum
|
||||||
for (int y = 0; y < 8 && (boxIn == 0 || boxOut == 0); y++)
|
for (u8 y = 0; y < 8 && (boxIn == 0 || boxOut == 0); y++)
|
||||||
{
|
{
|
||||||
boxCalcTemp.set(
|
boxCalcTemp.set(
|
||||||
boundingBox[y].x + position.x,
|
boundingBoxObj->getVertex(y).x + position.x,
|
||||||
boundingBox[y].y + position.y,
|
boundingBoxObj->getVertex(y).y + position.y,
|
||||||
boundingBox[y].z + position.z);
|
boundingBoxObj->getVertex(y).z + position.z);
|
||||||
if (t_frustumPlanes[i].distanceTo(boxCalcTemp) < 0)
|
if (t_frustumPlanes[i].distanceTo(boxCalcTemp) < 0)
|
||||||
boxOut++;
|
boxOut++;
|
||||||
else
|
else
|
||||||
@@ -121,6 +122,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);
|
||||||
@@ -131,4 +134,37 @@ void MeshMaterial::calculateBoundingBox(Vector3 *t_vertices, u32 t_vertCount)
|
|||||||
boundingBox[6].set(hiX, hiY, lowZ);
|
boundingBox[6].set(hiX, hiY, lowZ);
|
||||||
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
|
||||||
|
// constructor instantiated BoundingBox objects.
|
||||||
|
boundingBoxObj = new BoundingBox(boundingBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshMaterial::copyFrom(MeshMaterial *t_refCopy)
|
||||||
|
{
|
||||||
|
_isNameSet = true;
|
||||||
|
name = t_refCopy->name;
|
||||||
|
|
||||||
|
_isBoundingBoxCalculated = true;
|
||||||
|
boundingBoxObj = t_refCopy->boundingBoxObj;
|
||||||
|
|
||||||
|
vertexFaces = t_refCopy->vertexFaces;
|
||||||
|
stFaces = t_refCopy->stFaces;
|
||||||
|
normalFaces = t_refCopy->normalFaces;
|
||||||
|
facesCount = t_refCopy->facesCount;
|
||||||
|
_areSTsPresent = t_refCopy->_areSTsPresent;
|
||||||
|
_areNormalsPresent = t_refCopy->_areNormalsPresent;
|
||||||
|
_areFacesAllocated = true;
|
||||||
|
|
||||||
|
_isMother = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set's default object color + no transparency */
|
||||||
|
void MeshMaterial::setDefaultColor()
|
||||||
|
{
|
||||||
|
color.r = 0x80;
|
||||||
|
color.g = 0x80;
|
||||||
|
color.b = 0x80;
|
||||||
|
color.a = 0x80;
|
||||||
|
color.q = 1.0F;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../include/models/sprite.hpp"
|
||||||
|
#include "../include/utils/debug.hpp"
|
||||||
|
#include "../include/utils/string.hpp"
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Constructors/Destructors
|
||||||
|
// ----
|
||||||
|
|
||||||
|
Sprite::Sprite()
|
||||||
|
{
|
||||||
|
id = rand() % 1000000;
|
||||||
|
_isSizeSet = false;
|
||||||
|
_flipH = false;
|
||||||
|
_flipV = false;
|
||||||
|
scale = 1.0F;
|
||||||
|
mode = MODE_REPEAT;
|
||||||
|
setDefaultColor();
|
||||||
|
setDefaultLODAndClut();
|
||||||
|
}
|
||||||
|
|
||||||
|
Sprite::~Sprite() {}
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Methods
|
||||||
|
// ----
|
||||||
|
|
||||||
|
/** Set's default object color + no transparency */
|
||||||
|
void Sprite::setDefaultColor()
|
||||||
|
{
|
||||||
|
color.r = 0x80;
|
||||||
|
color.g = 0x80;
|
||||||
|
color.b = 0x80;
|
||||||
|
color.a = 0x80;
|
||||||
|
color.q = 0.0F;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sets texture level of details settings and CLUT settings */
|
||||||
|
void Sprite::setDefaultLODAndClut()
|
||||||
|
{
|
||||||
|
clut.storage_mode = CLUT_STORAGE_MODE1;
|
||||||
|
clut.start = 0;
|
||||||
|
clut.psm = 0;
|
||||||
|
clut.load_method = CLUT_NO_LOAD;
|
||||||
|
clut.address = 0;
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../include/models/mesh_texture.hpp"
|
#include "../include/models/texture.hpp"
|
||||||
#include "../include/utils/string.hpp"
|
#include "../include/utils/string.hpp"
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <draw_sampling.h>
|
#include <draw_sampling.h>
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
// Constructors/Destructors
|
// Constructors/Destructors
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
MeshTexture::MeshTexture()
|
Texture::Texture()
|
||||||
{
|
{
|
||||||
id = rand() % 1000000;
|
id = rand() % 1000000;
|
||||||
_isSizeSet = false;
|
_isSizeSet = false;
|
||||||
@@ -25,7 +25,7 @@ MeshTexture::MeshTexture()
|
|||||||
setDefaultWrapSettings();
|
setDefaultWrapSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
MeshTexture::~MeshTexture()
|
Texture::~Texture()
|
||||||
{
|
{
|
||||||
if (getTextureLinksCount() > 0)
|
if (getTextureLinksCount() > 0)
|
||||||
texLinks.clear();
|
texLinks.clear();
|
||||||
@@ -39,31 +39,25 @@ MeshTexture::~MeshTexture()
|
|||||||
// Methods
|
// Methods
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
void MeshTexture::setSize(const u8 &t_width, const u8 &t_height)
|
void Texture::setSize(const u8 &t_width, const u8 &t_height, const TextureType &t_type)
|
||||||
{
|
{
|
||||||
if (_isSizeSet)
|
assertMsg(!_isSizeSet, "Can't set size, because was already set!");
|
||||||
{
|
assertMsg(t_width <= 256 && t_height <= 256, "Given texture can be too big for PS2. Please strict to 256x256 max. Prefer 128x128.");
|
||||||
PRINT_ERR("Can't set size, because was already set!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
width = t_width;
|
width = t_width;
|
||||||
height = t_height;
|
height = t_height;
|
||||||
|
_type = t_type;
|
||||||
data = new unsigned char[getDataSize()];
|
data = new unsigned char[getDataSize()];
|
||||||
_isSizeSet = true;
|
_isSizeSet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshTexture::setName(char *t_val)
|
void Texture::setName(char *t_val)
|
||||||
{
|
{
|
||||||
if (_isNameSet)
|
assertMsg(!_isNameSet, "Can't set name, because was already set!");
|
||||||
{
|
|
||||||
PRINT_ERR("Can't set name, because was already set!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
name = String::createCopy(t_val);
|
name = String::createCopy(t_val);
|
||||||
_isNameSet = true;
|
_isNameSet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshTexture::setDefaultWrapSettings()
|
void Texture::setDefaultWrapSettings()
|
||||||
{
|
{
|
||||||
wrapSettings.horizontal = WRAP_REPEAT;
|
wrapSettings.horizontal = WRAP_REPEAT;
|
||||||
wrapSettings.vertical = WRAP_REPEAT;
|
wrapSettings.vertical = WRAP_REPEAT;
|
||||||
@@ -73,16 +67,15 @@ void MeshTexture::setDefaultWrapSettings()
|
|||||||
wrapSettings.minv = 0;
|
wrapSettings.minv = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshTexture::setWrapSettings(const WrapSettings t_horizontal, const WrapSettings t_vertical)
|
void Texture::setWrapSettings(const WrapSettings t_horizontal, const WrapSettings t_vertical)
|
||||||
{
|
{
|
||||||
wrapSettings.horizontal = t_horizontal;
|
wrapSettings.horizontal = t_horizontal;
|
||||||
wrapSettings.vertical = t_vertical;
|
wrapSettings.vertical = t_vertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshTexture::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.meshId = t_meshId;
|
|
||||||
texLinks.push_back(link);
|
texLinks.push_back(link);
|
||||||
}
|
}
|
||||||
+241
-181
@@ -9,30 +9,34 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../include/modules/audio.hpp"
|
#include "../include/modules/audio.hpp"
|
||||||
|
|
||||||
#include <loadfile.h>
|
|
||||||
#include "../include/utils/string.hpp"
|
#include "../include/utils/string.hpp"
|
||||||
#include "../include/utils/debug.hpp"
|
#include "../include/utils/debug.hpp"
|
||||||
|
#include <loadfile.h>
|
||||||
#define SONG_NAME "MOV-CIRC.WAV"
|
#include <cstdlib>
|
||||||
const int AUDSRV_BUFFER_SIZE = 1024 * 4;
|
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
// Constructors/Destructors
|
// Constructors/Destructors
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
Audio *audioRef;
|
Audio *audioRef;
|
||||||
|
|
||||||
Audio::Audio()
|
Audio::Audio()
|
||||||
{
|
{
|
||||||
addedListeners = 0;
|
// We must set it to 0 on songStop();
|
||||||
isInitialized = 0;
|
realVolume = 100;
|
||||||
songLoaded = 0;
|
volume = 100;
|
||||||
isVolumeSet = 0;
|
chunkReadStatus = 0;
|
||||||
shouldPlay = 0;
|
|
||||||
|
songLoaded = false;
|
||||||
|
songPlaying = false;
|
||||||
|
songInLoop = false;
|
||||||
|
songFinished = false;
|
||||||
|
|
||||||
audioRef = this;
|
audioRef = this;
|
||||||
initSema();
|
initSema();
|
||||||
loadModules();
|
loadModules();
|
||||||
initAUDSRV();
|
initAUDSRV();
|
||||||
|
setSongFormat();
|
||||||
}
|
}
|
||||||
|
|
||||||
Audio::~Audio() {}
|
Audio::~Audio() {}
|
||||||
@@ -41,208 +45,264 @@ Audio::~Audio() {}
|
|||||||
// Methods
|
// Methods
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
/** Initialize audio module
|
void Audio::loadSong(char *t_path)
|
||||||
*
|
{
|
||||||
* - Initialize threading semaphore
|
if (songLoaded)
|
||||||
* - Load modules
|
unloadSong();
|
||||||
* - Initialize AUDSRV
|
char *fullFilename = String::createConcatenated("host:", t_path);
|
||||||
* - Load background song
|
wav = fopen(fullFilename, "rb");
|
||||||
|
delete[] fullFilename;
|
||||||
|
assertMsg(wav != NULL, "Failed to open wav file!");
|
||||||
|
rewindSongToStart();
|
||||||
|
songLoaded = true;
|
||||||
|
consoleLog("Song loaded!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Audio::playSong()
|
||||||
|
{
|
||||||
|
assertMsg(songLoaded, "Cant play song because was not loaded!");
|
||||||
|
if (songFinished)
|
||||||
|
rewindSongToStart();
|
||||||
|
volume = realVolume;
|
||||||
|
songPlaying = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Audio::stopSong()
|
||||||
|
{
|
||||||
|
volume = 0;
|
||||||
|
audsrv_set_volume(volume);
|
||||||
|
songPlaying = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Audio::setSongVolume(const u8 &t_vol)
|
||||||
|
{
|
||||||
|
realVolume = t_vol;
|
||||||
|
if (songPlaying)
|
||||||
|
volume = t_vol;
|
||||||
|
audsrv_set_volume(volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 Audio::addSongListener(AudioListener *t_listener)
|
||||||
|
{
|
||||||
|
AudioListenerRef *ref = new AudioListenerRef;
|
||||||
|
ref->id = rand() % 1000000;
|
||||||
|
ref->listener = t_listener;
|
||||||
|
songListeners.push_back(ref);
|
||||||
|
return ref->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Audio::removeSongListener(const u32 &t_id)
|
||||||
|
{
|
||||||
|
s32 index = -1;
|
||||||
|
for (u32 i = 0; i < songListeners.size(); i++)
|
||||||
|
if (songListeners[i]->id == t_id)
|
||||||
|
{
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
assertMsg(index != -1, "Cant remove listener because given id was not found!");
|
||||||
|
delete songListeners[index];
|
||||||
|
songListeners.erase(songListeners.begin() + index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ADPCM
|
||||||
|
|
||||||
|
audsrv_adpcm_t *Audio::loadADPCM(char *t_path)
|
||||||
|
{
|
||||||
|
char *fullFilename = String::createConcatenated("host:", t_path);
|
||||||
|
FILE *file = fopen(fullFilename, "rb");
|
||||||
|
delete[] fullFilename;
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
u32 adpcmFileSize = ftell(file);
|
||||||
|
u8 data[adpcmFileSize];
|
||||||
|
rewind(file);
|
||||||
|
fread(data, sizeof(u8), adpcmFileSize, file);
|
||||||
|
audsrv_adpcm_t *result = new audsrv_adpcm_t();
|
||||||
|
result->size = 0;
|
||||||
|
result->buffer = 0;
|
||||||
|
result->loop = 0;
|
||||||
|
result->pitch = 0;
|
||||||
|
result->channels = 0;
|
||||||
|
if (audsrv_load_adpcm(result, data, adpcmFileSize))
|
||||||
|
{
|
||||||
|
printf("AUDSRV returned error string: %s", audsrv_get_error_string());
|
||||||
|
assertMsg(true == false, "audsrv_load_adpcm() failed!");
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Audio::playADPCM(audsrv_adpcm_t *t_adpcm)
|
||||||
|
{
|
||||||
|
if (audsrv_play_adpcm(t_adpcm))
|
||||||
|
{
|
||||||
|
printf("AUDSRV returned error string: %s", audsrv_get_error_string());
|
||||||
|
assertMsg(true == false, "audsrv_play_adpcm() failed!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Audio::playADPCM(audsrv_adpcm_t *t_adpcm, const s8 &t_ch)
|
||||||
|
{
|
||||||
|
if (audsrv_ch_play_adpcm(t_ch, t_adpcm))
|
||||||
|
{
|
||||||
|
printf("AUDSRV returned error string: %s", audsrv_get_error_string());
|
||||||
|
assertMsg(true == false, "audsrv_ch_play_adpcm() failed!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Other
|
||||||
|
|
||||||
|
void Audio::startThread(FileService *t_fileService)
|
||||||
|
{
|
||||||
|
consoleLog("Creating audio thread");
|
||||||
|
// fileService = t_fileService;
|
||||||
|
extern void *_gp;
|
||||||
|
thread.func = (void *)Audio::mainThread;
|
||||||
|
thread.stack = threadStack;
|
||||||
|
thread.stack_size = getThreadStackSize();
|
||||||
|
thread.gp_reg = (void *)&_gp;
|
||||||
|
thread.initial_priority = 0x17;
|
||||||
|
threadId = CreateThread(&thread);
|
||||||
|
assertMsg(threadId >= 0, "Create audio thread failed!");
|
||||||
|
consoleLog("Audio thread created");
|
||||||
|
StartThread(threadId, NULL);
|
||||||
|
consoleLog("Audio thread started");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Main thread loop */
|
||||||
|
void Audio::threadLoop()
|
||||||
|
{
|
||||||
|
// ---
|
||||||
|
// TODO - bug here, GCC11 is doing some optimizations and this method probably think that
|
||||||
|
// "songPlaying" is false + on real PS2 I see that program tries to turn on this
|
||||||
|
// method as rarely as possible (slow, flickering sound). On GCC 3.2.3 this one was fine lol!.
|
||||||
|
if (songPlaying) // HACK1 - im not proud of that
|
||||||
|
songPlaying = 1;
|
||||||
|
if (songLoaded)
|
||||||
|
songLoaded = 1;
|
||||||
|
if (hack == 1) // HACK2 - lets give some work to gcc lol
|
||||||
|
hack = 2;
|
||||||
|
else
|
||||||
|
hack = 1;
|
||||||
|
// ---
|
||||||
|
|
||||||
|
if (!songPlaying || !songLoaded)
|
||||||
|
return;
|
||||||
|
if (songFinished)
|
||||||
|
{
|
||||||
|
printf("Audio: Song finished. ");
|
||||||
|
if (songInLoop)
|
||||||
|
{
|
||||||
|
printf("Running again.\n");
|
||||||
|
for (u32 i = 0; i < getSongListenersCount(); i++)
|
||||||
|
songListeners[i]->listener->onAudioFinish();
|
||||||
|
rewindSongToStart();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Stopping song.\n");
|
||||||
|
stopSong();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chunkReadStatus > 0)
|
||||||
|
{
|
||||||
|
WaitSema(fillbufferSema); // wait until previous chunk wasn't finished
|
||||||
|
audsrv_play_audio(wavChunk, chunkReadStatus);
|
||||||
|
for (u32 i = 0; i < getSongListenersCount(); i++)
|
||||||
|
songListeners[i]->listener->onAudioTick();
|
||||||
|
}
|
||||||
|
|
||||||
|
chunkReadStatus = fread(wavChunk, 1, sizeof(wavChunk), wav);
|
||||||
|
|
||||||
|
if (chunkReadStatus < (s32)sizeof(wavChunk))
|
||||||
|
songFinished = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close file.
|
||||||
|
* Delete song path from memory.
|
||||||
*/
|
*/
|
||||||
void Audio::init(u32 t_listenersAmount)
|
void Audio::unloadSong()
|
||||||
{
|
{
|
||||||
PRINT_LOG("Initialize audio module started");
|
songLoaded = false;
|
||||||
listenersAmount = t_listenersAmount;
|
fclose(wav);
|
||||||
listeners = new AudioListener *[t_listenersAmount];
|
|
||||||
isInitialized = true;
|
|
||||||
PRINT_LOG("Audio module initialized!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Audio::addListener(AudioListener *t_listener)
|
/** Set WAV format to 16bit, 22050Hz, stereo. */
|
||||||
|
void Audio::setSongFormat()
|
||||||
{
|
{
|
||||||
listeners[addedListeners++] = t_listener;
|
format.bits = 16;
|
||||||
|
format.freq = 22050;
|
||||||
|
format.channels = 2;
|
||||||
|
audsrv_set_format(&format);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Initialize threading semaphore */
|
/** Fseek on wav. */
|
||||||
|
void Audio::rewindSongToStart()
|
||||||
|
{
|
||||||
|
if (wav != NULL)
|
||||||
|
fseek(wav, 0x30, SEEK_SET);
|
||||||
|
songFinished = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Initialize semaphore which will wait until chunk of the song is not finished. */
|
||||||
void Audio::initSema()
|
void Audio::initSema()
|
||||||
{
|
{
|
||||||
PRINT_LOG("Creating semaphore started");
|
consoleLog("Creating audio semaphore");
|
||||||
sema.init_count = 0;
|
sema.init_count = 0;
|
||||||
sema.max_count = 1;
|
sema.max_count = 1;
|
||||||
sema.option = 0;
|
sema.option = 0;
|
||||||
fillbufferSema = CreateSema(&sema);
|
fillbufferSema = CreateSema(&sema);
|
||||||
PRINT_LOG("Semaphore created");
|
consoleLog("Audio semaphore created");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Load LIBSD and AUDSRV */
|
/** Load LIBSD and AUDSRV modules */
|
||||||
void Audio::loadModules()
|
void Audio::loadModules()
|
||||||
{
|
{
|
||||||
PRINT_LOG("Modules loading started (LIBSD, AUDSRV)");
|
consoleLog("Modules loading started (LIBSD, AUDSRV)");
|
||||||
ret = SifLoadModule("rom0:LIBSD", 0, NULL);
|
int ret = SifLoadModule("rom0:LIBSD", 0, NULL);
|
||||||
|
assertMsg(ret != -203, "LIBSD loading failed!");
|
||||||
ret = SifLoadModule("host:AUDSRV.IRX", 0, NULL);
|
ret = SifLoadModule("host:AUDSRV.IRX", 0, NULL);
|
||||||
PRINT_LOG("Modules loaded");
|
assertMsg(ret != -203, "AUDSRV.IRX loading failed!");
|
||||||
|
consoleLog("Audio modules loaded");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Initialize AUDSRV and install fillbuffer callback */
|
/**
|
||||||
|
* Initialize AUDSRV main and ADPCM module.
|
||||||
|
* Install AUDSRV callback.
|
||||||
|
*/
|
||||||
void Audio::initAUDSRV()
|
void Audio::initAUDSRV()
|
||||||
{
|
{
|
||||||
PRINT_LOG("Initialize AUDSRV started");
|
consoleLog("Initializing AUDSRV");
|
||||||
ret = audsrv_init();
|
int ret = audsrv_init();
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
{
|
{
|
||||||
PRINT_ERR("Failed to initialize AUDSRV!");
|
|
||||||
printf("AUDSRV returned error string: %s", audsrv_get_error_string());
|
printf("AUDSRV returned error string: %s", audsrv_get_error_string());
|
||||||
|
assertMsg(true == false, "Failed to initialize AUDSRV!");
|
||||||
}
|
}
|
||||||
else
|
ret = audsrv_adpcm_init();
|
||||||
|
if (ret != 0)
|
||||||
{
|
{
|
||||||
ret = audsrv_on_fillbuf(AUDSRV_BUFFER_SIZE, Audio::fillbuffer, (void *)fillbufferSema);
|
|
||||||
PRINT_LOG("AUDSRV initialized!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set audio format, volume and load song */
|
|
||||||
void Audio::loadSong(char *t_filename)
|
|
||||||
{
|
|
||||||
if (!isInitialized)
|
|
||||||
{
|
|
||||||
PRINT_ERR("Please initialize audio class first!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
PRINT_LOG("Song loading started");
|
|
||||||
format.bits = 16;
|
|
||||||
format.freq = 22050;
|
|
||||||
format.channels = 2;
|
|
||||||
char *fullFilename = String::createConcatenated("host:", t_filename);
|
|
||||||
int err = audsrv_set_format(&format);
|
|
||||||
if (err == 0)
|
|
||||||
{
|
|
||||||
PRINT_LOG("Audio format set");
|
|
||||||
if (!isVolumeSet)
|
|
||||||
setVolume(MAX_VOLUME);
|
|
||||||
PRINT_LOG("Opening song file: " SONG_NAME);
|
|
||||||
wav = fopen(fullFilename, "rb");
|
|
||||||
delete[] fullFilename;
|
|
||||||
if (wav == NULL)
|
|
||||||
{
|
|
||||||
PRINT_ERR("Failed to open wav file!");
|
|
||||||
audsrv_quit();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fseek(wav, 0x30, SEEK_SET);
|
|
||||||
played = 0;
|
|
||||||
songLoaded = 1;
|
|
||||||
PRINT_LOG("Song loaded!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PRINT_ERR("Failed to set audio format!");
|
|
||||||
printf("AUDSRV returned error string: %s", audsrv_get_error_string());
|
printf("AUDSRV returned error string: %s", audsrv_get_error_string());
|
||||||
|
assertMsg(true == false, "Failed to initialize AUDSRV ADPCM!");
|
||||||
}
|
}
|
||||||
|
ret = audsrv_on_fillbuf(getSongBufferSize(), (audsrv_callback_t)iSignalSema, (void *)fillbufferSema);
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
printf("AUDSRV returned error string: %s", audsrv_get_error_string());
|
||||||
|
assertMsg(true == false, "Failed to initialize AUDSRV fillbuffer!");
|
||||||
|
}
|
||||||
|
consoleLog("AUDSRV initialized!");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Audio::setVolume(u8 t_volume)
|
/**
|
||||||
{
|
* Do not call this function.
|
||||||
audsrv_set_volume(t_volume);
|
* This is a audio thread, runned by engine
|
||||||
isVolumeSet = true;
|
*/
|
||||||
}
|
void Audio::mainThread()
|
||||||
|
|
||||||
/** Create and start audio thread. */
|
|
||||||
void Audio::startThread()
|
|
||||||
{
|
|
||||||
PRINT_LOG("Creating audio thread");
|
|
||||||
extern void *_gp;
|
|
||||||
audioThreadAttr.func = (void *)Audio::audioThread;
|
|
||||||
audioThreadAttr.stack = audioThreadStack;
|
|
||||||
audioThreadAttr.stack_size = STACK_SIZE;
|
|
||||||
audioThreadAttr.gp_reg = (void *)&_gp;
|
|
||||||
audioThreadAttr.initial_priority = 0x17;
|
|
||||||
if ((audioThreadId = CreateThread(&audioThreadAttr)) < 0)
|
|
||||||
PRINT_ERR("Create audio thread failed!");
|
|
||||||
PRINT_LOG("Audio thread created");
|
|
||||||
StartThread(audioThreadId, NULL);
|
|
||||||
PRINT_LOG("Audio thread started");
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Do not call this function.
|
|
||||||
* This is a audio thread, runned by AudioThread::start()
|
|
||||||
*/
|
|
||||||
void Audio::audioThread()
|
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
audioRef->threadLoop();
|
||||||
if (audioRef->shouldPlay)
|
|
||||||
audioRef->work();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Audio::play()
|
|
||||||
{
|
|
||||||
if (!isInitialized)
|
|
||||||
{
|
|
||||||
PRINT_ERR("Please initialize audio class first!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
shouldPlay = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Audio::stop()
|
|
||||||
{
|
|
||||||
if (!isInitialized)
|
|
||||||
{
|
|
||||||
PRINT_ERR("Please initialize audio class first!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
shouldPlay = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Play song and run it again on finish */
|
|
||||||
void Audio::work()
|
|
||||||
{
|
|
||||||
if (!isTrackDone)
|
|
||||||
{
|
|
||||||
ret = fread(chunk, 1, sizeof(chunk), wav);
|
|
||||||
if (ret > 0)
|
|
||||||
{
|
|
||||||
WaitSema(fillbufferSema);
|
|
||||||
audsrv_play_audio(chunk, ret);
|
|
||||||
}
|
|
||||||
if (ret < (int)sizeof(chunk))
|
|
||||||
{
|
|
||||||
isTrackDone = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
played++;
|
|
||||||
if ((played + 20) % 41 == 0 && addedListeners)
|
|
||||||
for (u32 i = 0; i < addedListeners; i++)
|
|
||||||
listeners[i]->onAudioTick();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PRINT_LOG("Song " SONG_NAME " finished. Running again...");
|
|
||||||
played = 0;
|
|
||||||
fseek(wav, 0x30, SEEK_SET);
|
|
||||||
isTrackDone = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Unload audio module by closing file stream and stopping AUDSRV */
|
|
||||||
void Audio::unloadSong()
|
|
||||||
{
|
|
||||||
PRINT_LOG("Unloading audio module started");
|
|
||||||
fclose(wav);
|
|
||||||
PRINT_LOG("Song file stream closed");
|
|
||||||
audsrv_quit();
|
|
||||||
PRINT_LOG("AUDSRV stopped");
|
|
||||||
PRINT_LOG("Audio module unloaded");
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Do not call this function.
|
|
||||||
* This is a static callback function
|
|
||||||
* for AUDSRV fillbuffer (semaphore)
|
|
||||||
*/
|
|
||||||
int Audio::fillbuffer(void *arg)
|
|
||||||
{
|
|
||||||
iSignalSema((int)arg);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,14 +18,10 @@
|
|||||||
// Constructors/Destructors
|
// Constructors/Destructors
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
/** Initializes vars and calculate width/height of near and far plane
|
CameraBase::CameraBase(ScreenSettings *t_screen, Vector3 *t_position)
|
||||||
* @param fov (FOV in radians)/2
|
|
||||||
* @param ratio Aspect ratio
|
|
||||||
*/
|
|
||||||
CameraBase::CameraBase(ScreenSettings *t_screen, Vector3 *t_position, Vector3 *t_up, Vector3 *t_unitCirclePosition)
|
|
||||||
: screen(t_screen)
|
: screen(t_screen)
|
||||||
{
|
{
|
||||||
PRINT_LOG("Initializing frustum");
|
consoleLog("Initializing frustum");
|
||||||
farPlaneDist = screen->farPlaneDist;
|
farPlaneDist = screen->farPlaneDist;
|
||||||
nearPlaneDist = screen->nearPlaneDist;
|
nearPlaneDist = screen->nearPlaneDist;
|
||||||
float tang = tanf(screen->fov * Math::HALF_ANG2RAD);
|
float tang = tanf(screen->fov * Math::HALF_ANG2RAD);
|
||||||
@@ -33,33 +29,35 @@ CameraBase::CameraBase(ScreenSettings *t_screen, Vector3 *t_position, Vector3 *t
|
|||||||
nearWidth = nearHeight * screen->aspectRatio;
|
nearWidth = nearHeight * screen->aspectRatio;
|
||||||
farHeight = tang * farPlaneDist;
|
farHeight = tang * farPlaneDist;
|
||||||
farWidth = farHeight * screen->aspectRatio;
|
farWidth = farHeight * screen->aspectRatio;
|
||||||
position2 = t_position;
|
p_position = t_position;
|
||||||
up2 = t_up;
|
up.set(0.0F, 1.0F, 0.0F);
|
||||||
unitCirclePosition2 = t_unitCirclePosition;
|
consoleLog("CameraBase initialized!");
|
||||||
PRINT_LOG("CameraBase initialized!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
// Methods
|
// Methods
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
/** Calculates and updates frustum planes
|
void CameraBase::lookAt(Vector3 &t_target)
|
||||||
* http://www.lighthouse3d.com/tutorials/view-frustum-culling/geometric-approach-extracting-the-planes/
|
{
|
||||||
*/
|
updatePlanes(t_target);
|
||||||
|
view.lookAt(*p_position, t_target);
|
||||||
|
}
|
||||||
|
|
||||||
void CameraBase::updatePlanes(Vector3 t_target)
|
void CameraBase::updatePlanes(Vector3 t_target)
|
||||||
{
|
{
|
||||||
Vector3 nearCenter, farCenter, X, Y, Z;
|
Vector3 nearCenter, farCenter, X, Y, Z;
|
||||||
// compute the Z axis of camera
|
// compute the Z axis of camera
|
||||||
Z = *position2 - 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 = *up2 * 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;
|
||||||
// compute the center of the near and far planes
|
// compute the center of the near and far planes
|
||||||
nearCenter = *position2 - Z * nearPlaneDist;
|
nearCenter = *p_position - Z * nearPlaneDist;
|
||||||
farCenter = *position2 - Z * farPlaneDist;
|
farCenter = *p_position - Z * farPlaneDist;
|
||||||
// compute the 8 corners of the frustum
|
// compute the 8 corners of the frustum
|
||||||
ntl = nearCenter + Y * nearHeight - X * nearWidth;
|
ntl = nearCenter + Y * nearHeight - X * nearWidth;
|
||||||
ntr = nearCenter + Y * nearHeight + X * nearWidth;
|
ntr = nearCenter + Y * nearHeight + X * nearWidth;
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../include/modules/file_service.hpp"
|
||||||
|
#include "../include/utils/string.hpp"
|
||||||
|
#include "../include/utils/debug.hpp"
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Constructors/Destructors
|
||||||
|
// ----
|
||||||
|
|
||||||
|
FileService *fsRef;
|
||||||
|
|
||||||
|
FileService::FileService() {}
|
||||||
|
|
||||||
|
FileService::~FileService() {}
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Methods
|
||||||
|
// ----
|
||||||
|
|
||||||
|
u32 FileService::addReadChunk(FILE *t_file, void *t_destination, const u32 &t_size, const u32 &t_n)
|
||||||
|
{
|
||||||
|
FileServiceTask task;
|
||||||
|
task.id = rand() % 1000000;
|
||||||
|
task.file = t_file;
|
||||||
|
task.destination = t_destination;
|
||||||
|
task.size = t_size;
|
||||||
|
task.n = t_n;
|
||||||
|
task.readStatus = -2137;
|
||||||
|
tasks.push_back(task);
|
||||||
|
return task.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 FileService::isTaskDone(const u32 &t_taskId)
|
||||||
|
{
|
||||||
|
s32 taskIndex = getIndexOf(t_taskId);
|
||||||
|
assertMsg(taskIndex != -1, "Task was not found!");
|
||||||
|
s32 result = tasks[taskIndex].readStatus;
|
||||||
|
if (result != -2137)
|
||||||
|
removeByIndex(taskIndex);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const void FileService::removeById(const u32 &t_taskId)
|
||||||
|
{
|
||||||
|
s32 index = getIndexOf(t_taskId);
|
||||||
|
assertMsg(index != -1, "Cant remove task, because it was not found!");
|
||||||
|
removeByIndex(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
const s32 FileService::getIndexOf(const u32 &t_taskId)
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < tasks.size(); i++)
|
||||||
|
if (tasks[i].id == t_taskId)
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Other
|
||||||
|
|
||||||
|
void FileService::startThread()
|
||||||
|
{
|
||||||
|
consoleLog("Creating file service thread");
|
||||||
|
extern void *_gp;
|
||||||
|
thread.func = (void *)FileService::mainThread;
|
||||||
|
thread.stack = threadStack;
|
||||||
|
thread.stack_size = getThreadStackSize();
|
||||||
|
thread.gp_reg = (void *)&_gp;
|
||||||
|
thread.initial_priority = 0x12;
|
||||||
|
threadId = CreateThread(&thread);
|
||||||
|
assertMsg(threadId >= 0, "Create audio thread failed!");
|
||||||
|
consoleLog("File service created");
|
||||||
|
StartThread(threadId, NULL);
|
||||||
|
consoleLog("File service started");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Main thread loop */
|
||||||
|
void FileService::threadLoop()
|
||||||
|
{
|
||||||
|
// This will cause an error
|
||||||
|
// printf("\n\n\n\n\nsize:%d\n", tasks.size());
|
||||||
|
// for (size_t i = 0; i < tasks.size(); i++)
|
||||||
|
// {
|
||||||
|
// switch (tasks[i].type)
|
||||||
|
// {
|
||||||
|
// case ReadChunk:
|
||||||
|
// tasks[i].readStatus = fread(tasks[i].destination, tasks[i].n, tasks[i].size, tasks[i].file);
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// default:
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
SleepThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not call this function.
|
||||||
|
* This is an file service thread, runned by engine
|
||||||
|
*/
|
||||||
|
void FileService::mainThread()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
fsRef->threadLoop();
|
||||||
|
}
|
||||||
@@ -12,7 +12,8 @@
|
|||||||
|
|
||||||
#include "../include/utils/math.hpp"
|
#include "../include/utils/math.hpp"
|
||||||
#include "../include/utils/debug.hpp"
|
#include "../include/utils/debug.hpp"
|
||||||
#include "../include/modules/light.hpp"
|
#include <packet2_chain.h>
|
||||||
|
#include <kernel.h>
|
||||||
#include <dma.h>
|
#include <dma.h>
|
||||||
#include <draw.h>
|
#include <draw.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -27,20 +28,21 @@
|
|||||||
/** Initializes vars and creates data transfer packets
|
/** Initializes vars and creates data transfer packets
|
||||||
* @param packetSize Size of data packet, should be increased when more data will be rendered
|
* @param packetSize Size of data packet, should be increased when more data will be rendered
|
||||||
*/
|
*/
|
||||||
GifSender::GifSender(u32 t_packetSize, ScreenSettings *t_screen) : screen(t_screen)
|
GifSender::GifSender(u32 t_packetSize, ScreenSettings *t_screen, Light *t_light) : screen(t_screen)
|
||||||
{
|
{
|
||||||
PRINT_LOG("Initializing GifSender");
|
consoleLog("Initializing GifSender");
|
||||||
|
light = t_light;
|
||||||
packetSize = t_packetSize;
|
packetSize = t_packetSize;
|
||||||
packets[0] = packet_init(t_packetSize, PACKET_NORMAL);
|
packets[0] = packet2_create(t_packetSize, P2_TYPE_NORMAL, P2_MODE_CHAIN, false);
|
||||||
packets[1] = packet_init(t_packetSize, PACKET_NORMAL);
|
packets[1] = packet2_create(t_packetSize, P2_TYPE_NORMAL, P2_MODE_CHAIN, false);
|
||||||
PRINT_LOG("GifSender initialized!");
|
consoleLog("GifSender initialized!");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Releases packets memory */
|
/** Releases packets memory */
|
||||||
GifSender::~GifSender()
|
GifSender::~GifSender()
|
||||||
{
|
{
|
||||||
packet_free(packets[0]);
|
packet2_free(packets[0]);
|
||||||
packet_free(packets[1]);
|
packet2_free(packets[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
@@ -51,37 +53,45 @@ GifSender::~GifSender()
|
|||||||
#include <gs_gp.h>
|
#include <gs_gp.h>
|
||||||
|
|
||||||
/** Send texture via GIF */
|
/** Send texture via GIF */
|
||||||
void GifSender::sendTexture(MeshTexture &texture, texbuffer_t *t_texBuffer)
|
void GifSender::sendTexture(Texture &texture, texbuffer_t *t_texBuffer)
|
||||||
{
|
{
|
||||||
const u16 packetSize = 40;
|
packet2_t *packet2 = packet2_create(15, P2_TYPE_NORMAL, P2_MODE_CHAIN, false);
|
||||||
packet_t *packet = packet_init(packetSize, PACKET_NORMAL);
|
packet2_update(
|
||||||
qword_t *q = packet->data;
|
packet2,
|
||||||
q = draw_texture_transfer(q, texture.getData(), texture.getWidth(), texture.getHeight(), GS_PSM_24, t_texBuffer->address, t_texBuffer->width);
|
draw_texture_transfer(
|
||||||
DMATAG_CNT(q, 2, 0, 0, 0);
|
packet2->base,
|
||||||
q++;
|
texture.getData(),
|
||||||
q = draw_texture_wrapping(q, 0, texture.getWrapSettings());
|
texture.getWidth(),
|
||||||
q = draw_texture_flush(q);
|
texture.getHeight(),
|
||||||
dma_channel_send_chain(DMA_CHANNEL_GIF, packet->data, q - packet->data, 0, 0);
|
texture.getType(),
|
||||||
dma_wait_fast();
|
t_texBuffer->address,
|
||||||
packet_free(packet);
|
t_texBuffer->width));
|
||||||
|
packet2_chain_open_cnt(packet2, 0, 0, 0);
|
||||||
|
packet2_update(packet2, draw_texture_wrapping(packet2->next, 0, texture.getWrapSettings()));
|
||||||
|
packet2_chain_close_tag(packet2);
|
||||||
|
packet2_update(packet2, draw_texture_flush(packet2->next));
|
||||||
|
dma_channel_wait(DMA_CHANNEL_GIF, 0);
|
||||||
|
dma_channel_send_packet2(packet2, DMA_CHANNEL_GIF, true);
|
||||||
|
dma_channel_wait(DMA_CHANNEL_GIF, 0);
|
||||||
|
packet2_free(packet2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GifSender::sendClear(zbuffer_t *t_zBuffer)
|
void GifSender::sendClear(zbuffer_t *t_zBuffer, color_t *t_rgb)
|
||||||
{
|
{
|
||||||
packet_t *packet = packet_init(100, PACKET_NORMAL);
|
packet2_t *packet2 = packet2_create(36, P2_TYPE_NORMAL, P2_MODE_CHAIN, false);
|
||||||
qword_t *q = packet->data;
|
packet2_chain_open_end(packet2, 0, 0);
|
||||||
q++;
|
packet2_update(packet2, draw_disable_tests(packet2->next, 0, t_zBuffer));
|
||||||
q = draw_disable_tests(q, 0, t_zBuffer);
|
packet2_update(packet2, draw_clear(packet2->next, 0,
|
||||||
q = draw_clear(q, 0,
|
2048.0F - (screen->width / 2), 2048.0F - (screen->height / 2),
|
||||||
2048.0F - (screen->width / 2), 2048.0F - (screen->height / 2),
|
screen->width, screen->height,
|
||||||
screen->width, screen->height,
|
t_rgb->r, t_rgb->g, t_rgb->b));
|
||||||
0x10, 0x10, 0x10);
|
packet2_update(packet2, draw_enable_tests(packet2->next, 0, t_zBuffer));
|
||||||
q = draw_enable_tests(q, 0, t_zBuffer);
|
packet2_update(packet2, draw_finish(packet2->next));
|
||||||
q = draw_finish(q);
|
packet2_chain_close_tag(packet2);
|
||||||
DMATAG_END(packet->data, q - packet->data - 1, 0, 0, 0);
|
dma_channel_wait(DMA_CHANNEL_GIF, 0);
|
||||||
dma_channel_send_chain(DMA_CHANNEL_GIF, packet->data, q - packet->data, 0, 0);
|
dma_channel_send_packet2(packet2, DMA_CHANNEL_GIF, true);
|
||||||
dma_wait_fast();
|
dma_channel_wait(DMA_CHANNEL_GIF, 0);
|
||||||
packet_free(packet);
|
packet2_free(packet2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Used in game loop.
|
/** Used in game loop.
|
||||||
@@ -90,12 +100,8 @@ void GifSender::sendClear(zbuffer_t *t_zBuffer)
|
|||||||
void GifSender::initPacket(u8 t_context)
|
void GifSender::initPacket(u8 t_context)
|
||||||
{
|
{
|
||||||
currentPacket = packets[t_context];
|
currentPacket = packets[t_context];
|
||||||
if (currentPacket->qwords > (u32)packetSize || currentPacket->qwords < 0)
|
packet2_reset(currentPacket, false);
|
||||||
PRINT_ERR("GifSender packet size error. Please consider to change packet size!\n");
|
isAnyObjectAdded = false;
|
||||||
q = currentPacket->data;
|
|
||||||
dmatag = q;
|
|
||||||
q++;
|
|
||||||
isAnyObjectAdded = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sends packet to GIF. */
|
/** Sends packet to GIF. */
|
||||||
@@ -103,71 +109,50 @@ void GifSender::sendPacket()
|
|||||||
{
|
{
|
||||||
if (isAnyObjectAdded)
|
if (isAnyObjectAdded)
|
||||||
{
|
{
|
||||||
dmatag = q;
|
packet2_chain_open_end(currentPacket, 0, 0);
|
||||||
q++;
|
packet2_update(currentPacket, draw_finish(currentPacket->next));
|
||||||
|
packet2_chain_close_tag(currentPacket);
|
||||||
}
|
}
|
||||||
q = draw_finish(q);
|
dma_channel_wait(DMA_CHANNEL_GIF, 0);
|
||||||
DMATAG_END(dmatag, q - dmatag - 1, 0, 0, 0);
|
dma_channel_send_packet2(currentPacket, DMA_CHANNEL_GIF, true);
|
||||||
dma_wait_fast();
|
|
||||||
dma_channel_send_chain(DMA_CHANNEL_GIF, currentPacket->data, q - currentPacket->data, 0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Adds clear screen to current packet */
|
/** Adds clear screen to current packet */
|
||||||
void GifSender::addClear(zbuffer_t *t_zBuffer)
|
void GifSender::addClear(zbuffer_t *t_zBuffer, color_t *t_rgb)
|
||||||
{
|
{
|
||||||
q = draw_disable_tests(q, 0, t_zBuffer);
|
packet2_chain_open_cnt(currentPacket, 0, 0, 0);
|
||||||
q = draw_clear(q, 0,
|
packet2_update(currentPacket, draw_disable_tests(currentPacket->next, 0, t_zBuffer));
|
||||||
2048.0F - (screen->width / 2), 2048.0F - (screen->height / 2),
|
packet2_update(currentPacket, draw_clear(currentPacket->next, 0,
|
||||||
screen->width, screen->height,
|
2048.0F - (screen->width / 2), 2048.0F - (screen->height / 2),
|
||||||
0x10, 0x10, 0x10);
|
screen->width, screen->height,
|
||||||
q = draw_enable_tests(q, 0, t_zBuffer);
|
t_rgb->r, t_rgb->g, t_rgb->b));
|
||||||
|
packet2_update(currentPacket, draw_enable_tests(currentPacket->next, 0, t_zBuffer));
|
||||||
|
packet2_chain_close_tag(currentPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Adds 3D objects to current packet
|
/** 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)
|
|
||||||
{
|
{
|
||||||
if (!isAnyObjectAdded)
|
packet2_chain_open_cnt(currentPacket, 0, 0, 0);
|
||||||
{
|
packet2_update(currentPacket, draw_texture_sampling(currentPacket->next, 0, &t_mesh.lod));
|
||||||
isAnyObjectAdded = true;
|
packet2_update(currentPacket, draw_texturebuffer(currentPacket->next, 0, textureBuffer, &t_mesh.clut));
|
||||||
DMATAG_CNT(dmatag, q - dmatag - 1, 0, 0, 0); // init tag (before first 3d obj)
|
packet2_update(currentPacket, draw_prim_start(currentPacket->next, 0, t_renderData->prim, t_color));
|
||||||
}
|
|
||||||
qword_t *tempDMATag;
|
|
||||||
tempDMATag = q;
|
|
||||||
q++;
|
|
||||||
|
|
||||||
q = draw_texture_sampling(q, 0, &t_mesh->lod);
|
|
||||||
q = draw_texturebuffer(q, 0, textureBuffer, &t_mesh->clut);
|
|
||||||
dw = (u64 *)draw_prim_start(q, 0, t_renderData->prim, &t_mesh->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;
|
||||||
delete[] st;
|
delete[] st;
|
||||||
|
packet2_update(currentPacket, draw_prim_end(currentPacket->next, 3, DRAW_STQ_REGLIST));
|
||||||
if ((u32)dw % 16) // if we are in the middle of qw, switch packet
|
packet2_chain_close_tag(currentPacket);
|
||||||
*dw++ = 0;
|
|
||||||
|
|
||||||
q = draw_prim_end((qword_t *)dw, 3, DRAW_STQ_REGLIST);
|
|
||||||
|
|
||||||
DMATAG_CNT(tempDMATag, q - tempDMATag - 1, 0, 0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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;
|
||||||
@@ -183,11 +168,11 @@ 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)
|
||||||
{
|
{
|
||||||
const u16 lightsCount = Light::getLightsCount(t_bulbsCount);
|
const u16 lightsCount = light->getLightsCount(t_bulbsCount);
|
||||||
VECTOR *lightDirections = new VECTOR[lightsCount];
|
VECTOR *lightDirections = new VECTOR[lightsCount];
|
||||||
VECTOR *lightColors = new VECTOR[lightsCount];
|
VECTOR *lightColors = new VECTOR[lightsCount];
|
||||||
int *lightTypes = new int[lightsCount];
|
int *lightTypes = new int[lightsCount];
|
||||||
@@ -195,17 +180,17 @@ void GifSender::calc3DObject(Matrix t_perspective, Mesh &t_mesh, u32 vertexCount
|
|||||||
VECTOR *lights = new VECTOR[vertexCount];
|
VECTOR *lights = new VECTOR[vertexCount];
|
||||||
calculate_normals(normals, vertexCount, normals, localLight);
|
calculate_normals(normals, vertexCount, normals, localLight);
|
||||||
|
|
||||||
Light::calculateLight(lightDirections, lightColors, lightTypes, t_bulbs, t_bulbsCount, t_mesh.position);
|
light->calculateLight(lightDirections, lightColors, lightTypes, t_bulbs, lightsCount, t_mesh.position);
|
||||||
|
|
||||||
calculate_lights(lights, vertexCount, normals, lightDirections, lightColors, lightTypes, lightsCount);
|
calculate_lights(lights, vertexCount, normals, lightDirections, lightColors, lightTypes, lightsCount);
|
||||||
|
|
||||||
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] / 128.0F);
|
colors[i][0] = (t_color->r * lights[i][0]);
|
||||||
colors[i][1] = (t_mesh.color.g * lights[i][1] / 128.0F);
|
colors[i][1] = (t_color->g * lights[i][1]);
|
||||||
colors[i][2] = (t_mesh.color.b * lights[i][2] / 128.0F);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] lightDirections;
|
delete[] lightDirections;
|
||||||
@@ -216,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;
|
||||||
}
|
}
|
||||||
@@ -262,8 +247,9 @@ void GifSender::addCurrentCalcs(u32 &t_vertexCount)
|
|||||||
{
|
{
|
||||||
for (u32 i = 0; i < t_vertexCount; i++)
|
for (u32 i = 0; i < t_vertexCount; i++)
|
||||||
{
|
{
|
||||||
*dw++ = rgbaq[i].rgbaq;
|
packet2_add_u64(currentPacket, rgbaq[i].rgbaq);
|
||||||
*dw++ = st[i].uv;
|
packet2_add_u64(currentPacket, st[i].uv);
|
||||||
*dw++ = xyz[i].xyz;
|
packet2_add_u64(currentPacket, xyz[i].xyz);
|
||||||
}
|
}
|
||||||
|
packet2_pad128(currentPacket, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,11 +23,15 @@ Light::~Light() {}
|
|||||||
// ----
|
// ----
|
||||||
|
|
||||||
const u8 ADDITIONAL_LIGHTS = 1; // Ambient
|
const u8 ADDITIONAL_LIGHTS = 1; // Ambient
|
||||||
|
const float LIGHT_MAX = 255.0F;
|
||||||
|
const float LIGHT_DIS_MOD = 4.0F;
|
||||||
|
|
||||||
|
void Light::setAmbientLight(const Vector3 &t_rgb) { ambientLight.set(t_rgb); }
|
||||||
|
|
||||||
u16 Light::getLightsCount(u32 t_bulbsCount) { return t_bulbsCount + ADDITIONAL_LIGHTS; }
|
u16 Light::getLightsCount(u32 t_bulbsCount) { return t_bulbsCount + ADDITIONAL_LIGHTS; }
|
||||||
|
|
||||||
/** Calculates lighting. Used in gifSender in object 3D calculations */
|
/** Calculates lighting. Used in gifSender in object 3D calculations */
|
||||||
void Light::calculateLight(VECTOR *t_lightDirections, VECTOR *t_lightColors, int *t_lightTypes, LightBulb *t_bulbs, u32 t_bulbsCount, Vector3 t_objPosition)
|
void Light::calculateLight(VECTOR *t_lightDirections, VECTOR *t_lightColors, int *t_lightTypes, LightBulb *t_bulbs, u32 t_lightsCount, Vector3 t_objPosition)
|
||||||
{
|
{
|
||||||
// --- Ambient light
|
// --- Ambient light
|
||||||
|
|
||||||
@@ -38,34 +42,37 @@ void Light::calculateLight(VECTOR *t_lightDirections, VECTOR *t_lightColors, int
|
|||||||
t_lightDirections[0][2] = 0.0F;
|
t_lightDirections[0][2] = 0.0F;
|
||||||
t_lightDirections[0][3] = 1.0F;
|
t_lightDirections[0][3] = 1.0F;
|
||||||
|
|
||||||
t_lightColors[0][0] = 0.0F;
|
t_lightColors[0][0] = ambientLight.x;
|
||||||
t_lightColors[0][1] = 0.0F;
|
t_lightColors[0][1] = ambientLight.y;
|
||||||
t_lightColors[0][2] = 0.0F;
|
t_lightColors[0][2] = ambientLight.z;
|
||||||
t_lightColors[0][3] = 1.0F;
|
t_lightColors[0][3] = 1.0F;
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
for (u8 i = 0; i < t_bulbsCount; i++)
|
for (u8 i = 1; i < t_lightsCount; i++)
|
||||||
{
|
{
|
||||||
t_lightTypes[i + 1] = LIGHT_DIRECTIONAL;
|
t_lightTypes[i] = LIGHT_DIRECTIONAL;
|
||||||
|
|
||||||
Vector3 newLight = Vector3(t_objPosition.x - t_bulbs[i].position.x,
|
|
||||||
t_objPosition.y - t_bulbs[i].position.y,
|
|
||||||
t_objPosition.z - t_bulbs[i].position.z);
|
|
||||||
|
|
||||||
|
Vector3 newLight = Vector3(t_objPosition.x - t_bulbs[i - 1].position.x,
|
||||||
|
t_objPosition.y - t_bulbs[i - 1].position.y,
|
||||||
|
t_objPosition.z - t_bulbs[i - 1].position.z);
|
||||||
newLight.normalize();
|
newLight.normalize();
|
||||||
newLight = newLight *
|
t_lightDirections[i][0] = newLight.x;
|
||||||
(.1F +
|
t_lightDirections[i][1] = newLight.y;
|
||||||
(t_bulbs[i].intensity / t_bulbs[i].position.distanceTo(t_objPosition)));
|
t_lightDirections[i][2] = newLight.z;
|
||||||
|
t_lightDirections[i][3] = 1.0F;
|
||||||
|
|
||||||
t_lightDirections[i + 1][0] = newLight.x;
|
// Intensity range 0.0F - 1.0F
|
||||||
t_lightDirections[i + 1][1] = newLight.y;
|
float intensity = t_bulbs[i - 1].intensity / LIGHT_MAX;
|
||||||
t_lightDirections[i + 1][2] = newLight.z;
|
// Distance range 0.0F - LIGHT_MAX * LIGHT_DIS_MOD (1020.0F at this time)
|
||||||
t_lightDirections[i + 1][3] = 1.0F;
|
float distance = t_bulbs[i - 1].position.distanceTo(t_objPosition);
|
||||||
|
// printf("Distance:%f\n", distance);
|
||||||
t_lightColors[i + 1][0] = 0.8F;
|
distance = distance > (LIGHT_MAX - LIGHT_DIS_MOD) * LIGHT_DIS_MOD ? LIGHT_MAX - LIGHT_DIS_MOD : distance;
|
||||||
t_lightColors[i + 1][1] = 0.8F;
|
intensity /= 1.0F + (distance / LIGHT_DIS_MOD); // intensity /= 1.0F - 251.0F
|
||||||
t_lightColors[i + 1][2] = 0.8F;
|
intensity /= 3.0F; // it looks better
|
||||||
t_lightColors[i + 1][3] = 1.0F;
|
t_lightColors[i][0] = intensity;
|
||||||
|
t_lightColors[i][1] = intensity;
|
||||||
|
t_lightColors[i][2] = intensity;
|
||||||
|
t_lightColors[i][3] = 1.0F;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-33
@@ -30,15 +30,10 @@ Pad::Pad()
|
|||||||
this->slot = 0; // Always zero if not using multitap
|
this->slot = 0; // Always zero if not using multitap
|
||||||
if ((this->ret = padPortOpen(this->port, this->slot, padBuf)) == 0)
|
if ((this->ret = padPortOpen(this->port, this->slot, padBuf)) == 0)
|
||||||
{
|
{
|
||||||
PRINT_ERR("padPortOpen failed!");
|
|
||||||
printf("padPortOpen returned: %d\n", this->ret);
|
printf("padPortOpen returned: %d\n", this->ret);
|
||||||
SleepThread();
|
assertMsg(true == false, "padPortOpen failed!");
|
||||||
}
|
|
||||||
if (!this->initPad())
|
|
||||||
{
|
|
||||||
PRINT_ERR("initPad failed!");
|
|
||||||
SleepThread();
|
|
||||||
}
|
}
|
||||||
|
assertMsg(this->initPad(), "initPad failed!");
|
||||||
}
|
}
|
||||||
|
|
||||||
Pad::~Pad() {}
|
Pad::~Pad() {}
|
||||||
@@ -50,22 +45,20 @@ Pad::~Pad() {}
|
|||||||
/** Load SIO2MAN and PADMAN modules */
|
/** Load SIO2MAN and PADMAN modules */
|
||||||
void Pad::loadModules()
|
void Pad::loadModules()
|
||||||
{
|
{
|
||||||
PRINT_LOG("Loading pad modules");
|
consoleLog("Loading pad modules");
|
||||||
this->ret = SifLoadModule("rom0:SIO2MAN", 0, NULL);
|
this->ret = SifLoadModule("rom0:SIO2MAN", 0, NULL);
|
||||||
if (this->ret < 0)
|
if (this->ret < 0)
|
||||||
{
|
{
|
||||||
PRINT_ERR("SifLoadModule (SIO2MAN) failed!");
|
|
||||||
printf("SifLoadModule returned: %d\n", this->ret);
|
printf("SifLoadModule returned: %d\n", this->ret);
|
||||||
SleepThread();
|
assertMsg(true == false, "SifLoadModule (SIO2MAN) failed!");
|
||||||
}
|
}
|
||||||
this->ret = SifLoadModule("rom0:PADMAN", 0, NULL);
|
this->ret = SifLoadModule("rom0:PADMAN", 0, NULL);
|
||||||
if (this->ret < 0)
|
if (this->ret < 0)
|
||||||
{
|
{
|
||||||
PRINT_ERR("SifLoadModule (PADMAN) failed!");
|
|
||||||
printf("SifLoadModule returned: %d\n", this->ret);
|
printf("SifLoadModule returned: %d\n", this->ret);
|
||||||
SleepThread();
|
assertMsg(true == false, "SifLoadModule (PADMAN) failed!");
|
||||||
}
|
}
|
||||||
PRINT_LOG("Pad modules loaded!");
|
consoleLog("Pad modules loaded!");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Wait when pad will be ready (stable and ready) */
|
/** Wait when pad will be ready (stable and ready) */
|
||||||
@@ -81,7 +74,7 @@ int Pad::waitPadReady()
|
|||||||
if (state != lastState)
|
if (state != lastState)
|
||||||
{
|
{
|
||||||
padStateInt2String(state, stateString);
|
padStateInt2String(state, stateString);
|
||||||
PRINT_LOG("Pad state changed");
|
consoleLog("Pad state changed");
|
||||||
printf("Curent pad(%d,%d) status: %s\n", this->port, this->slot, stateString);
|
printf("Curent pad(%d,%d) status: %s\n", this->port, this->slot, stateString);
|
||||||
}
|
}
|
||||||
lastState = state;
|
lastState = state;
|
||||||
@@ -89,23 +82,20 @@ int Pad::waitPadReady()
|
|||||||
}
|
}
|
||||||
// Were the pad ever 'out of sync'?
|
// Were the pad ever 'out of sync'?
|
||||||
if (lastState != -1)
|
if (lastState != -1)
|
||||||
PRINT_LOG("Pad is ready!");
|
consoleLog("Pad is ready!");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Initializes and checks type of pad */
|
/** Initializes and checks type of pad */
|
||||||
int Pad::initPad()
|
int Pad::initPad()
|
||||||
{
|
{
|
||||||
PRINT_LOG("Initializing pad");
|
consoleLog("Initializing pad");
|
||||||
this->waitPadReady();
|
this->waitPadReady();
|
||||||
// How many different modes can this device operate in?
|
// How many different modes can this device operate in?
|
||||||
// i.e. get # entrys in the modetable
|
// i.e. get # entrys in the modetable
|
||||||
int modes = padInfoMode(this->port, this->slot, PAD_MODETABLE, -1);
|
int modes = padInfoMode(this->port, this->slot, PAD_MODETABLE, -1);
|
||||||
if (modes == 0)
|
assertMsg(modes, "Connected device is not a dual shock controller!"); // (it has no actuator engines)
|
||||||
{
|
|
||||||
PRINT_ERR("Connected device is not a dual shock controller!"); // (it has no actuator engines)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
// Verify that the controller has a DUAL SHOCK mode
|
// Verify that the controller has a DUAL SHOCK mode
|
||||||
int i = 0;
|
int i = 0;
|
||||||
do
|
do
|
||||||
@@ -115,22 +105,14 @@ int Pad::initPad()
|
|||||||
i++;
|
i++;
|
||||||
} while (i < modes);
|
} while (i < modes);
|
||||||
|
|
||||||
if (i >= modes)
|
assertMsg(i < modes, "Connected device is not a dual shock controller!");
|
||||||
{
|
|
||||||
PRINT_ERR("Connected device is not a dual shock controller!");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If ExId != 0x0 => This controller has actuator engines
|
// If ExId != 0x0 => This controller has actuator engines
|
||||||
// This check should always pass if the Dual Shock test above passed
|
// This check should always pass if the Dual Shock test above passed
|
||||||
this->ret = padInfoMode(this->port, this->slot, PAD_MODECUREXID, 0);
|
this->ret = padInfoMode(this->port, this->slot, PAD_MODECUREXID, 0);
|
||||||
if (this->ret == 0)
|
assertMsg(this->ret, "Connected device is not a dual shock controller!");
|
||||||
{
|
|
||||||
PRINT_ERR("Connected device is not a dual shock controller!");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
PRINT_LOG("Enabling dual shock functions.");
|
consoleLog("Enabling dual shock functions.");
|
||||||
|
|
||||||
// When using MMODE_LOCK, user cant change mode with Select button
|
// When using MMODE_LOCK, user cant change mode with Select button
|
||||||
padSetMainMode(this->port, this->slot, PAD_MMODE_DUALSHOCK, PAD_MMODE_LOCK);
|
padSetMainMode(this->port, this->slot, PAD_MMODE_DUALSHOCK, PAD_MMODE_LOCK);
|
||||||
@@ -156,7 +138,7 @@ int Pad::initPad()
|
|||||||
else
|
else
|
||||||
printf("Did not find any actuators.\n");
|
printf("Did not find any actuators.\n");
|
||||||
this->waitPadReady();
|
this->waitPadReady();
|
||||||
PRINT_LOG("Pad initialized!");
|
consoleLog("Pad initialized!");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+213
-127
@@ -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
|
||||||
@@ -32,22 +33,27 @@
|
|||||||
*/
|
*/
|
||||||
Renderer::Renderer(u32 t_packetSize, ScreenSettings *t_screen)
|
Renderer::Renderer(u32 t_packetSize, ScreenSettings *t_screen)
|
||||||
{
|
{
|
||||||
PRINT_LOG("Initializing renderer");
|
consoleLog("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;
|
||||||
isFrameEmpty = false;
|
isFrameEmpty = false;
|
||||||
lastTextureId = 0;
|
lastTextureId = 0;
|
||||||
flipPacket = packet_init(3, PACKET_UCAB); // Uncached accelerated
|
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();
|
||||||
gifSender = new GifSender(t_packetSize, t_screen);
|
worldColor.r = 0x10;
|
||||||
vifSender = new VifSender();
|
worldColor.g = 0x10;
|
||||||
|
worldColor.b = 0x10;
|
||||||
|
gifSender = new GifSender(t_packetSize, t_screen, &light);
|
||||||
|
vifSender = new VifSender(&light);
|
||||||
perspective.setPerspective(*t_screen);
|
perspective.setPerspective(*t_screen);
|
||||||
renderData.perspective = &perspective;
|
renderData.projection = &perspective;
|
||||||
PRINT_LOG("Renderer initialized!");
|
consoleLog("Renderer initialized!");
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer::~Renderer() {}
|
Renderer::~Renderer() {}
|
||||||
@@ -57,16 +63,15 @@ Renderer::~Renderer() {}
|
|||||||
// ----
|
// ----
|
||||||
|
|
||||||
/** Configure and allocate vRAM for texture buffer */
|
/** Configure and allocate vRAM for texture buffer */
|
||||||
void Renderer::allocateTextureBuffer(u16 t_width, u16 t_height)
|
void Renderer::allocateTextureBuffer(Texture *t_texture)
|
||||||
{
|
{
|
||||||
textureBuffer.width = t_width;
|
textureBuffer.width = t_texture->getWidth();
|
||||||
textureBuffer.psm = GS_PSM_24;
|
textureBuffer.psm = t_texture->getType();
|
||||||
textureBuffer.address = graph_vram_allocate(t_width, t_height, GS_PSM_24, GRAPH_ALIGN_BLOCK);
|
textureBuffer.info.components = textureBuffer.psm == TEX_TYPE_RGBA ? TEXTURE_COMPONENTS_RGBA : TEXTURE_COMPONENTS_RGB;
|
||||||
if (textureBuffer.address <= 1)
|
textureBuffer.address = graph_vram_allocate(t_texture->getWidth(), t_texture->getHeight(), textureBuffer.psm, GRAPH_ALIGN_BLOCK);
|
||||||
PRINT_ERR("Texture buffer allocation error. No memory!");
|
assertMsg(textureBuffer.address > 1, "Texture buffer allocation error. No memory!");
|
||||||
textureBuffer.info.width = draw_log2(t_width);
|
textureBuffer.info.width = draw_log2(t_texture->getWidth());
|
||||||
textureBuffer.info.height = draw_log2(t_height);
|
textureBuffer.info.height = draw_log2(t_texture->getHeight());
|
||||||
textureBuffer.info.components = TEXTURE_COMPONENTS_RGB;
|
|
||||||
textureBuffer.info.function = TEXTURE_FUNCTION_MODULATE;
|
textureBuffer.info.function = TEXTURE_FUNCTION_MODULATE;
|
||||||
isTextureVRAMAllocated = true;
|
isTextureVRAMAllocated = true;
|
||||||
}
|
}
|
||||||
@@ -81,40 +86,90 @@ void Renderer::deallocateTextureBuffer()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::changeTexture(Mesh *t_mesh, u32 t_materialId)
|
void Renderer::changeTexture(Texture *t_tex)
|
||||||
{
|
{
|
||||||
|
assertMsg(t_tex != NULL, "Texture was not found in texture repository!");
|
||||||
MeshTexture *tex = textureRepo.getByMesh(t_mesh->getId(), t_materialId);
|
if (t_tex->getId() != lastTextureId)
|
||||||
if (tex != NULL)
|
|
||||||
{
|
{
|
||||||
if (tex->getId() != lastTextureId)
|
lastTextureId = t_tex->getId();
|
||||||
{
|
deallocateTextureBuffer();
|
||||||
lastTextureId = tex->getId();
|
allocateTextureBuffer(t_tex);
|
||||||
deallocateTextureBuffer();
|
GifSender::sendTexture(*t_tex, &textureBuffer);
|
||||||
allocateTextureBuffer(tex->getWidth(), tex->getHeight());
|
}
|
||||||
GifSender::sendTexture(*tex, &textureBuffer);
|
}
|
||||||
}
|
|
||||||
|
void Renderer::draw(Sprite &t_sprite)
|
||||||
|
{
|
||||||
|
Texture *texture = textureRepo.getBySpriteOrMesh(t_sprite.getId());
|
||||||
|
texrect_t rect;
|
||||||
|
float sizeX, sizeY;
|
||||||
|
if (t_sprite.getMode() == MODE_REPEAT)
|
||||||
|
{
|
||||||
|
sizeX = t_sprite.size.x;
|
||||||
|
sizeY = t_sprite.size.y;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
PRINT_ERR("Texture was not found in texture repository!");
|
{
|
||||||
|
sizeX = (float)texture->getWidth();
|
||||||
|
sizeY = (float)texture->getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
float texS, texT;
|
||||||
|
float texMax = texT = texS = sizeX > sizeY ? sizeX : sizeY;
|
||||||
|
if (sizeX > sizeY)
|
||||||
|
texT = texMax / (sizeX / sizeY);
|
||||||
|
else if (sizeY > sizeX)
|
||||||
|
texS = texMax / (sizeY / sizeX);
|
||||||
|
rect.t0.s = t_sprite.isFlippedHorizontally() ? texS : 0.0F;
|
||||||
|
rect.t0.t = t_sprite.isFlippedVertically() ? texT : 0.0F;
|
||||||
|
rect.t1.s = t_sprite.isFlippedHorizontally() ? 0.0F : texS;
|
||||||
|
rect.t1.t = t_sprite.isFlippedVertically() ? 0.0F : texT;
|
||||||
|
rect.color.r = t_sprite.color.r;
|
||||||
|
rect.color.g = t_sprite.color.g;
|
||||||
|
rect.color.b = t_sprite.color.b;
|
||||||
|
rect.color.a = t_sprite.color.a;
|
||||||
|
rect.color.q = 0;
|
||||||
|
rect.v0.x = t_sprite.position.x;
|
||||||
|
rect.v0.y = t_sprite.position.y;
|
||||||
|
rect.v0.z = (u32)-1;
|
||||||
|
rect.v1.x = (t_sprite.size.x * t_sprite.scale) + t_sprite.position.x;
|
||||||
|
rect.v1.y = (t_sprite.size.y * t_sprite.scale) + t_sprite.position.y;
|
||||||
|
rect.v1.z = (u32)-1;
|
||||||
|
beginFrameIfNeeded();
|
||||||
|
changeTexture(texture);
|
||||||
|
packet2_t *packet2 = packet2_create(12, P2_TYPE_NORMAL, P2_MODE_NORMAL, 0);
|
||||||
|
packet2_update(packet2, draw_primitive_xyoffset(packet2->next, 0, SCREEN_CENTER, SCREEN_CENTER));
|
||||||
|
packet2_utils_gif_add_set(packet2, 1);
|
||||||
|
packet2_utils_gs_add_texbuff_clut(packet2, &textureBuffer, &t_sprite.clut);
|
||||||
|
draw_enable_blending();
|
||||||
|
packet2_update(packet2, draw_rect_textured(packet2->next, 0, &rect));
|
||||||
|
packet2_update(packet2,
|
||||||
|
draw_primitive_xyoffset(
|
||||||
|
packet2->next,
|
||||||
|
0,
|
||||||
|
SCREEN_CENTER - (screen->width / 2.0F),
|
||||||
|
SCREEN_CENTER - (screen->height / 2.0F)));
|
||||||
|
draw_disable_blending();
|
||||||
|
packet2_update(packet2, draw_finish(packet2->next));
|
||||||
|
dma_channel_wait(DMA_CHANNEL_GIF, 0);
|
||||||
|
dma_channel_send_packet2(packet2, DMA_CHANNEL_GIF, true);
|
||||||
|
packet2_free(packet2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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");
|
consoleLog("Initializing drawing environment");
|
||||||
packet_t *packet = packet_init(20, PACKET_NORMAL);
|
packet2_t *packet2 = packet2_create(20, P2_TYPE_NORMAL, P2_MODE_NORMAL, 0);
|
||||||
u16 halfW = (u16)t_screenW / 2;
|
packet2_update(packet2, draw_setup_environment(packet2->base, 0, frameBuffers, &(zBuffer)));
|
||||||
u16 halfH = (u16)t_screenH / 2;
|
packet2_update(packet2, draw_primitive_xyoffset(packet2->next, 0,
|
||||||
qword_t *q = packet->data; // Generic qword pointer.
|
SCREEN_CENTER - (screen->width / 2.0F),
|
||||||
q = draw_setup_environment(q, 0, frameBuffers, &(zBuffer));
|
SCREEN_CENTER - (screen->height / 2.0F)));
|
||||||
q = draw_primitive_xyoffset(q, 0, (2048 - halfW), (2048 - halfH));
|
packet2_update(packet2, draw_finish(packet2->next));
|
||||||
q = draw_finish(q);
|
dma_channel_send_packet2(packet2, DMA_CHANNEL_GIF, true);
|
||||||
// Now send the packet, no need to wait since it's the first.
|
dma_channel_wait(DMA_CHANNEL_GIF, 0);
|
||||||
dma_channel_send_normal(DMA_CHANNEL_GIF, packet->data, q - packet->data, 0, 0);
|
packet2_free(packet2);
|
||||||
dma_wait_fast();
|
consoleLog("Drawing environment initialized!");
|
||||||
packet_free(packet);
|
|
||||||
PRINT_LOG("Drawing environment initialized!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sets drawing prim for all 3D objects */
|
/** Sets drawing prim for all 3D objects */
|
||||||
@@ -129,124 +184,157 @@ void Renderer::setPrim()
|
|||||||
prim.mapping_type = PRIM_MAP_ST;
|
prim.mapping_type = PRIM_MAP_ST;
|
||||||
prim.colorfix = PRIM_UNFIXED;
|
prim.colorfix = PRIM_UNFIXED;
|
||||||
renderData.prim = &prim;
|
renderData.prim = &prim;
|
||||||
PRINT_LOG("Prim set!");
|
consoleLog("Prim set!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::setWorldColor(const color_t &t_rgb)
|
||||||
|
{
|
||||||
|
worldColor.r = t_rgb.r;
|
||||||
|
worldColor.g = t_rgb.g;
|
||||||
|
worldColor.b = t_rgb.b;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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_32;
|
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_32;
|
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_32;
|
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!");
|
consoleLog("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
|
||||||
|
|
||||||
/** PATH3 Many + lighting */
|
// Obsolete
|
||||||
void Renderer::drawByPath3(Mesh **t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount)
|
// void Renderer::drawByPath3(Mesh *t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount)
|
||||||
{
|
// {
|
||||||
for (u16 i = 0; i < t_amount; i++)
|
// for (u16 i = 0; i < t_amount; i++)
|
||||||
drawByPath3(t_meshes[i], t_bulbs, t_bulbsCount);
|
// drawByPath3(t_meshes[i], t_bulbs, t_bulbsCount);
|
||||||
}
|
// }
|
||||||
|
|
||||||
/** PATH3 Single + lighting */
|
// Obsolete
|
||||||
void Renderer::drawByPath3(Mesh *t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount)
|
// void Renderer::drawByPath3(Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount)
|
||||||
{
|
// {
|
||||||
beginFrameIfNeeded();
|
// beginFrameIfNeeded();
|
||||||
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!");
|
||||||
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);
|
||||||
return;
|
// if (t_mesh.shouldBeFrustumCulled && !material->isInFrustum(renderData.frustumPlanes, t_mesh.position))
|
||||||
changeTexture(t_mesh, t_mesh->getMaterial(i).getId());
|
// 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;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
/** PATH3 Many */
|
// Obsolete
|
||||||
void Renderer::drawByPath3(Mesh **t_meshes, u16 t_amount) { drawByPath3(t_meshes, t_amount, NULL, 0); }
|
// void Renderer::drawByPath3(Mesh *t_meshes, u16 t_amount) { drawByPath3(t_meshes, t_amount, NULL, 0); }
|
||||||
|
|
||||||
/** PATH3 Single */
|
// Obsolete
|
||||||
void Renderer::drawByPath3(Mesh *t_mesh) { drawByPath3(t_mesh, NULL, 0); }
|
// void Renderer::drawByPath3(Mesh &t_mesh) { drawByPath3(t_mesh, NULL, 0); }
|
||||||
|
|
||||||
/// --- Draw: PATH1
|
/// --- Draw: PATH1
|
||||||
|
|
||||||
/** PATH1 Many + lighting */
|
|
||||||
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);
|
assertMsg(t_meshes[0]->isDataLoaded(), "Can't draw, because no mesh data was loaded!");
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** PATH1 Single + lighting */
|
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())
|
assertMsg(t_mesh.isDataLoaded(), "Can't draw, because no mesh data was loaded!");
|
||||||
PRINT_ERR("Can't draw, because no mesh data was loaded!");
|
camRotation.identity();
|
||||||
|
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 *vertices = new VECTOR[vertCount];
|
VECTOR vertices[vertCount] __attribute__((aligned(16)));
|
||||||
VECTOR *normals = new VECTOR[vertCount];
|
VECTOR normals[vertCount] __attribute__((aligned(16)));
|
||||||
VECTOR *coordinates = new VECTOR[vertCount];
|
VECTOR coordinates[vertCount] __attribute__((aligned(16)));
|
||||||
changeTexture(t_mesh, t_mesh->getMaterial(i).getId());
|
Texture *tex = textureRepo.getBySpriteOrMesh(material->getId());
|
||||||
vertCount = t_mesh->getDrawData(i, vertices, normals, coordinates, *renderData.cameraPosition);
|
changeTexture(tex);
|
||||||
vifSender->drawMesh(&renderData, perspective, vertCount, vertices, normals, coordinates, t_mesh, t_bulbs, t_bulbsCount, &textureBuffer);
|
vertCount = t_mesh.getDrawData(i, vertices, normals, coordinates, rotatedCamera);
|
||||||
delete[] vertices;
|
vifSender->drawMesh(&renderData, perspective, vertCount, vertices, normals, coordinates, t_mesh, t_bulbs, t_bulbsCount, &textureBuffer, &material->color, !material->areSTsPresent());
|
||||||
delete[] normals;
|
|
||||||
delete[] coordinates;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** PATH1 Many */
|
void Renderer::draw(Mesh **t_meshes, u16 t_amount) { draw(t_meshes, t_amount, NULL, 0); }
|
||||||
void Renderer::draw(Mesh **t_objects3D, u16 t_amount) { draw(t_objects3D, t_amount, NULL, 0); }
|
|
||||||
|
|
||||||
/** PATH1 Single */
|
void Renderer::draw(Mesh &t_mesh) { draw(t_mesh, NULL, 0); }
|
||||||
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;
|
||||||
}
|
}
|
||||||
@@ -256,7 +344,7 @@ void Renderer::beginFrameIfNeeded()
|
|||||||
if (isFrameEmpty)
|
if (isFrameEmpty)
|
||||||
{
|
{
|
||||||
isFrameEmpty = false;
|
isFrameEmpty = false;
|
||||||
gifSender->sendClear(&zBuffer);
|
gifSender->sendClear(&zBuffer, &worldColor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,7 +352,7 @@ void Renderer::endFrame(float fps)
|
|||||||
{
|
{
|
||||||
if (!isFrameEmpty)
|
if (!isFrameEmpty)
|
||||||
{
|
{
|
||||||
if (fps > 49.0F)
|
if (fps > 49.0F && isVSyncEnabled)
|
||||||
graph_wait_vsync();
|
graph_wait_vsync();
|
||||||
flipBuffers();
|
flipBuffers();
|
||||||
}
|
}
|
||||||
@@ -284,10 +372,8 @@ void Renderer::flipBuffers()
|
|||||||
0);
|
0);
|
||||||
context ^= 1;
|
context ^= 1;
|
||||||
isFrameEmpty = 1;
|
isFrameEmpty = 1;
|
||||||
qword_t *q = flipPacket->data;
|
packet2_update(flipPacket, draw_framebuffer(flipPacket->base, 0, &frameBuffers[context]));
|
||||||
q = draw_framebuffer(q, 0, &frameBuffers[context]);
|
packet2_update(flipPacket, draw_finish(flipPacket->next));
|
||||||
q = draw_finish(q);
|
dma_channel_send_packet2(flipPacket, DMA_CHANNEL_GIF, true);
|
||||||
dma_wait_fast();
|
|
||||||
dma_channel_send_normal_ucab(DMA_CHANNEL_GIF, flipPacket->data, q - flipPacket->data, 0);
|
|
||||||
draw_wait_finish();
|
draw_wait_finish();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,8 @@
|
|||||||
|
|
||||||
TextureRepository::TextureRepository()
|
TextureRepository::TextureRepository()
|
||||||
{
|
{
|
||||||
PRINT_LOG("Initializing texture repository");
|
consoleLog("Initializing texture repository");
|
||||||
PRINT_LOG("Texture repository initialized!");
|
consoleLog("Texture repository initialized!");
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureRepository::~TextureRepository()
|
TextureRepository::~TextureRepository()
|
||||||
@@ -35,23 +35,29 @@ TextureRepository::~TextureRepository()
|
|||||||
// Methods
|
// Methods
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
MeshTexture *TextureRepository::add(char *t_subfolder, char *t_name)
|
Texture *TextureRepository::add(char *t_subfolder, char *t_name, TextureFormat t_format)
|
||||||
{
|
{
|
||||||
MeshTexture *texture = new MeshTexture();
|
Texture *texture = new Texture();
|
||||||
loader.load(*texture, t_subfolder, t_name, ".bmp");
|
if (t_format == BMP)
|
||||||
|
bmpLoader.load(*texture, t_subfolder, t_name, ".bmp");
|
||||||
|
else
|
||||||
|
pngLoader.load(*texture, t_subfolder, t_name, ".png");
|
||||||
texture->setName(t_name);
|
texture->setName(t_name);
|
||||||
textures.push_back(texture);
|
textures.push_back(texture);
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureRepository::addByMesh(char *t_path, Mesh &mesh)
|
void TextureRepository::addByMesh(char *t_path, Mesh &mesh, TextureFormat t_format)
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < mesh.getMaterialsCount(); i++)
|
for (u32 i = 0; i < mesh.getMaterialsCount(); i++)
|
||||||
{
|
{
|
||||||
MeshTexture *texture = new MeshTexture();
|
Texture *texture = new Texture();
|
||||||
loader.load(*texture, t_path, mesh.getMaterial(i).getName(), ".bmp");
|
if (t_format == BMP)
|
||||||
|
bmpLoader.load(*texture, t_path, mesh.getMaterial(i).getName(), ".bmp");
|
||||||
|
else
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,16 +10,11 @@
|
|||||||
|
|
||||||
#include "../include/modules/timer.hpp"
|
#include "../include/modules/timer.hpp"
|
||||||
|
|
||||||
#include <timer.h>
|
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
// Constructors/Destructors
|
// Constructors/Destructors
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
Timer::Timer()
|
Timer::Timer() { prime(); }
|
||||||
{
|
|
||||||
this->lastTime = *T3_COUNT;
|
|
||||||
}
|
|
||||||
|
|
||||||
Timer::~Timer() {}
|
Timer::~Timer() {}
|
||||||
|
|
||||||
@@ -29,20 +24,13 @@ Timer::~Timer() {}
|
|||||||
|
|
||||||
u32 Timer::getTimeDelta()
|
u32 Timer::getTimeDelta()
|
||||||
{
|
{
|
||||||
this->time = *T3_COUNT;
|
time = *T3_COUNT;
|
||||||
|
|
||||||
if (this->time < this->lastTime) // The counter has wrapped
|
if (time < lastTime) // The counter has wrapped
|
||||||
this->change = this->time + (65536 - this->lastTime);
|
change = time + (65536 - lastTime);
|
||||||
else
|
else
|
||||||
this->change = this->time - this->lastTime;
|
change = time - lastTime;
|
||||||
|
return change;
|
||||||
this->lastTime = this->time;
|
|
||||||
return this->change;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Timer::primeTimer()
|
|
||||||
{
|
|
||||||
lastTime = *T3_COUNT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float Timer::getFPS()
|
float Timer::getFPS()
|
||||||
|
|||||||
+190
-123
@@ -16,49 +16,88 @@
|
|||||||
#include "../include/utils/math.hpp"
|
#include "../include/utils/math.hpp"
|
||||||
#include "../include/utils/debug.hpp"
|
#include "../include/utils/debug.hpp"
|
||||||
|
|
||||||
// Similiar set is in PS2SDK, but for VU1 we have to switch ST with RGBAQ, because VU1 must know Q before sending RGBAQ
|
|
||||||
#define DRAW_R_STQ_REGLIST ((u64)GIF_REG_ST) << 0 | ((u64)GIF_REG_RGBAQ) << 4 | ((u64)GIF_REG_XYZ2) << 8
|
|
||||||
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 = 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
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
VifSender::VifSender()
|
// VU1 micro program
|
||||||
|
extern u32 VU1Draw3D_CodeStart __attribute__((section(".vudata")));
|
||||||
|
extern u32 VU1Draw3D_CodeEnd __attribute__((section(".vudata")));
|
||||||
|
//
|
||||||
|
|
||||||
|
VifSender::VifSender(Light *t_light)
|
||||||
{
|
{
|
||||||
PRINT_LOG("Initializing VifSender");
|
consoleLog("Initializing VifSender");
|
||||||
PRINT_LOG("VifSender initialized!");
|
light = t_light;
|
||||||
|
lastVertCount = 0;
|
||||||
|
isDrawWaitEnabled = true;
|
||||||
|
dma_channel_initialize(DMA_CHANNEL_VIF1, NULL, 0);
|
||||||
|
dma_channel_fast_waits(DMA_CHANNEL_VIF1);
|
||||||
|
uploadMicroProgram();
|
||||||
|
packets[0] = packet2_create(VU1_PACKET_SIZE, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
|
||||||
|
packets[1] = packet2_create(VU1_PACKET_SIZE, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
|
||||||
|
context = 0;
|
||||||
|
setDoubleBufferAddStaticData();
|
||||||
|
consoleLog("VifSender initialized!");
|
||||||
}
|
}
|
||||||
|
|
||||||
VifSender::~VifSender() {}
|
VifSender::~VifSender()
|
||||||
|
{
|
||||||
|
packet2_free(packets[0]);
|
||||||
|
packet2_free(packets[1]);
|
||||||
|
}
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
// Methods
|
// Methods
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
void VifSender::sendMatrices(const RenderData &t_renderData, const Vector3 &t_position, const Vector3 &t_rotation)
|
void VifSender::uploadMicroProgram()
|
||||||
{
|
{
|
||||||
vec3ToNative(position, t_position, 1.0F);
|
packet2_t *packet2 = packet2_create(
|
||||||
vec3ToNative(rotation, t_rotation, 1.0F);
|
packet2_utils_get_packet_size_for_program(&VU1Draw3D_CodeStart, &VU1Draw3D_CodeEnd) + 1, // + end tag
|
||||||
create_local_world(localWorld, position, rotation);
|
P2_TYPE_NORMAL,
|
||||||
create_local_screen(localScreen, localWorld, t_renderData.worldView->data, t_renderData.perspective->data);
|
P2_MODE_CHAIN,
|
||||||
vu1.sendSingleRefList(0, &localScreen, 4);
|
1);
|
||||||
|
packet2_vif_add_micro_program(packet2, 0, &VU1Draw3D_CodeStart, &VU1Draw3D_CodeEnd);
|
||||||
|
packet2_utils_vu_add_end_tag(packet2);
|
||||||
|
dma_channel_wait(DMA_CHANNEL_VIF1, 0);
|
||||||
|
dma_channel_send_packet2(packet2, DMA_CHANNEL_VIF1, 1);
|
||||||
|
packet2_free(packet2);
|
||||||
}
|
}
|
||||||
|
|
||||||
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::calcMatrix(const RenderData &t_renderData, const Vector3 &t_position, const Vector3 &t_rotation)
|
||||||
|
{
|
||||||
|
model.identity();
|
||||||
|
model.rotate(t_rotation);
|
||||||
|
model.translate(t_position);
|
||||||
|
|
||||||
|
modelViewProj.identity();
|
||||||
|
modelViewProj = model * modelViewProj;
|
||||||
|
modelViewProj = *t_renderData.view * modelViewProj;
|
||||||
|
modelViewProj = *t_renderData.projection * modelViewProj;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VifSender::drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 vertCount2, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer, 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
|
||||||
|
|
||||||
for (u32 i = 0; i < vertCount2;)
|
for (u32 i = 0; i < vertCount2;)
|
||||||
{
|
{
|
||||||
vu1.createList();
|
currPacket = packets[context];
|
||||||
|
packet2_reset(currPacket, false);
|
||||||
for (u8 j = 0; j < VU1_PACKAGES_PER_PACKET; j++) // how many "packages" per one packet
|
for (u8 j = 0; j < VU1_PACKAGES_PER_PACKET; j++) // how many "packages" per one packet
|
||||||
{
|
{
|
||||||
if (i != 0) // we have to go back to avoid the visual artifacts
|
if (i != 0) // we have to go back to avoid the visual artifacts
|
||||||
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;
|
||||||
@@ -67,117 +106,145 @@ void VifSender::drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 ver
|
|||||||
i += (VU1_PACKAGE_VERTS_PER_BUFF - 1);
|
i += (VU1_PACKAGE_VERTS_PER_BUFF - 1);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
vu1.sendList();
|
packet2_utils_vu_add_end_tag(currPacket);
|
||||||
|
dma_channel_send_packet2(currPacket, DMA_CHANNEL_VIF1, 1);
|
||||||
|
dma_channel_wait(DMA_CHANNEL_VIF1, 0);
|
||||||
|
context = !context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VifSender::setDoubleBufferAddStaticData()
|
||||||
|
{
|
||||||
|
packet2_t *settings = packet2_create(10, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
|
||||||
|
packet2_utils_vu_open_unpack(settings, 0, false);
|
||||||
|
{
|
||||||
|
packet2_utils_gs_add_draw_finish_giftag(settings);
|
||||||
|
packet2_utils_gif_add_set(settings, 1);
|
||||||
|
}
|
||||||
|
packet2_utils_vu_close_unpack(settings);
|
||||||
|
packet2_utils_vu_add_double_buffer(settings, 10, 498);
|
||||||
|
packet2_utils_vu_add_end_tag(settings);
|
||||||
|
dma_channel_send_packet2(settings, DMA_CHANNEL_VIF1, true);
|
||||||
|
dma_channel_wait(DMA_CHANNEL_VIF1, 0);
|
||||||
|
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;
|
||||||
vu1.addListBeginning();
|
lastVertCount = vertCount;
|
||||||
|
isLastRGBAOnly = t_rgbaOnly;
|
||||||
// TODO get this via screensettings
|
packet2_utils_vu_open_unpack(currPacket, 0, true);
|
||||||
vu1.addFloat(2048.0F); // scale
|
packet2_add_data(currPacket, modelViewProj.data, 4);
|
||||||
vu1.addFloat(2048.0F); // scale
|
packet2_add_u32(currPacket, t_addDrawWait); // Draw finish?
|
||||||
vu1.addFloat(((float)0xFFFFFF) / 32.0F); // scale
|
packet2_add_u32(currPacket, vertCount); // Vertex count
|
||||||
vu1.add32(vertCount); // vertex count
|
packet2_add_u32(currPacket, vertCount / 3); // Triangles count
|
||||||
|
packet2_add_u32(currPacket, t_rgbaOnly); // 0 = STQ+RGBA, 1 = RGBA
|
||||||
vu1.add128(GIF_SET_TAG(1, 0, 0, 0, GIF_FLG_PACKED, 1), GIF_REG_AD); // 1x set tag
|
packet2_utils_gs_add_lod(currPacket, &t_mesh.lod);
|
||||||
|
packet2_utils_gs_add_texbuff_clut(currPacket, t_texBuff, &t_mesh.clut);
|
||||||
vu1.add128( // tex -> lod
|
if (t_rgbaOnly)
|
||||||
GS_SET_TEX1(
|
packet2_utils_gs_add_prim_giftag(currPacket, t_prim, vertCount, DRAW_RGBAQ_REGLIST, 2, 0);
|
||||||
t_mesh->lod.calculation,
|
else
|
||||||
t_mesh->lod.max_level,
|
packet2_utils_gs_add_prim_giftag(currPacket, t_prim, vertCount, DRAW_STQ2_REGLIST, 3, 0);
|
||||||
t_mesh->lod.mag_filter,
|
packet2_add_u32(currPacket, t_color->r);
|
||||||
t_mesh->lod.min_filter,
|
packet2_add_u32(currPacket, t_color->g);
|
||||||
t_mesh->lod.mipmap_select,
|
packet2_add_u32(currPacket, t_color->b);
|
||||||
t_mesh->lod.l,
|
packet2_add_u32(currPacket, t_color->a);
|
||||||
(int)(t_mesh->lod.k * 16.0F)),
|
u32 vif_added_bytes = packet2_utils_vu_close_unpack(currPacket);
|
||||||
GS_REG_TEX1);
|
packet2_utils_vu_add_unpack_data(currPacket, vif_added_bytes, t_vertices + t_start, vertCount, true);
|
||||||
|
if (!t_rgbaOnly)
|
||||||
vu1.add128( // tex -> buff + clut
|
{
|
||||||
GS_SET_TEX0(
|
vif_added_bytes += vertCount;
|
||||||
textureBuffer->address >> 6,
|
packet2_utils_vu_add_unpack_data(currPacket, vif_added_bytes, t_coordinates + t_start, vertCount, true);
|
||||||
textureBuffer->width >> 6,
|
}
|
||||||
textureBuffer->psm,
|
packet2_utils_vu_add_start_program(currPacket, 0);
|
||||||
textureBuffer->info.width,
|
}
|
||||||
textureBuffer->info.height,
|
|
||||||
textureBuffer->info.components,
|
void VifSender::drawTheSameWithOtherMatrices(const RenderData &t_renderData, Mesh **t_meshes, const u32 &t_skip, const u32 &t_count)
|
||||||
textureBuffer->info.function,
|
{
|
||||||
t_mesh->clut.address >> 6,
|
// Standard double buffering (packets)
|
||||||
t_mesh->clut.psm,
|
packet2_t *packet1 = packet2_create(300, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
|
||||||
t_mesh->clut.storage_mode,
|
packet2_t *packet2 = packet2_create(300, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
|
||||||
t_mesh->clut.start,
|
packet2_t *currMPacket = packet1;
|
||||||
t_mesh->clut.load_method),
|
u8 currPacketIndex = 1;
|
||||||
GS_REG_TEX0);
|
|
||||||
|
// We are sending 32 matrices max per one VU1 send
|
||||||
vu1.add128(
|
u8 switchCounter = 0;
|
||||||
GS_GIFTAG(
|
for (u32 i = t_skip; i < t_count; i++)
|
||||||
vertCount, // amount of loops
|
{
|
||||||
1,
|
model.identity();
|
||||||
1,
|
model.rotate(t_meshes[i]->rotation);
|
||||||
GS_PRIM(
|
model.translate(t_meshes[i]->position);
|
||||||
t_prim->type,
|
|
||||||
t_prim->shading,
|
modelViewProj.identity();
|
||||||
t_prim->mapping,
|
modelViewProj = model * modelViewProj;
|
||||||
t_prim->fogging,
|
modelViewProj = *t_renderData.view * modelViewProj;
|
||||||
t_prim->blending,
|
modelViewProj = *t_renderData.projection * modelViewProj;
|
||||||
t_prim->antialiasing,
|
|
||||||
t_prim->mapping_type,
|
packet2_utils_vu_open_unpack(currMPacket, 0, true);
|
||||||
0, // context
|
{
|
||||||
t_prim->colorfix),
|
packet2_add_data(currMPacket, modelViewProj.data, 4);
|
||||||
GS_GIFTAG_PACKED,
|
}
|
||||||
3), // STQ + RGBA + XYZ
|
packet2_utils_vu_close_unpack(currMPacket);
|
||||||
DRAW_R_STQ_REGLIST);
|
packet2_utils_vu_open_unpack(currMPacket, VU1_RGBA_ADDRESS, true);
|
||||||
|
{
|
||||||
for (u8 j = 0; j < 4; j++)
|
packet2_add_u32(currMPacket, t_meshes[i]->getMaterial(0).color.r);
|
||||||
vu1.add32(128);
|
packet2_add_u32(currMPacket, t_meshes[i]->getMaterial(0).color.g);
|
||||||
|
packet2_add_u32(currMPacket, t_meshes[i]->getMaterial(0).color.b);
|
||||||
//// Clipping tests start
|
packet2_add_u32(currMPacket, t_meshes[i]->getMaterial(0).color.a);
|
||||||
|
}
|
||||||
// // const float minZ = 1;
|
packet2_utils_vu_close_unpack(currMPacket);
|
||||||
// // const float maxZ = 65535;
|
|
||||||
// // const int iGuardDimXY = 2048;
|
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);
|
||||||
// // vu1.addFloat(1.0F); // f_TODO clipping maybe there is problem?
|
|
||||||
// // vu1.addFloat(1.0F);
|
if (switchCounter++ >= 32)
|
||||||
// // vu1.addFloat(1.0F);
|
{
|
||||||
// // vu1.addFloat(1.0F);
|
switchCounter = 0;
|
||||||
// // float xClip = (float)2048.0f/(drawContext.GetFBWidth() * 0.5f * 2.0f);
|
if (i == t_count - 1) // is last
|
||||||
// // packet += Math::Max( xClip, 1.0f );
|
{
|
||||||
// // float yClip = (float)2048.0f/(drawContext.GetFBHeight() * 0.5f * 2.0f);
|
packet2_utils_vu_open_unpack(currMPacket, VU1_PARAMS_ADDRESS, true);
|
||||||
// // packet += Math::Max( yClip, 1.0f );
|
{
|
||||||
// // float depthClip = 2048.0f / depthClipToGs;
|
packet2_add_u32(currMPacket, true); // Draw wait finish?
|
||||||
// // // F_FIXME: maybe these 2048's should be 2047.5s...
|
packet2_add_u32(currMPacket, lastVertCount); // Vertex count
|
||||||
// // depthClip *= 1.003f; // round up a bit for fp error (????)
|
packet2_add_u32(currMPacket, lastVertCount / 3); // Triangles count
|
||||||
// // packet += depthClip;
|
packet2_add_u32(currMPacket, isLastRGBAOnly); // 0 = STQ+RGBA, 1 = RGBA
|
||||||
// // // enable/disable clipping
|
}
|
||||||
// // packet += (drawContext.GetDoClipping()) ? 1 : 0;
|
packet2_utils_vu_close_unpack(currMPacket);
|
||||||
|
packet2_utils_vu_add_start_program(currMPacket, 0); // and start program
|
||||||
// u32 depthBits = 24; // or 28(fog) or 16
|
}
|
||||||
// float depthClipToGs = (float)((1 << depthBits) - 1) / 2.0f;
|
packet2_utils_vu_add_end_tag(currMPacket);
|
||||||
// vu1.addFloat(2048.0f / (640.0F * 0.5f * 2.0f));
|
dma_channel_wait(DMA_CHANNEL_VIF1, 0);
|
||||||
// vu1.addFloat(2048.0f / (480.0F * 0.5f * 2.0f));
|
dma_channel_send_packet2(currMPacket, DMA_CHANNEL_VIF1, 1);
|
||||||
// vu1.addFloat((2048.0f / depthClipToGs) * 1.003F);
|
if (currPacketIndex == 1) // Switch double buffer (packets)
|
||||||
// // vu1.addFloat(2048.0F); // scale
|
{
|
||||||
// // vu1.addFloat(2048.0F); // scale
|
currPacketIndex = 2;
|
||||||
// // vu1.addFloat(((float)0xFFFFFF) / 32.0F); // scale
|
currMPacket = packet2;
|
||||||
// vu1.addFloat(0.0F);
|
}
|
||||||
// // vu1.addFloat(0.5f * iGuardDimXY);
|
else
|
||||||
// // vu1.addFloat(-0.5f * iGuardDimXY);
|
{
|
||||||
// // vu1.addFloat(1.0F);
|
currPacketIndex = 1;
|
||||||
// // vu1.addFloat(500.0F); // far
|
currMPacket = packet1;
|
||||||
|
}
|
||||||
vu1.addFloat(0.0F);
|
packet2_reset(currMPacket, false);
|
||||||
vu1.addFloat(0.0F);
|
}
|
||||||
vu1.addFloat(0.0F);
|
}
|
||||||
vu1.addFloat(0.0F);
|
if (switchCounter != 0) // if there are any not sended matrices
|
||||||
|
{
|
||||||
//// Clipping tests end
|
packet2_utils_vu_open_unpack(currMPacket, VU1_PARAMS_ADDRESS, true);
|
||||||
|
{
|
||||||
vu1.addListEnding();
|
packet2_add_u32(currMPacket, true); // Draw wait finish?
|
||||||
vu1.addReferenceList(0, t_vertices + t_start, 2 * vertCount, 1);
|
packet2_add_u32(currMPacket, lastVertCount); // Vertex count
|
||||||
vu1.addReferenceList(0, t_coordinates + t_start, 2 * vertCount, 1);
|
packet2_add_u32(currMPacket, lastVertCount / 3); // Triangles count
|
||||||
vu1.addStartProgram();
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,275 +0,0 @@
|
|||||||
/*
|
|
||||||
# ______ ____ ___
|
|
||||||
# | \/ ____| |___|
|
|
||||||
# | | | \ | |
|
|
||||||
#-----------------------------------------------------------------------
|
|
||||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
|
||||||
# Licenced under Apache License 2.0
|
|
||||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../include/modules/vu1.hpp"
|
|
||||||
|
|
||||||
#include "../include/utils/debug.hpp"
|
|
||||||
#include <dma.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <kernel.h>
|
|
||||||
|
|
||||||
// ----
|
|
||||||
// Constructors/Destructors
|
|
||||||
// ----
|
|
||||||
|
|
||||||
VU1::VU1()
|
|
||||||
{
|
|
||||||
PRINT_LOG("Initializing VU1");
|
|
||||||
currentBuffer = 0;
|
|
||||||
switchBuffer = 0;
|
|
||||||
PRINT_LOG("VU1 initialized!");
|
|
||||||
}
|
|
||||||
|
|
||||||
VU1::~VU1() {}
|
|
||||||
|
|
||||||
// ----
|
|
||||||
// Methods
|
|
||||||
// -
|
|
||||||
|
|
||||||
/** Create dynamic list */
|
|
||||||
void VU1::createList()
|
|
||||||
{
|
|
||||||
switchBuffer = !switchBuffer;
|
|
||||||
memset((char *)&buildList, 0, sizeof(buildList));
|
|
||||||
|
|
||||||
if (switchBuffer)
|
|
||||||
currentBuffer = (char *)&dmaBuffer1;
|
|
||||||
else
|
|
||||||
currentBuffer = (char *)&dmaBuffer2;
|
|
||||||
buildList.kickBuffer = currentBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Add reference list and send via VIF1
|
|
||||||
* Not using TOPS register
|
|
||||||
* Similar to addReferenceList()
|
|
||||||
*/
|
|
||||||
void VU1::sendSingleRefList(int t_destAddress, void *t_data, int t_quadSize)
|
|
||||||
{
|
|
||||||
checkDataAlignment(t_data);
|
|
||||||
|
|
||||||
u8 tempBuffer[32] __attribute__((aligned(16)));
|
|
||||||
void *chain = (u64 *)&tempBuffer; // uncached
|
|
||||||
|
|
||||||
*((u64 *)chain)++ = DMA_REF_TAG((u32)t_data, t_quadSize);
|
|
||||||
*((u32 *)chain)++ = VIF_CODE(VIF_STCYL, 0, 0x0101);
|
|
||||||
*((u32 *)chain)++ = VIF_CODE(VIF_UNPACK_V4_32, t_quadSize, t_destAddress);
|
|
||||||
|
|
||||||
*((u64 *)chain)++ = DMA_END_TAG(0);
|
|
||||||
*((u32 *)chain)++ = VIF_CODE(VIF_NOP, 0, 0);
|
|
||||||
*((u32 *)chain)++ = VIF_CODE(VIF_NOP, 0, 0);
|
|
||||||
|
|
||||||
FlushCache(0);
|
|
||||||
dma_channel_send_chain(DMA_CHANNEL_VIF1, tempBuffer, 0, DMA_FLAG_TRANSFERTAG, 0);
|
|
||||||
dma_channel_wait(DMA_CHANNEL_VIF1, VU1_DMA_CHAN_TIMEOUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Add list beginning, set's double buffer if not set */
|
|
||||||
void VU1::addListBeginning()
|
|
||||||
{
|
|
||||||
if (buildList.isBuilding == 1)
|
|
||||||
PRINT_ERR("Please end current list list before adding new one!");
|
|
||||||
|
|
||||||
if (isDoubleBufferSet == 0)
|
|
||||||
addDoubleBufferSetting();
|
|
||||||
else
|
|
||||||
addFlush();
|
|
||||||
|
|
||||||
buildList.dmaSizeAll += buildList.dmaSize;
|
|
||||||
buildList.dmaSize = 0;
|
|
||||||
buildList.offset = currentBuffer;
|
|
||||||
*((u64 *)currentBuffer)++ = DMA_CNT_TAG(0); // placeholder
|
|
||||||
*((u32 *)currentBuffer)++ = VIF_CODE(VIF_STCYL, 0, 0x0101); // placeholder
|
|
||||||
*((u32 *)currentBuffer)++ = VIF_CODE(VIF_UNPACK_V4_32, 0, 0); // placeholder
|
|
||||||
buildList.isBuilding = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Add list ending and fix unpack size */
|
|
||||||
void VU1::addListEnding()
|
|
||||||
{
|
|
||||||
if (buildList.isBuilding == 0)
|
|
||||||
{
|
|
||||||
PRINT_ERR("Please add list beginning first. Nothing to end!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((buildList.dmaSize & 0xF))
|
|
||||||
{
|
|
||||||
*((u32 *)currentBuffer)++ = 0;
|
|
||||||
buildList.dmaSize += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
*((u64 *)buildList.offset)++ = DMA_CNT_TAG(buildList.dmaSize >> 4);
|
|
||||||
*((u32 *)buildList.offset)++ = VIF_CODE(VIF_STCYL, 0, 0x0101);
|
|
||||||
*((u32 *)buildList.offset)++ = AddUnpack(V4_32, 0, buildList.dmaSize >> 4, 1);
|
|
||||||
|
|
||||||
buildList.isBuilding = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Add list which will load data from given pointer
|
|
||||||
* A lot faster than standard list.
|
|
||||||
* @param offset offset before data in quadwords
|
|
||||||
* @param data data pointer
|
|
||||||
* @param size in quadwords
|
|
||||||
* @param useTops when true, data will be loaded at the beginning of buffer (BASE+OFFSET)
|
|
||||||
*/
|
|
||||||
void VU1::addReferenceList(u32 t_offset, void *t_data, u32 t_size, u8 t_useTops)
|
|
||||||
{
|
|
||||||
checkDataAlignment(t_data);
|
|
||||||
if (buildList.isBuilding == 1)
|
|
||||||
PRINT_ERR("Please end current list list before adding new one!");
|
|
||||||
*((u64 *)currentBuffer)++ = DMA_REF_TAG((u32)t_data, t_size);
|
|
||||||
*((u32 *)currentBuffer)++ = VIF_CODE(VIF_STCYL, 0, 0x0101);
|
|
||||||
*((u32 *)currentBuffer)++ =
|
|
||||||
AddUnpack(V4_32, t_useTops == 1 ? buildList.dmaSize / 16 : t_offset / 16, t_size, t_useTops);
|
|
||||||
buildList.dmaSize += t_size * 8;
|
|
||||||
buildList.dmaSizeAll += buildList.dmaSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Start VU1 program */
|
|
||||||
void VU1::addStartProgram()
|
|
||||||
{
|
|
||||||
*((u64 *)currentBuffer)++ = DMA_CNT_TAG(8 >> 4);
|
|
||||||
*((u32 *)currentBuffer)++ = VIF_CODE(VIF_MSCAL, 0, 0);
|
|
||||||
*((u32 *)currentBuffer)++ = VIF_CODE(VIF_FLUSH, 0, 0);
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Continue VU1 program from "--cont" line */
|
|
||||||
void VU1::addContinueProgram()
|
|
||||||
{
|
|
||||||
*((u64 *)currentBuffer)++ = DMA_CNT_TAG(8 >> 4);
|
|
||||||
*((u32 *)currentBuffer)++ = VIF_CODE(VIF_MSCAL, 0, 0);
|
|
||||||
*((u32 *)currentBuffer)++ = VIF_CODE(VIF_FLUSH, 0, 0);
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Add end tag and send packet via VIF1 */
|
|
||||||
void VU1::sendList()
|
|
||||||
{
|
|
||||||
*((u64 *)currentBuffer)++ = DMA_END_TAG(0);
|
|
||||||
*((u32 *)currentBuffer)++ = VIF_CODE(VIF_NOP, 0, 0);
|
|
||||||
*((u32 *)currentBuffer)++ = VIF_CODE(VIF_NOP, 0, 0);
|
|
||||||
dma_channel_wait(DMA_CHANNEL_VIF1, VU1_DMA_CHAN_TIMEOUT);
|
|
||||||
dma_channel_send_chain(DMA_CHANNEL_VIF1, buildList.kickBuffer, (u32 *)currentBuffer - (u32 *)buildList.kickBuffer, DMA_FLAG_TRANSFERTAG, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VU1::addDoubleBufferSetting()
|
|
||||||
{
|
|
||||||
*((u64 *)currentBuffer)++ = DMA_CNT_TAG(8 >> 4);
|
|
||||||
*((u32 *)currentBuffer)++ = VIF_CODE(VIF_BASE, 0, 8);
|
|
||||||
*((u32 *)currentBuffer)++ = VIF_CODE(VIF_OFFSET, 0, 496);
|
|
||||||
isDoubleBufferSet = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VU1::addFlush()
|
|
||||||
{
|
|
||||||
*((u64 *)currentBuffer)++ = DMA_CNT_TAG(8 >> 4);
|
|
||||||
*((u32 *)currentBuffer)++ = VIF_CODE(VIF_NOP, 0, 0);
|
|
||||||
*((u32 *)currentBuffer)++ = VIF_CODE(VIF_FLUSH, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VU1::checkDataAlignment(void *t_data)
|
|
||||||
{
|
|
||||||
if (((u32)t_data & 0xF))
|
|
||||||
PRINT_ERR("data is not 16 byte aligned!");
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----
|
|
||||||
// List adding
|
|
||||||
// ----
|
|
||||||
|
|
||||||
void VU1::add128(u64 v1, u64 v2)
|
|
||||||
{
|
|
||||||
checkList();
|
|
||||||
*((u64 *)currentBuffer)++ = v1;
|
|
||||||
*((u64 *)currentBuffer)++ = v2;
|
|
||||||
buildList.dmaSize += 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VU1::add64(u64 v)
|
|
||||||
{
|
|
||||||
checkList();
|
|
||||||
*((u64 *)currentBuffer)++ = v;
|
|
||||||
buildList.dmaSize += 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VU1::add32(u32 v)
|
|
||||||
{
|
|
||||||
checkList();
|
|
||||||
*((u32 *)currentBuffer)++ = v;
|
|
||||||
buildList.dmaSize += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VU1::addFloat(float v)
|
|
||||||
{
|
|
||||||
checkList();
|
|
||||||
*((float *)currentBuffer)++ = v;
|
|
||||||
buildList.dmaSize += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VU1::checkList()
|
|
||||||
{
|
|
||||||
if (buildList.isBuilding == 0)
|
|
||||||
PRINT_ERR("Please add list beginning before adding data!");
|
|
||||||
if (buildList.dmaSizeAll > VIF_BUFFER_SIZE)
|
|
||||||
PRINT_ERR("Buffer size exceed!");
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----
|
|
||||||
// Static
|
|
||||||
// ----
|
|
||||||
|
|
||||||
u8 IS_DMA_VIF1_INITIALIZED = 0;
|
|
||||||
/** TODO */
|
|
||||||
void VU1::uploadProgram(int t_dest, u32 *t_start, u32 *t_end)
|
|
||||||
{
|
|
||||||
if (!IS_DMA_VIF1_INITIALIZED)
|
|
||||||
{
|
|
||||||
IS_DMA_VIF1_INITIALIZED = 1;
|
|
||||||
dma_channel_initialize(DMA_CHANNEL_VIF1, NULL, 0);
|
|
||||||
dma_channel_fast_waits(DMA_CHANNEL_VIF1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int count = 0;
|
|
||||||
u8 tempBuffer[512] __attribute__((aligned(16)));
|
|
||||||
void *chain = (u64 *)&tempBuffer; // uncached
|
|
||||||
|
|
||||||
// get the size of the code as we can only send 256 instructions in each MPGtag
|
|
||||||
count = VU1::countProgramSize(t_start, t_end);
|
|
||||||
while (count > 0)
|
|
||||||
{
|
|
||||||
u32 currentCount = count > 256 ? 256 : count;
|
|
||||||
|
|
||||||
*((u64 *)chain)++ = DMA_REF_TAG((u32)t_start, currentCount / 2);
|
|
||||||
*((u32 *)chain)++ = VIF_CODE(VIF_NOP, 0, 0);
|
|
||||||
*((u32 *)chain)++ = VIF_CODE(VIF_MPG, currentCount & 0xFF, t_dest);
|
|
||||||
|
|
||||||
t_start += currentCount * 2;
|
|
||||||
count -= currentCount;
|
|
||||||
t_dest += currentCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
*((u64 *)chain)++ = DMA_END_TAG(0);
|
|
||||||
*((u32 *)chain)++ = VIF_CODE(VIF_NOP, 0, 0);
|
|
||||||
*((u32 *)chain)++ = VIF_CODE(VIF_NOP, 0, 0);
|
|
||||||
|
|
||||||
// Send it to vif1
|
|
||||||
FlushCache(0);
|
|
||||||
dma_channel_send_chain(DMA_CHANNEL_VIF1, tempBuffer, 0, DMA_FLAG_TRANSFERTAG, 0);
|
|
||||||
dma_channel_wait(DMA_CHANNEL_VIF1, VU1_DMA_CHAN_TIMEOUT); // synchronize immediately.
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 VU1::countProgramSize(u32 *t_start, u32 *t_end)
|
|
||||||
{
|
|
||||||
u32 size = (t_end - t_start) / 2;
|
|
||||||
if (size & 1)
|
|
||||||
size++;
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
+84
-11
@@ -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 */
|
||||||
@@ -99,3 +88,87 @@ void manyVec3ToNative(VECTOR *o_result, Vector3 *t_vec, int t_amount, float t_fo
|
|||||||
for (int i = 0; i < t_amount; i++)
|
for (int i = 0; i < t_amount; i++)
|
||||||
vec3ToNative(o_result[i], t_vec[i], t_fourthVal);
|
vec3ToNative(o_result[i], t_vec[i], t_fourthVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float Math::asin(float x)
|
||||||
|
{
|
||||||
|
float r;
|
||||||
|
asm volatile(
|
||||||
|
"lui $9, 0x3f00 \n\t"
|
||||||
|
".set noreorder \n\t"
|
||||||
|
".align 3 \n\t"
|
||||||
|
"abs.s %0, %1 \n\t"
|
||||||
|
"lui $8, 0xbe22 \n\t"
|
||||||
|
"mtc1 $9, $f1 \n\t"
|
||||||
|
"ori $8, $8, 0xf983 \n\t"
|
||||||
|
"mtc1 $8, $f8 \n\t"
|
||||||
|
"lui $9, 0x4b00 \n\t"
|
||||||
|
"mtc1 $9, $f3 \n\t"
|
||||||
|
"lui $8, 0x3f80 \n\t"
|
||||||
|
"mtc1 $8, $f2 \n\t"
|
||||||
|
"mula.s %0, $f8 \n\t"
|
||||||
|
"msuba.s $f3, $f2 \n\t"
|
||||||
|
"madda.s $f3, $f2 \n\t"
|
||||||
|
"lui $8, 0x40c9 \n\t"
|
||||||
|
"msuba.s %0, $f8 \n\t"
|
||||||
|
"ori $8, 0x0fdb \n\t"
|
||||||
|
"msub.s %0, $f1, $f2 \n\t"
|
||||||
|
"lui $9, 0xc225 \n\t"
|
||||||
|
"abs.s %0, %0 \n\t"
|
||||||
|
"lui $10, 0x3e80 \n\t"
|
||||||
|
"mtc1 $10, $f7 \n\t"
|
||||||
|
"ori $9, 0x5de1 \n\t"
|
||||||
|
"sub.s %0, %0, $f7 \n\t"
|
||||||
|
"lui $10, 0x42a3 \n\t"
|
||||||
|
"mtc1 $8, $f3 \n\t"
|
||||||
|
"ori $10, 0x3458 \n\t"
|
||||||
|
"mtc1 $9, $f4 \n\t"
|
||||||
|
"lui $8, 0xc299 \n\t"
|
||||||
|
"mtc1 $10, $f5 \n\t"
|
||||||
|
"ori $8, 0x2663 \n\t"
|
||||||
|
"mul.s $f8, %0, %0 \n\t"
|
||||||
|
"lui $9, 0x421e \n\t"
|
||||||
|
"mtc1 $8, $f6 \n\t"
|
||||||
|
"ori $9, 0xd7bb \n\t"
|
||||||
|
"mtc1 $9, $f7 \n\t"
|
||||||
|
"nop \n\t"
|
||||||
|
"mul.s $f1, %0, $f8 \n\t"
|
||||||
|
"mul.s $f9, $f8, $f8 \n\t"
|
||||||
|
"mula.s $f3, %0 \n\t"
|
||||||
|
"mul.s $f2, $f1, $f8 \n\t"
|
||||||
|
"madda.s $f4, $f1 \n\t"
|
||||||
|
"mul.s $f1, $f1, $f9 \n\t"
|
||||||
|
"mul.s %0, $f2, $f9 \n\t"
|
||||||
|
"madda.s $f5, $f2 \n\t"
|
||||||
|
"madda.s $f6, $f1 \n\t"
|
||||||
|
"madd.s %0, $f7, %0 \n\t"
|
||||||
|
".set reorder \n\t"
|
||||||
|
: "=&f"(r)
|
||||||
|
: "f"(x)
|
||||||
|
: "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", "$f9", "$8", "$9", "$10");
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Math::mod(float x, float y)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Portable fmod(x,y) implementation for systems
|
||||||
|
* that don't have it. Adapted from code found here:
|
||||||
|
* http://www.opensource.apple.com/source/python/python-3/python/Python/fmod.c
|
||||||
|
*/
|
||||||
|
float i, f;
|
||||||
|
|
||||||
|
if (y == 0.0f)
|
||||||
|
{
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = floorf(x / y);
|
||||||
|
f = x - i * y;
|
||||||
|
|
||||||
|
if ((x < 0.0f) != (y < 0.0f))
|
||||||
|
{
|
||||||
|
f = f - y;
|
||||||
|
}
|
||||||
|
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,8 +11,9 @@
|
|||||||
#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(const u32 a)
|
||||||
{
|
{
|
||||||
char *result = new char[(((sizeof a) * CHAR_BIT) + 2) / 3 + 2];
|
char *result = new char[(((sizeof a) * CHAR_BIT) + 2) / 3 + 2];
|
||||||
sprintf(result, "%d", a);
|
sprintf(result, "%d", a);
|
||||||
@@ -20,7 +21,7 @@ char *String::createU32ToString(u32 a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Converts "123" to "000123". 6 digits length */
|
/** Converts "123" to "000123". 6 digits length */
|
||||||
char *String::createWithLeadingZeros(char *a)
|
char *String::createWithLeadingZeros(const char *a)
|
||||||
{
|
{
|
||||||
const u8 digitsAmount = 6;
|
const u8 digitsAmount = 6;
|
||||||
char *part = createConcatenated("00000000", a);
|
char *part = createConcatenated("00000000", a);
|
||||||
@@ -34,7 +35,7 @@ char *String::createWithLeadingZeros(char *a)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *String::createWithoutExtension(char *source)
|
char *String::createWithoutExtension(const char *source)
|
||||||
{
|
{
|
||||||
u32 length = 0;
|
u32 length = 0;
|
||||||
for (;; length++)
|
for (;; length++)
|
||||||
@@ -47,7 +48,7 @@ char *String::createWithoutExtension(char *source)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *String::createCopy(char *source)
|
char *String::createCopy(const char *source)
|
||||||
{
|
{
|
||||||
u32 srcLength = getLength(source);
|
u32 srcLength = getLength(source);
|
||||||
char *res = new char[srcLength + 1];
|
char *res = new char[srcLength + 1];
|
||||||
@@ -58,7 +59,7 @@ char *String::createCopy(char *source)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// For test\0 will return 4
|
// For test\0 will return 4
|
||||||
u32 String::getLength(char *a)
|
u32 String::getLength(const char *a)
|
||||||
{
|
{
|
||||||
if (a == NULL)
|
if (a == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -67,7 +68,7 @@ u32 String::getLength(char *a)
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *String::createConcatenated(char *a, char *b)
|
char *String::createConcatenated(const char *a, const char *b)
|
||||||
{
|
{
|
||||||
u32 aLength = getLength(a);
|
u32 aLength = getLength(a);
|
||||||
u32 bLength = getLength(b);
|
u32 bLength = getLength(b);
|
||||||
|
|||||||
@@ -1,154 +0,0 @@
|
|||||||
; ______ ____ ___
|
|
||||||
; | \/ ____| |___|
|
|
||||||
; | | | \ | |
|
|
||||||
;---------------------------
|
|
||||||
; Copyright 2020, tyra - https://github.com/h4570/tyra
|
|
||||||
; Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
|
||||||
;
|
|
||||||
;---------------------------------------------------------------
|
|
||||||
; draw3D.vcl |
|
|
||||||
;---------------------------------------------------------------
|
|
||||||
; A VU1 microprogram to draw 3D object using XYZ2, RGBAQ and ST|
|
|
||||||
; This program uses double buffering (xtop) |
|
|
||||||
; |
|
|
||||||
; Many thanks to: |
|
|
||||||
; - Dr Henry Fortuna |
|
|
||||||
; - Jesper Svennevid, Daniel Collin |
|
|
||||||
; - Guilherme Lampert |
|
|
||||||
;---------------------------------------------------------------
|
|
||||||
|
|
||||||
; TODO
|
|
||||||
; - Fix vertex clipping (is clipping visible triangles :/)
|
|
||||||
; - Move lerp() from EE to VU1 (performance)
|
|
||||||
; - Add dynamic lighting (feature)
|
|
||||||
; - Add --cont + MSCNT instead of alltime MSCAL (performance)
|
|
||||||
|
|
||||||
.syntax new
|
|
||||||
.name VU1Draw3D
|
|
||||||
.vu
|
|
||||||
.init_vf_all
|
|
||||||
.init_vi_all
|
|
||||||
|
|
||||||
--enter
|
|
||||||
--endenter
|
|
||||||
|
|
||||||
;//////////// --- Load data 1 --- /////////////
|
|
||||||
; Updated once per frame
|
|
||||||
lq matrixRow0, 0(vi00) ; load view-projection matrix
|
|
||||||
lq matrixRow1, 1(vi00)
|
|
||||||
lq matrixRow2, 2(vi00)
|
|
||||||
lq matrixRow3, 3(vi00)
|
|
||||||
;/////////////////////////////////////////////
|
|
||||||
|
|
||||||
fcset 0x000000 ; VCL won't let us use CLIP without first zeroing
|
|
||||||
; the clip flags
|
|
||||||
|
|
||||||
;//////////// --- Load data 2 --- /////////////
|
|
||||||
; Updated dynamically
|
|
||||||
xtop iBase
|
|
||||||
|
|
||||||
lq.xyz scale, 0(iBase) ; load program params
|
|
||||||
; float : X, Y, Z - scale vector that we will use to scale the verts after projecting them.
|
|
||||||
; float : W - vert count.
|
|
||||||
lq gifSetTag, 1(iBase) ; GIF tag - set
|
|
||||||
lq texGifTag1, 2(iBase) ; GIF tag - texture LOD
|
|
||||||
lq texGifTag2, 3(iBase) ; GIF tag - texture buffer & CLUT
|
|
||||||
lq primTag, 4(iBase) ; GIF tag - tell GS how many data we will send
|
|
||||||
lq rgba, 5(iBase) ; RGBA
|
|
||||||
;lq clipScale, 6(iBase) ; TODO clipping tests
|
|
||||||
; u32 : R, G, B, A (0-128)
|
|
||||||
iaddiu vertexData, iBase, 7 ; pointer to vertex data
|
|
||||||
ilw.w vertCount, 0(iBase) ; load vert count from scale vector
|
|
||||||
iadd stqData, vertexData, vertCount ; pointer to stq
|
|
||||||
iadd kickAddress, stqData, vertCount ; pointer for XGKICK
|
|
||||||
iadd destAddress, stqData, vertCount ; helper pointer for data inserting
|
|
||||||
;////////////////////////////////////////////
|
|
||||||
|
|
||||||
;/////////// --- Store tags --- /////////////
|
|
||||||
sqi gifSetTag, (destAddress++) ;
|
|
||||||
sqi texGifTag1, (destAddress++) ; texture LOD tag
|
|
||||||
sqi gifSetTag, (destAddress++) ;
|
|
||||||
sqi texGifTag2, (destAddress++) ; texture buffer & CLUT tag
|
|
||||||
sqi primTag, (destAddress++) ; prim + tell gs how many data will be
|
|
||||||
;////////////////////////////////////////////
|
|
||||||
|
|
||||||
;/////////////// --- Loop --- ///////////////
|
|
||||||
iadd vertexCounter, iBase, vertCount ; loop vertCount times
|
|
||||||
vertexLoop:
|
|
||||||
|
|
||||||
;////////// --- Load loop data --- //////////
|
|
||||||
lq vertex, 0(vertexData) ; load xyz
|
|
||||||
; float : X, Y, Z
|
|
||||||
; any32 : _ = 0
|
|
||||||
lq stq, 0(stqData) ; load stq
|
|
||||||
; float : S, T
|
|
||||||
; any32 : Q = 1 ; 1, because we will mul this by 1/vert[w] and this
|
|
||||||
; will be our q for texture perspective correction
|
|
||||||
; any32 : _ = 0
|
|
||||||
;////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
;////////////// --- Vertex --- //////////////
|
|
||||||
mul acc, matrixRow0, vertex[x] ; transform each vertex by the matrix
|
|
||||||
madd acc, matrixRow1, vertex[y]
|
|
||||||
madd acc, matrixRow2, vertex[z]
|
|
||||||
madd vertex, matrixRow3, vertex[w]
|
|
||||||
|
|
||||||
;add.z acc, vf0, clipScale[w] ; TODO clipping maybe this?
|
|
||||||
;madd.z clipVec, clipScale, vertex
|
|
||||||
;mul.xy clipVec, clipScale, vertex
|
|
||||||
;mul.w clipVec, vf0, vertex[z]
|
|
||||||
|
|
||||||
;mul.xyz clipVec, vertex, clipScale ; TODO clipping maybe this?
|
|
||||||
|
|
||||||
clipw.xyz vertex, vertex ; Dr. Fortuna: This instruction checks if the vertex is outside
|
|
||||||
; the viewing frustum. If it is, then the appropriate
|
|
||||||
; clipping flags are set
|
|
||||||
fcand VI01, 0x3FFFF ; Bitwise AND the clipping flags with 0x3FFFF, this makes
|
|
||||||
; sure that we get the clipping judgement for the last three
|
|
||||||
; verts (i.e. that make up the triangle we are about to draw)
|
|
||||||
iaddiu iADC, VI01, 0x7FFF ; Add 0x7FFF. If any of the clipping flags were set this will
|
|
||||||
; cause the triangle not to be drawn (any values above 0x8000
|
|
||||||
; that are stored in the w component of XYZ2 will set the ADC
|
|
||||||
; bit, which tells the GS not to perform a drawing kick on this
|
|
||||||
; triangle.
|
|
||||||
|
|
||||||
;ilw.w iNoDraw, UVStart(Counter) ; Load the iNoDraw flag. If true we should set the ADC bit so the vert isn't drawn
|
|
||||||
;iadd iADC, iADC, iNoDraw ; TODO clipping maybe this?
|
|
||||||
|
|
||||||
isw.w iADC, 2(destAddress)
|
|
||||||
|
|
||||||
div q, vf00[w], vertex[w] ; perspective divide (1/vert[w]):
|
|
||||||
mul.xyz vertex, vertex, q
|
|
||||||
mula.xyz acc, scale, vf00[w] ; scale to GS screen space
|
|
||||||
madd.xyz vertex, vertex, scale ; multiply and add the scales -> vert = vert * scale + scale
|
|
||||||
ftoi4.xyz vertex, vertex ; convert vertex to 12:4 fixed point format
|
|
||||||
;////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
;//////////////// --- ST --- ////////////////
|
|
||||||
mulq modStq, stq, q
|
|
||||||
;////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
;//////////// --- Store data --- ////////////
|
|
||||||
sq modStq, 0(destAddress) ; STQ
|
|
||||||
sq rgba, 1(destAddress) ; RGBA ; q is grabbed from stq
|
|
||||||
sq.xyz vertex, 2(destAddress) ; XYZ2
|
|
||||||
;////////////////////////////////////////////
|
|
||||||
|
|
||||||
iaddiu vertexData, vertexData, 1
|
|
||||||
iaddiu stqData, stqData, 1
|
|
||||||
iaddiu destAddress, destAddress, 3
|
|
||||||
|
|
||||||
iaddi vertexCounter, vertexCounter, -1 ; decrement the loop counter
|
|
||||||
ibne vertexCounter, iBase, vertexLoop ; and repeat if needed
|
|
||||||
|
|
||||||
;////////////////////////////////////////////
|
|
||||||
|
|
||||||
--barrier
|
|
||||||
|
|
||||||
xgkick kickAddress ; dispatch to the GS rasterizer.
|
|
||||||
|
|
||||||
--exit
|
|
||||||
--endexit
|
|
||||||
@@ -0,0 +1,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
@@ -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
|
||||||
;-------------------------
|
;-------------------------
|
||||||
;-------------------------
|
;-------------------------
|
||||||
;-------------------------
|
;-------------------------
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
; Load GS offsets to center xformed vertex in gs coord space and color clamping constant
|
||||||
|
#macro LoadScaleConstant: gs_scale
|
||||||
|
loi 2047.5
|
||||||
|
addi.xy gs_scale, vf00, i
|
||||||
|
loi 699050.625000 // ((float)0xFFFFFF) / 24.0F
|
||||||
|
addi.z gs_scale, vf00, i
|
||||||
|
#endmacro
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#macro MatrixLoad: matrix, offset, vumem
|
||||||
|
lq matrix[0], offset+0(vumem)
|
||||||
|
lq matrix[1], offset+1(vumem)
|
||||||
|
lq matrix[2], offset+2(vumem)
|
||||||
|
lq matrix[3], offset+3(vumem)
|
||||||
|
#endmacro
|
||||||
|
|
||||||
|
#macro MatrixXForm: output_vertex, matrix, input_vertex
|
||||||
|
mul acc, matrix[0], input_vertex[x]
|
||||||
|
madd acc, matrix[1], input_vertex[y]
|
||||||
|
madd acc, matrix[2], input_vertex[z]
|
||||||
|
madd output_vertex, matrix[3], input_vertex[w]
|
||||||
|
#endmacro
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#macro VectorPerspectiveDivide: vertex
|
||||||
|
div q, vf00[w], vertex[w]
|
||||||
|
mulq.xyz vertex, vertex, q
|
||||||
|
#endmacro
|
||||||
|
|
||||||
|
#macro VectorAddGSScales: output_vertex, input_vertex, gs_scale
|
||||||
|
mula.xyz acc, gs_scale, vf00[w]
|
||||||
|
madd.xyz output_vertex, input_vertex, gs_scale
|
||||||
|
ftoi4.xyz output_vertex, output_vertex
|
||||||
|
#endmacro
|
||||||
|
|
||||||
|
#macro VectorTexturePerspectiveCorrection: output_vertex, input_vertex
|
||||||
|
mulq output_vertex, input_vertex, q
|
||||||
|
#endmacro
|
||||||
|
|
||||||
|
#macro VectorStore: vertex, vumem, num
|
||||||
|
sq vertex, num(vumem)
|
||||||
|
#endmacro
|
||||||
|
|
||||||
|
#macro VectorClip: output_vertex, input_vertex
|
||||||
|
clipw.xyz input_vertex, input_vertex
|
||||||
|
mfir.w output_vertex, adc_bit
|
||||||
|
#endmacro
|
||||||
|
|
||||||
|
#macro VectorLoad: output_vertex, vumem, offset
|
||||||
|
lq output_vertex, offset(vumem)
|
||||||
|
#endmacro
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
EE_BIN = ari.elf
|
|
||||||
|
|
||||||
EE_OBJS = \
|
|
||||||
../../engine/models/math/matrix.o \
|
|
||||||
../../engine/models/math/plane.o \
|
|
||||||
../../engine/models/math/point.o \
|
|
||||||
../../engine/models/math/vector3.o \
|
|
||||||
../../engine/models/mesh_frame.o \
|
|
||||||
../../engine/models/mesh_material.o \
|
|
||||||
../../engine/models/mesh.o \
|
|
||||||
../../engine/models/mesh_texture.o \
|
|
||||||
../../engine/modules/audio.o \
|
|
||||||
../../engine/modules/camera_base.o \
|
|
||||||
../../engine/modules/gif_sender.o \
|
|
||||||
../../engine/modules/light.o \
|
|
||||||
../../engine/modules/pad.o \
|
|
||||||
../../engine/modules/renderer.o \
|
|
||||||
../../engine/modules/texture_repository.o \
|
|
||||||
../../engine/modules/timer.o \
|
|
||||||
../../engine/modules/vif_sender.o \
|
|
||||||
../../engine/modules/vu1.o \
|
|
||||||
../../engine/utils/math.o \
|
|
||||||
../../engine/utils/string.o \
|
|
||||||
../../engine/loaders/bmp_loader.o \
|
|
||||||
../../engine/loaders/dff_loader.o \
|
|
||||||
../../engine/loaders/md2_loader.o \
|
|
||||||
../../engine/loaders/obj_loader.o \
|
|
||||||
../../engine/vu1_progs/draw3D.o \
|
|
||||||
../../engine/engine.o \
|
|
||||||
camera.o \
|
|
||||||
objects/player.o \
|
|
||||||
ari.o \
|
|
||||||
main.o
|
|
||||||
|
|
||||||
EE_LIBS = -ldraw -lgraph -lmath3d -lpacket -ldma -lpad -laudsrv -lc -lstdc++
|
|
||||||
EE_INCS := -I./../../engine/include $(EE_INCS)
|
|
||||||
EE_DVP = dvp-as
|
|
||||||
EE_VCL = vcl
|
|
||||||
|
|
||||||
all: $(EE_BIN)
|
|
||||||
$(EE_STRIP) --strip-all $(EE_BIN)
|
|
||||||
mv $(EE_BIN) bin/$(EE_BIN)
|
|
||||||
rm $(EE_OBJS)
|
|
||||||
|
|
||||||
# https://github.com/microsoft/wsl/issues/2468#issuecomment-374904520
|
|
||||||
#%.vsm: %.vcl # sudo service binfmt-support start
|
|
||||||
# $(EE_VCL) $< >> $@
|
|
||||||
|
|
||||||
%.o: %.vsm
|
|
||||||
$(EE_DVP) $< -o $@
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f $(EE_OBJS)
|
|
||||||
|
|
||||||
include $(PS2SDK)/samples/Makefile.pref
|
|
||||||
include $(PS2SDK)/samples/Makefile.eeglobal
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
## Ari sample
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
* .obj (skybox, water)
|
|
||||||
* .dff (island)
|
|
||||||
* .md2 (ari)
|
|
||||||
* mesh cloning (water)
|
|
||||||
|
|
||||||
Testing demo. In future there will be Ariana Grande demo.
|
|
||||||
|
|
||||||
### Assets
|
|
||||||
[Download](http://apgcglz.cluster028.hosting.ovh.net/tyra/1.1.0/samples/ari/assets.zip)
|
|
||||||
|
|
||||||
### Screenshot
|
|
||||||
|
|
||||||
[![Ari screenshot][ari-screenshot]](#)
|
|
||||||
|
|
||||||
[ari-screenshot]: http://apgcglz.cluster028.hosting.ovh.net/tyra/1.1.0/samples/ari/ari.gif
|
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
/*
|
|
||||||
# ______ ____ ___
|
|
||||||
# | \/ ____| |___|
|
|
||||||
# | | | \ | |
|
|
||||||
#-----------------------------------------------------------------------
|
|
||||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
|
||||||
# Licenced under Apache License 2.0
|
|
||||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ari.hpp"
|
|
||||||
|
|
||||||
#include "utils/math.hpp"
|
|
||||||
|
|
||||||
// ----
|
|
||||||
// Constructors/Destructors
|
|
||||||
// ----
|
|
||||||
|
|
||||||
Ari::Ari() {}
|
|
||||||
|
|
||||||
Ari::~Ari() {}
|
|
||||||
|
|
||||||
// ----
|
|
||||||
// Methods
|
|
||||||
// ----
|
|
||||||
|
|
||||||
// TEST START
|
|
||||||
const u8 WATER_TILES_COUNT = 64;
|
|
||||||
Mesh *island, *islandAddons, *skybox, *test;
|
|
||||||
Mesh **waterFloors;
|
|
||||||
Point *spirals;
|
|
||||||
|
|
||||||
void 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TEST END
|
|
||||||
|
|
||||||
// TODO 1 - const & in parameters
|
|
||||||
// TODO 2 - Destructor mesh
|
|
||||||
|
|
||||||
void Ari::onInit()
|
|
||||||
{
|
|
||||||
player = new Player();
|
|
||||||
camera = new Camera(&engine.screen);
|
|
||||||
engine.renderer->setCameraDefinitions(&camera->worldView, &camera->unitCirclePosition, camera->planes);
|
|
||||||
engine.audio.init(0);
|
|
||||||
engine.audio.setVolume(40);
|
|
||||||
engine.audio.loadSong("MOV-CIRC.WAV");
|
|
||||||
engine.audio.play();
|
|
||||||
|
|
||||||
texRepo = engine.renderer->getTextureRepository();
|
|
||||||
|
|
||||||
island = new Mesh();
|
|
||||||
island->loadDff("sunnyisl/", "sunnyisl", 0.1F, false);
|
|
||||||
island->rotation.x = -1.6F;
|
|
||||||
island->position.set(0.0F, 10.0F, 20.0F);
|
|
||||||
island->shouldBeBackfaceCulled = true;
|
|
||||||
island->shouldBeFrustumCulled = false;
|
|
||||||
|
|
||||||
islandAddons = new Mesh();
|
|
||||||
islandAddons->loadDff("sunnyisl/", "sunnyisl3", 0.1F, false);
|
|
||||||
islandAddons->rotation.x = -1.6F;
|
|
||||||
islandAddons->position.set(0.0F, 10.0F, 20.0F);
|
|
||||||
|
|
||||||
skybox = new Mesh();
|
|
||||||
skybox->loadObj("skybox/", "skybox", 100.0F, false);
|
|
||||||
skybox->shouldBeFrustumCulled = false;
|
|
||||||
|
|
||||||
waterFloors = new Mesh *[WATER_TILES_COUNT];
|
|
||||||
spirals = new Point[WATER_TILES_COUNT];
|
|
||||||
waterFloors[0] = new Mesh();
|
|
||||||
waterFloors[0]->loadObj("water/", "water", 5.0F, false);
|
|
||||||
waterFloors[0]->position.set(0.0F, 8.0F, 0.0F);
|
|
||||||
texRepo->addByMesh("water/", *waterFloors[0]);
|
|
||||||
for (u8 i = 0; i < WATER_TILES_COUNT; i++)
|
|
||||||
{
|
|
||||||
spirals[i].x = 1.0F;
|
|
||||||
spirals[i].y = 2.0F;
|
|
||||||
}
|
|
||||||
u32 spiralOffset = (u32)Math::sqrt(WATER_TILES_COUNT);
|
|
||||||
calcSpiral(spiralOffset, spiralOffset);
|
|
||||||
for (u8 i = 1; i < WATER_TILES_COUNT; i++)
|
|
||||||
{
|
|
||||||
waterFloors[i] = new Mesh();
|
|
||||||
waterFloors[i]->loadFrom(*waterFloors[0]);
|
|
||||||
waterFloors[i]->position.set(10.0F * spirals[i].x, 8.0F, 10.0F * spirals[i].y);
|
|
||||||
texRepo->getByMesh(waterFloors[0]->getId(), waterFloors[0]->getMaterial(0).getId())
|
|
||||||
->addLink(waterFloors[i]->getId(), waterFloors[i]->getMaterial(0).getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
texRepo->addByMesh("sunnyisl/", *island);
|
|
||||||
texRepo->addByMesh("sunnyisl/", *islandAddons);
|
|
||||||
texRepo->addByMesh("skybox/", *skybox);
|
|
||||||
texRepo->addByMesh("ari/", player->mesh);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Ari::initBulb()
|
|
||||||
{
|
|
||||||
bulb.intensity = 15;
|
|
||||||
bulb.position.set(5.0F, 10.0F, 10.0F);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Ari::onUpdate()
|
|
||||||
{
|
|
||||||
if (engine.pad.isCrossClicked)
|
|
||||||
printf("FPS:%f\n", engine.fps);
|
|
||||||
camera->update(engine.pad, player->mesh);
|
|
||||||
engine.renderer->draw(skybox);
|
|
||||||
engine.renderer->draw(island);
|
|
||||||
engine.renderer->draw(islandAddons);
|
|
||||||
engine.renderer->draw(&player->mesh);
|
|
||||||
for (u8 i = 0; i < WATER_TILES_COUNT; i++)
|
|
||||||
engine.renderer->draw(waterFloors[i]);
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
# ______ ____ ___
|
|
||||||
# | \/ ____| |___|
|
|
||||||
# | | | \ | |
|
|
||||||
#-----------------------------------------------------------------------
|
|
||||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
|
||||||
# Licenced under Apache License 2.0
|
|
||||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "player.hpp"
|
|
||||||
|
|
||||||
#include <loaders/obj_loader.hpp>
|
|
||||||
#include <loaders/bmp_loader.hpp>
|
|
||||||
#include <modules/gif_sender.hpp>
|
|
||||||
#include <utils/debug.hpp>
|
|
||||||
#include <utils/math.hpp>
|
|
||||||
|
|
||||||
// ----
|
|
||||||
// Constructors/Destructors
|
|
||||||
// ----
|
|
||||||
|
|
||||||
Player::Player()
|
|
||||||
{
|
|
||||||
PRINT_LOG("Creating player object");
|
|
||||||
this->gravity = 0.1F;
|
|
||||||
this->lift = -1.0F;
|
|
||||||
this->mesh.loadMD2("ari/", "ari", 0.0001F, true);
|
|
||||||
this->mesh.position.set(0.0F, 10.0F, 0.0F);
|
|
||||||
this->mesh.shouldBeBackfaceCulled = true;
|
|
||||||
this->mesh.shouldBeFrustumCulled = false;
|
|
||||||
this->mesh.shouldBeLighted = true;
|
|
||||||
this->mesh.setAnimSpeed(0.05F);
|
|
||||||
this->mesh.playAnimation(0, 1);
|
|
||||||
PRINT_LOG("Player object created!");
|
|
||||||
}
|
|
||||||
|
|
||||||
Player::~Player()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----
|
|
||||||
// Methods
|
|
||||||
// ----
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
/*
|
|
||||||
# ______ ____ ___
|
|
||||||
# | \/ ____| |___|
|
|
||||||
# | | | \ | |
|
|
||||||
#-----------------------------------------------------------------------
|
|
||||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
|
||||||
# Licenced under Apache License 2.0
|
|
||||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _PLAYER_
|
|
||||||
#define _PLAYER_
|
|
||||||
|
|
||||||
#include "../camera.hpp"
|
|
||||||
#include <modules/pad.hpp>
|
|
||||||
#include <tamtypes.h>
|
|
||||||
|
|
||||||
/** Player 3D object class */
|
|
||||||
class Player
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
float gravity, velocity, lift;
|
|
||||||
u8 isOnFloor, isCollideFloor, indexOfCurrentFloor;
|
|
||||||
Mesh mesh;
|
|
||||||
Player();
|
|
||||||
~Player();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Vector3 playerNextPosition;
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO Rysowanie idzie wg tekstur
|
|
||||||
|
|
||||||
// 2 Graczy, 1 mesh 2 tekstury
|
|
||||||
// sharedFrames = objLoader.load("meshes/", "block", 1.0F);
|
|
||||||
// var addedTextures = texturesRepo.addByMaterialNames("textures/dirt/", sharedFrames);
|
|
||||||
// var addedTexture = texturesRepo.add("textures/blocks/sand.bmp");
|
|
||||||
// dirt = new Mesh(sharedFrames);
|
|
||||||
// sand = new Mesh(sharedFrames);
|
|
||||||
// addedTextures[0].addUsage(dirt.Id, sharedFrames.getMaterialId(0));
|
|
||||||
// addedTexture.addUsage(sand.Id, sand.getMaterialId(0));
|
|
||||||
|
|
||||||
// 1 gracz, 2 dynamic tekstury
|
|
||||||
// sharedFrames = objLoader.load("meshes/", "block", 1.0F);
|
|
||||||
// var addedTexture1 = texturesRepo.add("textures/blocks/sand.bmp");
|
|
||||||
// var addedTexture2 = texturesRepo.add("textures/blocks/sand_damaged.bmp");
|
|
||||||
// sand = new Mesh(sharedFrames);
|
|
||||||
// addedTexture1.removeUsage(sand.Id, sand.getMaterialId(0));
|
|
||||||
// draw()
|
|
||||||
// addedTexture2.addUsage(sand.Id, sand.getMaterialId(0));
|
|
||||||
|
|
||||||
// 2 różne obj, te same tekstury
|
|
||||||
// frames1 = objLoader.load("meshes/", "island", 1.0F);
|
|
||||||
// frames2 = objLoader.load("meshes/", "islandAddons", 1.0F);
|
|
||||||
// island = new Mesh(frames1);
|
|
||||||
// islandAddons = new Mesh(frames2);
|
|
||||||
// var addedTextures1 = texturesRepo.addByMaterialNames("textures/island/",frames1);
|
|
||||||
// var addedTextures2 = texturesRepo.addByMaterialNames("textures/island/",frames2);
|
|
||||||
// texturesRepo.remove(addedTextures2[0]); // duplicate
|
|
||||||
// addedTextures1[0].addUsage(islandAddons.Id, islandAddons.getMaterialId(0));
|
|
||||||
|
|
||||||
// Mesh -> position, rotation, color, scale, shouldBeLighted, clut, lod
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
.vscode/
|
||||||
|
fonts/**
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# Project settings
|
||||||
|
|
||||||
|
DIR_NAME = cube
|
||||||
|
EE_LIBS = -ltyra
|
||||||
|
EE_OBJS = \
|
||||||
|
objects/cube.o \
|
||||||
|
camera.o \
|
||||||
|
cubes.o \
|
||||||
|
main.o
|
||||||
|
|
||||||
|
# ----------------
|
||||||
|
# Other
|
||||||
|
|
||||||
|
EE_BIN = $(DIR_NAME).elf
|
||||||
|
|
||||||
|
all: $(EE_BIN)
|
||||||
|
$(EE_STRIP) --strip-all $(EE_BIN)
|
||||||
|
mv $(EE_BIN) bin/$(EE_BIN)
|
||||||
|
|
||||||
|
rebuild-engine:
|
||||||
|
cd $(TYRA)/src/engine && make clean && make EE_CXXFLAGS="-DNDEBUG $(EE_CXXFLAGS)"
|
||||||
|
|
||||||
|
rebuild-dbg-engine:
|
||||||
|
cd $(TYRA)/src/engine && make clean && make
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(EE_OBJS)
|
||||||
|
|
||||||
|
run:
|
||||||
|
killall -v ps2client || true
|
||||||
|
ps2client reset
|
||||||
|
ps2client reset
|
||||||
|
cd bin/ && ps2client execee host:$(EE_BIN)
|
||||||
|
|
||||||
|
run-pcsx2:
|
||||||
|
taskkill.exe /f /t /im pcsx2.exe || true
|
||||||
|
$(WSL_LINUX_PCSX2)/pcsx2.exe --elf=$(WSL_MAKE_WINDOWS)\\repos\\tyra\\src\\samples\\$(DIR_NAME)\\bin\\$(EE_BIN)
|
||||||
|
|
||||||
|
include $(TYRA)/src/engine/Makefile.pref
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
## Cube Sample
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- Rotating Cube
|
||||||
|
|
||||||
|
### Assets
|
||||||
|
You can download assets from [latest release](https://github.com/h4570/tyra/releases/latest) (unpack to `/repos/tyra/src/samples/cube/bin`)
|
||||||
|
|
||||||
|
### Screenshot
|
||||||
|
|
||||||
|
[![Cube screenshot][Cube-screenshot]](#)
|
||||||
|
|
||||||
|
[Cube-screenshot]: http://apgcglz.cluster028.hosting.ovh.net/tyra/cube.gif
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# Ignore everything in this directory
|
||||||
|
*
|
||||||
|
# Except this file
|
||||||
|
!.gitignore
|
||||||
@@ -5,28 +5,25 @@
|
|||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
# Licenced under Apache License 2.0
|
# Licenced under Apache License 2.0
|
||||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
# Wellington Carvalho <wellcoj@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "camera.hpp"
|
#include "camera.hpp"
|
||||||
|
|
||||||
#include <utils/math.hpp>
|
|
||||||
#include <utils/debug.hpp>
|
#include <utils/debug.hpp>
|
||||||
|
#include <fastmath.h>
|
||||||
|
|
||||||
const float CAMERA_Y = 15.0F;
|
const float CAMERA_Y = 30.0F;
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
// Constructors/Destructors
|
// Constructors/Destructors
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
Camera::Camera(ScreenSettings *t_screen) : CameraBase(t_screen, &position, &up, &unitCirclePosition)
|
Camera::Camera(ScreenSettings *t_screen) : CameraBase(t_screen, &position)
|
||||||
{
|
{
|
||||||
PRINT_LOG("Initializing camera");
|
consoleLog("Initializing camera");
|
||||||
verticalLevel = 80.0F;
|
verticalLevel = 80.0F;
|
||||||
up.x = 0.0F;
|
consoleLog("Camera initialized!");
|
||||||
up.y = 1.0F;
|
|
||||||
up.z = 0.0F;
|
|
||||||
PRINT_LOG("Camera initialized!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Camera::~Camera() {}
|
Camera::~Camera() {}
|
||||||
@@ -39,9 +36,7 @@ void Camera::update(Pad &t_pad, Mesh &t_mesh)
|
|||||||
{
|
{
|
||||||
rotate(t_pad);
|
rotate(t_pad);
|
||||||
followBy(t_mesh);
|
followBy(t_mesh);
|
||||||
updatePlanes(t_mesh.position); // TODO move it out
|
lookAt(t_mesh.position);
|
||||||
Vector3 newPos = Vector3(t_mesh.position.x, t_mesh.position.y + 10.0F, t_mesh.position.z);
|
|
||||||
worldView.lookAt(up, position, newPos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set camera rotation by pad right joy and update unit circle
|
/** Set camera rotation by pad right joy and update unit circle
|
||||||
@@ -50,17 +45,17 @@ void Camera::update(Pad &t_pad, Mesh &t_mesh)
|
|||||||
*/
|
*/
|
||||||
void Camera::rotate(Pad &t_pad)
|
void Camera::rotate(Pad &t_pad)
|
||||||
{
|
{
|
||||||
if (t_pad.rJoyH <= 50)
|
if (t_pad.rJoyH <= 100)
|
||||||
horizontalLevel -= 0.08;
|
horizontalLevel -= 0.08;
|
||||||
else if (t_pad.rJoyH >= 200)
|
else if (t_pad.rJoyH >= 200)
|
||||||
horizontalLevel += 0.04;
|
horizontalLevel += 0.08;
|
||||||
if (t_pad.rJoyV <= 50 && verticalLevel > 25.0F)
|
if (t_pad.rJoyV <= 50 && verticalLevel > 25.0F)
|
||||||
verticalLevel -= 0.9F;
|
verticalLevel -= 0.9F;
|
||||||
else if (t_pad.rJoyV >= 200 && verticalLevel < 80.0F)
|
else if (t_pad.rJoyV >= 200 && verticalLevel < 80.0F)
|
||||||
verticalLevel += 0.9F;
|
verticalLevel += 0.9F;
|
||||||
unitCirclePosition.x = (Math::sin(horizontalLevel) * verticalLevel);
|
unitCirclePosition.x = (sin(horizontalLevel) * verticalLevel);
|
||||||
unitCirclePosition.y = CAMERA_Y;
|
unitCirclePosition.y = CAMERA_Y;
|
||||||
unitCirclePosition.z = (Math::cos(horizontalLevel) * verticalLevel);
|
unitCirclePosition.z = (cos(horizontalLevel) * verticalLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Rotate camera around 3D object */
|
/** Rotate camera around 3D object */
|
||||||
@@ -69,15 +64,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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
# Licenced under Apache License 2.0
|
# Licenced under Apache License 2.0
|
||||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
# Wellington Carvalho <wellcoj@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _CAMERA_
|
#ifndef _CAMERA_
|
||||||
@@ -35,7 +35,6 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
Vector3 *getPosition() { return &position; };
|
Vector3 *getPosition() { return &position; };
|
||||||
Vector3 *getUp() { return &up; };
|
|
||||||
ScreenSettings screen;
|
ScreenSettings screen;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Wellington Carvalho <wellcoj@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cubes.hpp"
|
||||||
|
|
||||||
|
Cubes::Cubes(Engine *t_engine)
|
||||||
|
: engine(t_engine), camera(&t_engine->screen)
|
||||||
|
{
|
||||||
|
consoleLog("Initing cubes sample");
|
||||||
|
}
|
||||||
|
|
||||||
|
Cubes::~Cubes()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cubes::onInit()
|
||||||
|
{
|
||||||
|
texRepo = engine->renderer->getTextureRepository();
|
||||||
|
cube = new Cube(texRepo);
|
||||||
|
setBgColorAndAmbientColor();
|
||||||
|
engine->renderer->setCameraDefinitions(&camera.view, &camera.unitCirclePosition, camera.planes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cubes::onUpdate()
|
||||||
|
{
|
||||||
|
camera.update(engine->pad, cube->mesh);
|
||||||
|
cube->update(engine->pad, camera);
|
||||||
|
engine->renderer->draw(cube->mesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cubes::setBgColorAndAmbientColor()
|
||||||
|
{
|
||||||
|
color_t bgColor;
|
||||||
|
bgColor.r = 0x20;
|
||||||
|
bgColor.g = 0x20;
|
||||||
|
bgColor.b = 0x20;
|
||||||
|
engine->renderer->setWorldColor(bgColor);
|
||||||
|
Vector3 ambient = Vector3(0.2F, 0.2F, 0.2F);
|
||||||
|
engine->renderer->setAmbientLight(ambient);
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Wellington Carvalho <wellcoj@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CUBES_
|
||||||
|
#define _CUBES_
|
||||||
|
|
||||||
|
#include <tamtypes.h>
|
||||||
|
#include <game.hpp>
|
||||||
|
#include <engine.hpp>
|
||||||
|
#include "modules/texture_repository.hpp"
|
||||||
|
#include "camera.hpp"
|
||||||
|
#include "objects/cube.hpp"
|
||||||
|
|
||||||
|
class Cubes : public Game
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
Cubes(Engine *t_engine);
|
||||||
|
~Cubes();
|
||||||
|
|
||||||
|
void onInit();
|
||||||
|
void onUpdate();
|
||||||
|
|
||||||
|
Engine *engine;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setBgColorAndAmbientColor();
|
||||||
|
TextureRepository *texRepo;
|
||||||
|
Cube *cube;
|
||||||
|
Camera camera;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -5,16 +5,16 @@
|
|||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
# Licenced under Apache License 2.0
|
# Licenced under Apache License 2.0
|
||||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
# Wellington Carvalho <wellcoj@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ari.hpp"
|
#include "cubes.hpp"
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
Ari game = Ari();
|
Engine engine = Engine();
|
||||||
game.engine.setDefaultScreen();
|
Cubes game = Cubes(&engine);
|
||||||
game.engine.init(&game, 40000);
|
game.engine->init(&game, 128);
|
||||||
SleepThread();
|
SleepThread();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Wellington Carvalho <wellcoj@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cube.hpp"
|
||||||
|
#include <models/mesh.hpp>
|
||||||
|
#include <loaders/obj_loader.hpp>
|
||||||
|
#include <utils/debug.hpp>
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Constructors/Destructors
|
||||||
|
// ----
|
||||||
|
|
||||||
|
Cube::Cube(TextureRepository *t_texRepo)
|
||||||
|
{
|
||||||
|
consoleLog("Creating cube");
|
||||||
|
texRepo = t_texRepo;
|
||||||
|
speed = 1.2F;
|
||||||
|
|
||||||
|
mesh.loadObj("meshes/cube/", "cube", 10.0F, true);
|
||||||
|
mesh.position.set(20.00F, 40.00F, 10.00F);
|
||||||
|
mesh.rotation.x = -1.566F;
|
||||||
|
mesh.rotation.z = 1.566F;
|
||||||
|
|
||||||
|
texRepo->addByMesh("meshes/cube/", mesh, PNG);
|
||||||
|
|
||||||
|
consoleLog("Cube object created!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cube::update(const Pad &t_pad, const Camera &t_camera)
|
||||||
|
{
|
||||||
|
rotate(t_pad);
|
||||||
|
Vector3 *nextPos = getNextPosition(t_pad, t_camera);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 *Cube::getNextPosition(const Pad &t_pad, const Camera &t_camera)
|
||||||
|
{
|
||||||
|
Vector3 *result = new Vector3(mesh.position);
|
||||||
|
Vector3 normalizedCamera = Vector3(t_camera.unitCirclePosition);
|
||||||
|
normalizedCamera.normalize();
|
||||||
|
normalizedCamera *= speed;
|
||||||
|
if (t_pad.lJoyV <= 100)
|
||||||
|
{
|
||||||
|
result->x += -normalizedCamera.x;
|
||||||
|
result->z += -normalizedCamera.z;
|
||||||
|
}
|
||||||
|
else if (t_pad.lJoyV >= 200)
|
||||||
|
{
|
||||||
|
result->x += normalizedCamera.x;
|
||||||
|
result->z += normalizedCamera.z;
|
||||||
|
}
|
||||||
|
if (t_pad.lJoyH <= 100)
|
||||||
|
{
|
||||||
|
result->x += -normalizedCamera.z;
|
||||||
|
result->z += normalizedCamera.x;
|
||||||
|
}
|
||||||
|
else if (t_pad.lJoyH >= 200)
|
||||||
|
{
|
||||||
|
result->x += normalizedCamera.z;
|
||||||
|
result->z += -normalizedCamera.x;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cube::rotate(const Pad &t_pad)
|
||||||
|
{
|
||||||
|
//if (t_pad.rJoyH >= 200)
|
||||||
|
//else if (t_pad.rJoyH <= 100)
|
||||||
|
mesh.rotation.x += (0.01 * speed);
|
||||||
|
mesh.rotation.y += (0.01 * speed);
|
||||||
|
mesh.rotation.z += (0.01 * speed);
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Wellington Carvalho <wellcoj@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CUBE_
|
||||||
|
#define _CUBE_
|
||||||
|
|
||||||
|
#include "../camera.hpp"
|
||||||
|
#include <tamtypes.h>
|
||||||
|
#include <modules/pad.hpp>
|
||||||
|
#include <modules/timer.hpp>
|
||||||
|
#include "modules/texture_repository.hpp"
|
||||||
|
|
||||||
|
/** Cube 3D object class */
|
||||||
|
class Cube
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Mesh mesh;
|
||||||
|
Cube( TextureRepository *t_texRepo );
|
||||||
|
~Cube();
|
||||||
|
|
||||||
|
void update(const Pad &t_pad, const Camera &t_camera);
|
||||||
|
|
||||||
|
private:
|
||||||
|
TextureRepository *texRepo;
|
||||||
|
Vector3 *getNextPosition(const Pad &t_pad, const Camera &t_camera);
|
||||||
|
void rotate(const Pad &t_pad);
|
||||||
|
float speed;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
.vscode/
|
||||||
|
fonts/**
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
# Project settings
|
||||||
|
|
||||||
|
DIR_NAME = dolphin
|
||||||
|
EE_LIBS = -ltyra
|
||||||
|
EE_OBJS = \
|
||||||
|
camera.o \
|
||||||
|
objects/player.o \
|
||||||
|
objects/collectible.o \
|
||||||
|
objects/mine.o \
|
||||||
|
dolphin.o \
|
||||||
|
main.o
|
||||||
|
|
||||||
|
# ----------------
|
||||||
|
# Other
|
||||||
|
|
||||||
|
EE_BIN = $(DIR_NAME).elf
|
||||||
|
|
||||||
|
all: $(EE_BIN)
|
||||||
|
$(EE_STRIP) --strip-all $(EE_BIN)
|
||||||
|
mv $(EE_BIN) bin/$(EE_BIN)
|
||||||
|
|
||||||
|
rebuild-engine:
|
||||||
|
cd $(TYRA)/src/engine && make clean && make EE_CXXFLAGS="-DNDEBUG $(EE_CXXFLAGS)"
|
||||||
|
|
||||||
|
rebuild-dbg-engine:
|
||||||
|
cd $(TYRA)/src/engine && make clean && make
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(EE_OBJS)
|
||||||
|
|
||||||
|
run:
|
||||||
|
killall -v ps2client || true
|
||||||
|
ps2client reset
|
||||||
|
ps2client reset
|
||||||
|
cd bin/ && ps2client execee host:$(EE_BIN)
|
||||||
|
|
||||||
|
run-pcsx2:
|
||||||
|
taskkill.exe /f /t /im pcsx2.exe || true
|
||||||
|
$(WSL_LINUX_PCSX2)/pcsx2.exe --elf=$(WSL_MAKE_WINDOWS)\\repos\\tyra\\src\\samples\\$(DIR_NAME)\\bin\\$(EE_BIN)
|
||||||
|
|
||||||
|
include $(TYRA)/src/engine/Makefile.pref
|
||||||
@@ -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
|
||||||
|
You can download assets from [latest release](https://github.com/h4570/tyra/releases/latest) (unpack to `/repos/tyra/src/samples/dolphin/bin`)
|
||||||
|
|
||||||
|
### Screenshot
|
||||||
|
|
||||||
|
[![Dolphin screenshot][dolphin-screenshot]](#)
|
||||||
|
|
||||||
|
[dolphin-screenshot]: http://apgcglz.cluster028.hosting.ovh.net/tyra/dolphin.gif
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# Ignore everything in this directory
|
||||||
|
*
|
||||||
|
# Except this file
|
||||||
|
!.gitignore
|
||||||
Executable
+54
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Michał Mostowik <mostek3pl@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "camera.hpp"
|
||||||
|
|
||||||
|
#include <utils/math.hpp>
|
||||||
|
|
||||||
|
const float CAMERA_Y = 25.0F;
|
||||||
|
|
||||||
|
Camera::Camera(ScreenSettings *t_screen) : CameraBase(t_screen, &position)
|
||||||
|
{
|
||||||
|
verticalLevel = 30.0F;
|
||||||
|
}
|
||||||
|
|
||||||
|
Camera::~Camera() {}
|
||||||
|
|
||||||
|
void Camera::update(Pad &t_pad, Mesh &t_mesh)
|
||||||
|
{
|
||||||
|
float cameraRot = (t_mesh.rotation.z * 180 / Math::PI) - (horizontalLevel * 180 / Math::PI);
|
||||||
|
cameraRot += 180;
|
||||||
|
cameraRot /= 15;
|
||||||
|
horizontalLevel += cameraRot / (180 / Math::PI);
|
||||||
|
rotate(t_pad);
|
||||||
|
followBy(t_mesh);
|
||||||
|
Vector3 lookPos = Vector3(t_mesh.position.x, t_mesh.position.y + 10.0F, t_mesh.position.z);
|
||||||
|
lookAt(lookPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Camera::rotate(Pad &t_pad)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (t_pad.rJoyH <= 100)
|
||||||
|
horizontalLevel -= 0.08;
|
||||||
|
else if (t_pad.rJoyH >= 200)
|
||||||
|
horizontalLevel += 0.08;
|
||||||
|
|
||||||
|
unitCirclePosition.x = (Math::sin(horizontalLevel) * verticalLevel);
|
||||||
|
unitCirclePosition.y = CAMERA_Y;
|
||||||
|
unitCirclePosition.z = (Math::cos(horizontalLevel) * verticalLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Camera::followBy(Mesh &t_mesh)
|
||||||
|
{
|
||||||
|
position.x = unitCirclePosition.x + t_mesh.position.x;
|
||||||
|
position.y = unitCirclePosition.y + t_mesh.position.y;
|
||||||
|
position.z = unitCirclePosition.z + t_mesh.position.z;
|
||||||
|
}
|
||||||
Executable
+40
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Michał Mostowik <mostek3pl@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CAMERA_
|
||||||
|
#define _CAMERA_
|
||||||
|
|
||||||
|
#include <modules/pad.hpp>
|
||||||
|
#include <models/mesh.hpp>
|
||||||
|
#include <models/math/vector3.hpp>
|
||||||
|
#include <models/screen_settings.hpp>
|
||||||
|
#include <modules/camera_base.hpp>
|
||||||
|
#include <tamtypes.h>
|
||||||
|
|
||||||
|
class Camera : public CameraBase
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
Vector3 position, up, unitCirclePosition;
|
||||||
|
float horizontalLevel, verticalLevel;
|
||||||
|
|
||||||
|
Camera(ScreenSettings *t_screen);
|
||||||
|
~Camera();
|
||||||
|
|
||||||
|
void update(Pad &t_pad, Mesh &t_mesh);
|
||||||
|
void rotate(Pad &t_pad);
|
||||||
|
void followBy(Mesh &t_mesh);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Vector3 *getPosition() { return &position; };
|
||||||
|
ScreenSettings screen;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
Executable
+300
@@ -0,0 +1,300 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Michał Mostowik <mostek3pl@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dolphin.hpp"
|
||||||
|
#include "utils/math.hpp"
|
||||||
|
|
||||||
|
float Dolphin::engineFPS = 60.0F;
|
||||||
|
const float WATER_TILE_SCALE = 6.0F;
|
||||||
|
const u8 WATER_SIZE = 4;
|
||||||
|
const u8 MINES_COUNT = 15;
|
||||||
|
const u8 OYSTERS_COUNT = 5;
|
||||||
|
|
||||||
|
Dolphin::Dolphin(Engine *t_engine) : engine(t_engine), camera(&engine->screen)
|
||||||
|
{
|
||||||
|
oysters = new Collectible[OYSTERS_COUNT];
|
||||||
|
mines = new Mine[MINES_COUNT];
|
||||||
|
}
|
||||||
|
|
||||||
|
Dolphin::~Dolphin()
|
||||||
|
{
|
||||||
|
delete[] oysters;
|
||||||
|
delete[] mines;
|
||||||
|
delete[] waterDrawList;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dolphin::onInit()
|
||||||
|
{
|
||||||
|
player.init(engine);
|
||||||
|
engine->renderer->setCameraDefinitions(&camera.view, &camera.position, camera.planes);
|
||||||
|
|
||||||
|
engine->audio.loadSong("sound/dirediredocks.wav");
|
||||||
|
engine->audio.playSong();
|
||||||
|
engine->audio.setSongVolume(60);
|
||||||
|
|
||||||
|
surfaceAmbient = engine->audio.loadADPCM("sound/surface.sad");
|
||||||
|
underwaterAmbient = engine->audio.loadADPCM("sound/underwater.sad");
|
||||||
|
pickupSound = engine->audio.loadADPCM("sound/pickup.sad");
|
||||||
|
boomSound = engine->audio.loadADPCM("sound/boom.sad");
|
||||||
|
|
||||||
|
engine->audio.playADPCM(surfaceAmbient, 0);
|
||||||
|
engine->audio.playADPCM(underwaterAmbient, 1);
|
||||||
|
|
||||||
|
texRepo = engine->renderer->getTextureRepository();
|
||||||
|
|
||||||
|
engine->renderer->disableVSync();
|
||||||
|
|
||||||
|
printf("loading island..\n");
|
||||||
|
island.loadDff("sunnyisl/", "sunnyisl", 5.0F, false);
|
||||||
|
printf("Loaded..\n");
|
||||||
|
island.rotation.x = -1.6F;
|
||||||
|
island.position.set(0.0F, 60.0F, 20.0F);
|
||||||
|
island.shouldBeBackfaceCulled = true;
|
||||||
|
island.shouldBeFrustumCulled = false;
|
||||||
|
|
||||||
|
gameOver.size.set(640.0F, 480.0F);
|
||||||
|
Texture *gameOverTex = texRepo->add("2d/", "gameover", PNG);
|
||||||
|
gameOver.setMode(MODE_STRETCH);
|
||||||
|
gameOverTex->addLink(gameOver.getId());
|
||||||
|
|
||||||
|
printf("Loading water overlay...\n");
|
||||||
|
waterOverlay.size.set(640.0F, 480.0F);
|
||||||
|
Texture *watOverlayTex = texRepo->add("2d/", "underwater_overlay", PNG);
|
||||||
|
waterOverlay.setMode(MODE_STRETCH);
|
||||||
|
watOverlayTex->addLink(waterOverlay.getId());
|
||||||
|
printf("Loaded.\n");
|
||||||
|
|
||||||
|
printf("Loading water...\n");
|
||||||
|
|
||||||
|
u32 spiralOffset = (u32)sqrt(WATER_TILES_COUNT);
|
||||||
|
waterDrawList = new Mesh *[WATER_TILES_COUNT];
|
||||||
|
calcSpiral(spiralOffset, spiralOffset);
|
||||||
|
water[0].loadObj("water/", "water", WATER_TILE_SCALE, false);
|
||||||
|
water[0].position.set(0.0F, WATER_LEVEL, 0.0F);
|
||||||
|
texRepo->addByMesh("water/", water[0], BMP);
|
||||||
|
water[0].shouldBeFrustumCulled = true;
|
||||||
|
water[0].shouldBeBackfaceCulled = false;
|
||||||
|
waterDrawList[0] = &water[0];
|
||||||
|
for (size_t i = 1; i < WATER_TILES_COUNT; i++)
|
||||||
|
{
|
||||||
|
water[i].loadFrom(water[0]);
|
||||||
|
water[i].shouldBeFrustumCulled = true;
|
||||||
|
water[i].shouldBeBackfaceCulled = false;
|
||||||
|
water[i].position.set(WATER_TILE_SCALE * 2.0F * spirals[i].x, WATER_LEVEL, WATER_TILE_SCALE * 2.0F * spirals[i].y);
|
||||||
|
texRepo->getBySpriteOrMesh(water[0].getMaterial(0).getId())->addLink(water[i].getMaterial(0).getId());
|
||||||
|
waterDrawList[i] = &water[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Loading seabed...\n");
|
||||||
|
seabed.loadObj("seabed/", "seabed", 10.0F, false);
|
||||||
|
seabed.position.set(0, -250.0F, 0);
|
||||||
|
texRepo->addByMesh("seabed/", seabed, BMP);
|
||||||
|
seabed.shouldBeBackfaceCulled = false;
|
||||||
|
seabed.shouldBeFrustumCulled = false;
|
||||||
|
|
||||||
|
skybox.loadObj("skybox/", "skybox", 400.0F, false);
|
||||||
|
skybox.shouldBeFrustumCulled = false;
|
||||||
|
|
||||||
|
waterbox.loadObj("waterbox/", "waterbox", 250.0F, false);
|
||||||
|
waterbox.shouldBeFrustumCulled = false;
|
||||||
|
waterbox.shouldBeBackfaceCulled = false;
|
||||||
|
waterbox.rotation.x = Math::PI;
|
||||||
|
waterbox.position.y = -100.F;
|
||||||
|
|
||||||
|
printf("Loading oyster dff\n");
|
||||||
|
oysters[0].mesh.loadObj("oyster/", "oyster", 10.F, false);
|
||||||
|
printf("Loaded.");
|
||||||
|
oysters[0].mesh.shouldBeBackfaceCulled = false;
|
||||||
|
oysters[0].mesh.shouldBeFrustumCulled = false;
|
||||||
|
oysters[0].mesh.position.set(15, 0, 15);
|
||||||
|
texRepo->addByMesh("oyster/", oysters[0].mesh, BMP);
|
||||||
|
printf("Adding oyster texture.\n");
|
||||||
|
for (int i = 1; i < OYSTERS_COUNT; i++)
|
||||||
|
{
|
||||||
|
printf("Processing oyster %d\n", i);
|
||||||
|
oysters[i].mesh.loadFrom(oysters[0].mesh);
|
||||||
|
oysters[i].mesh.shouldBeBackfaceCulled = false;
|
||||||
|
oysters[i].mesh.shouldBeFrustumCulled = false;
|
||||||
|
texRepo->getBySpriteOrMesh(oysters[0].mesh.getMaterial(0).getId())->addLink(oysters[i].mesh.getMaterial(0).getId());
|
||||||
|
oysters[i].mesh.position.set(i * -100, 5.0F, i * -100);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Loading mine .obj\n");
|
||||||
|
mines[0].mesh.loadObj("mine/", "mine", 10.F, false);
|
||||||
|
mines[0].mesh.shouldBeBackfaceCulled = false;
|
||||||
|
mines[0].mesh.shouldBeFrustumCulled = false;
|
||||||
|
mines[0].mesh.position.set(5, -15, 32);
|
||||||
|
texRepo->addByMesh("mine/", mines[0].mesh, BMP);
|
||||||
|
printf("Adding mine texture.\n");
|
||||||
|
for (int i = 1; i < MINES_COUNT; i++)
|
||||||
|
{
|
||||||
|
printf("Processing mine %d\n", i);
|
||||||
|
mines[i].mesh.loadFrom(mines[0].mesh);
|
||||||
|
mines[i].mesh.shouldBeBackfaceCulled = false;
|
||||||
|
mines[i].mesh.shouldBeFrustumCulled = false;
|
||||||
|
texRepo->getBySpriteOrMesh(mines[0].mesh.getMaterial(0).getId())->addLink(mines[i].mesh.getMaterial(0).getId());
|
||||||
|
mines[i].mesh.position.set(i * -10, 0.0F, i * -68);
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture *pLifeTex = texRepo->add("2d/", "life", PNG);
|
||||||
|
// pLifeTex->addLink(lifeSprites[0].getId());
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
lifeSprites[i].size.set(64.0F, 64.0F);
|
||||||
|
lifeSprites[i].setMode(MODE_STRETCH);
|
||||||
|
lifeSprites[i].position.set(395 + (64 * i), 0);
|
||||||
|
pLifeTex->addLink(lifeSprites[i].getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
texRepo->addByMesh("dolphin/", player.mesh, BMP);
|
||||||
|
texRepo->addByMesh("sunnyisl/", island, BMP);
|
||||||
|
texRepo->addByMesh("skybox/", skybox, BMP);
|
||||||
|
texRepo->addByMesh("waterbox/", waterbox, BMP);
|
||||||
|
|
||||||
|
bulb.intensity = 55;
|
||||||
|
bulb.position.set(5.0F, 10.0F, 10.0f);
|
||||||
|
printf("Finished initialization\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dolphin::onUpdate()
|
||||||
|
{
|
||||||
|
if (player.getLifes() <= 0)
|
||||||
|
{
|
||||||
|
engine->audio.stopSong();
|
||||||
|
engine->audio.setADPCMVolume(0, 0);
|
||||||
|
engine->audio.setADPCMVolume(75, 1);
|
||||||
|
engine->renderer->draw(gameOver);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dolphin::engineFPS = engine->fps;
|
||||||
|
// if (engine->pad.isCrossClicked)
|
||||||
|
// printf("Delta multiplier: %f\n", 60.0F / engine->fps);
|
||||||
|
|
||||||
|
float xDist = player.mesh.position.x - water[0].position.x;
|
||||||
|
float zDist = player.mesh.position.z - water[0].position.z;
|
||||||
|
if (xDist < 0)
|
||||||
|
xDist *= -1;
|
||||||
|
if (zDist < 0)
|
||||||
|
zDist *= -1;
|
||||||
|
if (xDist > WATER_SIZE * WATER_TILE_SCALE / 4 ||
|
||||||
|
zDist > WATER_SIZE * WATER_TILE_SCALE / 4)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < WATER_TILES_COUNT; i++)
|
||||||
|
{
|
||||||
|
water[i].position.x = player.mesh.position.x + (WATER_TILE_SCALE * 2.0F * spirals[i].x);
|
||||||
|
water[i].position.z = player.mesh.position.z + (WATER_TILE_SCALE * 2.0F * spirals[i].y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < OYSTERS_COUNT; i++)
|
||||||
|
{
|
||||||
|
oysters[i].update();
|
||||||
|
Vector3 vecDist = oysters[i].mesh.position - player.mesh.position;
|
||||||
|
float dist = vecDist.length();
|
||||||
|
if (dist < 20.F && player.isJumping() && oysters[i].isActive())
|
||||||
|
{
|
||||||
|
printf("Pickup:%d Dist:%f\n", i, dist);
|
||||||
|
oysters[i].disappear();
|
||||||
|
player.setLife(player.getLifes() + 1);
|
||||||
|
engine->audio.setADPCMVolume(30, 3);
|
||||||
|
engine->audio.playADPCM(pickupSound, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < MINES_COUNT; i++)
|
||||||
|
{
|
||||||
|
mines[i].update();
|
||||||
|
Vector3 vecDist = mines[i].mesh.position - player.mesh.position;
|
||||||
|
float dist = vecDist.length();
|
||||||
|
|
||||||
|
if (dist < 20.F && !mines[i].getExplosionTicks())
|
||||||
|
{
|
||||||
|
printf("Vecdist: %f,%f,%f\n", vecDist.x, vecDist.y, vecDist.z);
|
||||||
|
printf("Explode:%d Dist:%f\n", i, dist);
|
||||||
|
mines[i].explode();
|
||||||
|
player.setLife(player.getLifes() - 1);
|
||||||
|
// Buffer switching to prevent playing two sounds on one buffer
|
||||||
|
engine->audio.setADPCMVolume(65, Mine::lastSoundBuffer);
|
||||||
|
engine->audio.playADPCM(boomSound, Mine::lastSoundBuffer);
|
||||||
|
Mine::lastSoundBuffer = Mine::lastSoundBuffer == 4 ? 5 : 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.mesh.position.y > WATER_LEVEL - 5)
|
||||||
|
player.mesh.position.y = WATER_LEVEL - 5;
|
||||||
|
|
||||||
|
player.update(engine->pad);
|
||||||
|
camera.update(engine->pad, player.mesh);
|
||||||
|
|
||||||
|
skybox.position.set(player.mesh.position.x, +200.0F, player.mesh.position.z);
|
||||||
|
waterbox.position.set(player.mesh.position.x, -260.0F, player.mesh.position.z);
|
||||||
|
|
||||||
|
engine->renderer->draw(island);
|
||||||
|
|
||||||
|
for (int i = 0; i < WATER_TILES_COUNT; i++)
|
||||||
|
{
|
||||||
|
engine->renderer->draw(*waterDrawList[i]);
|
||||||
|
}
|
||||||
|
engine->renderer->draw(skybox);
|
||||||
|
engine->renderer->draw(waterbox);
|
||||||
|
engine->renderer->draw(seabed);
|
||||||
|
|
||||||
|
for (u8 i = 0; i < OYSTERS_COUNT; i++)
|
||||||
|
if (oysters[i].isActive())
|
||||||
|
engine->renderer->draw(oysters[i].mesh);
|
||||||
|
|
||||||
|
for (u8 i = 0; i < MINES_COUNT; i++)
|
||||||
|
if (mines[i].getExplosionTicks() < MINE_EXPLOSION_TICKS)
|
||||||
|
engine->renderer->draw(mines[i].mesh);
|
||||||
|
|
||||||
|
for (u8 i = 0; i < player.getLifes(); i++)
|
||||||
|
engine->renderer->draw(lifeSprites[i]);
|
||||||
|
|
||||||
|
engine->renderer->draw(player.mesh);
|
||||||
|
|
||||||
|
if (camera.position.y < WATER_LEVEL)
|
||||||
|
{
|
||||||
|
engine->renderer->draw(waterOverlay);
|
||||||
|
engine->audio.setADPCMVolume(0, 0); // Surface ambient
|
||||||
|
engine->audio.setADPCMVolume(65, 1); // Underwater ambient
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
engine->audio.setADPCMVolume(50, 0); //Surface ambient
|
||||||
|
engine->audio.setADPCMVolume(0, 1); //Underwater ambient
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dolphin::calcSpiral(int X, int Y)
|
||||||
|
{
|
||||||
|
int x, y, dx;
|
||||||
|
x = y = dx = 0;
|
||||||
|
int dy = -1;
|
||||||
|
int t = X > Y ? X : Y;
|
||||||
|
int maxI = t * t;
|
||||||
|
for (int i = 0; i < maxI; i++)
|
||||||
|
{
|
||||||
|
if ((-X / 2 <= x) && (x <= X / 2) && (-Y / 2 <= y) && (y <= Y / 2))
|
||||||
|
{
|
||||||
|
spirals[i].x = x;
|
||||||
|
spirals[i].y = y;
|
||||||
|
}
|
||||||
|
if ((x == y) || ((x < 0) && (x == -y)) || ((x > 0) && (x == 1 - y)))
|
||||||
|
{
|
||||||
|
t = dx;
|
||||||
|
dx = -dy;
|
||||||
|
dy = t;
|
||||||
|
}
|
||||||
|
x += dx;
|
||||||
|
y += dy;
|
||||||
|
}
|
||||||
|
}
|
||||||
Executable
+69
@@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Michał Mostowik <mostek3pl@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _DRIVER_
|
||||||
|
#define _DRIVER_
|
||||||
|
|
||||||
|
#include <tamtypes.h>
|
||||||
|
#include <audsrv.h>
|
||||||
|
#include <game.hpp>
|
||||||
|
#include <engine.hpp>
|
||||||
|
#include <models/light_bulb.hpp>
|
||||||
|
#include <models/sprite.hpp>
|
||||||
|
#include <modules/texture_repository.hpp>
|
||||||
|
#include "./camera.hpp"
|
||||||
|
#include "./objects/player.hpp"
|
||||||
|
#include "./objects/collectible.hpp"
|
||||||
|
#include "./objects/mine.hpp"
|
||||||
|
|
||||||
|
class Dolphin : public Game
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
Dolphin(Engine *t_engine);
|
||||||
|
~Dolphin();
|
||||||
|
|
||||||
|
void onInit();
|
||||||
|
void onUpdate();
|
||||||
|
|
||||||
|
Engine *engine;
|
||||||
|
static float engineFPS;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void calcSpiral(int X, int Y);
|
||||||
|
static const u16 WATER_TILES_COUNT = 1024;
|
||||||
|
|
||||||
|
Point spirals[WATER_TILES_COUNT];
|
||||||
|
Mesh **waterDrawList;
|
||||||
|
/**
|
||||||
|
* DO NOT TOUCH ORDER OF DECLARATION!
|
||||||
|
* GCC BUG CAUSES RENDERING TO FAIL IN ANY OTHER ORDER OF DECLARATION!
|
||||||
|
*/
|
||||||
|
Mesh seabed;
|
||||||
|
Mesh island;
|
||||||
|
Mesh skybox;
|
||||||
|
Mesh mine;
|
||||||
|
LightBulb bulb;
|
||||||
|
Player player;
|
||||||
|
Camera camera;
|
||||||
|
Collectible *oysters;
|
||||||
|
TextureRepository *texRepo;
|
||||||
|
Sprite waterOverlay;
|
||||||
|
Mesh water[WATER_TILES_COUNT];
|
||||||
|
Mesh waterbox;
|
||||||
|
Sprite lifeSprites[3];
|
||||||
|
Sprite gameOver;
|
||||||
|
audsrv_adpcm_t *underwaterAmbient, *surfaceAmbient;
|
||||||
|
audsrv_adpcm_t *pickupSound;
|
||||||
|
audsrv_adpcm_t *boomSound;
|
||||||
|
Mine *mines;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
Executable
+21
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Michał Mostowik <mostek3pl@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dolphin.hpp"
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Engine engine = Engine();
|
||||||
|
engine.screen.fov = 75.F;
|
||||||
|
Dolphin game = Dolphin(&engine);
|
||||||
|
game.engine->init(&game, 128);
|
||||||
|
SleepThread();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Michał Mostowik <mostek3pl@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "collectible.hpp"
|
||||||
|
|
||||||
|
#include <loaders/obj_loader.hpp>
|
||||||
|
#include <loaders/bmp_loader.hpp>
|
||||||
|
#include <modules/gif_sender.hpp>
|
||||||
|
#include <utils/debug.hpp>
|
||||||
|
#include <utils/math.hpp>
|
||||||
|
|
||||||
|
Collectible::Collectible()
|
||||||
|
{
|
||||||
|
mesh.loadObj("oyster/", "oyster", 10.F, false);
|
||||||
|
mesh.shouldBeFrustumCulled = false;
|
||||||
|
mesh.position.set(0.0F, 0.0F, 0.0f);
|
||||||
|
bActive = true;
|
||||||
|
bDisappearing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Collectible::disappear()
|
||||||
|
{
|
||||||
|
bDisappearing = true;
|
||||||
|
lift = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Collectible::update()
|
||||||
|
{
|
||||||
|
mesh.rotation.y += 0.08F;
|
||||||
|
if (bDisappearing)
|
||||||
|
{
|
||||||
|
mesh.position.y += lift;
|
||||||
|
lift = lift > 0 ? lift / 2 : 0;
|
||||||
|
if (lift < 1)
|
||||||
|
{
|
||||||
|
setActive(false);
|
||||||
|
bDisappearing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user