Compare commits
351 Commits
| 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 | |||
| b75b2d6e4f | |||
| 5aa2a9bdb5 | |||
| 06a440243a | |||
| 138ab762ba | |||
| 200fa3e4d5 | |||
| ef7bd425db | |||
| d4be8e94e7 | |||
| f9dc79caf1 | |||
| 885e8b4f2b | |||
| 3cfe7ba8f1 | |||
| ebf2a9ac24 | |||
| 24016ffa7e | |||
| aa97e471ed | |||
| 99d4c3633b | |||
| 8501a85f49 | |||
| ab69ba28e3 | |||
| 5320d7f84d | |||
| 9e00ef3634 | |||
| abda2fe3fa | |||
| 18e00f8e17 | |||
| bde819903b | |||
| ec6555aca3 | |||
| 034ea34931 | |||
| 887fcc1ba6 |
@@ -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/
|
||||||
*.bmp
|
|
||||||
*.obj
|
|
||||||
*.wav
|
|
||||||
*.md2
|
|
||||||
*.dff
|
|
||||||
*.irx
|
|
||||||
|
|
||||||
# ---
|
# ---
|
||||||
|
|
||||||
|
|||||||
+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,19 +1,22 @@
|
|||||||
[![Contributors][contributors-shield]][contributors-url]
|
[![Contributors][contributors-shield]][contributors-url]
|
||||||
[![MIT License][license-shield]][license-url]
|
[![MIT License][license-shield]][license-url]
|
||||||
[![LinkedIn][linkedin-shield]][linkedin-url]
|
[](https://discord.gg/NhhTmg3Gm5)
|
||||||
|
[](https://discord.gg/7dCr6ThSN5)
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/h4570/tyra">
|
<a href="https://github.com/h4570/tyra">
|
||||||
<img src="http://allvectorlogo.com/img/2016/05/ps2-logo.png" alt="Logo" width="230" height="125">
|
<img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/github-splash.png" alt="Logo" width="100%" height="auto">
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<h3 align="center">Tyra (Work in progress)</h3>
|
<h3 align="center">Tyra - alpha 1.36.3</h3>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
Tiny game engine for PS2 (PlayStation 2™) homebrew, written in C++98
|
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/h4570/tyra/issues">Report Bug</a>
|
<a href="https://github.com/h4570/tyra/issues">Report Bug</a>
|
||||||
@@ -22,129 +25,166 @@
|
|||||||
</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)
|
||||||
|
* [Description](#description)
|
||||||
* [Features](#features)
|
* [Features](#features)
|
||||||
* [Built With](#built-with)
|
* [Branches](#branches)
|
||||||
* [Getting Started](#getting-started)
|
* [Getting Started](#getting-started)
|
||||||
* [Prerequisites](#prerequisites)
|
|
||||||
* [Installation](#installation)
|
* [Installation](#installation)
|
||||||
|
* [Prerequisites](#prerequisites)
|
||||||
* [Roadmap](#roadmap)
|
* [Roadmap](#roadmap)
|
||||||
* [Contributing](#contributing)
|
* [Contributing](#contributing)
|
||||||
* [License](#license)
|
* [License](#license)
|
||||||
* [Contact](#contact)
|
* [Built With](#built-with)
|
||||||
|
* [Acronyms](#acronyms)
|
||||||
|
* [Thanks](#thanks)
|
||||||
|
|
||||||
## About The Project
|
<br />
|
||||||
|
|
||||||
<img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/1.0.0/tyra.gif" alt="sample" width="600" height="auto">
|
## About the Project
|
||||||
|
|
||||||
This repository contains a early version of game engine with simple demos for PS2 (PlayStation 2™) that I've developed using the freely available PS2DEV, unofficial SDK.
|
<img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/tyra.gif" alt="Sample code" width="600" height="auto">
|
||||||
Developing for PS2 was and is a big challenge for me, it's pretty low-level and hard (for me :D). The architecture is completely different from an Intel x86 and there are lots of extra things that you need to take into account. There are some samples available to teach on, but overall community died several years ago :/
|
<img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/dolphin.gif " alt="Sample game" width="500" height="auto">
|
||||||
|
|
||||||
**Why PS2 game dev is so different?** Creating games for PS2 is completly different from dragging colored buttons from side to side through an application with nice GUI (ex. Unity).
|
|
||||||
Coding something for PS2 requires from you doing everything from scratch, even data transfer management through (/co)processors like:
|
|
||||||
* EE (Emotion Engine) - whole set of processors and subsystems that make up the PlayStation 2
|
|
||||||
* GS (Graphic synthesizer) - configurable rasterizer and texture mapper, geometry transformations are not done by it. Has only 2MB~ memory for textures, but very high transfer rate, so you can switch them in the blink
|
|
||||||
* VU0 - vector processor accessed by inline assembly code injected into C program
|
|
||||||
* VU1 - vector processor (similar vertex shader) accessed via DMAC
|
|
||||||
* IOP - I/O processor which enables access to peripheral devices, such the game controller
|
|
||||||
|
|
||||||
### Samples
|
### Samples
|
||||||
|
* [Dolphin](https://github.com/h4570/tyra/tree/master/src/samples/dolphin)
|
||||||
* [Floors](https://github.com/h4570/tyra/tree/master/src/samples/floors)
|
* [Floors](https://github.com/h4570/tyra/tree/master/src/samples/floors)
|
||||||
* [Ari (WIP)](https://github.com/h4570/tyra/tree/master/src/samples/ari)
|
* [Cube](https://github.com/h4570/tyra/tree/master/src/samples/cube)
|
||||||
|
|
||||||
|
### Description
|
||||||
|
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.**
|
||||||
|
|
||||||
|
When project will be on beta stage, we plan to create some YouTube tutorials :)
|
||||||
|
|
||||||
|
**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
|
||||||
|
|
||||||
|
but with Tyra you can do it with methods like `loadObj()` and `draw()` 😁.
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
* VU1 (PATH 1 rendering) with double buffering
|
* 3D support - VU1 "Path 1 rendering"
|
||||||
* GIF (PATH 3 rendering) with double buffering
|
* 2D support - PNG & BMP
|
||||||
* Optimized calculations using VU0
|
* Frustum culling, backface culling
|
||||||
* Frustum culling
|
* OpenGL adaptions: Perspective projection, lookAt camera
|
||||||
* Backface culling
|
* Texture support - .bmp and png
|
||||||
* Perspective projection (like OpenGL's)
|
* Mesh loaders: ".obj", ".dff" (RenderWare, GTA:SA) and ".md2" (Quake II)
|
||||||
* Audio support
|
* Threading support
|
||||||
* Animation support
|
* Animation support for obj and md2
|
||||||
* Third person view "lookAt" camera (like OpenGL's)
|
* Audio support - .wav and .adpcm
|
||||||
* Dualshock 2 pad support
|
* Pad support
|
||||||
* RGB 888 24bit texture support (with .bmp loader)
|
|
||||||
* 3D files loaders: ".obj", ".dff" (renderware) and ".md2"
|
|
||||||
* Multi threading management
|
|
||||||
* 3D object management
|
|
||||||
* Lighting support (now PATH3 only)
|
|
||||||
* Other: collision, gravity etc.
|
|
||||||
|
|
||||||
### 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
|
||||||
|
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/h4570/tyra.git
|
|
||||||
```
|
|
||||||
2. Get into src folder and compile it!
|
|
||||||
```sh
|
|
||||||
make
|
|
||||||
```
|
|
||||||
|
|
||||||
## Extra info
|
## Extra info
|
||||||
* Textures can be saved using GIMP. Just replace red with green color, and when exporting select .bmp, 24bit: RGB888, without saving information about colors
|
* 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
|
||||||
|
|
||||||
Here is a list of the things I'm working on:
|
### Roadmap for next master release:
|
||||||
|
[Next release roadmap](https://github.com/h4570/tyra/projects/4)
|
||||||
* Fix PATH3 and PATH1 triangle clipping
|
|
||||||
* Add skybox with 6 textures to ari sample
|
|
||||||
* Ariana textures
|
|
||||||
* Bugfix: Player speed on different zoom
|
|
||||||
* Implement player rotation
|
|
||||||
* Bugfix: Backface culling bug on rotation
|
|
||||||
* Bugfix: Remove camera rotation reset flickering
|
|
||||||
* Bugfix: 2x Audio tick overflow
|
|
||||||
* Audio - change listeners logic
|
|
||||||
* Sound effects
|
|
||||||
* Code documentation
|
|
||||||
|
|
||||||
See the [open issues](https://github.com/h4570/tyra/issues) for a list of proposed features (and known issues).
|
See the [open issues](https://github.com/h4570/tyra/issues) for a list of proposed features (and known issues).
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**.
|
Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**.
|
||||||
|
|
||||||
1. Fork the Project
|
1. Fork the Project
|
||||||
2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
|
2. Create your Feature Branch (`git checkout -b feature/amazing-feature`)
|
||||||
3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
|
3. Commit your Changes (`git commit -m 'Add some amazing-feature'`)
|
||||||
4. Push to the Branch (`git push origin feature/AmazingFeature`)
|
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 - hastoklai@gmail.com
|
## Built With
|
||||||
|
|
||||||
|
* [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
|
||||||
|
|
||||||
|
Without these guys, everything would be harder:
|
||||||
|
* Dr Henry Fortuna - for code sources
|
||||||
|
* Rick Gaiser, fjtrujy - for help and new GCC!
|
||||||
|
* Lukasz D.K. - for huge archive of PS2 stuff
|
||||||
|
* Guilherme Lampert - for code sources
|
||||||
|
* Jesper Svennevid, Daniel Collin - for openvcl's code samples
|
||||||
|
* Whole PS2DEV team
|
||||||
|
* Manieq - for nice splash screens!
|
||||||
|
* And so many other guys. Thanks!
|
||||||
|
|
||||||
Project Link: [https://github.com/h4570/tyra](https://github.com/h4570/tyra)
|
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)
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<a href="https://github.com/h4570/tyra">
|
||||||
|
<img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/github-splash2.png" alt="Logo" width="100%" height="auto">
|
||||||
|
</a>
|
||||||
|
|
||||||
[contributors-shield]: https://img.shields.io/github/contributors/h4570/tyra.svg?style=flat-square
|
[contributors-shield]: https://img.shields.io/github/contributors/h4570/tyra.svg?style=flat-square
|
||||||
[contributors-url]: https://github.com/h4570/tyra/graphs/contributors
|
[contributors-url]: https://github.com/h4570/tyra/graphs/contributors
|
||||||
[linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=flat-square&logo=linkedin&colorB=555
|
[linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=flat-square&logo=linkedin&colorB=555
|
||||||
[linkedin-url]: https://linkedin.com/in/sandro-sobczyński-28820b15a/
|
|
||||||
[license-shield]: https://img.shields.io/github/license/h4570/tyra.svg?style=flat-square
|
[license-shield]: https://img.shields.io/github/license/h4570/tyra.svg?style=flat-square
|
||||||
[license-url]: https://github.com/h4570/tyra/blob/master/LICENSE
|
[license-url]: https://github.com/h4570/tyra/blob/master/LICENSE
|
||||||
|
|||||||
+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
|
||||||
+24
-32
@@ -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!");
|
|
||||||
else if (isInitialized)
|
|
||||||
PRINT_ERR("Already initialized!");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
game = t_game;
|
game = t_game;
|
||||||
renderer = new Renderer(t_gifPacketSize, &screen);
|
renderer = new Renderer(t_gifPacketSize, &screen);
|
||||||
isInitialized = true;
|
isInitialized = true;
|
||||||
game->onInit();
|
game->onInit();
|
||||||
gameLoop();
|
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
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
#ifndef _TYRA_DFF_LOADER_
|
#ifndef _TYRA_DFF_LOADER_
|
||||||
#define _TYRA_DFF_LOADER_
|
#define _TYRA_DFF_LOADER_
|
||||||
|
|
||||||
#include "../models/dff_model.hpp"
|
#include "../models/mesh_frame.hpp"
|
||||||
#include "./dff_structure.hpp"
|
#include "./dff_structure.hpp"
|
||||||
|
|
||||||
/** Class responsible for loading&parsing .obj 3D files */
|
/** Class responsible for loading&parsing .obj 3D files */
|
||||||
@@ -22,30 +22,28 @@ public:
|
|||||||
DffLoader();
|
DffLoader();
|
||||||
~DffLoader();
|
~DffLoader();
|
||||||
|
|
||||||
void load(RwClump &o_clump, char *t_fileName, float t_scale);
|
// void im_not_used_anywhere(MeshFrame *o_result, char *t_fileName, float t_scale, u8 t_invertT);
|
||||||
void serialize(RwClump &t_clump, u8 *t_data, float t_scale);
|
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);
|
||||||
static u8 readByteFromArrayLE(u8 *t_buffer, u32 &t_ptrPos);
|
|
||||||
static u16 readWordFromArrayLE(u8 *t_buffer, u32 &t_ptrPos);
|
|
||||||
static u32 readDwordFromArrayLE(u8 *t_buffer, u32 &t_ptrPos);
|
|
||||||
static float readFloatFromArrayLE(u8 *t_buffer, u32 &t_ptrPos);
|
|
||||||
static u8 *readData(u8 *t_buffer, u32 &t_ptrPos, u32 t_dataSize);
|
|
||||||
static char *readString(u8 *t_buffer, u32 &t_ptrPos, u32 t_dataSize = 0);
|
|
||||||
|
|
||||||
void readSectionHeader(RwSectionHeader &t_sh, u8 *t_buffer, u32 &t_ptrPos);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// ---
|
// ---
|
||||||
void readFrameListData(RwFrameListData &t_frd, u8 *t_buffer, u32 &t_ptrPos);
|
void readFrameListData(RwFrameListData &t_frd, u8 *t_buffer, u32 &t_ptrPos);
|
||||||
void readClumpData(RwClumpData &t_cd, u8 *t_buffer, u32 &t_ptrPos);
|
void readClumpData(RwClumpData &t_cd, u8 *t_buffer, u32 &t_ptrPos);
|
||||||
void readGeometryListData(RwGeometryListData &t_gld, u8 *t_buffer, u32 &t_ptrPos);
|
void readGeometryListData(RwGeometryListData &t_gld, u8 *t_buffer, u32 &t_ptrPos);
|
||||||
void readGeometryExtension(RwGeometryExtension &t_ge, u8 *t_buffer, u32 &t_ptrPos);
|
void readGeometryExtension(MeshFrame *o_frame, char **materialNames, u8 *t_buffer, u32 &t_ptrPos);
|
||||||
void readGeometryData(RwGeometryData &t_gd, u8 *t_buffer, u32 &t_ptrPos, float t_scale);
|
void readGeometryData(MeshFrame *o_frame, u8 t_invertT, u8 *t_buffer, u32 &t_ptrPos, float t_scale);
|
||||||
void readMaterialListData(RwMaterialListData &t_mld, u8 *t_buffer, u32 &t_ptrPos);
|
void readMaterialListData(RwMaterialListData &t_mld, u8 *t_buffer, u32 &t_ptrPos);
|
||||||
void readMaterialData(RwMaterialData &t_md, u8 *t_buffer, u32 &t_ptrPos);
|
void readMaterialData(RwMaterialData &t_md, u8 *t_buffer, u32 &t_ptrPos);
|
||||||
void readTextureData(RwTextureData &t_td, u8 *t_buffer, u32 &t_ptrPos);
|
void readTextureData(RwTextureData &t_td, u8 *t_buffer, u32 &t_ptrPos);
|
||||||
void readStringData(RwString &t_s, u8 *bt_uffer, u32 &t_ptrPos);
|
void readStringData(RwString &t_s, u8 *bt_uffer, u32 &t_ptrPos);
|
||||||
|
void readSectionHeader(RwSectionHeader &t_sh, u8 *t_buffer, u32 &t_ptrPos);
|
||||||
// ---
|
// ---
|
||||||
|
u8 readByteFromArrayLE(u8 *t_buffer, u32 &t_ptrPos);
|
||||||
|
u16 readWordFromArrayLE(u8 *t_buffer, u32 &t_ptrPos);
|
||||||
|
u32 readDwordFromArrayLE(u8 *t_buffer, u32 &t_ptrPos);
|
||||||
|
float readFloatFromArrayLE(u8 *t_buffer, u32 &t_ptrPos);
|
||||||
|
char *readString(u8 *t_buffer, u32 &t_ptrPos, u32 t_dataSize = 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public:
|
|||||||
class RwFrameListChunk
|
class RwFrameListChunk
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~RwFrameListChunk() { delete[] rotationalMatrix; }
|
~RwFrameListChunk() {}
|
||||||
float *rotationalMatrix; // [ROT_MAT_DIM]
|
float *rotationalMatrix; // [ROT_MAT_DIM]
|
||||||
float coordinatesOffsetX;
|
float coordinatesOffsetX;
|
||||||
float coordinatesOffsetY;
|
float coordinatesOffsetY;
|
||||||
@@ -50,7 +50,7 @@ public:
|
|||||||
class RwFrameListData : public RwSectionHeader
|
class RwFrameListData : public RwSectionHeader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~RwFrameListData() { delete frameInformation; }
|
~RwFrameListData() {}
|
||||||
static const u32 ROT_MAT_DIM = 9;
|
static const u32 ROT_MAT_DIM = 9;
|
||||||
u32 frameCount;
|
u32 frameCount;
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ public:
|
|||||||
class RwFrame : public RwSectionHeader
|
class RwFrame : public RwSectionHeader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~RwFrame() { delete[] frameName; }
|
~RwFrame() {}
|
||||||
u8 *frameName; // [sectionSize] - should be interpreted as string
|
u8 *frameName; // [sectionSize] - should be interpreted as string
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ class RwFrameList : public RwSectionHeader
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RwFrameListData data;
|
RwFrameListData data;
|
||||||
~RwFrameList() { delete[] extensions; }
|
~RwFrameList() {}
|
||||||
RwFrameListExtension *extensions;
|
RwFrameListExtension *extensions;
|
||||||
};
|
};
|
||||||
// ---
|
// ---
|
||||||
@@ -89,50 +89,65 @@ public:
|
|||||||
u32 morphTargetCount;
|
u32 morphTargetCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RwGeometryDataLightingHeader
|
struct RwGeometryDataLightingHeader
|
||||||
{ // IF versionNumber = 4099 - according to not complete documentation
|
{ // IF versionNumber = 4099 - according to not complete documentation
|
||||||
public:
|
|
||||||
float ambient;
|
float ambient;
|
||||||
float diffuse;
|
float diffuse;
|
||||||
float specular;
|
float specular;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RwGeometryDataColorInformationChunk
|
struct RwGeometryDataColorInformationChunk
|
||||||
{ // if rwOBJECT_VERTEX_PREILIT in flags
|
{ // if rwOBJECT_VERTEX_PREILIT in flags
|
||||||
public:
|
|
||||||
u8 red;
|
u8 red;
|
||||||
u8 green;
|
u8 green;
|
||||||
u8 blue;
|
u8 blue;
|
||||||
u8 alpha;
|
u8 alpha;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RwGeometryDataTextureMappingInformationChunk
|
struct RwGeometryDataTextureMappingInformationChunk
|
||||||
{ // if rwOBJECT_VERTEX_TEXTURED in flags
|
{ // if rwOBJECT_VERTEX_TEXTURED in flags
|
||||||
public:
|
|
||||||
float u;
|
float u;
|
||||||
float v;
|
float v;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RwGeometryDataFaceInformation
|
struct RwGeometryDataFaceInformation
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
u16 vertex2; // this
|
u16 vertex2; // this
|
||||||
u16 vertex1; // is
|
u16 vertex1; // is
|
||||||
u16 flags; // weird
|
u16 flags; // weird
|
||||||
u16 vertex3; // order
|
u16 vertex3; // order
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class RwGeometryDataNonameInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
float boundingSphereX;
|
||||||
|
float boundingSphereY;
|
||||||
|
float boundingSphereZ;
|
||||||
|
float boundingSphereR;
|
||||||
|
u32 hasPosition;
|
||||||
|
u32 hasNormals;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
// Section: Geometry
|
// Section: Geometry
|
||||||
class RwGeometryData : public RwSectionHeader
|
class RwGeometryData : public RwSectionHeader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~RwGeometryData()
|
~RwGeometryData()
|
||||||
{
|
{
|
||||||
delete colorInformation;
|
// if (dataHeader.flags & rwOBJECT_VERTEX_NORMALS)
|
||||||
delete textureMappingInformation;
|
// delete[] normalInformation;
|
||||||
delete faceInformation;
|
// delete[] vertexInformation;
|
||||||
delete vertexInformation;
|
// free(vertexInformation);
|
||||||
delete normalInformation;
|
// delete[] faceInformation;
|
||||||
|
// if (dataHeader.flags & rwOBJECT_VERTEX_PRELIT)
|
||||||
|
// delete[] colorInformation;
|
||||||
|
// if (dataHeader.flags & rwOBJECT_VERTEX_TEXTURED)
|
||||||
|
// delete[] textureMappingInformation;
|
||||||
}
|
}
|
||||||
RwGeometryDataHeader dataHeader;
|
RwGeometryDataHeader dataHeader;
|
||||||
|
|
||||||
@@ -144,16 +159,7 @@ public:
|
|||||||
|
|
||||||
RwGeometryDataFaceInformation *faceInformation; // [triangleCount]
|
RwGeometryDataFaceInformation *faceInformation; // [triangleCount]
|
||||||
|
|
||||||
class RwGeometryDataNonameInfo
|
RwGeometryDataNonameInfo nonameInfo;
|
||||||
{
|
|
||||||
public:
|
|
||||||
float boundingSphereX;
|
|
||||||
float boundingSphereY;
|
|
||||||
float boundingSphereZ;
|
|
||||||
float boundingSphereR;
|
|
||||||
u32 hasPosition;
|
|
||||||
u32 hasNormals;
|
|
||||||
} nonameInfo;
|
|
||||||
|
|
||||||
Vector3 *vertexInformation; // [vertexCount]
|
Vector3 *vertexInformation; // [vertexCount]
|
||||||
|
|
||||||
@@ -211,7 +217,7 @@ class RwMaterialExtension : public RwSectionHeader
|
|||||||
class RwMaterial : public RwSectionHeader
|
class RwMaterial : public RwSectionHeader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~RwMaterial() { delete[] textures; }
|
~RwMaterial() {}
|
||||||
RwMaterialData data;
|
RwMaterialData data;
|
||||||
RwTexture *textures;
|
RwTexture *textures;
|
||||||
RwMaterialExtension extension;
|
RwMaterialExtension extension;
|
||||||
@@ -220,7 +226,7 @@ public:
|
|||||||
class RwMaterialListData : public RwSectionHeader
|
class RwMaterialListData : public RwSectionHeader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~RwMaterialListData() { delete[] arrayOfUnks; }
|
~RwMaterialListData() {}
|
||||||
u32 materialCount;
|
u32 materialCount;
|
||||||
u32 *arrayOfUnks; // Filled with '-1's, [materialCount] - it wasn't mentioned in docs.
|
u32 *arrayOfUnks; // Filled with '-1's, [materialCount] - it wasn't mentioned in docs.
|
||||||
};
|
};
|
||||||
@@ -228,7 +234,7 @@ public:
|
|||||||
class RwMaterialList : public RwSectionHeader
|
class RwMaterialList : public RwSectionHeader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~RwMaterialList() { delete[] materials; }
|
~RwMaterialList() {}
|
||||||
RwMaterialListData data;
|
RwMaterialListData data;
|
||||||
RwMaterial *materials;
|
RwMaterial *materials;
|
||||||
};
|
};
|
||||||
@@ -242,24 +248,26 @@ public:
|
|||||||
class RwGeometryListInfoChunk
|
class RwGeometryListInfoChunk
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~RwGeometryListInfoChunk() { delete vertexInformation; }
|
~RwGeometryListInfoChunk() {}
|
||||||
u32 faceIndex;
|
u32 faceIndex;
|
||||||
u32 materialIndex;
|
u32 materialIndex;
|
||||||
|
|
||||||
RwGeometryListVertexInfoChunk *vertexInformation; // [faceIndex]
|
RwGeometryListVertexInfoChunk *vertexInformation; // [faceIndex]
|
||||||
};
|
};
|
||||||
|
|
||||||
class RwMaterialSplit
|
class RwMaterialSplitHeader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~RwMaterialSplit() { delete splitInformation; }
|
|
||||||
class Header
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
u32 triangleStrip;
|
u32 triangleStrip;
|
||||||
u32 splitCount;
|
u32 splitCount;
|
||||||
u32 faceCount;
|
u32 faceCount;
|
||||||
} header;
|
};
|
||||||
|
|
||||||
|
class RwMaterialSplit
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~RwMaterialSplit() {}
|
||||||
|
RwMaterialSplitHeader header;
|
||||||
|
|
||||||
RwGeometryListInfoChunk *splitInformation; // [splitCount]
|
RwGeometryListInfoChunk *splitInformation; // [splitCount]
|
||||||
};
|
};
|
||||||
@@ -289,7 +297,7 @@ public:
|
|||||||
class RwGeometryList : public RwSectionHeader
|
class RwGeometryList : public RwSectionHeader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~RwGeometryList() { delete[] geometries; }
|
~RwGeometryList() {}
|
||||||
RwGeometryListData data;
|
RwGeometryListData data;
|
||||||
RwGeometry *geometries;
|
RwGeometry *geometries;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
#ifndef _TYRA_MD2_LOADER_
|
#ifndef _TYRA_MD2_LOADER_
|
||||||
#define _TYRA_MD2_LOADER_
|
#define _TYRA_MD2_LOADER_
|
||||||
|
|
||||||
#include "../models/md2_model.hpp"
|
#include "../models/mesh_frame.hpp"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
// magic number "IDP2" or 844121161
|
// magic number "IDP2" or 844121161
|
||||||
@@ -83,7 +83,7 @@ public:
|
|||||||
MD2Loader();
|
MD2Loader();
|
||||||
~MD2Loader();
|
~MD2Loader();
|
||||||
|
|
||||||
void load(MD2Model *o_result, char *t_fileName, float t_scale);
|
MeshFrame *load(u32 &o_framesCount, char *t_subpath, char *t_nameWithoutExtension, float t_scale, u8 t_invertT);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
#ifndef _TYRA_OBJ_LOADER_
|
#ifndef _TYRA_OBJ_LOADER_
|
||||||
#define _TYRA_OBJ_LOADER_
|
#define _TYRA_OBJ_LOADER_
|
||||||
|
|
||||||
#include "../models/obj_model.hpp"
|
#include "../models/mesh_frame.hpp"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
/** Class responsible for loading&parsing .obj 3D files */
|
/** Class responsible for loading&parsing .obj 3D files */
|
||||||
@@ -22,10 +22,14 @@ public:
|
|||||||
ObjLoader();
|
ObjLoader();
|
||||||
~ObjLoader();
|
~ObjLoader();
|
||||||
|
|
||||||
void load(ObjModel *o_result, char *t_fileName, float t_scale);
|
/** Parse .obj file, allocate output data and store it. Multitexture support
|
||||||
|
* Notice: At this moment textures names are MATERIAL names from .obj file!
|
||||||
|
* Notice 2: Faces MUST be triangulated (check out blender export settings).
|
||||||
|
*/
|
||||||
|
void load(MeshFrame *o_result, char *t_fileName, float t_scale, u8 t_invertT);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setObjDataQuantities(FILE *t_file, ObjModel *t_result);
|
void allocateObjMemory(FILE *t_file, MeshFrame *t_result);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TYRA_ANIM_STATE_
|
||||||
|
#define _TYRA_ANIM_STATE_
|
||||||
|
|
||||||
|
#include <tamtypes.h>
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u32 startFrame;
|
||||||
|
u32 endFrame;
|
||||||
|
u32 stayFrame;
|
||||||
|
u8 isStayFrameSet;
|
||||||
|
float speed;
|
||||||
|
float interpolation;
|
||||||
|
u32 animType;
|
||||||
|
u32 currentFrame;
|
||||||
|
u32 nextFrame;
|
||||||
|
} AnimState;
|
||||||
|
|
||||||
|
#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
|
||||||
@@ -1,35 +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_DFF_MODEL_
|
|
||||||
#define _TYRA_DFF_MODEL_
|
|
||||||
|
|
||||||
#include <tamtypes.h>
|
|
||||||
#include <math3d.h>
|
|
||||||
#include "../loaders/dff_structure.hpp"
|
|
||||||
#include "./math/vector3.hpp"
|
|
||||||
|
|
||||||
/** Class which have common types for all 3D objects */
|
|
||||||
class DffModel
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
DffModel();
|
|
||||||
~DffModel();
|
|
||||||
|
|
||||||
u32 getDrawData(u32 splitIndex, VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, VECTOR *o_colors, Vector3 &t_cameraPos, float t_scale, u8 t_shouldBeBackfaceCulled);
|
|
||||||
RwClump clump;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void fillNextFace(VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, VECTOR *o_colors, u8 geometry, u32 t_getI, u32 t_setI);
|
|
||||||
u8 isMemoryAllocated;
|
|
||||||
};
|
|
||||||
|
|
||||||
#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
|
||||||
|
|||||||
@@ -26,12 +26,15 @@ public:
|
|||||||
float xy[2] __attribute__((__aligned__(16)));
|
float xy[2] __attribute__((__aligned__(16)));
|
||||||
};
|
};
|
||||||
|
|
||||||
Point(float x, float y);
|
Point(const float &t_x, const float &t_y);
|
||||||
|
Point(const Point &v);
|
||||||
Point();
|
Point();
|
||||||
~Point();
|
~Point();
|
||||||
|
|
||||||
void set(float x, float y);
|
void set(const float &t_x, const float &t_y);
|
||||||
void print();
|
void rotate(const float &t_angle, const float &t_x, const float &t_y);
|
||||||
|
void set(const Point &v);
|
||||||
|
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 x, float y, float 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();
|
// ----
|
||||||
|
// Operators
|
||||||
|
// ----
|
||||||
|
|
||||||
|
Vector3 operator+(const Vector3 &v) const;
|
||||||
|
Vector3 operator-(const Vector3 &v) const;
|
||||||
|
/** Also called "cross product" */
|
||||||
|
Vector3 operator*(const Vector3 &v) const;
|
||||||
|
Vector3 operator*(const float &t) const;
|
||||||
|
Vector3 operator/(const float &t) const;
|
||||||
|
Vector3 operator-(void) const { return Vector3(-x, -y, -z); }
|
||||||
|
void operator+=(const Vector3 &t);
|
||||||
|
void operator*=(const float &t);
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Functions
|
||||||
|
// ----
|
||||||
|
|
||||||
|
/** Set vector values via VU0. */
|
||||||
|
void set(const Vector3 &v);
|
||||||
|
|
||||||
|
/** Set vector values. */
|
||||||
|
void set(const float &t_x, const float &t_y, const float &t_z);
|
||||||
|
|
||||||
|
/** Also called dot3. */
|
||||||
|
float innerProduct(const Vector3 &v) const;
|
||||||
|
|
||||||
|
/** Get vector length */
|
||||||
|
float length() const;
|
||||||
|
|
||||||
|
/** Normalize vector. */
|
||||||
void normalize();
|
void normalize();
|
||||||
void setByLerp(const Vector3 &v1, const Vector3 &v2, const float t_interp);
|
|
||||||
float innerProduct(Vector3 &v);
|
/** Returns distance between two vectors */
|
||||||
void set(Vector3 &v);
|
float distanceTo(const Vector3 &v) const;
|
||||||
void set(float x, float y, float z);
|
|
||||||
void copy(Vector3 &v);
|
/**
|
||||||
float distanceTo(Vector3 &v);
|
* Checks intersection with given box
|
||||||
void print();
|
* @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
|
||||||
|
|||||||
@@ -1,59 +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_MD2_MODEL_
|
|
||||||
#define _TYRA_MD2_MODEL_
|
|
||||||
|
|
||||||
#include <tamtypes.h>
|
|
||||||
#include <math3d.h>
|
|
||||||
#include "math/vector3.hpp"
|
|
||||||
#include "math/point.hpp"
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
u32 startFrame;
|
|
||||||
u32 endFrame;
|
|
||||||
float speed;
|
|
||||||
float interpolation;
|
|
||||||
u32 animType;
|
|
||||||
u32 currentFrame;
|
|
||||||
u32 nextFrame;
|
|
||||||
} MD2AnimState;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
u16 verticeIndexes[3];
|
|
||||||
u16 coordIndexes[3];
|
|
||||||
} MD2Triangle;
|
|
||||||
|
|
||||||
/** Class which have common types for all 3D objects */
|
|
||||||
class MD2Model
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
u32 verticesPerFrameCount, framesCount, coordinatesCount, trianglesCount;
|
|
||||||
Vector3 *vertices __attribute__((aligned(16)));
|
|
||||||
Point *coordinates;
|
|
||||||
u32 *normalIndexes;
|
|
||||||
MD2Triangle *triangles;
|
|
||||||
MD2AnimState animState;
|
|
||||||
/** File name without extension */
|
|
||||||
char *filename;
|
|
||||||
MD2Model(char *t_md2File);
|
|
||||||
~MD2Model();
|
|
||||||
u32 getCurrentFrameData(VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, VECTOR *o_colors, Vector3 &t_cameraPos, float t_scale, u8 t_shouldBeBackfaceCulled);
|
|
||||||
void allocateMemory();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Vector3 calcVector;
|
|
||||||
Vector3 calc3Vectors[3];
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -8,61 +8,208 @@
|
|||||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TYRA_OBJECT3D_
|
#ifndef _TYRA_MESH_
|
||||||
#define _TYRA_OBJECT3D_
|
#define _TYRA_MESH_
|
||||||
|
|
||||||
#include "math/vector3.hpp"
|
#include "math/vector3.hpp"
|
||||||
#include "math/plane.hpp"
|
#include "math/plane.hpp"
|
||||||
#include "mesh_spec.hpp"
|
#include "./texture.hpp"
|
||||||
#include "obj_model.hpp"
|
#include "./mesh_frame.hpp"
|
||||||
#include "dff_model.hpp"
|
|
||||||
#include "md2_model.hpp"
|
|
||||||
#include <tamtypes.h>
|
#include <tamtypes.h>
|
||||||
#include <draw_types.h>
|
#include <draw_buffers.h>
|
||||||
|
#include <draw_sampling.h>
|
||||||
|
#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
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Vector3 position, rotation;
|
|
||||||
u8 shouldBeLighted, shouldBeBackfaceCulled, shouldBeFrustumCulled;
|
|
||||||
|
|
||||||
MeshSpec *spec;
|
|
||||||
MD2Model *md2;
|
|
||||||
ObjModel *obj;
|
|
||||||
DffModel *dff;
|
|
||||||
float scale;
|
|
||||||
color_t color;
|
|
||||||
Vector3 boxVertices[8];
|
|
||||||
|
|
||||||
Mesh();
|
Mesh();
|
||||||
~Mesh();
|
~Mesh();
|
||||||
|
|
||||||
void loadObj(char *t_subfolder, char *t_objFile, Vector3 &t_initPos, float t_scale);
|
Vector3 position, rotation;
|
||||||
void setObj(Vector3 &t_initPos, ObjModel *t_objModel, MeshSpec *t_spec);
|
float scale;
|
||||||
void loadDff(char *t_subfolder, char *t_dffFile, Vector3 &t_initPos, float t_scale);
|
u8 shouldBeLighted;
|
||||||
void setDff(Vector3 &t_initPos, DffModel *t_dffModel, MeshSpec *t_spec);
|
/**
|
||||||
void loadMD2(char *t_subfolder, char *t_md2File, Vector3 &t_initPos, float t_scale);
|
* When true, invisible triangles of mesh materials are not drawn.
|
||||||
void getMinMax(Vector3 *t_min, Vector3 *t_max);
|
*/
|
||||||
void playAnimation(u32 t_startFrame, u32 t_endFrame);
|
u8 shouldBeBackfaceCulled;
|
||||||
u32 getVertexCount();
|
/**
|
||||||
void setAnimSpeed(float t_value);
|
* When true, mesh materials are not drawn when they are outside of view frustum.
|
||||||
u32 getDrawData(u32 splitIndex, VECTOR *t_vertices, VECTOR *t_normals, VECTOR *t_coordinates, VECTOR *t_colors, Vector3 &t_cameraPos);
|
*/
|
||||||
|
u8 shouldBeFrustumCulled;
|
||||||
|
clutbuffer_t clut;
|
||||||
|
lod_t lod;
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Getters
|
||||||
|
// ----
|
||||||
|
|
||||||
|
/** Auto generated unique Id. */
|
||||||
|
const u32 &getId() const { return id; };
|
||||||
|
|
||||||
|
/** Array of materials. Size of getMaterialsCount() */
|
||||||
|
MeshMaterial *getMaterials() const { return frames[0].getMaterials(); };
|
||||||
|
|
||||||
|
const u32 &getMaterialsCount() const { return frames[0].getMaterialsCount(); };
|
||||||
|
|
||||||
|
/** Returns material, which is a mesh "subgroup". */
|
||||||
|
MeshMaterial &getMaterial(const u32 &i) const { return frames[0].getMaterial(i); };
|
||||||
|
|
||||||
|
/** Count of frames. Static object (not animated) will have only 1 frame. */
|
||||||
|
const u32 &getFramesCount() const { return framesCount; };
|
||||||
|
|
||||||
|
/** Count of vertices. */
|
||||||
|
u32 getVertexCount() { return frames[0].getVertexCount(); };
|
||||||
|
|
||||||
|
/** Returns single frame. */
|
||||||
|
MeshFrame &getFrame(const u32 &i) const { return frames[i]; };
|
||||||
|
|
||||||
|
/** Array of frames. Size of getFramesCount() */
|
||||||
|
MeshFrame *getFrames() const { return frames; };
|
||||||
|
|
||||||
|
const u32 &getCurrentAnimationFrame() const { return animState.currentFrame; };
|
||||||
|
|
||||||
|
const u32 &getNextAnimationFrame() const { return animState.nextFrame; };
|
||||||
|
|
||||||
|
const u32 &getStartAnimationFrame() const { return animState.startFrame; };
|
||||||
|
|
||||||
|
const u32 &getEndAnimationFrame() const { return animState.endFrame; };
|
||||||
|
|
||||||
|
const u32 &getStayAnimationFrame() const { return animState.stayFrame; };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns material, which is a mesh "subgroup".
|
||||||
|
* NULL if not found.
|
||||||
|
*/
|
||||||
|
MeshMaterial *getMaterialById(const u32 &t_id) const { return frames[0].getMaterialById(t_id); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns bounding vertex of current frame.
|
||||||
|
* @param i 0-7. Because, bounding box have 8 corners
|
||||||
|
*/
|
||||||
|
const Vector3 &getCurrentBoundingBoxVertex(const u8 &i) { return frames[animState.currentFrame].getBoundingBoxVertex(i); };
|
||||||
|
|
||||||
|
/** @returns bounding box vertex array of current frame. Size: 8 */
|
||||||
|
const Vector3 *getCurrentBoundingBoxVertices() const { return frames[animState.currentFrame].getBoundingBoxVertices(); };
|
||||||
|
|
||||||
|
/** @returns bounding box object of current frame. */
|
||||||
|
const BoundingBox *getCurrentBoundingBox() const { return frames[animState.currentFrame].getBoundingBox(); };
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Setters
|
||||||
|
// ----
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Other
|
||||||
|
// ----
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load mesh data from .obj files. Animation supported.
|
||||||
|
* 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
|
||||||
|
* are equal to texture file names.
|
||||||
|
* @param t_subfolder Relative path. Example "meshes/blocks"
|
||||||
|
* @param t_objFile File name without extension. Example "sand"
|
||||||
|
* @param t_scale Scale. For 1:1, type 1.0F
|
||||||
|
* @param t_framesCount Amount of frames.
|
||||||
|
* Example: 2.
|
||||||
|
* Searched files: sand_000001.obj, sand_000002.obj
|
||||||
|
* @param t_invertT Sometimes textures are in UV format, in this case, invertT should be set to true.
|
||||||
|
* Converts Y coordinate texture from Y to 1.0F - Y
|
||||||
|
*/
|
||||||
|
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 not supported.
|
||||||
|
* 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
|
||||||
|
* are equal to texture file names.
|
||||||
|
* @param t_subfolder Relative path. Example "meshes/blocks"
|
||||||
|
* @param t_objFile File name without extension. Example "sand"
|
||||||
|
* @param t_scale Scale. For 1:1, type 1.0F
|
||||||
|
* @param t_invertT Sometimes textures are in UV format, in this case, invertT should be set to true.
|
||||||
|
* Converts Y coordinate texture from Y to 1.0F - Y
|
||||||
|
*/
|
||||||
|
void loadObj(char *t_subfolder, char *t_objFile, const float &t_scale, const u8 &t_invertT);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load mesh data from RenderWare .dff file. Animation not supported
|
||||||
|
* @param t_subfolder Relative path. Example "meshes/blocks"
|
||||||
|
* @param t_objFile File name without extension. Example "sand"
|
||||||
|
* @param t_scale Scale. For 1:1, type 1.0F
|
||||||
|
* @param t_invertT Sometimes textures are in UV format, in this case, invertT should be set to true.
|
||||||
|
* Converts Y coordinate texture from Y to 1.0F - Y
|
||||||
|
*/
|
||||||
|
void loadDff(char *t_subfolder, char *t_dffFile, const float &t_scale, const u8 &t_invertT);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load mesh data from Quake II .md2 file. Animation supported.
|
||||||
|
* @param t_subfolder Relative path. Example "meshes/blocks"
|
||||||
|
* @param t_objFile File name without extension. Example "sand"
|
||||||
|
* @param t_scale Scale. For 1:1, type 1.0F
|
||||||
|
* @param t_invertT Sometimes textures are in UV format, in this case, invertT should be set to true.
|
||||||
|
* Converts Y coordinate texture from Y to 1.0F - Y
|
||||||
|
*/
|
||||||
|
void loadMD2(char *t_subfolder, char *t_md2File, const float &t_scale, const u8 &t_invertT);
|
||||||
|
|
||||||
|
/** Copy by reference mesh data from other mesh */
|
||||||
|
void loadFrom(const Mesh &t_mesh);
|
||||||
|
|
||||||
|
/** Check if are there any frames */
|
||||||
|
u8 isDataLoaded() const { return framesCount > 0; };
|
||||||
|
|
||||||
|
/** Loop in one frame */
|
||||||
|
void playAnimation(const u32 &t_frame) { playAnimation(t_frame, t_frame); }
|
||||||
|
|
||||||
|
/** Play animation in loop from startFrame to endFrame */
|
||||||
|
void playAnimation(const u32 &t_startFrame, const u32 &t_endFrame);
|
||||||
|
|
||||||
|
/** Play animation from startFrame to endFrame and after loop in stayFrame */
|
||||||
|
void playAnimation(const u32 &t_startFrame, const u32 &t_endFrame, const u32 &t_stayFrame);
|
||||||
|
|
||||||
|
void setAnimSpeed(const float &t_value) { animState.speed = t_value; }
|
||||||
|
|
||||||
|
const u8 &areFramesAllocated() const { return _areFramesAllocated; };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this class loaded mesh data first.
|
||||||
|
* Meshes which use loadFrom() method have false there.
|
||||||
|
*/
|
||||||
|
const u8 &isMother() const { return _isMother; };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this class loaded mesh data first.
|
||||||
|
* Meshes which use loadFrom() method have false there.
|
||||||
|
*/
|
||||||
|
const u8 &isStayAnimationSet() const { return animState.isStayFrameSet; };
|
||||||
|
|
||||||
|
/** True when mesh is in view frustum */
|
||||||
u8 isInFrustum(Plane *t_frustumPlanes);
|
u8 isInFrustum(Plane *t_frustumPlanes);
|
||||||
|
|
||||||
u8 isMd2Loaded, isObjLoaded, isDffLoaded, isSpecInitialized;
|
/**
|
||||||
|
* Do not call this method unless you know what you do.
|
||||||
|
* Should be called by renderer.
|
||||||
|
*/
|
||||||
|
void animate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not call this method unless you know what you do.
|
||||||
|
* Should be called by renderer.
|
||||||
|
*/
|
||||||
|
u32 getDrawData(u32 t_materialIndex, VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, Vector3 &t_cameraPos);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setDefaultWrapSettings(texwrap_t &t_wrapSettings);
|
AnimState animState;
|
||||||
u32 verticesCount;
|
MeshFrame *frames;
|
||||||
Vector3 *vertices;
|
u32 id, framesCount;
|
||||||
void loadTextures(char *t_subfolder, char *t_extension);
|
u8 _isMother, _areFramesAllocated;
|
||||||
void computeBoundingBox();
|
Vector3 calc3Vectors[3];
|
||||||
void setVerticesReference(u32 t_verticesCount, Vector3 *t_verticesRef);
|
void setDefaultLODAndClut();
|
||||||
void createSpecIfNotCreated();
|
|
||||||
void setDefaultColor();
|
|
||||||
void getFarthestVertex(Vector3 *o_result, int t_offset);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,182 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TYRA_MESH_FRAME_
|
||||||
|
#define _TYRA_MESH_FRAME_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <tamtypes.h>
|
||||||
|
#include "bounding_box.hpp"
|
||||||
|
#include "math/point.hpp"
|
||||||
|
#include "math/vector3.hpp"
|
||||||
|
#include "./mesh_material.hpp"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class which contains core mesh data
|
||||||
|
* which are needed for drawing.
|
||||||
|
* Static object (not animated), will have
|
||||||
|
* only one instance of this class.
|
||||||
|
*/
|
||||||
|
class MeshFrame
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
MeshFrame();
|
||||||
|
~MeshFrame();
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Getters
|
||||||
|
// ----
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto generated unique Id.
|
||||||
|
* Core role of this variable is to select correct texture to draw
|
||||||
|
*/
|
||||||
|
const u32 &getId() const { return id; };
|
||||||
|
|
||||||
|
const u32 &getVertexCount() const { return vertexCount; };
|
||||||
|
const u32 &getSTsCount() const { return stsCount; };
|
||||||
|
const u32 &getNormalsCount() const { return normalsCount; };
|
||||||
|
const u32 &getMaterialsCount() const { return materialsCount; };
|
||||||
|
|
||||||
|
/** Returns vertex. 3 vertices = 1 triangle. */
|
||||||
|
Vector3 &getVertex(const u32 &i) const { return vertices[i]; };
|
||||||
|
|
||||||
|
/** Returns texture coordinate. */
|
||||||
|
Point &getST(const u32 &i) const { return sts[i]; };
|
||||||
|
|
||||||
|
/** Returns normal vector. Used for lighting. */
|
||||||
|
Vector3 &getNormal(const u32 &i) const { return normals[i]; };
|
||||||
|
|
||||||
|
/** Returns material, which is a mesh "subgroup". */
|
||||||
|
MeshMaterial &getMaterial(const u32 &i) const { return materials[i]; };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns material, which is a mesh "subgroup".
|
||||||
|
* NULL if not found.
|
||||||
|
*/
|
||||||
|
MeshMaterial *getMaterialById(const u32 &t_id) const
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < materialsCount; i++)
|
||||||
|
if (materials[i].getId() == t_id)
|
||||||
|
return &materials[i];
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Array of vertices. Size of getVertexCount() */
|
||||||
|
Vector3 *getVertices() const { return vertices; };
|
||||||
|
|
||||||
|
/** Array of vertices. Size of getSTsCount() */
|
||||||
|
Point *getSTs() const { return sts; };
|
||||||
|
|
||||||
|
/** Array of vertices. Size of getNormalsCount() */
|
||||||
|
Vector3 *getNormals() const { return normals; };
|
||||||
|
|
||||||
|
/** Array of materials. Size of getMaterialsCount() */
|
||||||
|
MeshMaterial *getMaterials() const { return materials; };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns bounding box (AABB).
|
||||||
|
* Total length: 8
|
||||||
|
*/
|
||||||
|
Vector3 *getBoundingBoxVertices() { return boundingBoxObj->getVertices(); };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns bounding box (AABB) vertex.
|
||||||
|
* Total length: 8
|
||||||
|
*/
|
||||||
|
const Vector3 &getBoundingBoxVertex(const u8 &i) { return boundingBoxObj->getVertex(i); };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns bounding box (AABB) object pointer.
|
||||||
|
*/
|
||||||
|
BoundingBox *getBoundingBox() { return boundingBoxObj; };
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Setters
|
||||||
|
// ----
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not call this method unless you know what you do.
|
||||||
|
* Should be called by data loader.
|
||||||
|
*/
|
||||||
|
void setVertex(const u32 &t_index, const Vector3 &t_val) { vertices[t_index].set(t_val); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not call this method unless you know what you do.
|
||||||
|
* Should be called by data loader.
|
||||||
|
*/
|
||||||
|
void setNormal(const u32 &t_index, const Vector3 &t_val) { normals[t_index].set(t_val); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not call this method unless you know what you do.
|
||||||
|
* Should be called by data loader.
|
||||||
|
*/
|
||||||
|
void setST(const u32 &t_index, const Point &t_val) { sts[t_index].set(t_val); }
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Other
|
||||||
|
// ----
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this object is mother.
|
||||||
|
* Mother = object loaded with loadObj(), loadDff()..
|
||||||
|
* Have all mother data: vertex, st, etc..
|
||||||
|
* Non-mother = object loaded with loadFrom().
|
||||||
|
* Have reference copy to mother data: vertex, st, etc..
|
||||||
|
*
|
||||||
|
* When you will destruct mother object, all vertex, st data will be deleted.
|
||||||
|
* When you will destruct non-mother object, all vertex, st data will be NOT deleted.
|
||||||
|
*/
|
||||||
|
const u8 &isMother() const { return _isMother; };
|
||||||
|
|
||||||
|
const u8 &areSTsAllocated() const { return _areSTsAllocated; };
|
||||||
|
const u8 &areVerticesAllocated() const { return _areVerticesAllocated; };
|
||||||
|
const u8 &areNormalsAllocated() const { return _areNormalsAllocated; };
|
||||||
|
const u8 &areMaterialsAllocated() const { return _areMaterialsAllocated; };
|
||||||
|
const u8 &isBoundingBoxCalculated() const { return _isBoundingBoxCalculated; };
|
||||||
|
|
||||||
|
/** Create reference copy (non-mother) */
|
||||||
|
void copyFrom(MeshFrame *t_refCopy);
|
||||||
|
|
||||||
|
/** Set STs count and allocate memory. */
|
||||||
|
void allocateSTs(const u32 &t_val);
|
||||||
|
|
||||||
|
/** Set vertex count and allocate memory. */
|
||||||
|
void allocateVertices(const u32 &t_val);
|
||||||
|
|
||||||
|
/** Set normals count and allocate memory. */
|
||||||
|
void allocateNormals(const u32 &t_val);
|
||||||
|
|
||||||
|
/** Set materials count and allocate memory. */
|
||||||
|
void allocateMaterials(const u32 &t_val);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates bounding box (AABB) for frame and for materiaals.
|
||||||
|
* Should be called by data loader,
|
||||||
|
* so there is no need to run it again.
|
||||||
|
*/
|
||||||
|
void calculateBoundingBoxes();
|
||||||
|
|
||||||
|
private:
|
||||||
|
BoundingBox *boundingBoxObj;
|
||||||
|
u8 _isMother,
|
||||||
|
_areSTsAllocated,
|
||||||
|
_areVerticesAllocated,
|
||||||
|
_areNormalsAllocated,
|
||||||
|
_areMaterialsAllocated,
|
||||||
|
_isBoundingBoxCalculated;
|
||||||
|
u32 vertexCount, stsCount, normalsCount, materialsCount, id;
|
||||||
|
MeshMaterial *materials;
|
||||||
|
Point __attribute__((aligned(16))) * sts;
|
||||||
|
Vector3 __attribute__((aligned(16))) * vertices, *normals;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,176 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TYRA_MESH_MATERIAL_
|
||||||
|
#define _TYRA_MESH_MATERIAL_
|
||||||
|
|
||||||
|
#include <tamtypes.h>
|
||||||
|
#include <draw_types.h>
|
||||||
|
#include "bounding_box.hpp"
|
||||||
|
#include "./math/vector3.hpp"
|
||||||
|
#include "./math/plane.hpp"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class which contains draw instructions for part of mesh.
|
||||||
|
* Mesh can have many materials.
|
||||||
|
* For example, car mesh can have three materials:
|
||||||
|
* body, tires and windows.
|
||||||
|
*/
|
||||||
|
class MeshMaterial
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
MeshMaterial();
|
||||||
|
~MeshMaterial();
|
||||||
|
|
||||||
|
color_t color;
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Getters
|
||||||
|
// ----
|
||||||
|
|
||||||
|
/** Material name. */
|
||||||
|
char *getName() const { return name; };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto generated unique Id.
|
||||||
|
* Core role of this variable is to select correct texture to draw
|
||||||
|
*/
|
||||||
|
const u32 &getId() const { return id; };
|
||||||
|
|
||||||
|
const u32 &getFacesCount() const { return facesCount; };
|
||||||
|
|
||||||
|
/** Indexes of vertices. Each 3 faces will give you vertices of next triangle. */
|
||||||
|
u32 &getVertexFace(const u32 &i) const { return vertexFaces[i]; };
|
||||||
|
|
||||||
|
/** Indexes of texture coords. Each 3 faces will give you texture coords of next triangle. */
|
||||||
|
u32 &getSTFace(const u32 &i) const { return stFaces[i]; };
|
||||||
|
|
||||||
|
/** Indexes of normal vectors used for lighting. Each 3 faces will give you normal vectors of next triangle. */
|
||||||
|
u32 &getNormalFace(const u32 &i) const { return normalFaces[i]; };
|
||||||
|
|
||||||
|
/** Array of vertex faces. Size of getFacesCount() */
|
||||||
|
u32 *getVertexFaces() const { return vertexFaces; };
|
||||||
|
|
||||||
|
/** Array of texture coords faces. Size of getFacesCount() */
|
||||||
|
u32 *getSTFaces() const { return stFaces; };
|
||||||
|
|
||||||
|
/** Array of normal vector faces. Size of getFacesCount() */
|
||||||
|
u32 *getNormalFaces() const { return normalFaces; };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns bounding box (AABB).
|
||||||
|
* Total length: 8
|
||||||
|
*/
|
||||||
|
Vector3 *getBoundingBoxVertices() { return boundingBoxObj->getVertices(); };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns bounding box (AABB) vertex.
|
||||||
|
* Total length: 8
|
||||||
|
*/
|
||||||
|
const Vector3 &getBoundingBoxVertex(const u8 &i) { return boundingBoxObj->getVertex(i); };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns bounding box (AABB) object pointer.
|
||||||
|
*/
|
||||||
|
BoundingBox *getBoundingBox() { return boundingBoxObj; };
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Setters
|
||||||
|
// ----
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not call this method unless you know what you do.
|
||||||
|
* Should be called by data loader.
|
||||||
|
*/
|
||||||
|
void setVertexFace(const u32 &t_index, const u32 &t_val) { vertexFaces[t_index] = t_val; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not call this method unless you know what you do.
|
||||||
|
* Should be called by data loader.
|
||||||
|
*/
|
||||||
|
void setSTFace(const u32 &t_index, const u32 &t_val) { stFaces[t_index] = t_val; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not call this method unless you know what you do.
|
||||||
|
* Should be called by data loader.
|
||||||
|
*/
|
||||||
|
void setNormalFace(const u32 &t_index, const u32 &t_val) { normalFaces[t_index] = t_val; }
|
||||||
|
|
||||||
|
/** Set material name. */
|
||||||
|
void setName(char *t_val);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not call this method unless you know what you do.
|
||||||
|
* Should be called by data loader.
|
||||||
|
*/
|
||||||
|
void setSTsPresent(const u8 &b) { _areSTsPresent = b; };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not call this method unless you know what you do.
|
||||||
|
* Should be called by data loader.
|
||||||
|
*/
|
||||||
|
void setNormalsPresent(const u8 &b) { _areNormalsPresent = b; };
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Other
|
||||||
|
// ----
|
||||||
|
|
||||||
|
const u8 &areSTsPresent() const { return _areSTsPresent; };
|
||||||
|
|
||||||
|
const u8 &areNormalsPresent() const { return _areNormalsPresent; };
|
||||||
|
|
||||||
|
/** Create reference copy (non-mother) */
|
||||||
|
void copyFrom(MeshMaterial *t_refCopy);
|
||||||
|
|
||||||
|
const u8 &isNameSet() const { return _isNameSet; };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this object is mother.
|
||||||
|
* Mother = object loaded with loadObj(), loadDff()..
|
||||||
|
* Have all mother data: vertex faces, st faces, etc..
|
||||||
|
* Non-mother = object loaded with loadFrom().
|
||||||
|
* Have reference copy to mother data: vertex faces, st faces, etc..
|
||||||
|
*
|
||||||
|
* When you will destruct mother object, all faces data will be deleted.
|
||||||
|
* When you will destruct non-mother object, all faces data will be NOT deleted.
|
||||||
|
*/
|
||||||
|
const u8 &isMother() const { return _isMother; };
|
||||||
|
|
||||||
|
const u8 &areFacesAllocated() const { return _areFacesAllocated; };
|
||||||
|
|
||||||
|
/** Set faces count and allocate memory. */
|
||||||
|
void allocateFaces(const u32 &t_val);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not call this method unless you know what you do.
|
||||||
|
* Calculates bounding box (AABB).
|
||||||
|
* Called automatically in mesh frame class on data loading.
|
||||||
|
*/
|
||||||
|
void calculateBoundingBox(Vector3 *t_vertices, u32 t_vertCount);
|
||||||
|
|
||||||
|
/** True when mesh is in view frustum */
|
||||||
|
u8 isInFrustum(Plane *t_frustumPlanes, const Vector3 &position);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setDefaultColor();
|
||||||
|
BoundingBox *boundingBoxObj;
|
||||||
|
u32 facesCount, id;
|
||||||
|
u32 *vertexFaces, *stFaces, *normalFaces;
|
||||||
|
u8 _isMother,
|
||||||
|
_isNameSet,
|
||||||
|
_areFacesAllocated,
|
||||||
|
_isBoundingBoxCalculated,
|
||||||
|
_areSTsPresent,
|
||||||
|
_areNormalsPresent;
|
||||||
|
char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,41 +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_OBJECT3D_SPEC_
|
|
||||||
#define _TYRA_OBJECT3D_SPEC_
|
|
||||||
|
|
||||||
#include "math/vector3.hpp"
|
|
||||||
#include "./texture.hpp"
|
|
||||||
#include <tamtypes.h>
|
|
||||||
#include <draw_buffers.h>
|
|
||||||
#include <draw_sampling.h>
|
|
||||||
|
|
||||||
/** Class which contain 3D object specification */
|
|
||||||
class MeshSpec
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
texbuffer_t textureBuffer;
|
|
||||||
clutbuffer_t clut;
|
|
||||||
lod_t lod;
|
|
||||||
|
|
||||||
MeshSpec();
|
|
||||||
~MeshSpec();
|
|
||||||
void allocateTextureBuffer(u16 t_width, u16 t_height);
|
|
||||||
void deallocateTextureBuffer();
|
|
||||||
void allocateMemory();
|
|
||||||
void setupLodAndClut();
|
|
||||||
Texture *textures;
|
|
||||||
|
|
||||||
private:
|
|
||||||
u8 isTextureVRAMAllocated;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,42 +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_OBJ_MODEL_
|
|
||||||
#define _TYRA_OBJ_MODEL_
|
|
||||||
|
|
||||||
#include <tamtypes.h>
|
|
||||||
#include <math3d.h>
|
|
||||||
#include "math/vector3.hpp"
|
|
||||||
|
|
||||||
/** Class which have common types for all 3D objects */
|
|
||||||
class ObjModel
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
u32 verticesCount, coordinatesCount, normalsCount, facesCount;
|
|
||||||
Vector3 *vertices __attribute__((aligned(16))),
|
|
||||||
*coordinates __attribute__((aligned(16))),
|
|
||||||
*normals __attribute__((aligned(16)));
|
|
||||||
u32 *verticeFaces, *coordinateFaces, *normalFaces;
|
|
||||||
|
|
||||||
/** File name without extension */
|
|
||||||
char *filename;
|
|
||||||
|
|
||||||
ObjModel(char *t_objFile);
|
|
||||||
~ObjModel();
|
|
||||||
u32 getDrawData(VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, VECTOR *o_colors, Vector3 &t_cameraPos, float t_scale, u8 t_shouldBeBackfaceCulled);
|
|
||||||
void allocateMemory();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void fillNextFace(VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, VECTOR *o_colors, u32 t_getI, u32 t_setI);
|
|
||||||
u8 isMemoryAllocated;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -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
|
||||||
@@ -13,14 +13,174 @@
|
|||||||
|
|
||||||
#include <tamtypes.h>
|
#include <tamtypes.h>
|
||||||
#include <draw_sampling.h>
|
#include <draw_sampling.h>
|
||||||
|
#include "./texture_wrap_settings.hpp"
|
||||||
|
#include "./texture_link.hpp"
|
||||||
|
#include "../include/utils/debug.hpp"
|
||||||
|
#include <vector>
|
||||||
|
#include <gs_psm.h>
|
||||||
|
|
||||||
struct Texture
|
enum TextureType
|
||||||
{
|
{
|
||||||
u32 id;
|
TEX_TYPE_RGB = GS_PSM_24, // BMP
|
||||||
unsigned char *data;
|
TEX_TYPE_RGBA = GS_PSM_32 // PNG
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class which contains texture data.
|
||||||
|
* Textures are paired with meshes/sprites via addLink() and
|
||||||
|
* removeLink() functions which use meshId/spriteId and materialId (for mesh).
|
||||||
|
*/
|
||||||
|
class Texture
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
Texture();
|
||||||
|
~Texture();
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Getters
|
||||||
|
// ----
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto generated unique Id.
|
||||||
|
* Core role of this variable is to dont send
|
||||||
|
* again texture in renderer, when last sent texture id
|
||||||
|
* by renderer will be equal to this id.
|
||||||
|
*/
|
||||||
|
inline const u32 getId() const { return id; };
|
||||||
|
|
||||||
|
inline const u16 getWidth() const { return width; };
|
||||||
|
|
||||||
|
inline const u16 getHeight() const { return height; };
|
||||||
|
|
||||||
|
inline const TextureType getType() const { return _type; };
|
||||||
|
|
||||||
|
inline u32 getTextureLinksCount() const { return static_cast<u32>(texLinks.size()); };
|
||||||
|
|
||||||
|
inline texwrap_t *getWrapSettings() { return &wrapSettings; };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns always width * width * 3/4.
|
||||||
|
* 3 for RGB, 4 for RGBA.
|
||||||
|
*/
|
||||||
|
inline u32 getDataSize() const { return _type == TEX_TYPE_RGB ? width * height * 3 : width * height * 4; };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Texture data, used by renderer.
|
||||||
|
* Array of size getDataSize().
|
||||||
|
*/
|
||||||
|
inline unsigned char *getData() const { return data; };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get texture name.
|
||||||
|
* For "textures/abc.bmp" result will be: "abc"
|
||||||
|
*/
|
||||||
|
inline char *getName() const { return name; };
|
||||||
|
|
||||||
|
/** Array of texture links. Size of getTextureLinksCount() */
|
||||||
|
inline const std::vector<TextureLink> &getTextureLinks() const { return texLinks; };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns index of link.
|
||||||
|
* -1 if not found.
|
||||||
|
* @param t_id
|
||||||
|
* For 3D: Mesh material id.
|
||||||
|
* For 2D: Sprite id.
|
||||||
|
*/
|
||||||
|
const s32 getIndexOfLink(const u32 &t_id) const
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < texLinks.size(); i++)
|
||||||
|
if (texLinks[i].id == t_id)
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Setters
|
||||||
|
// ----
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set texture size and allocate texture data
|
||||||
|
* Do not call this method unless you know what you do.
|
||||||
|
* Should be called by data loader.
|
||||||
|
*/
|
||||||
|
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.
|
||||||
|
* Should be called by data loader.
|
||||||
|
*/
|
||||||
|
void setHeight(const u8 &t_val) { height = t_val; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not call this method unless you know what you do.
|
||||||
|
* Should be called by data loader.
|
||||||
|
*/
|
||||||
|
void setData(const u32 &t_index, const unsigned char &t_val) { data[t_index] = t_val; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set texture name.
|
||||||
|
* Should be the file name without extension
|
||||||
|
*/
|
||||||
|
void setName(char *t_val);
|
||||||
|
|
||||||
|
/** Set texture wrapping */
|
||||||
|
void setWrapSettings(const WrapSettings t_horizontal, const WrapSettings t_vertical);
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Other
|
||||||
|
// ----
|
||||||
|
|
||||||
|
/** Assign texture to mesh and mesh material. */
|
||||||
|
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 &isSizeSet() const { return _isSizeSet; };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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_id);
|
||||||
|
if (index != -1)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
void removeLinkByIndex(const u32 &t_index) { texLinks.erase(texLinks.begin() + t_index); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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_id);
|
||||||
|
assertMsg(index != -1, "Cant remove link, because it was not found!");
|
||||||
|
removeLinkByIndex(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setDefaultWrapSettings();
|
||||||
texwrap_t wrapSettings;
|
texwrap_t wrapSettings;
|
||||||
char *name;
|
char *name;
|
||||||
u8 width, height;
|
TextureType _type;
|
||||||
|
std::vector<TextureLink> texLinks;
|
||||||
|
u32 id;
|
||||||
|
u16 width, height;
|
||||||
|
u8 _isNameSet, _isSizeSet;
|
||||||
|
unsigned char *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TYRA_TEXTURE_USAGE_
|
||||||
|
#define _TYRA_TEXTURE_USAGE_
|
||||||
|
|
||||||
|
#include <tamtypes.h>
|
||||||
|
|
||||||
|
struct TextureLink
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* For 3D: Mesh material id.
|
||||||
|
* For 2D: Sprite id.
|
||||||
|
*/
|
||||||
|
u32 id;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TYRA_TEXTURE_WRAP_SETTINGS_
|
||||||
|
#define _TYRA_TEXTURE_WRAP_SETTINGS_
|
||||||
|
|
||||||
|
enum WrapSettings
|
||||||
|
{
|
||||||
|
Repeat = 0,
|
||||||
|
Clamp = 1,
|
||||||
|
RegionClamp = 2,
|
||||||
|
RegionRepeat = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
#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,46 @@
|
|||||||
#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/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 addObjects(RenderData *t_renderData, Mesh **t_objects3D, u32 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount);
|
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(Texture &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;
|
||||||
|
|
||||||
u32 calc3DObject(Matrix t_perspective, Mesh &t_mesh, 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, u8 t_alpha);
|
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,12 +13,17 @@
|
|||||||
|
|
||||||
#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"
|
||||||
|
|
||||||
/** Class responsible for intializing draw env, textures and buffers */
|
/** Class responsible for intializing draw env, textures and buffers */
|
||||||
class Renderer
|
class Renderer
|
||||||
@@ -29,46 +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);
|
||||||
|
|
||||||
|
void setAmbientLight(const Vector3 &t_rgb) { light.setAmbientLight(t_rgb); }
|
||||||
|
|
||||||
|
TextureRepository *getTextureRepository()
|
||||||
|
{
|
||||||
|
return &textureRepo;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void changeTexture(Mesh *t_mesh, u8 t_textureIndex);
|
// We have some GCC bug here. Just try to reorder declarations. For example move worldColor up - game will crash.
|
||||||
|
void changeTexture(Texture *t_tex);
|
||||||
|
u32 lastTextureId;
|
||||||
|
texbuffer_t textureBuffer;
|
||||||
|
u8 isTextureVRAMAllocated, isVSyncEnabled;
|
||||||
|
void allocateTextureBuffer(Texture *t_texture);
|
||||||
|
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;
|
||||||
u32 lastTextureId;
|
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();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TYRA_TEXTURE_REPOSITORY_
|
||||||
|
#define _TYRA_TEXTURE_REPOSITORY_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <tamtypes.h>
|
||||||
|
#include <draw_buffers.h>
|
||||||
|
#include "../models/mesh.hpp"
|
||||||
|
#include "../models/mesh_frame.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 TextureRepository
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
TextureRepository();
|
||||||
|
~TextureRepository();
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Getters
|
||||||
|
// ----
|
||||||
|
|
||||||
|
/** Returns all repository textures. */
|
||||||
|
std::vector<Texture *> *getAll() { return &textures; }
|
||||||
|
|
||||||
|
u32 getTexturesCount() const { return static_cast<u32>(textures.size()); };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns single texture.
|
||||||
|
* NULL if not found.
|
||||||
|
* @param t_id
|
||||||
|
* For 3D: Mesh material id.
|
||||||
|
* For 2D: Sprite id.
|
||||||
|
*/
|
||||||
|
Texture *getBySpriteOrMesh(const u32 &t_id)
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < textures.size(); i++)
|
||||||
|
if (textures[i]->isLinkedWith(t_id))
|
||||||
|
return textures[i];
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns single texture.
|
||||||
|
* NULL if not found.
|
||||||
|
*/
|
||||||
|
Texture *getByTextureId(const u32 &t_id) const
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < textures.size(); i++)
|
||||||
|
if (t_id == textures[i]->getId())
|
||||||
|
return textures[i];
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns index of link.
|
||||||
|
* -1 if not found.
|
||||||
|
*/
|
||||||
|
const s32 getIndexOf(const u32 &t_texId) const
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < textures.size(); i++)
|
||||||
|
if (textures[i]->getId() == t_texId)
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Setters
|
||||||
|
// ----
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Other
|
||||||
|
// ----
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add unlinked texture.
|
||||||
|
* @param t_subfolder Relative path. Ex.: "textures/"
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
|
Texture *add(char *t_subfolder, char *t_name, TextureFormat t_format);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add linked textures in given subpath for mesh material names.
|
||||||
|
* @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, TextureFormat t_format);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove texture from repository.
|
||||||
|
* Texture is NOT destructed.
|
||||||
|
*/
|
||||||
|
void removeByIndex(const u32 &t_index) { textures.erase(textures.begin() + t_index); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove texture from repository.
|
||||||
|
* Texture is NOT destructed.
|
||||||
|
*/
|
||||||
|
const void removeById(const u32 &t_texId)
|
||||||
|
{
|
||||||
|
s32 index = getIndexOf(t_texId);
|
||||||
|
assertMsg(index != -1, "Cant remove texture, because it was not found!");
|
||||||
|
removeByIndex(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<Texture *> textures;
|
||||||
|
BmpLoader bmpLoader;
|
||||||
|
PngLoader pngLoader;
|
||||||
|
};
|
||||||
|
|
||||||
|
#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,31 +12,52 @@
|
|||||||
#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, VECTOR *colors, Mesh *t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount);
|
void drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 vertCount2, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer, color_t *t_color, u8 t_rgbaOnly);
|
||||||
|
void calcMatrix(const RenderData &t_renderData, const Vector3 &t_position, const Vector3 &t_rotation);
|
||||||
|
void drawTheSameWithOtherMatrices(const RenderData &t_renderData, Mesh **t_meshes, const u32 &t_skip, const u32 &t_count);
|
||||||
|
void enableWait() { isDrawWaitEnabled = true; }
|
||||||
|
void disableWait() { isDrawWaitEnabled = false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void drawVertices(Mesh *t_mesh, u32 t_start, u32 t_end, VECTOR *t_vertices, VECTOR *t_colors, VECTOR *t_coordinates, prim_t *t_prim);
|
u32 lastVertCount; // needed for drawTheSameWithOtherMatrices()
|
||||||
|
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;
|
||||||
VU1 vu1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -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,11 +11,30 @@
|
|||||||
#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)
|
||||||
|
#define assertMsg(condition, message) ((void)0)
|
||||||
|
|
||||||
|
#else // IF Debug
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
class Debug
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void trap(const char *t_text, const char *t_file)
|
||||||
|
{
|
||||||
|
printf("\n");
|
||||||
|
printf("====================================\n");
|
||||||
|
printf("| ERROR: %s\n", t_text);
|
||||||
|
printf("| File : %s\n", t_file);
|
||||||
|
printf("====================================\n\n");
|
||||||
|
for (;;)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#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) printf("---\n--- ---\n--- --- --- ERR: " TEXT " (" __FILE__ ")\n--- ---\n---\n")
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -14,23 +14,33 @@
|
|||||||
#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
|
||||||
|
|
||||||
void manyVec3ToNative(VECTOR *t_result, Vector3 *t_vec, int t_amount, float t_fourthVal);
|
void manyVec3ToNative(VECTOR *t_result, Vector3 *t_vec, int t_amount, float t_fourthVal);
|
||||||
void vec3ToNative(VECTOR t_result, Vector3 &t_vec, float t_fourthVal);
|
void vec3ToNative(VECTOR t_result, const Vector3 &t_vec, float t_fourthVal);
|
||||||
|
|
||||||
class Math
|
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,10 +17,12 @@ class String
|
|||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static char *createCopy(char *source);
|
static char *createU32ToString(const u32 a);
|
||||||
static u32 getLength(char *a);
|
static char *createWithLeadingZeros(const char *a);
|
||||||
static char *createConcatenated(char *a, char *b);
|
static char *createCopy(const char *source);
|
||||||
static char *createWithoutExtension(char *source);
|
static u32 getLength(const char *a);
|
||||||
|
static char *createConcatenated(const char *a, const char *b);
|
||||||
|
static char *createWithoutExtension(const char *source);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -32,48 +32,47 @@ BmpLoader::~BmpLoader() {}
|
|||||||
*/
|
*/
|
||||||
void BmpLoader::load(Texture &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);
|
||||||
|
delete[] path_part1;
|
||||||
FILE *file = fopen(t_path, "rb");
|
delete[] path_part2;
|
||||||
|
FILE *file = fopen(path, "rb");
|
||||||
if (file == NULL)
|
assertMsg(file != NULL, "Failed to load .bmp file!");
|
||||||
PRINT_ERR("Failed to load .bmp file!");
|
|
||||||
|
|
||||||
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.id = rand() % 100000;
|
u32 bits = (u32)header[28];
|
||||||
o_texture.width = width;
|
u32 dataOffset = (u32)header[10];
|
||||||
o_texture.height = height;
|
|
||||||
o_texture.data = new unsigned char[width * height * 3];
|
assertMsg(bits == 24, "Invalid bits per pixel in .bmp file - expected 24!");
|
||||||
printf("BMPLoader - width: %d | height: %d\n", width, height);
|
|
||||||
|
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.data[x] = data[j];
|
|
||||||
o_texture.data[x + 1] = data[j + 1];
|
|
||||||
o_texture.data[x + 2] = data[j + 2];
|
|
||||||
x += 3;
|
x += 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete[] t_path;
|
delete[] path;
|
||||||
delete[] data;
|
fclose(file);
|
||||||
}
|
}
|
||||||
|
|||||||
+231
-164
@@ -34,95 +34,156 @@ DffLoader::~DffLoader() {}
|
|||||||
// Methods
|
// Methods
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
void DffLoader::load(RwClump &o_clump, char *t_filename, float t_scale)
|
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 = new u8[fileSize];
|
u8 data[fileSize];
|
||||||
rewind(file);
|
rewind(file);
|
||||||
fread(data, sizeof(u8), fileSize, file);
|
fread(&data, sizeof(u8), fileSize, file);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
serialize(o_clump, data, t_scale);
|
serialize(o_result, t_invertT, data, t_scale);
|
||||||
delete[] data;
|
o_result->calculateBoundingBoxes();
|
||||||
PRINT_LOG("Dff file loaded!");
|
delete[] path;
|
||||||
|
consoleLog("Dff file loaded!");
|
||||||
}
|
}
|
||||||
|
|
||||||
void DffLoader::serialize(RwClump &t_clump, u8 *t_data, float t_scale)
|
// 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)
|
||||||
{
|
{
|
||||||
u32 ptrPos = 0;
|
u32 ptrPos = 0;
|
||||||
readSectionHeader(t_clump, t_data, ptrPos);
|
|
||||||
readSectionHeader(t_clump.data, t_data, ptrPos);
|
|
||||||
readClumpData(t_clump.data, t_data, ptrPos);
|
|
||||||
readSectionHeader(t_clump.frameList, t_data, ptrPos);
|
|
||||||
readSectionHeader(t_clump.frameList.data, t_data, ptrPos);
|
|
||||||
readFrameListData(t_clump.frameList.data, t_data, ptrPos);
|
|
||||||
|
|
||||||
t_clump.frameList.extensions = new RwFrameListExtension[t_clump.frameList.data.frameCount];
|
// readSectionHeader(t_clump, t_data, ptrPos);
|
||||||
for (u32 i = 0; i < t_clump.frameList.data.frameCount; i++)
|
// readSectionHeader(t_clump.data, t_data, ptrPos);
|
||||||
{
|
// readClumpData(t_clump.data, t_data, ptrPos);
|
||||||
readSectionHeader(t_clump.frameList.extensions[i], t_data, ptrPos);
|
for (u8 i = 0; i < 3 * 3; i++)
|
||||||
ptrPos += t_clump.frameList.extensions[i].sectionSize;
|
ptrPos += sizeof(u32);
|
||||||
}
|
|
||||||
|
|
||||||
readSectionHeader(t_clump.geometryList, t_data, ptrPos);
|
// readSectionHeader(t_clump.frameList, t_data, ptrPos);
|
||||||
readSectionHeader(t_clump.geometryList.data, t_data, ptrPos);
|
// readSectionHeader(t_clump.frameList.data, t_data, ptrPos);
|
||||||
readGeometryListData(t_clump.geometryList.data, t_data, ptrPos);
|
// readFrameListData(t_clump.frameList.data, t_data, ptrPos);
|
||||||
|
// t_clump.frameList.extensions = new RwFrameListExtension[t_clump.frameList.data.frameCount];
|
||||||
|
// for (u32 i = 0; i < t_clump.frameList.data.frameCount; i++)
|
||||||
|
// {
|
||||||
|
// readSectionHeader(t_clump.frameList.extensions[i], t_data, ptrPos);
|
||||||
|
// ptrPos += t_clump.frameList.extensions[i].sectionSize;
|
||||||
|
// }
|
||||||
|
RwSectionHeader header1 = RwSectionHeader();
|
||||||
|
readSectionHeader(header1, t_data, ptrPos);
|
||||||
|
ptrPos += header1.sectionSize;
|
||||||
|
|
||||||
t_clump.geometryList.geometries = new RwGeometry[t_clump.geometryList.data.geometryCount];
|
// readSectionHeader(t_clump.geometryList, t_data, ptrPos);
|
||||||
printf("Geometries:%d\n", t_clump.geometryList.data.geometryCount);
|
// readSectionHeader(t_clump.geometryList.data, t_data, ptrPos);
|
||||||
for (u32 i = 0; i < t_clump.geometryList.data.geometryCount; i++)
|
for (u8 i = 0; i < 2 * 3; i++)
|
||||||
{
|
ptrPos += sizeof(u32);
|
||||||
readSectionHeader(t_clump.geometryList.geometries[i], t_data, ptrPos);
|
|
||||||
readSectionHeader(t_clump.geometryList.geometries[i].data, t_data, ptrPos);
|
|
||||||
readGeometryData(t_clump.geometryList.geometries[i].data, t_data, ptrPos, t_scale);
|
|
||||||
|
|
||||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList, t_data, ptrPos);
|
// readGeometryListData(t_clump.geometryList.data, t_data, ptrPos);
|
||||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList.data, t_data, ptrPos);
|
ptrPos += sizeof(u32);
|
||||||
readMaterialListData(t_clump.geometryList.geometries[i].materialList.data, t_data, ptrPos);
|
|
||||||
|
|
||||||
u32 materialCount = t_clump.geometryList.geometries[i].materialList.data.materialCount;
|
// readSectionHeader(geometry, t_data, ptrPos);
|
||||||
printf("Materials:%d\n", materialCount);
|
// readSectionHeader(geometry.data, t_data, ptrPos);
|
||||||
|
for (size_t i = 0; i < 2 * 3; i++)
|
||||||
|
ptrPos += sizeof(u32);
|
||||||
|
|
||||||
t_clump.geometryList.geometries[i].materialList.materials = new RwMaterial[materialCount];
|
readGeometryData(o_result, t_invertT, t_data, ptrPos, t_scale);
|
||||||
|
|
||||||
|
// readSectionHeader(geometry.materialList, t_data, ptrPos);
|
||||||
|
// readSectionHeader(geometry.materialList.data, t_data, ptrPos);
|
||||||
|
for (size_t i = 0; i < 2 * 3; i++)
|
||||||
|
ptrPos += sizeof(u32);
|
||||||
|
|
||||||
|
RwMaterialListData materialListData = RwMaterialListData();
|
||||||
|
readMaterialListData(materialListData, t_data, ptrPos);
|
||||||
|
u32 materialCount = materialListData.materialCount;
|
||||||
|
|
||||||
|
char **materialNames = new char *[materialCount];
|
||||||
for (u32 j = 0; j < materialCount; j++)
|
for (u32 j = 0; j < materialCount; j++)
|
||||||
{
|
{
|
||||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList.materials[j], t_data, ptrPos);
|
// readSectionHeader(geometry.materialList.materials[j], t_data, ptrPos);
|
||||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList.materials[j].data, t_data, ptrPos);
|
for (size_t i = 0; i < 3; i++)
|
||||||
readMaterialData(t_clump.geometryList.geometries[i].materialList.materials[j].data, t_data, ptrPos);
|
ptrPos += sizeof(u32);
|
||||||
|
|
||||||
u32 textureCount = t_clump.geometryList.geometries[i].materialList.materials[j].data.textureCount;
|
// RwMaterialData materialData = RwMaterialData();
|
||||||
t_clump.geometryList.geometries[i].materialList.materials[j].textures = new RwTexture[textureCount];
|
// readSectionHeader(materialData, t_data, ptrPos);
|
||||||
for (u32 k = 0; k < textureCount; k++)
|
// readMaterialData(materialData, t_data, ptrPos);
|
||||||
{
|
RwSectionHeader header1 = RwSectionHeader();
|
||||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList.materials[j].textures[k], t_data, ptrPos);
|
readSectionHeader(header1, t_data, ptrPos);
|
||||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList.materials[j].textures[k].data, t_data, ptrPos);
|
ptrPos += header1.sectionSize;
|
||||||
readTextureData(t_clump.geometryList.geometries[i].materialList.materials[j].textures[k].data, t_data, ptrPos);
|
|
||||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList.materials[j].textures[k].textureName, t_data, ptrPos);
|
// for (u32 k = 0; k < textureCount; k++)
|
||||||
readStringData(t_clump.geometryList.geometries[i].materialList.materials[j].textures[k].textureName, t_data, ptrPos);
|
// {
|
||||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList.materials[j].textures[k].textureAlphaName, t_data, ptrPos);
|
|
||||||
readStringData(t_clump.geometryList.geometries[i].materialList.materials[j].textures[k].textureAlphaName, t_data, ptrPos);
|
// readSectionHeader(geometry.materialList.materials[j].textures[k], t_data, ptrPos);
|
||||||
|
// readSectionHeader(geometry.materialList.materials[j].textures[k].data, t_data, ptrPos);
|
||||||
|
for (size_t i = 0; i < 2 * 3; i++)
|
||||||
|
ptrPos += sizeof(u32);
|
||||||
|
|
||||||
|
// readTextureData(geometry.materialList.materials[j].textures[k].data, t_data, ptrPos);
|
||||||
|
ptrPos += sizeof(u32);
|
||||||
|
|
||||||
|
RwSectionHeader header1b = RwSectionHeader();
|
||||||
|
readSectionHeader(header1b, t_data, ptrPos);
|
||||||
|
materialNames[j] = readString(t_data, ptrPos, header1b.sectionSize);
|
||||||
|
|
||||||
|
// readSectionHeader(geometry.materialList.materials[j].textures[k].textureAlphaName, t_data, ptrPos);
|
||||||
|
// readStringData(geometry.materialList.materials[j].textures[k].textureAlphaName, t_data, ptrPos);
|
||||||
|
RwSectionHeader header2 = RwSectionHeader();
|
||||||
|
readSectionHeader(header2, t_data, ptrPos);
|
||||||
|
ptrPos += header2.sectionSize;
|
||||||
|
|
||||||
// The content of extension is Sky Mipmap Val
|
// The content of extension is Sky Mipmap Val
|
||||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList.materials[j].textures[k].extension, t_data, ptrPos);
|
// readSectionHeader(geometry.materialList.materials[j].textures[k].extension, t_data, ptrPos);
|
||||||
ptrPos += t_clump.geometryList.geometries[i].materialList.materials[j].textures[k].extension.sectionSize;
|
RwSectionHeader header3 = RwSectionHeader();
|
||||||
}
|
readSectionHeader(header3, t_data, ptrPos);
|
||||||
// Probably always void extension
|
ptrPos += header3.sectionSize;
|
||||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList.materials[j].extension, t_data, ptrPos);
|
// }
|
||||||
ptrPos += t_clump.geometryList.geometries[i].materialList.materials[j].extension.sectionSize;
|
|
||||||
}
|
|
||||||
// For Bin Mesh aka Material split
|
|
||||||
readSectionHeader(t_clump.geometryList.geometries[i].extension, t_data, ptrPos);
|
|
||||||
readGeometryExtension(t_clump.geometryList.geometries[i].extension, t_data, ptrPos);
|
|
||||||
ptrPos += t_clump.geometryList.geometries[i].extension.sectionSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
readSectionHeader(t_clump.atomic, t_data, ptrPos);
|
// Probably always void extension
|
||||||
readSectionHeader(t_clump.atomic.data, t_data, ptrPos);
|
// readSectionHeader(geometry.materialList.materials[j].extension, t_data, ptrPos);
|
||||||
ptrPos += t_clump.atomic.data.sectionSize;
|
RwSectionHeader header4 = RwSectionHeader();
|
||||||
|
readSectionHeader(header4, t_data, ptrPos);
|
||||||
|
ptrPos += header4.sectionSize;
|
||||||
|
}
|
||||||
|
// delete[] materialNames; // TODO
|
||||||
|
|
||||||
|
// For Bin Mesh aka Material split
|
||||||
|
// readSectionHeader(geometry.extension, t_data, ptrPos);
|
||||||
|
for (size_t i = 0; i < 3; i++)
|
||||||
|
ptrPos += sizeof(u32);
|
||||||
|
readGeometryExtension(o_result, materialNames, t_data, ptrPos);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < materialCount; i++)
|
||||||
|
delete[] materialNames[i];
|
||||||
|
|
||||||
|
delete materialNames;
|
||||||
|
|
||||||
|
// ptrPos += geometry.extension.sectionSize;
|
||||||
|
|
||||||
|
// readSectionHeader(t_clump.atomic, t_data, ptrPos);
|
||||||
|
// readSectionHeader(t_clump.atomic.data, t_data, ptrPos);
|
||||||
|
// ptrPos += t_clump.atomic.data.sectionSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DffLoader::readSectionHeader(RwSectionHeader &t_sh, u8 *t_buffer, u32 &t_ptrPos)
|
void DffLoader::readSectionHeader(RwSectionHeader &t_sh, u8 *t_buffer, u32 &t_ptrPos)
|
||||||
@@ -136,139 +197,154 @@ void DffLoader::readSectionHeader(RwSectionHeader &t_sh, u8 *t_buffer, u32 &t_pt
|
|||||||
|
|
||||||
void DffLoader::readFrameListData(RwFrameListData &t_frd, u8 *t_buffer, u32 &t_ptrPos)
|
void DffLoader::readFrameListData(RwFrameListData &t_frd, u8 *t_buffer, u32 &t_ptrPos)
|
||||||
{
|
{
|
||||||
t_frd.frameCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
// t_frd.frameCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||||
printf("Frame count:%d\n", t_frd.frameCount);
|
// printf("Frame count:%d\n", t_frd.frameCount);
|
||||||
t_frd.frameInformation = new RwFrameListChunk[t_frd.frameCount];
|
// t_frd.frameInformation = new RwFrameListChunk[t_frd.frameCount];
|
||||||
|
|
||||||
for (u32 i = 0; i < t_frd.frameCount; i++)
|
// for (u32 i = 0; i < t_frd.frameCount; i++)
|
||||||
{
|
// {
|
||||||
t_frd.frameInformation[i].rotationalMatrix = new float[t_frd.ROT_MAT_DIM];
|
// t_frd.frameInformation[i].rotationalMatrix = new float[t_frd.ROT_MAT_DIM];
|
||||||
for (u32 j = 0; j < t_frd.ROT_MAT_DIM; j++)
|
// for (u32 j = 0; j < t_frd.ROT_MAT_DIM; j++)
|
||||||
t_frd.frameInformation[i].rotationalMatrix[j] = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
// t_frd.frameInformation[i].rotationalMatrix[j] = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||||
|
|
||||||
t_frd.frameInformation[i].coordinatesOffsetX = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
// t_frd.frameInformation[i].coordinatesOffsetX = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||||
t_frd.frameInformation[i].coordinatesOffsetY = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
// t_frd.frameInformation[i].coordinatesOffsetY = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||||
t_frd.frameInformation[i].coordinatesOffsetZ = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
// t_frd.frameInformation[i].coordinatesOffsetZ = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||||
t_frd.frameInformation[i]
|
// t_frd.frameInformation[i]
|
||||||
.parentFrame = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
// .parentFrame = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||||
t_frd.frameInformation[i].unk1 = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
// t_frd.frameInformation[i].unk1 = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
void DffLoader::readClumpData(RwClumpData &t_cd, u8 *t_buffer, u32 &t_ptrPos)
|
void DffLoader::readClumpData(RwClumpData &t_cd, u8 *t_buffer, u32 &t_ptrPos)
|
||||||
{
|
{
|
||||||
t_cd.objectCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
// t_cd.objectCount = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||||
t_cd.unk1 = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
// t_cd.unk1 = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||||
t_cd.unk2 = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
// t_cd.unk2 = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DffLoader::readGeometryListData(RwGeometryListData &t_gld, u8 *t_buffer, u32 &t_ptrPos)
|
void DffLoader::readGeometryListData(RwGeometryListData &t_gld, u8 *t_buffer, u32 &t_ptrPos)
|
||||||
{
|
{
|
||||||
t_gld.geometryCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
// t_gld.geometryCount = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DffLoader::readGeometryExtension(RwGeometryExtension &t_ge, u8 *t_buffer, u32 &t_ptrPos)
|
void DffLoader::readGeometryExtension(MeshFrame *o_frame, char **materialNames, u8 *t_buffer, u32 &t_ptrPos)
|
||||||
{
|
{
|
||||||
for (u8 i = 0; i < 3; i++)
|
for (u8 i = 0; i < 3; i++)
|
||||||
t_ptrPos += sizeof(u32);
|
t_ptrPos += sizeof(u32);
|
||||||
|
|
||||||
t_ge.materialSplit.header.triangleStrip = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
RwMaterialSplitHeader header = RwMaterialSplitHeader();
|
||||||
t_ge.materialSplit.header.splitCount = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
header.triangleStrip = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||||
t_ge.materialSplit.header.faceCount = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
header.splitCount = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||||
|
header.faceCount = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||||
|
|
||||||
t_ge.materialSplit.splitInformation = new RwGeometryListInfoChunk[t_ge.materialSplit.header.splitCount];
|
o_frame->allocateMaterials(header.splitCount);
|
||||||
for (u32 i = 0; i < t_ge.materialSplit.header.splitCount; i++)
|
for (u32 i = 0; i < header.splitCount; i++)
|
||||||
{
|
{
|
||||||
t_ge.materialSplit.splitInformation[i].faceIndex = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
u32 facesCount = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||||
t_ge.materialSplit.splitInformation[i].materialIndex = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
u32 materialIndex = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||||
|
o_frame->getMaterial(i).setSTsPresent(true);
|
||||||
t_ge.materialSplit.splitInformation[i].vertexInformation = new RwGeometryListVertexInfoChunk[t_ge.materialSplit.splitInformation[i].faceIndex];
|
o_frame->getMaterial(i).setNormalsPresent(true);
|
||||||
for (u32 j = 0; j < t_ge.materialSplit.splitInformation[i].faceIndex; j++)
|
o_frame->getMaterial(i).allocateFaces(facesCount);
|
||||||
t_ge.materialSplit.splitInformation[i].vertexInformation[j].vertex1 = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
o_frame->getMaterial(i).setName(materialNames[materialIndex]);
|
||||||
|
for (u32 j = 0; j < facesCount; j++)
|
||||||
|
{
|
||||||
|
u32 vertex1 = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||||
|
// Inverted insertind due to backface culling
|
||||||
|
o_frame->getMaterial(i).setVertexFace(facesCount - 1 - j, vertex1);
|
||||||
|
o_frame->getMaterial(i).setNormalFace(facesCount - 1 - j, vertex1);
|
||||||
|
o_frame->getMaterial(i).setSTFace(facesCount - 1 - j, vertex1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DffLoader::readGeometryData(RwGeometryData &t_gd, u8 *t_buffer, u32 &t_ptrPos, float t_scale)
|
void DffLoader::readGeometryData(MeshFrame *o_frame, u8 t_invertT, u8 *t_buffer, u32 &t_ptrPos, float t_scale)
|
||||||
{
|
{
|
||||||
t_gd.dataHeader.flags = readWordFromArrayLE(t_buffer, t_ptrPos);
|
Vector3 tempVec = Vector3();
|
||||||
t_gd.dataHeader.unk1 = readWordFromArrayLE(t_buffer, t_ptrPos);
|
Point tempPoint = Point();
|
||||||
t_gd.dataHeader.triangleCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
|
||||||
t_gd.dataHeader.vertexCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
RwGeometryDataHeader header;
|
||||||
t_gd.dataHeader.morphTargetCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
header.flags = readWordFromArrayLE(t_buffer, t_ptrPos);
|
||||||
|
header.unk1 = readWordFromArrayLE(t_buffer, t_ptrPos);
|
||||||
|
header.triangleCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||||
|
header.vertexCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||||
|
header.morphTargetCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||||
|
|
||||||
if (false)
|
if (false)
|
||||||
{ // version equals 4099 according to old documentation, disabled as for now
|
{ // version equals 4099 according to old documentation, disabled as for now
|
||||||
t_gd.lightingHeader.ambient = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
readDwordFromArrayLE(t_buffer, t_ptrPos); // ambient
|
||||||
t_gd.lightingHeader.diffuse = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
readDwordFromArrayLE(t_buffer, t_ptrPos); // diffuse
|
||||||
t_gd.lightingHeader.specular = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
readDwordFromArrayLE(t_buffer, t_ptrPos); // specular
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t_gd.dataHeader.flags & rwOBJECT_VERTEX_PRELIT)
|
if (header.flags & rwOBJECT_VERTEX_PRELIT)
|
||||||
|
for (u32 i = 0; i < header.vertexCount; i++)
|
||||||
{
|
{
|
||||||
t_gd.colorInformation = new RwGeometryDataColorInformationChunk[t_gd.dataHeader.vertexCount];
|
readByteFromArrayLE(t_buffer, t_ptrPos); // r
|
||||||
for (u32 i = 0; i < t_gd.dataHeader.vertexCount; i++)
|
readByteFromArrayLE(t_buffer, t_ptrPos); // g
|
||||||
|
readByteFromArrayLE(t_buffer, t_ptrPos); // b
|
||||||
|
readByteFromArrayLE(t_buffer, t_ptrPos); // a
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header.flags & rwOBJECT_VERTEX_TEXTURED)
|
||||||
{
|
{
|
||||||
t_gd.colorInformation[i].red = readByteFromArrayLE(t_buffer, t_ptrPos);
|
o_frame->allocateSTs(header.vertexCount);
|
||||||
t_gd.colorInformation[i].green = readByteFromArrayLE(t_buffer, t_ptrPos);
|
for (u32 i = 0; i < header.vertexCount; i++)
|
||||||
t_gd.colorInformation[i].blue = readByteFromArrayLE(t_buffer, t_ptrPos);
|
{
|
||||||
t_gd.colorInformation[i].alpha = readByteFromArrayLE(t_buffer, t_ptrPos);
|
float u = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||||
|
float v = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||||
|
tempPoint.set(u, v);
|
||||||
|
if (t_invertT)
|
||||||
|
tempPoint.y = 1.0F - tempPoint.y;
|
||||||
|
o_frame->setST(i, tempPoint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t_gd.dataHeader.flags & rwOBJECT_VERTEX_TEXTURED)
|
for (u32 i = 0; i < header.triangleCount; i++)
|
||||||
{
|
{
|
||||||
t_gd.textureMappingInformation = new RwGeometryDataTextureMappingInformationChunk[t_gd.dataHeader.vertexCount];
|
readWordFromArrayLE(t_buffer, t_ptrPos); // vert2
|
||||||
for (u32 i = 0; i < t_gd.dataHeader.vertexCount; i++)
|
readWordFromArrayLE(t_buffer, t_ptrPos); // vert1
|
||||||
{
|
readWordFromArrayLE(t_buffer, t_ptrPos); // flags
|
||||||
t_gd.textureMappingInformation[i].u = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
readWordFromArrayLE(t_buffer, t_ptrPos); // vert3
|
||||||
t_gd.textureMappingInformation[i].v = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
t_gd.faceInformation = new RwGeometryDataFaceInformation[t_gd.dataHeader.triangleCount];
|
for (size_t i = 0; i < 6; i++)
|
||||||
for (u32 i = 0; i < t_gd.dataHeader.triangleCount; i++)
|
t_ptrPos += sizeof(u32);
|
||||||
|
// t_gd.nonameInfo.boundingSphereX = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||||
|
// t_gd.nonameInfo.boundingSphereY = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||||
|
// t_gd.nonameInfo.boundingSphereZ = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||||
|
// t_gd.nonameInfo.boundingSphereR = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||||
|
// t_gd.nonameInfo.hasPosition = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||||
|
// t_gd.nonameInfo.hasNormals = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||||
|
|
||||||
|
o_frame->allocateVertices(header.vertexCount);
|
||||||
|
for (u32 i = 0; i < header.vertexCount; i++)
|
||||||
{
|
{
|
||||||
t_gd.faceInformation[i].vertex2 = readWordFromArrayLE(t_buffer, t_ptrPos);
|
float x = readFloatFromArrayLE(t_buffer, t_ptrPos) * t_scale;
|
||||||
t_gd.faceInformation[i].vertex1 = readWordFromArrayLE(t_buffer, t_ptrPos);
|
float y = readFloatFromArrayLE(t_buffer, t_ptrPos) * t_scale;
|
||||||
t_gd.faceInformation[i].flags = readWordFromArrayLE(t_buffer, t_ptrPos);
|
float z = readFloatFromArrayLE(t_buffer, t_ptrPos) * t_scale;
|
||||||
t_gd.faceInformation[i].vertex3 = readWordFromArrayLE(t_buffer, t_ptrPos);
|
tempVec.set(x, y, z);
|
||||||
|
o_frame->setVertex(i, tempVec);
|
||||||
}
|
}
|
||||||
|
|
||||||
t_gd.nonameInfo.boundingSphereX = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
o_frame->allocateNormals(header.vertexCount);
|
||||||
t_gd.nonameInfo.boundingSphereY = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
for (u32 i = 0; i < header.vertexCount; i++)
|
||||||
t_gd.nonameInfo.boundingSphereZ = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
|
||||||
t_gd.nonameInfo.boundingSphereR = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
|
||||||
t_gd.nonameInfo.hasPosition = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
|
||||||
t_gd.nonameInfo.hasNormals = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
|
||||||
|
|
||||||
t_gd.vertexInformation = new Vector3[t_gd.dataHeader.vertexCount];
|
|
||||||
for (u32 i = 0; i < t_gd.dataHeader.vertexCount; i++)
|
|
||||||
{
|
{
|
||||||
t_gd.vertexInformation[i].x = readFloatFromArrayLE(t_buffer, t_ptrPos) * t_scale;
|
float x = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||||
t_gd.vertexInformation[i].y = readFloatFromArrayLE(t_buffer, t_ptrPos) * t_scale;
|
float y = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||||
t_gd.vertexInformation[i].z = readFloatFromArrayLE(t_buffer, t_ptrPos) * t_scale;
|
float z = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||||
}
|
tempVec.set(x, y, z);
|
||||||
|
o_frame->setNormal(i, tempVec);
|
||||||
if (t_gd.dataHeader.flags & rwOBJECT_VERTEX_NORMALS)
|
|
||||||
{
|
|
||||||
t_gd.normalInformation = new Vector3[t_gd.dataHeader.vertexCount];
|
|
||||||
for (u32 i = 0; i < t_gd.dataHeader.vertexCount; i++)
|
|
||||||
{
|
|
||||||
t_gd.normalInformation[i].x = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
|
||||||
t_gd.normalInformation[i].y = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
|
||||||
t_gd.normalInformation[i].z = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DffLoader::readMaterialListData(RwMaterialListData &t_mld, u8 *t_buffer, u32 &t_ptrPos)
|
void DffLoader::readMaterialListData(RwMaterialListData &t_mld, u8 *t_buffer, u32 &t_ptrPos)
|
||||||
{
|
{
|
||||||
t_mld.materialCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
t_mld.materialCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||||
t_mld.arrayOfUnks = new u32[t_mld.materialCount];
|
// t_mld.arrayOfUnks = new u32[t_mld.materialCount];
|
||||||
for (u32 i = 0; i < t_mld.materialCount; i++)
|
for (u32 i = 0; i < t_mld.materialCount; i++)
|
||||||
{
|
readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||||
t_mld.arrayOfUnks[i] = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
// t_mld.arrayOfUnks[i] = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DffLoader::readMaterialData(RwMaterialData &t_md, u8 *t_buffer, u32 &t_ptrPos)
|
void DffLoader::readMaterialData(RwMaterialData &t_md, u8 *t_buffer, u32 &t_ptrPos)
|
||||||
@@ -325,15 +401,6 @@ float DffLoader::readFloatFromArrayLE(u8 *t_buffer, u32 &t_ptrPos)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 *DffLoader::readData(u8 *t_buffer, u32 &t_ptrPos, u32 t_dataSize)
|
|
||||||
{
|
|
||||||
u8 *arr = new u8[t_dataSize];
|
|
||||||
for (u32 i = 0; i < t_dataSize; ++i)
|
|
||||||
arr[i] = t_buffer[i + t_ptrPos];
|
|
||||||
t_ptrPos += t_dataSize;
|
|
||||||
return arr;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *DffLoader::readString(u8 *t_buffer, u32 &t_ptrPos, u32 t_dataSize)
|
char *DffLoader::readString(u8 *t_buffer, u32 &t_ptrPos, u32 t_dataSize)
|
||||||
{
|
{
|
||||||
u32 strLength = String::getLength((char *)&t_buffer[t_ptrPos]);
|
u32 strLength = String::getLength((char *)&t_buffer[t_ptrPos]);
|
||||||
|
|||||||
@@ -10,11 +10,12 @@
|
|||||||
|
|
||||||
#include "../include/loaders/md2_loader.hpp"
|
#include "../include/loaders/md2_loader.hpp"
|
||||||
|
|
||||||
|
#include "../include/utils/string.hpp"
|
||||||
#include "../include/utils/debug.hpp"
|
#include "../include/utils/debug.hpp"
|
||||||
|
#include "../include/loaders/anorms.hpp"
|
||||||
#include "../include/models/math/vector3.hpp"
|
#include "../include/models/math/vector3.hpp"
|
||||||
#include "../include/models/math/point.hpp"
|
#include "../include/models/math/point.hpp"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <iosfwd>
|
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
// Constructors/Destructors
|
// Constructors/Destructors
|
||||||
@@ -28,101 +29,119 @@ MD2Loader::~MD2Loader() {}
|
|||||||
// Methods
|
// Methods
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
/** Load, parse .obj file and load data into given MeshSpec */
|
int MEM_fread(char *buf, size_t size, size_t n, const FILE *f)
|
||||||
void MD2Loader::load(MD2Model *o_result, char *t_filename, float t_scale)
|
|
||||||
{
|
{
|
||||||
PRINT_LOG("Loading new MD2 file");
|
memcpy(buf, f, size * n);
|
||||||
md2_t header; // md2 header
|
f += size * n;
|
||||||
char *buffer; // buffer storing frame data
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
FILE *file = fopen(t_filename, "rb");
|
/**
|
||||||
|
* Sandro: Possible PS2SDK bug here?
|
||||||
|
* When I wanted to fopen() -> fread() -> allocate frames memory (vertices etc) -> fclose() = I had in about 10x errors in console
|
||||||
|
* When I did fopen() -> fread() -> fclose() -> allocate frames memory = I had no errors 🤨
|
||||||
|
* It looks like memory allocation during fopen()-fread()-fclose() is broken.
|
||||||
|
*/
|
||||||
|
MeshFrame *MD2Loader::load(u32 &o_framesCount, char *t_subpath, char *t_nameWithoutExtension, float t_scale, u8 t_invertT)
|
||||||
|
{
|
||||||
|
consoleLog("Loading new MD2 file");
|
||||||
|
char *part1 = String::createConcatenated(t_subpath, t_nameWithoutExtension);
|
||||||
|
char *part2 = String::createConcatenated("host:", part1);
|
||||||
|
char *finalPath = String::createConcatenated(part2, ".md2"); // "folder/object.md2"
|
||||||
|
delete[] part1;
|
||||||
|
delete[] part2;
|
||||||
|
md2_t header;
|
||||||
|
|
||||||
if (file == NULL)
|
FILE *file = fopen(finalPath, "rb");
|
||||||
PRINT_ERR("Failed to load .md2 file!");
|
assertMsg(file != NULL, "Failed to load .md2 file!");
|
||||||
|
|
||||||
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!");
|
|
||||||
|
|
||||||
o_result->framesCount = header.num_frames;
|
u32 framesCount = header.num_frames;
|
||||||
o_result->verticesPerFrameCount = header.num_xyz;
|
u32 vertexCount = header.num_xyz;
|
||||||
o_result->coordinatesCount = header.num_st;
|
u32 stsCount = header.num_st;
|
||||||
o_result->trianglesCount = header.num_tris;
|
u32 trianglesCount = header.num_tris;
|
||||||
|
|
||||||
printf("MD2 - Frames: %d\n", header.num_frames);
|
char framesBuffer[framesCount * header.framesize];
|
||||||
printf("MD2 - Vert: %d\n", header.num_xyz);
|
|
||||||
printf("MD2 - Tris: %d\n", header.num_tris);
|
|
||||||
printf("MD2 - STs: %d\n", header.num_st);
|
|
||||||
printf("MD2 - Skin W:%d H: %d\n", header.skinwidth, header.skinheight);
|
|
||||||
|
|
||||||
o_result->allocateMemory();
|
|
||||||
|
|
||||||
buffer = new char[o_result->framesCount * header.framesize];
|
|
||||||
fseek(file, header.ofs_frames, SEEK_SET);
|
fseek(file, header.ofs_frames, SEEK_SET);
|
||||||
fread((char *)buffer, o_result->framesCount * header.framesize, 1, file);
|
fread(&framesBuffer, framesCount * header.framesize, 1, file);
|
||||||
|
|
||||||
frame_t *frame; // temporary vars
|
char stsBuffer[stsCount * sizeof(texCoord_t)];
|
||||||
Vector3 *ptrVerts;
|
|
||||||
u32 *ptrNormals;
|
|
||||||
// vertex array initialization
|
|
||||||
for (u32 j = 0; j < o_result->framesCount; j++)
|
|
||||||
{
|
|
||||||
frame = (frame_t *)&buffer[header.framesize * j];
|
|
||||||
ptrVerts = &o_result->vertices[o_result->verticesPerFrameCount * j];
|
|
||||||
ptrNormals = &o_result->normalIndexes[o_result->verticesPerFrameCount * j];
|
|
||||||
|
|
||||||
for (u32 i = 0; i < o_result->verticesPerFrameCount; i++)
|
|
||||||
{
|
|
||||||
ptrVerts[i].x = ((frame->verts[i].v[0] * frame->scale[0]) + frame->translate[0]) * t_scale;
|
|
||||||
ptrVerts[i].y = ((frame->verts[i].v[1] * frame->scale[1]) + frame->translate[1]) * t_scale;
|
|
||||||
ptrVerts[i].z = ((frame->verts[i].v[2] * frame->scale[2]) + frame->translate[2]) * t_scale;
|
|
||||||
|
|
||||||
ptrNormals[i] = frame->verts[i].lightnormalindex;
|
|
||||||
}
|
|
||||||
if (j == o_result->framesCount - 1)
|
|
||||||
printf("Last frame, last vert: X:%f Y:%f Z:%f\n",
|
|
||||||
ptrVerts[o_result->verticesPerFrameCount - 1].x,
|
|
||||||
ptrVerts[o_result->verticesPerFrameCount - 1].y,
|
|
||||||
ptrVerts[o_result->verticesPerFrameCount - 1].z);
|
|
||||||
}
|
|
||||||
delete[] buffer;
|
|
||||||
|
|
||||||
buffer = new char[o_result->coordinatesCount * sizeof(texCoord_t)];
|
|
||||||
fseek(file, header.ofs_st, SEEK_SET);
|
fseek(file, header.ofs_st, SEEK_SET);
|
||||||
fread((char *)buffer, o_result->coordinatesCount * sizeof(texCoord_t), 1, file);
|
fread(&stsBuffer, stsCount * sizeof(texCoord_t), 1, file);
|
||||||
|
|
||||||
texCoord_t *texCoord;
|
char trianglesBuffer[trianglesCount * sizeof(triangle_t)];
|
||||||
for (u32 i = 0; i < o_result->coordinatesCount; i++)
|
|
||||||
{
|
|
||||||
texCoord = (texCoord_t *)&buffer[sizeof(texCoord_t) * i];
|
|
||||||
o_result->coordinates[i].x = (float)texCoord->s / header.skinwidth;
|
|
||||||
o_result->coordinates[i].y = (float)texCoord->t / header.skinheight;
|
|
||||||
}
|
|
||||||
delete[] buffer;
|
|
||||||
|
|
||||||
printf("Last tex coord(%d): S:%f T:%f\n",
|
|
||||||
o_result->coordinatesCount,
|
|
||||||
o_result->coordinates[o_result->coordinatesCount - 1].x,
|
|
||||||
o_result->coordinates[o_result->coordinatesCount - 1].y);
|
|
||||||
|
|
||||||
buffer = new char[o_result->trianglesCount * sizeof(triangle_t)];
|
|
||||||
fseek(file, header.ofs_tris, SEEK_SET);
|
fseek(file, header.ofs_tris, SEEK_SET);
|
||||||
fread((char *)buffer, o_result->trianglesCount * sizeof(triangle_t), 1, file);
|
fread(&trianglesBuffer, trianglesCount * sizeof(triangle_t), 1, file);
|
||||||
|
|
||||||
triangle_t *triangle; // temporary var
|
|
||||||
// vertex array initialization
|
|
||||||
for (u32 i = 0; i < o_result->trianglesCount; i++)
|
|
||||||
{
|
|
||||||
triangle = (triangle_t *)&buffer[sizeof(triangle_t) * i];
|
|
||||||
for (u8 j = 0; j < 3; j++)
|
|
||||||
{
|
|
||||||
o_result->triangles[i].verticeIndexes[j] = triangle->index_xyz[j];
|
|
||||||
o_result->triangles[i].coordIndexes[j] = triangle->index_st[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete[] buffer;
|
|
||||||
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
PRINT_LOG("MD2 file loaded!");
|
|
||||||
|
MeshFrame *resultFrames = new MeshFrame[framesCount];
|
||||||
|
|
||||||
|
frame_t *frame;
|
||||||
|
Vector3 tempVec = Vector3();
|
||||||
|
for (u32 j = 0; j < framesCount; j++)
|
||||||
|
{
|
||||||
|
resultFrames[j].allocateVertices(vertexCount);
|
||||||
|
resultFrames[j].allocateNormals(vertexCount); // can be optimized
|
||||||
|
resultFrames[j].allocateSTs(stsCount);
|
||||||
|
resultFrames[j].allocateMaterials(1);
|
||||||
|
resultFrames[j].getMaterial(0).allocateFaces(trianglesCount * 3);
|
||||||
|
resultFrames[j].getMaterial(0).setName(t_nameWithoutExtension);
|
||||||
|
frame = (frame_t *)&framesBuffer[header.framesize * j];
|
||||||
|
for (u32 i = 0; i < vertexCount; i++)
|
||||||
|
{
|
||||||
|
tempVec.set(
|
||||||
|
((frame->verts[i].v[0] * frame->scale[0]) + frame->translate[0]) * t_scale,
|
||||||
|
((frame->verts[i].v[1] * frame->scale[1]) + frame->translate[1]) * t_scale,
|
||||||
|
((frame->verts[i].v[2] * frame->scale[2]) + frame->translate[2]) * t_scale);
|
||||||
|
resultFrames[j].setVertex(i, tempVec);
|
||||||
|
|
||||||
|
tempVec.set(
|
||||||
|
ANORMS[frame->verts[i].lightnormalindex][0],
|
||||||
|
ANORMS[frame->verts[i].lightnormalindex][1],
|
||||||
|
ANORMS[frame->verts[i].lightnormalindex][2]);
|
||||||
|
resultFrames[j].setNormal(i, tempVec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Point tempPoint = Point();
|
||||||
|
texCoord_t *texCoord;
|
||||||
|
for (u32 i = 0; i < stsCount; i++)
|
||||||
|
{
|
||||||
|
texCoord = (texCoord_t *)&stsBuffer[sizeof(texCoord_t) * i];
|
||||||
|
tempPoint.set(
|
||||||
|
(float)texCoord->s / header.skinwidth,
|
||||||
|
(float)texCoord->t / header.skinheight);
|
||||||
|
if (t_invertT)
|
||||||
|
tempPoint.y = 1.0F - tempPoint.y;
|
||||||
|
for (u32 j = 0; j < framesCount; j++)
|
||||||
|
resultFrames[j].setST(i, tempPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
triangle_t *triangle;
|
||||||
|
for (u32 i = 0; i < trianglesCount; i++)
|
||||||
|
{
|
||||||
|
triangle = (triangle_t *)&trianglesBuffer[sizeof(triangle_t) * i];
|
||||||
|
for (u8 j = 0; j < 3; j++)
|
||||||
|
{
|
||||||
|
for (u32 x = 0; x < framesCount; x++)
|
||||||
|
{
|
||||||
|
resultFrames[x].getMaterial(0).setSTsPresent(true);
|
||||||
|
resultFrames[x].getMaterial(0).setNormalsPresent(true);
|
||||||
|
resultFrames[x].getMaterial(0).setVertexFace((i * 3) + j, triangle->index_xyz[j]);
|
||||||
|
resultFrames[x].getMaterial(0).setSTFace((i * 3) + j, triangle->index_st[j]);
|
||||||
|
resultFrames[x].getMaterial(0).setNormalFace((i * 3) + j, triangle->index_xyz[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
consoleLog("MD2 file loaded!");
|
||||||
|
delete[] finalPath;
|
||||||
|
o_framesCount = framesCount;
|
||||||
|
for (u32 i = 0; i < framesCount; i++)
|
||||||
|
resultFrames[i].calculateBoundingBoxes();
|
||||||
|
return resultFrames;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "../include/loaders/obj_loader.hpp"
|
#include "../include/loaders/obj_loader.hpp"
|
||||||
|
|
||||||
#include "../include/utils/debug.hpp"
|
#include "../include/utils/debug.hpp"
|
||||||
|
#include "../include/utils/string.hpp"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
@@ -25,15 +26,17 @@ ObjLoader::~ObjLoader() {}
|
|||||||
// Methods
|
// Methods
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
/** Load, parse .obj file and load data into given MeshSpec */
|
void ObjLoader::load(MeshFrame *o_result, char *t_filename, float t_scale, u8 t_invertT)
|
||||||
void ObjLoader::load(ObjModel *o_result, char *t_filename, float t_scale)
|
|
||||||
{
|
{
|
||||||
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!");
|
||||||
setObjDataQuantities(file, o_result);
|
allocateObjMemory(file, o_result);
|
||||||
o_result->allocateMemory();
|
fseek(file, 0, SEEK_SET);
|
||||||
u32 verticesI = 0, cordsI = 0, normalsI = 0, i = 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;
|
||||||
|
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
|
||||||
@@ -42,62 +45,149 @@ void ObjLoader::load(ObjModel *o_result, char *t_filename, float t_scale)
|
|||||||
{
|
{
|
||||||
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->vertices[verticesI++] = vector * t_scale;
|
o_result->setVertex(verticesI++, vector * t_scale);
|
||||||
}
|
}
|
||||||
else if (strcmp(lineHeader, "vt") == 0)
|
else if (strcmp(lineHeader, "vt") == 0)
|
||||||
{
|
{
|
||||||
Vector3 vector = Vector3();
|
fscanf(file, "%f %f\n", &point.x, &point.y);
|
||||||
fscanf(file, "%f %f\n", &vector.x, &vector.y);
|
if (t_invertT)
|
||||||
o_result->coordinates[cordsI++] = vector;
|
point.y = 1.0F - point.y;
|
||||||
|
o_result->setST(cordsI++, point);
|
||||||
}
|
}
|
||||||
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->normals[normalsI++] = vector;
|
o_result->setNormal(normalsI++, vector);
|
||||||
|
}
|
||||||
|
else if (strcmp(lineHeader, "usemtl") == 0)
|
||||||
|
{
|
||||||
|
char temp[30];
|
||||||
|
fscanf(file, "%s\n", temp);
|
||||||
|
o_result->getMaterial(++materialsI).setName(temp);
|
||||||
|
faceI = 0;
|
||||||
}
|
}
|
||||||
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
|
||||||
|
fpos_t start;
|
||||||
|
fgetpos(file, &start);
|
||||||
|
int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", x, x, x, x, x, x, x, x, x);
|
||||||
|
fsetpos(file, &start);
|
||||||
|
int newerMatches = 0;
|
||||||
|
switch (matches)
|
||||||
|
{
|
||||||
|
/** Vs, VTs and VNs all set */
|
||||||
|
case 9:
|
||||||
|
{
|
||||||
|
fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n",
|
||||||
&vertexIndex[0], &coordIndex[0], &normalIndex[0],
|
&vertexIndex[0], &coordIndex[0], &normalIndex[0],
|
||||||
&vertexIndex[1], &coordIndex[1], &normalIndex[1],
|
&vertexIndex[1], &coordIndex[1], &normalIndex[1],
|
||||||
&vertexIndex[2], &coordIndex[2], &normalIndex[2]);
|
&vertexIndex[2], &coordIndex[2], &normalIndex[2]);
|
||||||
if (matches != 9)
|
}
|
||||||
PRINT_ERR(".obj can't be read by this simple parser. Try exporting with other options");
|
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
|
else
|
||||||
{
|
{
|
||||||
o_result->verticeFaces[i] = vertexIndex[0] - 1;
|
/** Failed, checking configuration V//VN */
|
||||||
o_result->verticeFaces[i + 1] = vertexIndex[1] - 1;
|
newerMatches = fscanf(file, "%d//%d %d//%d %d//%d", x, x, x, x, x, x);
|
||||||
o_result->verticeFaces[i + 2] = vertexIndex[2] - 1;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
o_result->coordinateFaces[i] = coordIndex[0] - 1;
|
if (matches == 9 || matches == 2 || matches == 1)
|
||||||
o_result->coordinateFaces[i + 1] = coordIndex[1] - 1;
|
{
|
||||||
o_result->coordinateFaces[i + 2] = coordIndex[2] - 1;
|
o_result->getMaterial(materialsI).setVertexFace(faceI, vertexIndex[0] - 1);
|
||||||
|
o_result->getMaterial(materialsI).setVertexFace(faceI + 1, vertexIndex[1] - 1);
|
||||||
|
o_result->getMaterial(materialsI).setVertexFace(faceI + 2, vertexIndex[2] - 1);
|
||||||
|
}
|
||||||
|
if (matches == 9 || matches == 2)
|
||||||
|
{
|
||||||
|
o_result->getMaterial(materialsI).setSTFace(faceI, coordIndex[0] - 1);
|
||||||
|
o_result->getMaterial(materialsI).setSTFace(faceI + 1, coordIndex[1] - 1);
|
||||||
|
o_result->getMaterial(materialsI).setSTFace(faceI + 2, coordIndex[2] - 1);
|
||||||
|
o_result->getMaterial(materialsI).setSTsPresent(true);
|
||||||
|
}
|
||||||
|
|
||||||
o_result->normalFaces[i] = normalIndex[0] - 1;
|
if (matches == 9)
|
||||||
o_result->normalFaces[i + 1] = normalIndex[1] - 1;
|
{
|
||||||
o_result->normalFaces[i + 2] = normalIndex[2] - 1;
|
o_result->getMaterial(materialsI).setNormalFace(faceI, normalIndex[0] - 1);
|
||||||
i += 3;
|
o_result->getMaterial(materialsI).setNormalFace(faceI + 1, normalIndex[1] - 1);
|
||||||
|
o_result->getMaterial(materialsI).setNormalFace(faceI + 2, normalIndex[2] - 1);
|
||||||
|
o_result->getMaterial(materialsI).setNormalsPresent(true);
|
||||||
|
faceI += 3;
|
||||||
|
}
|
||||||
|
else if (matches == 2)
|
||||||
|
{
|
||||||
|
faceI += 2;
|
||||||
|
}
|
||||||
|
else if (matches == 1)
|
||||||
|
{
|
||||||
|
if (newerMatches == 3)
|
||||||
|
{
|
||||||
|
faceI += 1;
|
||||||
|
}
|
||||||
|
else if (newerMatches == 6)
|
||||||
|
{
|
||||||
|
o_result->getMaterial(materialsI).setNormalFace(faceI, normalIndex[0] - 1);
|
||||||
|
o_result->getMaterial(materialsI).setNormalFace(faceI + 1, normalIndex[1] - 1);
|
||||||
|
o_result->getMaterial(materialsI).setNormalFace(faceI + 2, normalIndex[2] - 1);
|
||||||
|
o_result->getMaterial(materialsI).setNormalsPresent(true);
|
||||||
|
faceI += 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 */
|
||||||
* When done, file read offset is resetted to the begginning of file
|
void ObjLoader::allocateObjMemory(FILE *t_file, MeshFrame *o_result)
|
||||||
*/
|
|
||||||
void ObjLoader::setObjDataQuantities(FILE *t_file, ObjModel *o_result)
|
|
||||||
{
|
{
|
||||||
o_result->verticesCount = 0;
|
u32 vertexCount = 0;
|
||||||
o_result->coordinatesCount = 0;
|
u32 stsCount = 0;
|
||||||
o_result->normalsCount = 0;
|
u32 normalsCount = 0;
|
||||||
o_result->facesCount = 0;
|
u32 materialsCount = 0;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
char lineHeader[128];
|
char lineHeader[128];
|
||||||
@@ -105,16 +195,50 @@ void ObjLoader::setObjDataQuantities(FILE *t_file, ObjModel *o_result)
|
|||||||
if (res != EOF)
|
if (res != EOF)
|
||||||
{
|
{
|
||||||
if (strcmp(lineHeader, "v") == 0)
|
if (strcmp(lineHeader, "v") == 0)
|
||||||
o_result->verticesCount += 1;
|
vertexCount += 1;
|
||||||
else if (strcmp(lineHeader, "vt") == 0)
|
else if (strcmp(lineHeader, "vt") == 0)
|
||||||
o_result->coordinatesCount += 1;
|
stsCount += 1;
|
||||||
else if (strcmp(lineHeader, "vn") == 0)
|
else if (strcmp(lineHeader, "vn") == 0)
|
||||||
o_result->normalsCount += 1;
|
normalsCount += 1;
|
||||||
else if (strcmp(lineHeader, "f") == 0)
|
else if (strcmp(lineHeader, "usemtl") == 0)
|
||||||
o_result->facesCount += 3;
|
materialsCount += 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
o_result->allocateVertices(vertexCount);
|
||||||
|
o_result->allocateNormals(normalsCount);
|
||||||
|
o_result->allocateSTs(stsCount);
|
||||||
|
o_result->allocateMaterials(materialsCount);
|
||||||
|
|
||||||
|
s16 currentMatI = -1;
|
||||||
|
|
||||||
fseek(t_file, 0, SEEK_SET);
|
fseek(t_file, 0, SEEK_SET);
|
||||||
|
u32 facesCounter = 0;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
char lineHeader[128];
|
||||||
|
int res = fscanf(t_file, "%s", lineHeader);
|
||||||
|
if (res != EOF)
|
||||||
|
{
|
||||||
|
if (strcmp(lineHeader, "usemtl") == 0)
|
||||||
|
{
|
||||||
|
if (currentMatI >= 0) // Skip -1
|
||||||
|
{
|
||||||
|
o_result->getMaterial(currentMatI).allocateFaces(facesCounter);
|
||||||
|
facesCounter = 0;
|
||||||
|
}
|
||||||
|
currentMatI++;
|
||||||
|
}
|
||||||
|
else if (strcmp(lineHeader, "f") == 0)
|
||||||
|
facesCounter += 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
o_result->getMaterial(currentMatI).allocateFaces(facesCounter); // Allocate last one
|
||||||
|
|
||||||
|
// o_result->isMemoryAllocated = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -1,59 +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/models/dff_model.hpp"
|
|
||||||
|
|
||||||
#include "../include/utils/debug.hpp"
|
|
||||||
|
|
||||||
// ----
|
|
||||||
// Constructors/Destructors
|
|
||||||
// ----
|
|
||||||
|
|
||||||
DffModel::DffModel() {}
|
|
||||||
|
|
||||||
DffModel::~DffModel() {}
|
|
||||||
|
|
||||||
// ----
|
|
||||||
// Methods
|
|
||||||
// ----
|
|
||||||
|
|
||||||
u32 DffModel::getDrawData(u32 splitIndex, VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, VECTOR *o_colors, Vector3 &t_cameraPos, float t_scale, u8 t_shouldBeBackfaceCulled)
|
|
||||||
{
|
|
||||||
u32 result = 0;
|
|
||||||
for (u32 i = 0; i < clump.geometryList.geometries[0].extension.materialSplit.splitInformation[splitIndex].faceIndex; i++)
|
|
||||||
fillNextFace(o_vertices, o_normals, o_coordinates, o_colors, 0,
|
|
||||||
clump.geometryList.geometries[0].extension.materialSplit.splitInformation[splitIndex].vertexInformation[i].vertex1,
|
|
||||||
result++);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DffModel::fillNextFace(VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, VECTOR *o_colors, u8 geometry, u32 t_getI, u32 t_setI)
|
|
||||||
{
|
|
||||||
o_vertices[t_setI][0] = clump.geometryList.geometries[geometry].data.vertexInformation[t_getI].x;
|
|
||||||
o_vertices[t_setI][1] = clump.geometryList.geometries[geometry].data.vertexInformation[t_getI].y;
|
|
||||||
o_vertices[t_setI][2] = clump.geometryList.geometries[geometry].data.vertexInformation[t_getI].z;
|
|
||||||
o_vertices[t_setI][3] = 1.0F;
|
|
||||||
|
|
||||||
o_normals[t_setI][0] = clump.geometryList.geometries[geometry].data.normalInformation[t_getI].x;
|
|
||||||
o_normals[t_setI][1] = clump.geometryList.geometries[geometry].data.normalInformation[t_getI].y;
|
|
||||||
o_normals[t_setI][2] = clump.geometryList.geometries[geometry].data.normalInformation[t_getI].z;
|
|
||||||
o_normals[t_setI][3] = 1.0F;
|
|
||||||
|
|
||||||
o_coordinates[t_setI][0] = clump.geometryList.geometries[geometry].data.textureMappingInformation[t_getI].u;
|
|
||||||
o_coordinates[t_setI][1] = 1.0F - clump.geometryList.geometries[geometry].data.textureMappingInformation[t_getI].v;
|
|
||||||
o_coordinates[t_setI][2] = 1.0F;
|
|
||||||
o_coordinates[t_setI][3] = 1.0F;
|
|
||||||
|
|
||||||
o_colors[t_setI][0] = 1.0F;
|
|
||||||
o_colors[t_setI][1] = 1.0F;
|
|
||||||
o_colors[t_setI][2] = 1.0F;
|
|
||||||
o_colors[t_setI][3] = 1.0F;
|
|
||||||
}
|
|
||||||
+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>
|
||||||
|
|
||||||
@@ -17,10 +18,17 @@
|
|||||||
// ----
|
// ----
|
||||||
|
|
||||||
/** Create by specifying values */
|
/** Create by specifying values */
|
||||||
Point::Point(float x, float y)
|
Point::Point(const float &t_x, const float &t_y)
|
||||||
{
|
{
|
||||||
this->x = x;
|
x = t_x;
|
||||||
this->y = y;
|
y = t_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create with other point values */
|
||||||
|
Point::Point(const Point &v)
|
||||||
|
{
|
||||||
|
x = v.x;
|
||||||
|
y = v.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Create empty point */
|
/** Create empty point */
|
||||||
@@ -36,13 +44,34 @@ Point::~Point() {}
|
|||||||
// Methods
|
// Methods
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
void Point::set(float x, float y)
|
void Point::set(const float &t_x, const float &t_y)
|
||||||
{
|
{
|
||||||
this->x = x;
|
x = t_x;
|
||||||
this->y = y;
|
y = t_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Point::print()
|
void Point::set(const Point &v)
|
||||||
|
{
|
||||||
|
x = v.x;
|
||||||
|
y = v.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
+157
-201
@@ -9,118 +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 x, float y, float z)
|
|
||||||
{
|
|
||||||
this->x = x;
|
|
||||||
this->y = y;
|
|
||||||
this->z = 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)
|
|
||||||
{
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 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;
|
||||||
@@ -129,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;
|
||||||
@@ -153,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);
|
||||||
}
|
}
|
||||||
@@ -212,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(float x, float y, 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(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);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,132 +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/models/md2_model.hpp"
|
|
||||||
|
|
||||||
#include "../include/utils/anorms.hpp"
|
|
||||||
#include "../include/utils/string.hpp"
|
|
||||||
#include "../include/utils/debug.hpp"
|
|
||||||
|
|
||||||
// ----
|
|
||||||
// Constructors/Destructors
|
|
||||||
// ----
|
|
||||||
|
|
||||||
MD2Model::MD2Model(char *t_md2File)
|
|
||||||
{
|
|
||||||
filename = String::createWithoutExtension(t_md2File);
|
|
||||||
|
|
||||||
verticesPerFrameCount = 0;
|
|
||||||
coordinatesCount = 0;
|
|
||||||
trianglesCount = 0;
|
|
||||||
framesCount = 0;
|
|
||||||
|
|
||||||
animState.startFrame = 0;
|
|
||||||
animState.endFrame = 0;
|
|
||||||
animState.interpolation = 0.0F;
|
|
||||||
animState.animType = 0;
|
|
||||||
animState.currentFrame = 0;
|
|
||||||
animState.nextFrame = 0;
|
|
||||||
animState.speed = 0.1F;
|
|
||||||
|
|
||||||
vertices = 0;
|
|
||||||
coordinates = 0;
|
|
||||||
normalIndexes = 0;
|
|
||||||
triangles = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
MD2Model::~MD2Model()
|
|
||||||
{
|
|
||||||
delete[] vertices;
|
|
||||||
delete[] normalIndexes;
|
|
||||||
delete[] coordinates;
|
|
||||||
delete[] triangles;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----
|
|
||||||
// Methods
|
|
||||||
// ----
|
|
||||||
|
|
||||||
u32 MD2Model::getCurrentFrameData(VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, VECTOR *o_colors, Vector3 &t_cameraPos, float t_scale, u8 t_shouldBeBackfaceCulled)
|
|
||||||
{
|
|
||||||
u32 i = 0;
|
|
||||||
animState.interpolation += animState.speed;
|
|
||||||
if (animState.interpolation >= 1.0F)
|
|
||||||
{
|
|
||||||
animState.interpolation = 0.0F;
|
|
||||||
animState.currentFrame = animState.nextFrame;
|
|
||||||
if (++animState.nextFrame > animState.endFrame)
|
|
||||||
animState.nextFrame = animState.startFrame;
|
|
||||||
}
|
|
||||||
for (u32 iTri = 0; iTri < trianglesCount; iTri++)
|
|
||||||
{
|
|
||||||
for (u32 iVert = 0; iVert < 3; iVert++)
|
|
||||||
{
|
|
||||||
const u32 CURR_VERTICE =
|
|
||||||
triangles[iTri].verticeIndexes[iVert] +
|
|
||||||
(verticesPerFrameCount * animState.currentFrame);
|
|
||||||
|
|
||||||
if (animState.startFrame == animState.endFrame)
|
|
||||||
{
|
|
||||||
calc3Vectors[iVert].x = vertices[CURR_VERTICE].x * t_scale;
|
|
||||||
calc3Vectors[iVert].y = vertices[CURR_VERTICE].y * t_scale;
|
|
||||||
calc3Vectors[iVert].z = vertices[CURR_VERTICE].z * t_scale;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const u32 NEXT_VERTICE =
|
|
||||||
triangles[iTri].verticeIndexes[iVert] +
|
|
||||||
(verticesPerFrameCount * animState.nextFrame);
|
|
||||||
calcVector.setByLerp(vertices[CURR_VERTICE], vertices[NEXT_VERTICE], animState.interpolation);
|
|
||||||
calc3Vectors[iVert].x = calcVector.x * t_scale;
|
|
||||||
calc3Vectors[iVert].y = calcVector.y * t_scale;
|
|
||||||
calc3Vectors[iVert].z = calcVector.z * t_scale;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!t_shouldBeBackfaceCulled || Vector3::shouldBeBackfaceCulled(&t_cameraPos, &calc3Vectors[2], &calc3Vectors[1], &calc3Vectors[0]) == 0)
|
|
||||||
for (u32 iVert = 0; iVert < 3; iVert++)
|
|
||||||
{
|
|
||||||
const u32 CURR_VERTICE =
|
|
||||||
triangles[iTri].verticeIndexes[iVert] +
|
|
||||||
(verticesPerFrameCount * animState.currentFrame);
|
|
||||||
|
|
||||||
const u32 CURR_COORD = triangles[iTri].coordIndexes[iVert];
|
|
||||||
|
|
||||||
o_vertices[i][0] = calc3Vectors[iVert].x;
|
|
||||||
o_vertices[i][1] = calc3Vectors[iVert].y;
|
|
||||||
o_vertices[i][2] = calc3Vectors[iVert].z;
|
|
||||||
o_vertices[i][3] = 1.0F;
|
|
||||||
|
|
||||||
o_normals[i][0] = ANORMS[normalIndexes[CURR_VERTICE]][0];
|
|
||||||
o_normals[i][1] = ANORMS[normalIndexes[CURR_VERTICE]][1];
|
|
||||||
o_normals[i][2] = ANORMS[normalIndexes[CURR_VERTICE]][2];
|
|
||||||
o_normals[i][3] = 1.0F;
|
|
||||||
|
|
||||||
o_coordinates[i][0] = coordinates[CURR_COORD].x;
|
|
||||||
o_coordinates[i][1] = 1.0F - coordinates[CURR_COORD].y;
|
|
||||||
o_coordinates[i][2] = 1.0F;
|
|
||||||
o_coordinates[i][3] = 1.0F;
|
|
||||||
|
|
||||||
o_colors[i][0] = 1.0F;
|
|
||||||
o_colors[i][1] = 1.0F;
|
|
||||||
o_colors[i][2] = 1.0F;
|
|
||||||
o_colors[i][3] = 1.0F;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MD2Model::allocateMemory()
|
|
||||||
{
|
|
||||||
vertices = new Vector3[verticesPerFrameCount * framesCount];
|
|
||||||
normalIndexes = new u32[verticesPerFrameCount * framesCount];
|
|
||||||
coordinates = new Point[coordinatesCount];
|
|
||||||
triangles = new MD2Triangle[trianglesCount];
|
|
||||||
}
|
|
||||||
+285
-238
@@ -9,13 +9,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../include/models/mesh.hpp"
|
#include "../include/models/mesh.hpp"
|
||||||
|
|
||||||
#include "../include/loaders/obj_loader.hpp"
|
#include "../include/loaders/obj_loader.hpp"
|
||||||
#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/texture.hpp"
|
||||||
#include "../include/utils/debug.hpp"
|
#include "../include/utils/debug.hpp"
|
||||||
#include "../include/utils/string.hpp"
|
#include "../include/utils/string.hpp"
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
// Constructors/Destructors
|
// Constructors/Destructors
|
||||||
@@ -23,262 +24,323 @@
|
|||||||
|
|
||||||
Mesh::Mesh()
|
Mesh::Mesh()
|
||||||
{
|
{
|
||||||
|
id = rand() % 1000000;
|
||||||
shouldBeFrustumCulled = true;
|
shouldBeFrustumCulled = true;
|
||||||
shouldBeBackfaceCulled = false;
|
shouldBeBackfaceCulled = false;
|
||||||
shouldBeLighted = false;
|
shouldBeLighted = false;
|
||||||
isMd2Loaded = false;
|
_areFramesAllocated = false;
|
||||||
isObjLoaded = false;
|
_isMother = false;
|
||||||
isDffLoaded = false;
|
|
||||||
isSpecInitialized = false;
|
|
||||||
scale = 1.0F;
|
scale = 1.0F;
|
||||||
|
framesCount = 0;
|
||||||
|
animState.startFrame = 0;
|
||||||
|
animState.endFrame = 0;
|
||||||
|
animState.interpolation = 0.0F;
|
||||||
|
animState.animType = 0;
|
||||||
|
animState.currentFrame = 0;
|
||||||
|
animState.stayFrame = 0;
|
||||||
|
animState.isStayFrameSet = false;
|
||||||
|
animState.nextFrame = 0;
|
||||||
|
animState.speed = 0.1F;
|
||||||
|
setDefaultLODAndClut();
|
||||||
}
|
}
|
||||||
|
|
||||||
Mesh::~Mesh()
|
Mesh::~Mesh()
|
||||||
{
|
{
|
||||||
if (isMd2Loaded)
|
if (_areFramesAllocated)
|
||||||
delete md2;
|
delete[] frames;
|
||||||
if (isObjLoaded)
|
|
||||||
delete obj;
|
|
||||||
if (isDffLoaded)
|
|
||||||
delete dff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
// Methods
|
// Methods
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
void Mesh::loadDff(char *t_subfolder, char *t_dffFile, Vector3 &t_initPos, float t_scale)
|
void Mesh::loadObj(char *t_subfolder, char *t_objFile, const float &t_scale, const u8 &t_invertT)
|
||||||
{
|
{
|
||||||
createSpecIfNotCreated();
|
|
||||||
DffLoader loader = DffLoader();
|
|
||||||
dff = new DffModel();
|
|
||||||
char *dffPath = String::createConcatenated(t_subfolder, t_dffFile);
|
|
||||||
loader.load(dff->clump, dffPath, t_scale);
|
|
||||||
delete[] dffPath;
|
|
||||||
position = t_initPos;
|
|
||||||
setVerticesReference(
|
|
||||||
dff->clump.geometryList.geometries[0].data.dataHeader.vertexCount,
|
|
||||||
dff->clump.geometryList.geometries[0].data.vertexInformation);
|
|
||||||
setDefaultColor();
|
|
||||||
isDffLoaded = true;
|
|
||||||
loadTextures(t_subfolder, ".bmp");
|
|
||||||
spec->allocateTextureBuffer(spec->textures[0].width, spec->textures[0].height); // wtf?
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mesh::setDff(Vector3 &t_initPos, DffModel *t_dffModel, MeshSpec *t_spec)
|
|
||||||
{
|
|
||||||
position = t_initPos;
|
|
||||||
spec = t_spec;
|
|
||||||
isSpecInitialized = 1;
|
|
||||||
dff = t_dffModel;
|
|
||||||
setVerticesReference(
|
|
||||||
dff->clump.geometryList.geometries[0].data.dataHeader.vertexCount,
|
|
||||||
dff->clump.geometryList.geometries[0].data.vertexInformation);
|
|
||||||
setDefaultColor();
|
|
||||||
isDffLoaded = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mesh::loadObj(char *t_subfolder, char *t_objFile, Vector3 &t_initPos, float t_scale)
|
|
||||||
{
|
|
||||||
createSpecIfNotCreated();
|
|
||||||
ObjLoader loader = ObjLoader();
|
ObjLoader loader = ObjLoader();
|
||||||
obj = new ObjModel(t_objFile);
|
framesCount = 1;
|
||||||
char *objPath = String::createConcatenated(t_subfolder, t_objFile);
|
frames = new MeshFrame[framesCount];
|
||||||
loader.load(obj, objPath, t_scale);
|
_areFramesAllocated = true;
|
||||||
delete[] objPath;
|
char *part1 = String::createConcatenated(t_subfolder, t_objFile); // "folder/object"
|
||||||
position = t_initPos;
|
char *finalPath = String::createConcatenated(part1, ".obj"); // "folder/object.obj"
|
||||||
setVerticesReference(obj->facesCount, obj->vertices);
|
loader.load(&frames[0], finalPath, t_scale, t_invertT);
|
||||||
setDefaultColor();
|
delete[] part1;
|
||||||
isObjLoaded = true;
|
delete[] finalPath;
|
||||||
loadTextures(t_subfolder, ".bmp");
|
_isMother = true;
|
||||||
spec->allocateTextureBuffer(spec->textures[0].width, spec->textures[0].height); // wtf?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mesh::setObj(Vector3 &t_initPos, ObjModel *t_objModel, MeshSpec *t_spec)
|
void Mesh::loadObj(char *t_subfolder, char *t_objFile, const float &t_scale, const u32 &t_framesCount, const u8 &t_invertT)
|
||||||
{
|
{
|
||||||
position = t_initPos;
|
assertMsg(t_framesCount != 0, "Frames count cannot be 0!");
|
||||||
spec = t_spec;
|
if (t_framesCount == 1)
|
||||||
isSpecInitialized = true;
|
loadObj(t_subfolder, t_objFile, t_scale, t_invertT);
|
||||||
obj = t_objModel;
|
|
||||||
setVerticesReference(obj->facesCount, obj->vertices);
|
|
||||||
setDefaultColor();
|
|
||||||
isObjLoaded = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mesh::createSpecIfNotCreated()
|
|
||||||
{
|
|
||||||
if (!isSpecInitialized)
|
|
||||||
{
|
|
||||||
isSpecInitialized = true;
|
|
||||||
spec = new MeshSpec();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mesh::setAnimSpeed(float t_value)
|
|
||||||
{
|
|
||||||
if (isMd2Loaded == 1)
|
|
||||||
md2->animState.speed = t_value;
|
|
||||||
else
|
|
||||||
PRINT_ERR("Animation speed set is not possible, because no md2 3D model was loaded!");
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mesh::setVerticesReference(u32 t_verticesCount, Vector3 *t_verticesRef)
|
|
||||||
{
|
|
||||||
verticesCount = t_verticesCount;
|
|
||||||
vertices = t_verticesRef;
|
|
||||||
computeBoundingBox();
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 Mesh::getVertexCount()
|
|
||||||
{
|
|
||||||
if (isMd2Loaded)
|
|
||||||
return md2->trianglesCount * 3;
|
|
||||||
else if (isObjLoaded)
|
|
||||||
return obj->facesCount;
|
|
||||||
else if (isDffLoaded)
|
|
||||||
return dff->clump.geometryList.geometries[0].data.dataHeader.triangleCount * 3;
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PRINT_ERR("Can't get vertex count, because no 3D model was loaded!");
|
ObjLoader loader = ObjLoader();
|
||||||
return 0;
|
framesCount = t_framesCount;
|
||||||
}
|
frames = new MeshFrame[framesCount];
|
||||||
}
|
_areFramesAllocated = true;
|
||||||
|
char *part1 = String::createConcatenated(t_subfolder, t_objFile); // "folder/object"
|
||||||
void Mesh::setDefaultWrapSettings(texwrap_t &t_wrapSettings)
|
char *part2 = String::createConcatenated(part1, "_"); // "folder/object_"
|
||||||
{
|
for (u32 i = 0; i < framesCount; i++)
|
||||||
t_wrapSettings.horizontal = WRAP_REPEAT;
|
|
||||||
t_wrapSettings.vertical = WRAP_REPEAT;
|
|
||||||
t_wrapSettings.maxu = 0;
|
|
||||||
t_wrapSettings.maxv = 0;
|
|
||||||
t_wrapSettings.minu = 0;
|
|
||||||
t_wrapSettings.minv = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mesh::loadTextures(char *t_subfolder, char *t_extension)
|
|
||||||
{
|
|
||||||
BmpLoader bmpLoader = BmpLoader();
|
|
||||||
if (isMd2Loaded || isObjLoaded)
|
|
||||||
{
|
{
|
||||||
spec->textures = new Texture[1];
|
char *part3 = String::createU32ToString(i + 1); // 0 -> "1"
|
||||||
if (isMd2Loaded)
|
char *part4 = String::createWithLeadingZeros(part3); // "000001"
|
||||||
bmpLoader.load(spec->textures[0], t_subfolder, md2->filename, t_extension);
|
char *part5 = String::createConcatenated(part2, part4); // "folder/object_000001"
|
||||||
if (isObjLoaded)
|
char *finalPath = String::createConcatenated(part5, ".obj"); // "folder/object_000001.obj"
|
||||||
bmpLoader.load(spec->textures[0], t_subfolder, obj->filename, t_extension);
|
loader.load(&frames[i], finalPath, t_scale, t_invertT);
|
||||||
setDefaultWrapSettings(spec->textures[0].wrapSettings);
|
delete[] part3;
|
||||||
|
delete[] part4;
|
||||||
|
delete[] part5;
|
||||||
|
delete[] finalPath;
|
||||||
}
|
}
|
||||||
else if (isDffLoaded)
|
delete[] part2;
|
||||||
{
|
delete[] part1;
|
||||||
spec->textures = new Texture[dff->clump.geometryList.geometries[0].materialList.data.materialCount];
|
_isMother = true;
|
||||||
for (u8 i = 0; i < dff->clump.geometryList.geometries[0].materialList.data.materialCount; i++)
|
|
||||||
for (u8 j = 0; j < dff->clump.geometryList.geometries[0].materialList.materials[i].data.textureCount; j++)
|
|
||||||
{
|
|
||||||
bmpLoader.load(spec->textures[i], t_subfolder, dff->clump.geometryList.geometries[0].materialList.materials[i].textures[j].textureName.text, t_extension);
|
|
||||||
setDefaultWrapSettings(spec->textures[i].wrapSettings);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
PRINT_ERR("Can't load textures, because no 3D model was loaded!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO refactor
|
void Mesh::loadDff(char *t_subfolder, char *t_dffFile, const float &t_scale, const u8 &t_invertT)
|
||||||
u32 Mesh::getDrawData(u32 splitIndex, VECTOR *t_vertices, VECTOR *t_normals, VECTOR *t_coordinates, VECTOR *t_colors, Vector3 &t_cameraPos)
|
|
||||||
{
|
{
|
||||||
if (isMd2Loaded)
|
DffLoader loader = DffLoader();
|
||||||
return md2->getCurrentFrameData(t_vertices, t_normals, t_coordinates, t_colors, t_cameraPos, scale, shouldBeBackfaceCulled);
|
char *part1 = String::createConcatenated(t_subfolder, t_dffFile);
|
||||||
else if (isObjLoaded)
|
char *dffPath = String::createConcatenated(part1, ".dff");
|
||||||
return obj->getDrawData(t_vertices, t_normals, t_coordinates, t_colors, t_cameraPos, scale, shouldBeBackfaceCulled);
|
framesCount = 1;
|
||||||
else if (isDffLoaded)
|
frames = new MeshFrame[1];
|
||||||
return dff->getDrawData(splitIndex, t_vertices, t_normals, t_coordinates, t_colors, t_cameraPos, scale, shouldBeBackfaceCulled);
|
_areFramesAllocated = true;
|
||||||
PRINT_ERR("Can't get draw data, because no 3D model was loaded!");
|
loader.load(frames, dffPath, t_scale, t_invertT);
|
||||||
return 0;
|
delete[] part1;
|
||||||
|
delete[] dffPath;
|
||||||
|
_isMother = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set object position and specification */
|
void Mesh::loadMD2(char *t_subfolder, char *t_md2File, const float &t_scale, const u8 &t_invertT)
|
||||||
void Mesh::loadMD2(char *t_subfolder, char *t_md2File, Vector3 &t_initPos, float t_scale)
|
|
||||||
{
|
{
|
||||||
createSpecIfNotCreated();
|
|
||||||
md2 = new MD2Model(t_md2File);
|
|
||||||
MD2Loader loader = MD2Loader();
|
MD2Loader loader = MD2Loader();
|
||||||
position = t_initPos;
|
frames = loader.load(framesCount, t_subfolder, t_md2File, t_scale, t_invertT);
|
||||||
char *md2Path = String::createConcatenated(t_subfolder, t_md2File);
|
_isMother = true;
|
||||||
loader.load(md2, md2Path, t_scale);
|
|
||||||
delete[] md2Path;
|
|
||||||
setVerticesReference(md2->verticesPerFrameCount * md2->framesCount, md2->vertices);
|
|
||||||
setDefaultColor();
|
|
||||||
isMd2Loaded = true;
|
|
||||||
loadTextures(t_subfolder, ".bmp");
|
|
||||||
spec->allocateTextureBuffer(spec->textures[0].width, spec->textures[0].height); // wtf?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set's default object color + no transparency */
|
void Mesh::loadFrom(const Mesh &t_mesh)
|
||||||
void Mesh::setDefaultColor()
|
|
||||||
{
|
{
|
||||||
color.r = 0x80;
|
framesCount = t_mesh.framesCount;
|
||||||
color.g = 0x80;
|
frames = new MeshFrame[framesCount];
|
||||||
color.b = 0x80;
|
_areFramesAllocated = true;
|
||||||
color.a = 0x80;
|
for (u32 i = 0; i < framesCount; i++)
|
||||||
color.q = 1.0F;
|
frames[i].copyFrom(&t_mesh.getFrame(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Calculates minimum and maximum X, Y, Z of this 3D objects vertices + current position */
|
void Mesh::playAnimation(const u32 &t_startFrame, const u32 &t_endFrame)
|
||||||
void Mesh::getMinMax(Vector3 *t_min, Vector3 *t_max)
|
|
||||||
{
|
{
|
||||||
Vector3 calc = Vector3();
|
assertMsg(framesCount > 0, "Cant play animation, because no mesh data was loaded!");
|
||||||
u8 isInitialized = 0;
|
assertMsg(framesCount != 1, "Cant play animation, because this mesh have only one frame.");
|
||||||
for (u32 i = 0; i < 8; i++)
|
assertMsg(t_endFrame < framesCount, "End frame value is too high. Valid range: (0, getFramesCount()-1)");
|
||||||
{
|
animState.startFrame = t_startFrame;
|
||||||
getFarthestVertex(&calc, i);
|
animState.endFrame = t_endFrame;
|
||||||
if (isInitialized == 0)
|
if (animState.currentFrame == t_startFrame)
|
||||||
{
|
animState.nextFrame = t_endFrame;
|
||||||
isInitialized = 1;
|
else
|
||||||
t_min->set(calc);
|
animState.nextFrame = t_startFrame;
|
||||||
t_max->set(calc);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t_min->x > calc.x)
|
|
||||||
t_min->x = calc.x;
|
|
||||||
if (calc.x > t_max->x)
|
|
||||||
t_max->x = calc.x;
|
|
||||||
|
|
||||||
if (t_min->y > calc.y)
|
|
||||||
t_min->y = calc.y;
|
|
||||||
if (calc.y > t_max->y)
|
|
||||||
t_max->y = calc.y;
|
|
||||||
|
|
||||||
if (t_min->z > calc.z)
|
|
||||||
t_min->z = calc.z;
|
|
||||||
if (calc.z > t_max->z)
|
|
||||||
t_max->z = calc.z;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mesh::playAnimation(u32 t_startFrame, u32 t_endFrame)
|
void Mesh::playAnimation(const u32 &t_startFrame, const u32 &t_endFrame, const u32 &t_stayFrame)
|
||||||
{
|
{
|
||||||
if (isMd2Loaded == 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.");
|
||||||
|
assertMsg(t_endFrame < framesCount, "End frame value is too high. Valid range: (0, getFramesCount()-1)");
|
||||||
|
animState.startFrame = t_startFrame;
|
||||||
|
animState.endFrame = t_endFrame;
|
||||||
|
animState.isStayFrameSet = true;
|
||||||
|
animState.stayFrame = t_stayFrame;
|
||||||
|
animState.nextFrame = t_startFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mesh::animate()
|
||||||
|
{
|
||||||
|
animState.interpolation += animState.speed;
|
||||||
|
if (animState.interpolation >= 1.0F)
|
||||||
{
|
{
|
||||||
md2->animState.startFrame = t_startFrame;
|
animState.interpolation = 0.0F;
|
||||||
md2->animState.endFrame = t_endFrame;
|
animState.currentFrame = animState.nextFrame;
|
||||||
|
if (++animState.nextFrame > animState.endFrame)
|
||||||
|
{
|
||||||
|
if (animState.isStayFrameSet)
|
||||||
|
{
|
||||||
|
animState.isStayFrameSet = false;
|
||||||
|
animState.nextFrame = animState.stayFrame;
|
||||||
|
animState.startFrame = animState.stayFrame;
|
||||||
|
animState.endFrame = animState.stayFrame;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
PRINT_ERR("Animation is only supported in MD2 format!");
|
animState.nextFrame = animState.startFrame;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns next farthest vertex of 3D object
|
u32 Mesh::getDrawData(u32 t_materialIndex, VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, Vector3 &t_cameraPos)
|
||||||
* @param offset Max 8 (because, box have 8 corners)
|
|
||||||
*/
|
|
||||||
void Mesh::getFarthestVertex(Vector3 *o_result, int t_offset)
|
|
||||||
{
|
{
|
||||||
o_result->x = boxVertices[t_offset].x + position.x;
|
VECTOR ONE_VEC = {1.0F, 1.0F, 1.0F, 1.0F};
|
||||||
o_result->y = boxVertices[t_offset].y + position.y;
|
asm volatile(
|
||||||
o_result->z = boxVertices[t_offset].z + position.z;
|
// 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;
|
||||||
|
#define CURR_FRAME frames[animState.currentFrame]
|
||||||
|
#define NEXT_FRAME frames[animState.nextFrame]
|
||||||
|
|
||||||
|
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 *nextVerts = NEXT_FRAME.getVertices(); // cache
|
||||||
|
Point *sts = CURR_FRAME.getSTs(); // cache
|
||||||
|
Vector3 *normals = CURR_FRAME.getNormals(); // cache
|
||||||
|
|
||||||
|
for (u32 faceI = 0; faceI < material->getFacesCount(); faceI += 3)
|
||||||
|
{
|
||||||
|
if (animState.currentFrame != animState.nextFrame)
|
||||||
|
{
|
||||||
|
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 ||
|
||||||
|
!Vector3::shouldBeBackfaceCulled(&t_cameraPos, &calc3Vectors[2], &calc3Vectors[1], &calc3Vectors[0]))
|
||||||
|
{
|
||||||
|
|
||||||
|
asm volatile(
|
||||||
|
// VU0 macro program:
|
||||||
|
// Copy data and set vert/normal "w" and st "z"+"w" to 1.0F
|
||||||
|
|
||||||
|
// Vertex 0
|
||||||
|
"lqc2 $vf1, 0x0(%3) \n\t" // load vert
|
||||||
|
"lqc2 $vf2, 0x0(%4) \n\t" // load normal
|
||||||
|
"lqc2 $vf3, 0x0(%5) \n\t" // load st
|
||||||
|
"vadd.w $vf1, $vf20, $vf21 \n\t" // set vert.w to 1.0F
|
||||||
|
"vadd.w $vf2, $vf20, $vf21 \n\t" // set normal.W to 1.0F
|
||||||
|
"vadd.zw $vf3, $vf20, $vf21 \n\t" // set st.zw to 1.0F
|
||||||
|
"sqc2 $vf1, 0x0(%0) \n\t" // store vert
|
||||||
|
"sqc2 $vf2, 0x0(%1) \n\t" // store normal
|
||||||
|
"sqc2 $vf3, 0x0(%2) \n\t" // store st
|
||||||
|
|
||||||
|
// Vertex 1
|
||||||
|
"lqc2 $vf1, 0x0(%9) \n\t" // load vert
|
||||||
|
"lqc2 $vf2, 0x0(%10) \n\t" // load normal
|
||||||
|
"lqc2 $vf3, 0x0(%11) \n\t" // load st
|
||||||
|
"vadd.w $vf1, $vf20, $vf21 \n\t" // set vert.w to 1.0F
|
||||||
|
"vadd.w $vf2, $vf20, $vf21 \n\t" // set normal.W to 1.0F
|
||||||
|
"vadd.zw $vf3, $vf20, $vf21 \n\t" // set st.zw to 1.0F
|
||||||
|
"sqc2 $vf1, 0x0(%6) \n\t" // store vert
|
||||||
|
"sqc2 $vf2, 0x0(%7) \n\t" // store normal
|
||||||
|
"sqc2 $vf3, 0x0(%8) \n\t" // store st
|
||||||
|
|
||||||
|
// Vertex 2
|
||||||
|
"lqc2 $vf1, 0x0(%15) \n\t" // load vert
|
||||||
|
"lqc2 $vf2, 0x0(%16) \n\t" // load normal
|
||||||
|
"lqc2 $vf3, 0x0(%17) \n\t" // load st
|
||||||
|
"vadd.w $vf1, $vf20, $vf21 \n\t" // set vert.w to 1.0F
|
||||||
|
"vadd.w $vf2, $vf20, $vf21 \n\t" // set normal.W to 1.0F
|
||||||
|
"vadd.zw $vf3, $vf20, $vf21 \n\t" // set st.zw to 1.0F
|
||||||
|
"sqc2 $vf1, 0x0(%12) \n\t" // store vert
|
||||||
|
"sqc2 $vf2, 0x0(%13) \n\t" // store normal
|
||||||
|
"sqc2 $vf3, 0x0(%14) \n\t" // store st
|
||||||
|
|
||||||
|
:
|
||||||
|
: "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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Check if box is visible in view frustum */
|
|
||||||
u8 Mesh::isInFrustum(Plane *t_frustumPlanes)
|
u8 Mesh::isInFrustum(Plane *t_frustumPlanes)
|
||||||
{
|
{
|
||||||
Vector3 boxCalcTemp;
|
Vector3 boxCalcTemp;
|
||||||
int boxResult = 1, boxIn = 0, boxOut = 0;
|
u8 boxResult = 1, boxIn = 0, boxOut = 0;
|
||||||
|
const Vector3 *currentBoundingBox = getCurrentBoundingBoxVertices();
|
||||||
for (int i = 0; i < 6; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
boxOut = 0;
|
boxOut = 0;
|
||||||
@@ -288,7 +350,10 @@ u8 Mesh::isInFrustum(Plane *t_frustumPlanes)
|
|||||||
// 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 (int y = 0; y < 8 && (boxIn == 0 || boxOut == 0); y++)
|
||||||
{
|
{
|
||||||
getFarthestVertex(&boxCalcTemp, y);
|
boxCalcTemp.set(
|
||||||
|
currentBoundingBox[y].x + position.x,
|
||||||
|
currentBoundingBox[y].y + position.y,
|
||||||
|
currentBoundingBox[y].z + position.z);
|
||||||
if (t_frustumPlanes[i].distanceTo(boxCalcTemp) < 0)
|
if (t_frustumPlanes[i].distanceTo(boxCalcTemp) < 0)
|
||||||
boxOut++;
|
boxOut++;
|
||||||
else
|
else
|
||||||
@@ -303,37 +368,19 @@ u8 Mesh::isInFrustum(Plane *t_frustumPlanes)
|
|||||||
return boxResult;
|
return boxResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Compute 8 farthest corners for intersection check */
|
/** Sets texture level of details settings and CLUT settings */
|
||||||
void Mesh::computeBoundingBox()
|
void Mesh::setDefaultLODAndClut()
|
||||||
{
|
{
|
||||||
float lowX, lowY, lowZ, hiX, hiY, hiZ;
|
lod.calculation = LOD_USE_K;
|
||||||
lowX = hiX = vertices[0].x;
|
lod.max_level = 0;
|
||||||
lowY = hiY = vertices[0].y;
|
lod.mag_filter = LOD_MAG_NEAREST;
|
||||||
lowZ = hiZ = vertices[0].z;
|
lod.min_filter = LOD_MIN_NEAREST;
|
||||||
for (u32 i = 0; i < verticesCount; i++)
|
lod.l = 0;
|
||||||
{
|
lod.k = 0.0F;
|
||||||
if (lowX > vertices[i].x)
|
|
||||||
lowX = vertices[i].x;
|
|
||||||
if (hiX < vertices[i].x)
|
|
||||||
hiX = vertices[i].x;
|
|
||||||
|
|
||||||
if (lowY > vertices[i].y)
|
clut.storage_mode = CLUT_STORAGE_MODE1;
|
||||||
lowY = vertices[i].y;
|
clut.start = 0;
|
||||||
if (hiY < vertices[i].y)
|
clut.psm = 0;
|
||||||
hiY = vertices[i].y;
|
clut.load_method = CLUT_NO_LOAD;
|
||||||
|
clut.address = 0;
|
||||||
if (lowZ > vertices[i].z)
|
|
||||||
lowZ = vertices[i].z;
|
|
||||||
if (hiZ < vertices[i].z)
|
|
||||||
hiZ = vertices[i].z;
|
|
||||||
}
|
|
||||||
boxVertices[0].set(lowX, lowY, lowZ);
|
|
||||||
boxVertices[1].set(lowX, lowY, hiZ);
|
|
||||||
boxVertices[2].set(lowX, hiY, lowZ);
|
|
||||||
boxVertices[3].set(lowX, hiY, hiZ);
|
|
||||||
|
|
||||||
boxVertices[4].set(hiX, lowY, lowZ);
|
|
||||||
boxVertices[5].set(hiX, lowY, hiZ);
|
|
||||||
boxVertices[6].set(hiX, hiY, lowZ);
|
|
||||||
boxVertices[7].set(hiX, hiY, hiZ);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include "../include/models/mesh_frame.hpp"
|
||||||
|
#include "../include/utils/debug.hpp"
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Constructors/Destructors
|
||||||
|
// ----
|
||||||
|
|
||||||
|
MeshFrame::MeshFrame()
|
||||||
|
{
|
||||||
|
id = rand() % 1000000;
|
||||||
|
vertexCount = 0;
|
||||||
|
stsCount = 0;
|
||||||
|
normalsCount = 0;
|
||||||
|
materialsCount = 0;
|
||||||
|
_areSTsAllocated = false;
|
||||||
|
_areVerticesAllocated = false;
|
||||||
|
_areNormalsAllocated = false;
|
||||||
|
_areMaterialsAllocated = false;
|
||||||
|
_isMother = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
MeshFrame::~MeshFrame()
|
||||||
|
{
|
||||||
|
if (_isMother)
|
||||||
|
{
|
||||||
|
if (_areSTsAllocated)
|
||||||
|
delete[] sts;
|
||||||
|
if (_areVerticesAllocated)
|
||||||
|
delete[] vertices;
|
||||||
|
if (_areNormalsAllocated)
|
||||||
|
delete[] normals;
|
||||||
|
delete boundingBoxObj;
|
||||||
|
}
|
||||||
|
if (_areMaterialsAllocated)
|
||||||
|
delete[] materials;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Methods
|
||||||
|
// ----
|
||||||
|
|
||||||
|
void MeshFrame::allocateSTs(const u32 &t_val)
|
||||||
|
{
|
||||||
|
assertMsg(!_areSTsAllocated, "Can't allocate STs, because were already set!");
|
||||||
|
stsCount = t_val;
|
||||||
|
sts = new Point[t_val];
|
||||||
|
_areSTsAllocated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshFrame::allocateVertices(const u32 &t_val)
|
||||||
|
{
|
||||||
|
assertMsg(!_areVerticesAllocated, "Can't allocate vertices, because were already set!");
|
||||||
|
vertexCount = t_val;
|
||||||
|
vertices = new Vector3[t_val];
|
||||||
|
_areVerticesAllocated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshFrame::allocateNormals(const u32 &t_val)
|
||||||
|
{
|
||||||
|
assertMsg(!_areNormalsAllocated, "Can't allocate normals, because were already set!");
|
||||||
|
normalsCount = t_val;
|
||||||
|
normals = new Vector3[t_val];
|
||||||
|
_areNormalsAllocated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshFrame::allocateMaterials(const u32 &t_val)
|
||||||
|
{
|
||||||
|
assertMsg(!_areMaterialsAllocated, "Can't allocate materials, because were already set!");
|
||||||
|
materialsCount = t_val;
|
||||||
|
materials = new MeshMaterial[t_val];
|
||||||
|
_areMaterialsAllocated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshFrame::calculateBoundingBoxes()
|
||||||
|
{
|
||||||
|
assertMsg(_areVerticesAllocated, "Can't calculate bounding box, because vertices were not allocated!");
|
||||||
|
for (u32 i = 0; i < materialsCount; i++)
|
||||||
|
materials->calculateBoundingBox(vertices, vertexCount);
|
||||||
|
|
||||||
|
float lowX, lowY, lowZ, hiX, hiY, hiZ;
|
||||||
|
lowX = hiX = vertices[0].x;
|
||||||
|
lowY = hiY = vertices[0].y;
|
||||||
|
lowZ = hiZ = vertices[0].z;
|
||||||
|
for (u32 i = 0; i < vertexCount; i++)
|
||||||
|
{
|
||||||
|
if (lowX > vertices[i].x)
|
||||||
|
lowX = vertices[i].x;
|
||||||
|
if (hiX < vertices[i].x)
|
||||||
|
hiX = vertices[i].x;
|
||||||
|
|
||||||
|
if (lowY > vertices[i].y)
|
||||||
|
lowY = vertices[i].y;
|
||||||
|
if (hiY < vertices[i].y)
|
||||||
|
hiY = vertices[i].y;
|
||||||
|
|
||||||
|
if (lowZ > vertices[i].z)
|
||||||
|
lowZ = vertices[i].z;
|
||||||
|
if (hiZ < vertices[i].z)
|
||||||
|
hiZ = vertices[i].z;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 boundingBox[8];
|
||||||
|
boundingBox[0].set(lowX, lowY, lowZ);
|
||||||
|
boundingBox[1].set(lowX, lowY, hiZ);
|
||||||
|
boundingBox[2].set(lowX, hiY, lowZ);
|
||||||
|
boundingBox[3].set(lowX, hiY, hiZ);
|
||||||
|
|
||||||
|
boundingBox[4].set(hiX, lowY, lowZ);
|
||||||
|
boundingBox[5].set(hiX, lowY, hiZ);
|
||||||
|
boundingBox[6].set(hiX, hiY, lowZ);
|
||||||
|
boundingBox[7].set(hiX, hiY, hiZ);
|
||||||
|
_isBoundingBoxCalculated = true;
|
||||||
|
|
||||||
|
// BoundingBox is declared on the heap to prevent any ill-formed default
|
||||||
|
// constructor instantiated BoundingBox objects.
|
||||||
|
boundingBoxObj = new BoundingBox(boundingBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,170 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../include/models/mesh_material.hpp"
|
||||||
|
#include "../include/models/bounding_box.hpp"
|
||||||
|
#include "../include/utils/debug.hpp"
|
||||||
|
#include "../include/utils/string.hpp"
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Constructors/Destructors
|
||||||
|
// ----
|
||||||
|
|
||||||
|
MeshMaterial::MeshMaterial()
|
||||||
|
{
|
||||||
|
id = rand() % 1000000;
|
||||||
|
facesCount = 0;
|
||||||
|
_isNameSet = false;
|
||||||
|
_areFacesAllocated = false;
|
||||||
|
_isBoundingBoxCalculated = false;
|
||||||
|
_areSTsPresent = false;
|
||||||
|
_areNormalsPresent = false;
|
||||||
|
_isMother = true;
|
||||||
|
setDefaultColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
MeshMaterial::~MeshMaterial()
|
||||||
|
{
|
||||||
|
if (_isMother)
|
||||||
|
{
|
||||||
|
if (_areFacesAllocated)
|
||||||
|
{
|
||||||
|
delete[] vertexFaces;
|
||||||
|
delete[] stFaces;
|
||||||
|
delete[] normalFaces;
|
||||||
|
}
|
||||||
|
if (_isNameSet)
|
||||||
|
delete[] name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Methods
|
||||||
|
// ----
|
||||||
|
|
||||||
|
void MeshMaterial::allocateFaces(const u32 &t_val)
|
||||||
|
{
|
||||||
|
assertMsg(!_areFacesAllocated, "Can't allocate faces, because were already set!");
|
||||||
|
facesCount = t_val;
|
||||||
|
stFaces = new u32[t_val];
|
||||||
|
normalFaces = new u32[t_val];
|
||||||
|
vertexFaces = new u32[t_val];
|
||||||
|
_areFacesAllocated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshMaterial::setName(char *t_val)
|
||||||
|
{
|
||||||
|
assertMsg(!_isNameSet, "Can't set name, because was already set!");
|
||||||
|
name = String::createCopy(t_val);
|
||||||
|
_isNameSet = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 MeshMaterial::isInFrustum(Plane *t_frustumPlanes, const Vector3 &position)
|
||||||
|
{
|
||||||
|
Vector3 boxCalcTemp;
|
||||||
|
u8 boxResult = 1, boxIn = 0, boxOut = 0;
|
||||||
|
|
||||||
|
for (u8 i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
boxOut = 0;
|
||||||
|
boxIn = 0;
|
||||||
|
// for each corner of the box do ...
|
||||||
|
// get out of the cycle as soon as a box as corners
|
||||||
|
// both inside and out of the frustum
|
||||||
|
for (u8 y = 0; y < 8 && (boxIn == 0 || boxOut == 0); y++)
|
||||||
|
{
|
||||||
|
boxCalcTemp.set(
|
||||||
|
boundingBoxObj->getVertex(y).x + position.x,
|
||||||
|
boundingBoxObj->getVertex(y).y + position.y,
|
||||||
|
boundingBoxObj->getVertex(y).z + position.z);
|
||||||
|
if (t_frustumPlanes[i].distanceTo(boxCalcTemp) < 0)
|
||||||
|
boxOut++;
|
||||||
|
else
|
||||||
|
boxIn++;
|
||||||
|
}
|
||||||
|
//if all corners are out
|
||||||
|
if (boxIn == 0)
|
||||||
|
return 0;
|
||||||
|
else if (boxOut)
|
||||||
|
boxResult = 1;
|
||||||
|
}
|
||||||
|
return boxResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshMaterial::calculateBoundingBox(Vector3 *t_vertices, u32 t_vertCount)
|
||||||
|
{
|
||||||
|
float lowX, lowY, lowZ, hiX, hiY, hiZ;
|
||||||
|
lowX = hiX = t_vertices[vertexFaces[0]].x;
|
||||||
|
lowY = hiY = t_vertices[vertexFaces[0]].y;
|
||||||
|
lowZ = hiZ = t_vertices[vertexFaces[0]].z;
|
||||||
|
for (u32 i = 0; i < facesCount; i++)
|
||||||
|
{
|
||||||
|
if (lowX > t_vertices[vertexFaces[i]].x)
|
||||||
|
lowX = t_vertices[vertexFaces[i]].x;
|
||||||
|
if (hiX < t_vertices[vertexFaces[i]].x)
|
||||||
|
hiX = t_vertices[vertexFaces[i]].x;
|
||||||
|
|
||||||
|
if (lowY > t_vertices[vertexFaces[i]].y)
|
||||||
|
lowY = t_vertices[vertexFaces[i]].y;
|
||||||
|
if (hiY < t_vertices[vertexFaces[i]].y)
|
||||||
|
hiY = t_vertices[vertexFaces[i]].y;
|
||||||
|
|
||||||
|
if (lowZ > t_vertices[vertexFaces[i]].z)
|
||||||
|
lowZ = t_vertices[vertexFaces[i]].z;
|
||||||
|
if (hiZ < t_vertices[vertexFaces[i]].z)
|
||||||
|
hiZ = t_vertices[vertexFaces[i]].z;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 boundingBox[8];
|
||||||
|
boundingBox[0].set(lowX, lowY, lowZ);
|
||||||
|
boundingBox[1].set(lowX, lowY, hiZ);
|
||||||
|
boundingBox[2].set(lowX, hiY, lowZ);
|
||||||
|
boundingBox[3].set(lowX, hiY, hiZ);
|
||||||
|
|
||||||
|
boundingBox[4].set(hiX, lowY, lowZ);
|
||||||
|
boundingBox[5].set(hiX, lowY, hiZ);
|
||||||
|
boundingBox[6].set(hiX, hiY, lowZ);
|
||||||
|
boundingBox[7].set(hiX, hiY, hiZ);
|
||||||
|
_isBoundingBoxCalculated = true;
|
||||||
|
|
||||||
|
// BoundingBox is declared on the heap to prevent any ill-formed default
|
||||||
|
// constructor instantiated BoundingBox objects.
|
||||||
|
boundingBoxObj = new BoundingBox(boundingBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
@@ -1,82 +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/models/mesh_spec.hpp"
|
|
||||||
|
|
||||||
#include "../include/utils/debug.hpp"
|
|
||||||
#include "../include/utils/math.hpp"
|
|
||||||
#include <graph_vram.h>
|
|
||||||
#include <gs_psm.h>
|
|
||||||
|
|
||||||
// ----
|
|
||||||
// Constructors/Destructors
|
|
||||||
// ----
|
|
||||||
|
|
||||||
MeshSpec::MeshSpec()
|
|
||||||
{
|
|
||||||
PRINT_LOG("Creating object 3D spec");
|
|
||||||
this->setupLodAndClut();
|
|
||||||
PRINT_LOG("Object 3D spec created!");
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Release memory if object was initialized */
|
|
||||||
MeshSpec::~MeshSpec()
|
|
||||||
{
|
|
||||||
if (this->isTextureVRAMAllocated == true)
|
|
||||||
graph_vram_free(this->textureBuffer.address);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----
|
|
||||||
// Methods
|
|
||||||
// ----
|
|
||||||
|
|
||||||
/** Configure and allocate vRAM for texture buffer */
|
|
||||||
void MeshSpec::allocateTextureBuffer(u16 t_width, u16 t_height)
|
|
||||||
{
|
|
||||||
this->textureBuffer.width = t_width;
|
|
||||||
this->textureBuffer.psm = GS_PSM_24;
|
|
||||||
this->textureBuffer.address = graph_vram_allocate(t_width, t_height, GS_PSM_24, GRAPH_ALIGN_BLOCK);
|
|
||||||
if (this->textureBuffer.address <= 1)
|
|
||||||
PRINT_ERR("Texture buffer allocation error. No memory!");
|
|
||||||
this->textureBuffer.info.width = draw_log2(t_width);
|
|
||||||
this->textureBuffer.info.height = draw_log2(t_height);
|
|
||||||
this->textureBuffer.info.components = TEXTURE_COMPONENTS_RGB;
|
|
||||||
this->textureBuffer.info.function = TEXTURE_FUNCTION_MODULATE;
|
|
||||||
this->isTextureVRAMAllocated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Configure and allocate vRAM for texture buffer */
|
|
||||||
void MeshSpec::deallocateTextureBuffer()
|
|
||||||
{
|
|
||||||
if (this->isTextureVRAMAllocated)
|
|
||||||
{
|
|
||||||
graph_vram_free(textureBuffer.address);
|
|
||||||
this->isTextureVRAMAllocated = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Sets texture level of details settings and CLUT settings */
|
|
||||||
void MeshSpec::setupLodAndClut()
|
|
||||||
{
|
|
||||||
PRINT_LOG("Setting LOD, CLUT");
|
|
||||||
this->lod.calculation = LOD_USE_K;
|
|
||||||
this->lod.max_level = 0;
|
|
||||||
this->lod.mag_filter = LOD_MAG_NEAREST;
|
|
||||||
this->lod.min_filter = LOD_MIN_NEAREST;
|
|
||||||
this->lod.l = 0;
|
|
||||||
this->lod.k = 0.0F;
|
|
||||||
|
|
||||||
this->clut.storage_mode = CLUT_STORAGE_MODE1;
|
|
||||||
this->clut.start = 0;
|
|
||||||
this->clut.psm = 0;
|
|
||||||
this->clut.load_method = CLUT_NO_LOAD;
|
|
||||||
this->clut.address = 0;
|
|
||||||
PRINT_LOG("LOD, CLUT set!");
|
|
||||||
}
|
|
||||||
@@ -1,99 +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/models/obj_model.hpp"
|
|
||||||
|
|
||||||
#include "../include/utils/debug.hpp"
|
|
||||||
#include "../include/utils/string.hpp"
|
|
||||||
|
|
||||||
// ----
|
|
||||||
// Constructors/Destructors
|
|
||||||
// ----
|
|
||||||
|
|
||||||
ObjModel::ObjModel(char *t_objFile)
|
|
||||||
{
|
|
||||||
filename = String::createWithoutExtension(t_objFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjModel::~ObjModel()
|
|
||||||
{
|
|
||||||
if (isMemoryAllocated == true)
|
|
||||||
{
|
|
||||||
delete[] vertices;
|
|
||||||
delete[] coordinates;
|
|
||||||
delete[] normals;
|
|
||||||
|
|
||||||
delete[] verticeFaces;
|
|
||||||
delete[] coordinateFaces;
|
|
||||||
delete[] normalFaces;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----
|
|
||||||
// Methods
|
|
||||||
// ----
|
|
||||||
|
|
||||||
u32 ObjModel::getDrawData(VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, VECTOR *o_colors, Vector3 &t_cameraPos, float t_scale, u8 t_shouldBeBackfaceCulled)
|
|
||||||
{
|
|
||||||
u32 addedFaces = 0;
|
|
||||||
for (u32 i = 0; i < facesCount; i += 3)
|
|
||||||
if (!t_shouldBeBackfaceCulled || Vector3::shouldBeBackfaceCulled(
|
|
||||||
&t_cameraPos,
|
|
||||||
&vertices[verticeFaces[i]],
|
|
||||||
&vertices[verticeFaces[i + 1]],
|
|
||||||
&vertices[verticeFaces[i + 2]]) == 0)
|
|
||||||
{
|
|
||||||
fillNextFace(o_vertices, o_normals, o_coordinates, o_colors, i, addedFaces++);
|
|
||||||
fillNextFace(o_vertices, o_normals, o_coordinates, o_colors, i + 1, addedFaces++);
|
|
||||||
fillNextFace(o_vertices, o_normals, o_coordinates, o_colors, i + 2, addedFaces++);
|
|
||||||
}
|
|
||||||
|
|
||||||
return addedFaces;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Allocate memory for vertices,coords etc.
|
|
||||||
* Called by ObjLoader
|
|
||||||
*/
|
|
||||||
void ObjModel::allocateMemory()
|
|
||||||
{
|
|
||||||
PRINT_LOG("Allocating 3D object specification memory");
|
|
||||||
vertices = new Vector3[verticesCount];
|
|
||||||
coordinates = new Vector3[coordinatesCount];
|
|
||||||
normals = new Vector3[normalsCount];
|
|
||||||
|
|
||||||
verticeFaces = new u32[facesCount];
|
|
||||||
coordinateFaces = new u32[facesCount];
|
|
||||||
normalFaces = new u32[facesCount];
|
|
||||||
isMemoryAllocated = true;
|
|
||||||
PRINT_LOG("3D object specification memory allocated!");
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjModel::fillNextFace(VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, VECTOR *o_colors, u32 t_getI, u32 t_setI)
|
|
||||||
{
|
|
||||||
o_vertices[t_setI][0] = vertices[verticeFaces[t_getI]].x;
|
|
||||||
o_vertices[t_setI][1] = vertices[verticeFaces[t_getI]].y;
|
|
||||||
o_vertices[t_setI][2] = vertices[verticeFaces[t_getI]].z;
|
|
||||||
o_vertices[t_setI][3] = 1.0F;
|
|
||||||
|
|
||||||
o_normals[t_setI][0] = normals[normalFaces[t_getI]].x;
|
|
||||||
o_normals[t_setI][1] = normals[normalFaces[t_getI]].y;
|
|
||||||
o_normals[t_setI][2] = normals[normalFaces[t_getI]].z;
|
|
||||||
o_normals[t_setI][3] = 1.0F;
|
|
||||||
|
|
||||||
o_coordinates[t_setI][0] = coordinates[coordinateFaces[t_getI]].x;
|
|
||||||
o_coordinates[t_setI][1] = coordinates[coordinateFaces[t_getI]].y;
|
|
||||||
o_coordinates[t_setI][2] = 1.0F;
|
|
||||||
o_coordinates[t_setI][3] = 1.0F;
|
|
||||||
|
|
||||||
o_colors[t_setI][0] = 1.0F;
|
|
||||||
o_colors[t_setI][1] = 1.0F;
|
|
||||||
o_colors[t_setI][2] = 1.0F;
|
|
||||||
o_colors[t_setI][3] = 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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../include/models/texture.hpp"
|
||||||
|
#include "../include/utils/string.hpp"
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <draw_sampling.h>
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Constructors/Destructors
|
||||||
|
// ----
|
||||||
|
|
||||||
|
Texture::Texture()
|
||||||
|
{
|
||||||
|
id = rand() % 1000000;
|
||||||
|
_isSizeSet = false;
|
||||||
|
_isNameSet = false;
|
||||||
|
setDefaultWrapSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture::~Texture()
|
||||||
|
{
|
||||||
|
if (getTextureLinksCount() > 0)
|
||||||
|
texLinks.clear();
|
||||||
|
if (_isNameSet)
|
||||||
|
delete[] name;
|
||||||
|
if (_isSizeSet)
|
||||||
|
delete[] data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Methods
|
||||||
|
// ----
|
||||||
|
|
||||||
|
void Texture::setSize(const u8 &t_width, const u8 &t_height, const TextureType &t_type)
|
||||||
|
{
|
||||||
|
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.");
|
||||||
|
width = t_width;
|
||||||
|
height = t_height;
|
||||||
|
_type = t_type;
|
||||||
|
data = new unsigned char[getDataSize()];
|
||||||
|
_isSizeSet = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::setName(char *t_val)
|
||||||
|
{
|
||||||
|
assertMsg(!_isNameSet, "Can't set name, because was already set!");
|
||||||
|
name = String::createCopy(t_val);
|
||||||
|
_isNameSet = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::setDefaultWrapSettings()
|
||||||
|
{
|
||||||
|
wrapSettings.horizontal = WRAP_REPEAT;
|
||||||
|
wrapSettings.vertical = WRAP_REPEAT;
|
||||||
|
wrapSettings.maxu = 0;
|
||||||
|
wrapSettings.maxv = 0;
|
||||||
|
wrapSettings.minu = 0;
|
||||||
|
wrapSettings.minv = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::setWrapSettings(const WrapSettings t_horizontal, const WrapSettings t_vertical)
|
||||||
|
{
|
||||||
|
wrapSettings.horizontal = t_horizontal;
|
||||||
|
wrapSettings.vertical = t_vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::addLink(const u32 &t_id)
|
||||||
|
{
|
||||||
|
TextureLink link;
|
||||||
|
link.id = t_id;
|
||||||
|
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]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
@@ -53,35 +55,43 @@ GifSender::~GifSender()
|
|||||||
/** Send texture via GIF */
|
/** Send texture via GIF */
|
||||||
void GifSender::sendTexture(Texture &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.data, texture.width, texture.height, 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.wrapSettings);
|
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,
|
||||||
0x10, 0x10, 0x10);
|
t_rgb->r, t_rgb->g, t_rgb->b));
|
||||||
q = draw_enable_tests(q, 0, t_zBuffer);
|
packet2_update(packet2, draw_enable_tests(packet2->next, 0, t_zBuffer));
|
||||||
q = draw_finish(q);
|
packet2_update(packet2, draw_finish(packet2->next));
|
||||||
DMATAG_END(packet->data, q - packet->data - 1, 0, 0, 0);
|
packet2_chain_close_tag(packet2);
|
||||||
dma_channel_send_chain(DMA_CHANNEL_GIF, packet->data, q - packet->data, 0, 0);
|
dma_channel_wait(DMA_CHANNEL_GIF, 0);
|
||||||
dma_wait_fast();
|
dma_channel_send_packet2(packet2, DMA_CHANNEL_GIF, true);
|
||||||
packet_free(packet);
|
dma_channel_wait(DMA_CHANNEL_GIF, 0);
|
||||||
|
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,86 +109,52 @@ 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));
|
||||||
|
packet2_update(currentPacket, draw_clear(currentPacket->next, 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,
|
||||||
0x10, 0x10, 0x10);
|
t_rgb->r, t_rgb->g, t_rgb->b));
|
||||||
q = draw_enable_tests(q, 0, t_zBuffer);
|
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::addObjects(RenderData *t_renderData, Mesh **t_objects3D, u32 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount)
|
|
||||||
{
|
{
|
||||||
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));
|
||||||
}
|
xyz = new xyz_t[vertexCount];
|
||||||
qword_t *tempDMATag;
|
rgbaq = new color_t[vertexCount];
|
||||||
tempDMATag = q;
|
st = new texel_t[vertexCount];
|
||||||
q++;
|
calc3DObject(*t_renderData->projection, t_mesh, vertexCount, vertices, normals, coordinates, t_renderData, t_bulbs, t_bulbsCount, t_color);
|
||||||
|
|
||||||
q = draw_texture_sampling(q, 0, &t_objects3D[0]->spec->lod);
|
|
||||||
q = draw_texturebuffer(q, 0, &t_objects3D[0]->spec->textureBuffer, &t_objects3D[0]->spec->clut);
|
|
||||||
dw = (u64 *)draw_prim_start(q, 0, t_renderData->prim, &t_objects3D[0]->color);
|
|
||||||
|
|
||||||
for (u32 i = 0; i < t_amount; i++)
|
|
||||||
if (t_objects3D[i]->shouldBeFrustumCulled == 0 || t_objects3D[i]->isInFrustum(t_renderData->frustumPlanes))
|
|
||||||
{
|
|
||||||
u32 vertexCount = calc3DObject(*t_renderData->perspective, *t_objects3D[i], t_renderData, t_bulbs, t_bulbsCount);
|
|
||||||
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));
|
||||||
|
packet2_chain_close_tag(currentPacket);
|
||||||
if ((u32)dw % 16) // if we are in the middle of qw, switch packet
|
|
||||||
*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
|
|
||||||
* @returns Vertex count
|
|
||||||
*/
|
*/
|
||||||
u32 GifSender::calc3DObject(Matrix t_perspective, Mesh &t_mesh, 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)
|
||||||
{
|
{
|
||||||
u32 vertexCount = t_mesh.getVertexCount();
|
|
||||||
|
|
||||||
VECTOR *vertices = new VECTOR[vertexCount];
|
|
||||||
VECTOR *normals = new VECTOR[vertexCount];
|
|
||||||
VECTOR *coordinates = new VECTOR[vertexCount];
|
|
||||||
VECTOR *colors = new VECTOR[vertexCount];
|
VECTOR *colors = new VECTOR[vertexCount];
|
||||||
vertexCount = t_mesh.getDrawData(0, vertices, normals, coordinates, colors, *t_renderData->cameraPosition);
|
|
||||||
|
|
||||||
xyz = new xyz_t[vertexCount];
|
|
||||||
rgbaq = new color_t[vertexCount];
|
|
||||||
st = new texel_t[vertexCount];
|
|
||||||
|
|
||||||
VECTOR position, rotation;
|
VECTOR position, rotation;
|
||||||
|
|
||||||
vec3ToNative(position, t_mesh.position, 1.0F);
|
vec3ToNative(position, t_mesh.position, 1.0F);
|
||||||
@@ -195,12 +167,12 @@ u32 GifSender::calc3DObject(Matrix t_perspective, Mesh &t_mesh, RenderData *t_re
|
|||||||
if (SHOULD_BE_LIGHTED)
|
if (SHOULD_BE_LIGHTED)
|
||||||
create_local_light(localLight, rotation);
|
create_local_light(localLight, rotation);
|
||||||
|
|
||||||
// I cant put perspective from renderData here. PS2SDK 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];
|
||||||
@@ -208,31 +180,40 @@ u32 GifSender::calc3DObject(Matrix t_perspective, Mesh &t_mesh, RenderData *t_re
|
|||||||
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);
|
||||||
|
|
||||||
calculate_colours(colors, vertexCount, colors, lights);
|
for (u32 i = 0; i < vertexCount; i++)
|
||||||
|
{
|
||||||
|
// Apply the light value to the colour.
|
||||||
|
colors[i][0] = (t_color->r * lights[i][0]);
|
||||||
|
colors[i][1] = (t_color->g * lights[i][1]);
|
||||||
|
colors[i][2] = (t_color->b * lights[i][2]);
|
||||||
|
vector_clamp(colors[i], colors[i], 0.00F, 1.99F);
|
||||||
|
}
|
||||||
|
|
||||||
delete[] lightDirections;
|
delete[] lightDirections;
|
||||||
delete[] lightColors;
|
delete[] lightColors;
|
||||||
delete[] lightTypes;
|
delete[] lightTypes;
|
||||||
delete[] lights;
|
delete[] lights;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
for (u32 i = 0; i < vertexCount; i++)
|
||||||
|
{
|
||||||
|
colors[i][0] = t_color->r / 128.0F;
|
||||||
|
colors[i][1] = t_color->g / 128.0F;
|
||||||
|
colors[i][2] = t_color->b / 128.0F;
|
||||||
|
}
|
||||||
|
|
||||||
calculate_vertices(vertices, vertexCount, vertices, localScreen);
|
calculate_vertices(vertices, vertexCount, vertices, localScreen);
|
||||||
|
|
||||||
convertCalcs(vertexCount, vertices, colors, coordinates, t_mesh.color.a);
|
convertCalcs(vertexCount, vertices, colors, coordinates, *t_color);
|
||||||
|
|
||||||
delete[] vertices;
|
|
||||||
delete[] normals;
|
|
||||||
delete[] coordinates;
|
|
||||||
delete[] colors;
|
delete[] colors;
|
||||||
|
|
||||||
return vertexCount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GifSender::convertCalcs(u32 t_vertexCount, VECTOR *t_vertices, VECTOR *t_colors, VECTOR *t_sts, u8 t_alpha)
|
void GifSender::convertCalcs(u32 t_vertexCount, VECTOR *t_vertices, VECTOR *t_colors, VECTOR *t_sts, color_t &t_color)
|
||||||
{
|
{
|
||||||
// TODO get this via screensettings
|
// TODO get this via screensettings
|
||||||
const s32 centerX = ftoi4(2048);
|
const s32 centerX = ftoi4(2048);
|
||||||
@@ -254,7 +235,7 @@ void GifSender::convertCalcs(u32 t_vertexCount, VECTOR *t_vertices, VECTOR *t_co
|
|||||||
rgbaq[i].r = (u8)(t_colors[i][0] * 128.0F);
|
rgbaq[i].r = (u8)(t_colors[i][0] * 128.0F);
|
||||||
rgbaq[i].g = (u8)(t_colors[i][1] * 128.0F);
|
rgbaq[i].g = (u8)(t_colors[i][1] * 128.0F);
|
||||||
rgbaq[i].b = (u8)(t_colors[i][2] * 128.0F);
|
rgbaq[i].b = (u8)(t_colors[i][2] * 128.0F);
|
||||||
rgbaq[i].a = t_alpha;
|
rgbaq[i].a = t_color.a;
|
||||||
rgbaq[i].q = q;
|
rgbaq[i].q = q;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -266,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+235
-113
@@ -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,21 +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;
|
||||||
lastTextureId = 0;
|
isTextureVRAMAllocated = false;
|
||||||
|
isVSyncEnabled = true;
|
||||||
isFrameEmpty = false;
|
isFrameEmpty = false;
|
||||||
flipPacket = packet_init(3, PACKET_UCAB); // Uncached accelerated
|
lastTextureId = 0;
|
||||||
allocateBuffers(t_screen->width, t_screen->height);
|
flipPacket = packet2_create(4, P2_TYPE_UNCACHED_ACCL, P2_MODE_NORMAL, 0);
|
||||||
initDrawingEnv(t_screen->width, t_screen->height);
|
allocateBuffers((int)t_screen->width, (int)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() {}
|
||||||
@@ -55,22 +62,114 @@ Renderer::~Renderer() {}
|
|||||||
// Methods
|
// Methods
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
/** Initializes drawing environment (1st app packet) */
|
/** Configure and allocate vRAM for texture buffer */
|
||||||
void Renderer::initDrawingEnv(float t_screenW, float t_screenH)
|
void Renderer::allocateTextureBuffer(Texture *t_texture)
|
||||||
{
|
{
|
||||||
PRINT_LOG("Initializing drawing environment");
|
textureBuffer.width = t_texture->getWidth();
|
||||||
packet_t *packet = packet_init(20, PACKET_NORMAL);
|
textureBuffer.psm = t_texture->getType();
|
||||||
u16 halfW = (u16)t_screenW / 2;
|
textureBuffer.info.components = textureBuffer.psm == TEX_TYPE_RGBA ? TEXTURE_COMPONENTS_RGBA : TEXTURE_COMPONENTS_RGB;
|
||||||
u16 halfH = (u16)t_screenH / 2;
|
textureBuffer.address = graph_vram_allocate(t_texture->getWidth(), t_texture->getHeight(), textureBuffer.psm, GRAPH_ALIGN_BLOCK);
|
||||||
qword_t *q = packet->data; // Generic qword pointer.
|
assertMsg(textureBuffer.address > 1, "Texture buffer allocation error. No memory!");
|
||||||
q = draw_setup_environment(q, 0, frameBuffers, &(zBuffer));
|
textureBuffer.info.width = draw_log2(t_texture->getWidth());
|
||||||
q = draw_primitive_xyoffset(q, 0, (2048 - halfW), (2048 - halfH));
|
textureBuffer.info.height = draw_log2(t_texture->getHeight());
|
||||||
q = draw_finish(q);
|
textureBuffer.info.function = TEXTURE_FUNCTION_MODULATE;
|
||||||
// Now send the packet, no need to wait since it's the first.
|
isTextureVRAMAllocated = true;
|
||||||
dma_channel_send_normal(DMA_CHANNEL_GIF, packet->data, q - packet->data, 0, 0);
|
}
|
||||||
dma_wait_fast();
|
|
||||||
packet_free(packet);
|
/** Configure and allocate vRAM for texture buffer */
|
||||||
PRINT_LOG("Drawing environment initialized!");
|
void Renderer::deallocateTextureBuffer()
|
||||||
|
{
|
||||||
|
if (isTextureVRAMAllocated)
|
||||||
|
{
|
||||||
|
graph_vram_free(textureBuffer.address);
|
||||||
|
isTextureVRAMAllocated = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::changeTexture(Texture *t_tex)
|
||||||
|
{
|
||||||
|
assertMsg(t_tex != NULL, "Texture was not found in texture repository!");
|
||||||
|
if (t_tex->getId() != lastTextureId)
|
||||||
|
{
|
||||||
|
lastTextureId = t_tex->getId();
|
||||||
|
deallocateTextureBuffer();
|
||||||
|
allocateTextureBuffer(t_tex);
|
||||||
|
GifSender::sendTexture(*t_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
|
||||||
|
{
|
||||||
|
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) */
|
||||||
|
void Renderer::initDrawingEnv()
|
||||||
|
{
|
||||||
|
consoleLog("Initializing drawing environment");
|
||||||
|
packet2_t *packet2 = packet2_create(20, P2_TYPE_NORMAL, P2_MODE_NORMAL, 0);
|
||||||
|
packet2_update(packet2, draw_setup_environment(packet2->base, 0, frameBuffers, &(zBuffer)));
|
||||||
|
packet2_update(packet2, draw_primitive_xyoffset(packet2->next, 0,
|
||||||
|
SCREEN_CENTER - (screen->width / 2.0F),
|
||||||
|
SCREEN_CENTER - (screen->height / 2.0F)));
|
||||||
|
packet2_update(packet2, draw_finish(packet2->next));
|
||||||
|
dma_channel_send_packet2(packet2, DMA_CHANNEL_GIF, true);
|
||||||
|
dma_channel_wait(DMA_CHANNEL_GIF, 0);
|
||||||
|
packet2_free(packet2);
|
||||||
|
consoleLog("Drawing environment initialized!");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sets drawing prim for all 3D objects */
|
/** Sets drawing prim for all 3D objects */
|
||||||
@@ -85,132 +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::changeTexture(Mesh *t_mesh, u8 t_textureIndex)
|
void Renderer::setWorldColor(const color_t &t_rgb)
|
||||||
{
|
{
|
||||||
if (t_mesh->spec->textures[t_textureIndex].id != lastTextureId)
|
worldColor.r = t_rgb.r;
|
||||||
{
|
worldColor.g = t_rgb.g;
|
||||||
lastTextureId = t_mesh->spec->textures[t_textureIndex].id;
|
worldColor.b = t_rgb.b;
|
||||||
t_mesh->spec->deallocateTextureBuffer();
|
|
||||||
t_mesh->spec->allocateTextureBuffer(t_mesh->spec->textures[t_textureIndex].width, t_mesh->spec->textures[t_textureIndex].height);
|
|
||||||
GifSender::sendTexture(t_mesh->spec->textures[t_textureIndex], &t_mesh->spec->textureBuffer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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)
|
||||||
{
|
// {
|
||||||
beginFrameIfNeeded();
|
// for (u16 i = 0; i < t_amount; i++)
|
||||||
gifSender->initPacket(context);
|
// drawByPath3(t_meshes[i], t_bulbs, t_bulbsCount);
|
||||||
// TODO
|
// }
|
||||||
changeTexture(t_meshes[0], 0);
|
|
||||||
gifSender->addObjects(&renderData, t_meshes, t_amount, t_bulbs, t_bulbsCount);
|
|
||||||
gifSender->sendPacket();
|
|
||||||
draw_wait_finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 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();
|
||||||
gifSender->initPacket(context);
|
// if (!t_mesh.isDataLoaded())
|
||||||
// TODO
|
// PRINT_ERR("Can't draw, because no mesh data was loaded!");
|
||||||
changeTexture(t_mesh, 0);
|
// if (t_mesh.getCurrentAnimationFrame() != t_mesh.getNextAnimationFrame())
|
||||||
gifSender->addObjects(&renderData, &t_mesh, 1, t_bulbs, t_bulbsCount);
|
// t_mesh.animate();
|
||||||
gifSender->sendPacket();
|
// for (u32 i = 0; i < t_mesh.getMaterialsCount(); i++)
|
||||||
draw_wait_finish();
|
// {
|
||||||
}
|
// MeshMaterial *material = &t_mesh.getMaterial(i);
|
||||||
|
// if (t_mesh.shouldBeFrustumCulled && !material->isInFrustum(renderData.frustumPlanes, t_mesh.position))
|
||||||
|
// return;
|
||||||
|
// Texture *tex = textureRepo.getBySpriteOrMesh(material->getId());
|
||||||
|
// changeTexture(tex);
|
||||||
|
// gifSender->initPacket(context);
|
||||||
|
// u32 vertCount = material->getFacesCount();
|
||||||
|
// VECTOR *vertices = new VECTOR[vertCount];
|
||||||
|
// VECTOR *normals = new VECTOR[vertCount];
|
||||||
|
// VECTOR *coordinates = new VECTOR[vertCount];
|
||||||
|
// vertCount = t_mesh.getDrawData(i, vertices, normals, coordinates, *renderData.cameraPosition);
|
||||||
|
// gifSender->addObject(&renderData, t_mesh, vertCount, vertices, normals, coordinates, t_bulbs, t_bulbsCount, &textureBuffer, &material->color);
|
||||||
|
// gifSender->sendPacket();
|
||||||
|
// delete[] vertices;
|
||||||
|
// delete[] normals;
|
||||||
|
// delete[] coordinates;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
/** 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)
|
||||||
{
|
{
|
||||||
// TODO
|
|
||||||
beginFrameIfNeeded();
|
beginFrameIfNeeded();
|
||||||
|
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++)
|
for (u16 i = 0; i < t_amount; i++)
|
||||||
draw(t_meshes[i], t_bulbs, t_bulbsCount);
|
if (t_meshes[i]->getMaterial(0).isInFrustum(renderData.frustumPlanes, t_meshes[i]->position))
|
||||||
|
meshesInFrustum[addedMeshes++] = t_meshes[i];
|
||||||
|
draw(*meshesInFrustum[0], t_bulbs, t_bulbsCount);
|
||||||
|
draw(*meshesInFrustum[1], t_bulbs, t_bulbsCount);
|
||||||
|
vifSender->enableWait();
|
||||||
|
resetWaitFlag();
|
||||||
|
vifSender->drawTheSameWithOtherMatrices(renderData, meshesInFrustum, 2, addedMeshes);
|
||||||
|
if (isWaitFlagSet())
|
||||||
|
resetWaitFlag();
|
||||||
|
else
|
||||||
|
waitForRender();
|
||||||
|
delete[] meshesInFrustum;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
for (u16 i = 0; i < t_amount; i++)
|
||||||
|
draw(*t_meshes[i], t_bulbs, t_bulbsCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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();
|
||||||
// TODO VU1 send single list here
|
vifSender->calcMatrix(renderData, t_mesh.position, t_mesh.rotation);
|
||||||
if (!t_mesh->isObjLoaded && !t_mesh->isDffLoaded && !t_mesh->isMd2Loaded)
|
assertMsg(t_mesh.isDataLoaded(), "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())
|
||||||
|
t_mesh.animate();
|
||||||
|
for (u32 i = 0; i < t_mesh.getMaterialsCount(); i++)
|
||||||
|
{
|
||||||
|
MeshMaterial *material = &t_mesh.getMaterial(i);
|
||||||
|
if (t_mesh.shouldBeFrustumCulled && !material->isInFrustum(renderData.frustumPlanes, t_mesh.position))
|
||||||
return;
|
return;
|
||||||
u32 vertCount = t_mesh->getVertexCount();
|
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)));
|
||||||
VECTOR *colors = new VECTOR[vertCount];
|
Texture *tex = textureRepo.getBySpriteOrMesh(material->getId());
|
||||||
if (t_mesh->isObjLoaded || t_mesh->isMd2Loaded)
|
changeTexture(tex);
|
||||||
{
|
vertCount = t_mesh.getDrawData(i, vertices, normals, coordinates, rotatedCamera);
|
||||||
changeTexture(t_mesh, 0);
|
vifSender->drawMesh(&renderData, perspective, vertCount, vertices, normals, coordinates, t_mesh, t_bulbs, t_bulbsCount, &textureBuffer, &material->color, !material->areSTsPresent());
|
||||||
vertCount = t_mesh->getDrawData(0, vertices, normals, coordinates, colors, *renderData.cameraPosition);
|
|
||||||
vifSender->drawMesh(&renderData, perspective, vertCount, vertices, normals, coordinates, colors, t_mesh, t_bulbs, t_bulbsCount);
|
|
||||||
}
|
}
|
||||||
else if (t_mesh->isDffLoaded)
|
|
||||||
for (u32 i = 0; i < t_mesh->dff->clump.geometryList.geometries[0].extension.materialSplit.header.splitCount; i++)
|
|
||||||
{
|
|
||||||
const u32 currentTexI = t_mesh->dff->clump.geometryList.geometries[0].extension.materialSplit.splitInformation[i].materialIndex;
|
|
||||||
changeTexture(t_mesh, currentTexI);
|
|
||||||
vertCount = t_mesh->getDrawData(i, vertices, normals, coordinates, colors, *renderData.cameraPosition);
|
|
||||||
vifSender->drawMesh(&renderData, perspective, vertCount, vertices, normals, coordinates, colors, t_mesh, t_bulbs, t_bulbsCount);
|
|
||||||
}
|
|
||||||
delete[] vertices;
|
|
||||||
delete[] normals;
|
|
||||||
delete[] coordinates;
|
|
||||||
delete[] colors;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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;
|
||||||
}
|
}
|
||||||
@@ -220,7 +344,7 @@ void Renderer::beginFrameIfNeeded()
|
|||||||
if (isFrameEmpty)
|
if (isFrameEmpty)
|
||||||
{
|
{
|
||||||
isFrameEmpty = false;
|
isFrameEmpty = false;
|
||||||
gifSender->sendClear(&zBuffer);
|
gifSender->sendClear(&zBuffer, &worldColor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,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();
|
||||||
}
|
}
|
||||||
@@ -248,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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../include/modules/texture_repository.hpp"
|
||||||
|
#include "../include/utils/debug.hpp"
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Constructors/Destructors
|
||||||
|
// ----
|
||||||
|
|
||||||
|
TextureRepository::TextureRepository()
|
||||||
|
{
|
||||||
|
consoleLog("Initializing texture repository");
|
||||||
|
consoleLog("Texture repository initialized!");
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureRepository::~TextureRepository()
|
||||||
|
{
|
||||||
|
if (getTexturesCount() > 0)
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < getTexturesCount(); i++)
|
||||||
|
delete textures[i];
|
||||||
|
textures.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Methods
|
||||||
|
// ----
|
||||||
|
|
||||||
|
Texture *TextureRepository::add(char *t_subfolder, char *t_name, TextureFormat t_format)
|
||||||
|
{
|
||||||
|
Texture *texture = new Texture();
|
||||||
|
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);
|
||||||
|
textures.push_back(texture);
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextureRepository::addByMesh(char *t_path, Mesh &mesh, TextureFormat t_format)
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < mesh.getMaterialsCount(); i++)
|
||||||
|
{
|
||||||
|
Texture *texture = new Texture();
|
||||||
|
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->addLink(mesh.getMaterial(i).getId());
|
||||||
|
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
-120
@@ -16,51 +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::drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 vertCount2, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, VECTOR *colors, Mesh *t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount)
|
void VifSender::uploadMicroProgram()
|
||||||
{
|
{
|
||||||
if (t_mesh->shouldBeFrustumCulled == 1 && !t_mesh->isInFrustum(t_renderData->frustumPlanes))
|
packet2_t *packet2 = packet2_create(
|
||||||
return;
|
packet2_utils_get_packet_size_for_program(&VU1Draw3D_CodeStart, &VU1Draw3D_CodeEnd) + 1, // + end tag
|
||||||
|
P2_TYPE_NORMAL,
|
||||||
|
P2_MODE_CHAIN,
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
vec3ToNative(position, t_mesh->position, 1.0F);
|
void VifSender::calcMatrix(const RenderData &t_renderData, const Vector3 &t_position, const Vector3 &t_rotation)
|
||||||
vec3ToNative(rotation, t_mesh->rotation, 1.0F);
|
{
|
||||||
create_local_world(localWorld, position, rotation);
|
model.identity();
|
||||||
create_local_screen(localScreen, localWorld, t_renderData->worldView->data, t_perspective.data);
|
model.rotate(t_rotation);
|
||||||
|
model.translate(t_position);
|
||||||
|
|
||||||
// TODO Send it once man xd
|
modelViewProj.identity();
|
||||||
vu1.sendSingleRefList(0, &localScreen, 4);
|
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, colors, coordinates, t_renderData->prim);
|
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;
|
||||||
@@ -69,112 +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_colors, VECTOR *t_coordinates, prim_t *t_prim)
|
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->spec->lod.calculation,
|
else
|
||||||
t_mesh->spec->lod.max_level,
|
packet2_utils_gs_add_prim_giftag(currPacket, t_prim, vertCount, DRAW_STQ2_REGLIST, 3, 0);
|
||||||
t_mesh->spec->lod.mag_filter,
|
packet2_add_u32(currPacket, t_color->r);
|
||||||
t_mesh->spec->lod.min_filter,
|
packet2_add_u32(currPacket, t_color->g);
|
||||||
t_mesh->spec->lod.mipmap_select,
|
packet2_add_u32(currPacket, t_color->b);
|
||||||
t_mesh->spec->lod.l,
|
packet2_add_u32(currPacket, t_color->a);
|
||||||
(int)(t_mesh->spec->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;
|
||||||
t_mesh->spec->textureBuffer.address >> 6,
|
packet2_utils_vu_add_unpack_data(currPacket, vif_added_bytes, t_coordinates + t_start, vertCount, true);
|
||||||
t_mesh->spec->textureBuffer.width >> 6,
|
}
|
||||||
t_mesh->spec->textureBuffer.psm,
|
packet2_utils_vu_add_start_program(currPacket, 0);
|
||||||
t_mesh->spec->textureBuffer.info.width,
|
}
|
||||||
t_mesh->spec->textureBuffer.info.height,
|
|
||||||
t_mesh->spec->textureBuffer.info.components,
|
void VifSender::drawTheSameWithOtherMatrices(const RenderData &t_renderData, Mesh **t_meshes, const u32 &t_skip, const u32 &t_count)
|
||||||
t_mesh->spec->textureBuffer.info.function,
|
{
|
||||||
t_mesh->spec->clut.address >> 6,
|
// Standard double buffering (packets)
|
||||||
t_mesh->spec->clut.psm,
|
packet2_t *packet1 = packet2_create(300, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
|
||||||
t_mesh->spec->clut.storage_mode,
|
packet2_t *packet2 = packet2_create(300, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
|
||||||
t_mesh->spec->clut.start,
|
packet2_t *currMPacket = packet1;
|
||||||
t_mesh->spec->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); // 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?
|
||||||
// // 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;
|
||||||
|
}
|
||||||
//// Clipping tests end
|
packet2_reset(currMPacket, false);
|
||||||
|
}
|
||||||
vu1.addListEnding();
|
}
|
||||||
vu1.addReferenceList(0, t_vertices + t_start, 2 * vertCount, 1);
|
if (switchCounter != 0) // if there are any not sended matrices
|
||||||
vu1.addReferenceList(0, t_coordinates + t_start, 2 * vertCount, 1);
|
{
|
||||||
vu1.addStartProgram();
|
packet2_utils_vu_open_unpack(currMPacket, VU1_PARAMS_ADDRESS, true);
|
||||||
|
{
|
||||||
|
packet2_add_u32(currMPacket, true); // Draw wait finish?
|
||||||
|
packet2_add_u32(currMPacket, lastVertCount); // Vertex count
|
||||||
|
packet2_add_u32(currMPacket, lastVertCount / 3); // Triangles count
|
||||||
|
packet2_add_u32(currMPacket, isLastRGBAOnly); // 0 = STQ+RGBA, 1 = RGBA
|
||||||
|
}
|
||||||
|
packet2_utils_vu_close_unpack(currMPacket);
|
||||||
|
packet2_utils_vu_add_start_program(currMPacket, 0);
|
||||||
|
packet2_utils_vu_add_end_tag(currMPacket);
|
||||||
|
dma_channel_wait(DMA_CHANNEL_VIF1, 0);
|
||||||
|
dma_channel_send_packet2(currMPacket, DMA_CHANNEL_VIF1, 1);
|
||||||
|
}
|
||||||
|
packet2_free(packet1);
|
||||||
|
packet2_free(packet2);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
+85
-12
@@ -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,20 +71,10 @@ 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 */
|
||||||
void vec3ToNative(VECTOR o_result, Vector3 &t_vec, float t_fourthVal)
|
void vec3ToNative(VECTOR o_result, const Vector3 &t_vec, float t_fourthVal)
|
||||||
{
|
{
|
||||||
o_result[0] = t_vec.x;
|
o_result[0] = t_vec.x;
|
||||||
o_result[1] = t_vec.y;
|
o_result[1] = t_vec.y;
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,9 +9,33 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../include/utils/string.hpp"
|
#include "../include/utils/string.hpp"
|
||||||
|
#include "../include/utils/debug.hpp"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#define CHAR_BIT 8
|
||||||
|
|
||||||
char *String::createWithoutExtension(char *source)
|
char *String::createU32ToString(const u32 a)
|
||||||
|
{
|
||||||
|
char *result = new char[(((sizeof a) * CHAR_BIT) + 2) / 3 + 2];
|
||||||
|
sprintf(result, "%d", a);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Converts "123" to "000123". 6 digits length */
|
||||||
|
char *String::createWithLeadingZeros(const char *a)
|
||||||
|
{
|
||||||
|
const u8 digitsAmount = 6;
|
||||||
|
char *part = createConcatenated("00000000", a);
|
||||||
|
u16 partLength = getLength(part);
|
||||||
|
u16 insert = 0;
|
||||||
|
char *result = new char[digitsAmount + 1];
|
||||||
|
for (u16 i = partLength - digitsAmount; i < partLength; i++)
|
||||||
|
result[insert++] = part[i];
|
||||||
|
delete[] part;
|
||||||
|
result[digitsAmount] = '\0';
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *String::createWithoutExtension(const char *source)
|
||||||
{
|
{
|
||||||
u32 length = 0;
|
u32 length = 0;
|
||||||
for (;; length++)
|
for (;; length++)
|
||||||
@@ -24,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];
|
||||||
@@ -34,7 +58,8 @@ char *String::createCopy(char *source)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 String::getLength(char *a)
|
// For test\0 will return 4
|
||||||
|
u32 String::getLength(const char *a)
|
||||||
{
|
{
|
||||||
if (a == NULL)
|
if (a == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -43,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/dff_model.o \
|
|
||||||
../../engine/models/md2_model.o \
|
|
||||||
../../engine/models/mesh.o \
|
|
||||||
../../engine/models/mesh_spec.o \
|
|
||||||
../../engine/models/obj_model.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/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_BIN) $(EE_OBJS)
|
|
||||||
|
|
||||||
include $(PS2SDK)/samples/Makefile.pref
|
|
||||||
include $(PS2SDK)/samples/Makefile.eeglobal
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
## Ari sample
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
Testing demo. In future there will be Ariana Grande demo.
|
|
||||||
|
|
||||||
### Assets
|
|
||||||
[Download](http://apgcglz.cluster028.hosting.ovh.net/tyra/1.0.0/samples/ari/assets.zip)
|
|
||||||
|
|
||||||
### Screenshot
|
|
||||||
|
|
||||||
[![Ari screenshot][ari-screenshot]](#)
|
|
||||||
|
|
||||||
[ari-screenshot]: http://apgcglz.cluster028.hosting.ovh.net/tyra/1.0.0/samples/ari/ari.gif
|
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
/*
|
|
||||||
# ______ ____ ___
|
|
||||||
# | \/ ____| |___|
|
|
||||||
# | | | \ | |
|
|
||||||
#-----------------------------------------------------------------------
|
|
||||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
|
||||||
# Licenced under Apache License 2.0
|
|
||||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
// SANDRO TODO
|
|
||||||
// Ogarnac czemu tekstura sie zle wczytuje
|
|
||||||
// Ogarnac wiele tekstur do skyboxa (wczytywane z .mtl i .obj)
|
|
||||||
// texture loading for obj and md2
|
|
||||||
// animation for dff
|
|
||||||
// TODO obj destructor
|
|
||||||
// TODO md2 destructor
|
|
||||||
// TODO dff destructor
|
|
||||||
|
|
||||||
#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;
|
|
||||||
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
|
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
Vector3 islandPos = Vector3(0.0F, 10.0F, 0.0F);
|
|
||||||
island = new Mesh();
|
|
||||||
island->rotation.x = -1.6F;
|
|
||||||
island->loadDff("sunnyisl/", "sunnyisl.dff", islandPos, 0.1F);
|
|
||||||
island->shouldBeFrustumCulled = false;
|
|
||||||
island->shouldBeBackfaceCulled = true;
|
|
||||||
|
|
||||||
islandAddons = new Mesh();
|
|
||||||
islandAddons->rotation.x = -1.6F;
|
|
||||||
islandAddons->loadDff("sunnyisl/", "sunnyisl3.dff", islandPos, 0.1F);
|
|
||||||
islandAddons->shouldBeFrustumCulled = false;
|
|
||||||
|
|
||||||
skybox = new Mesh();
|
|
||||||
Vector3 skyboxPos = Vector3(0.0F, 0.0F, 0.0F);
|
|
||||||
skybox->loadObj("skybox/", "skybox.obj", skyboxPos, 100.0F);
|
|
||||||
skybox->shouldBeFrustumCulled = true;
|
|
||||||
|
|
||||||
waterFloors = new Mesh *[WATER_TILES_COUNT];
|
|
||||||
spirals = new Point[WATER_TILES_COUNT];
|
|
||||||
Vector3 initPos = Vector3(0.0F, 8.0F, 0.0F);
|
|
||||||
waterFloors[0] = new Mesh();
|
|
||||||
waterFloors[0]->loadObj("water/", "water.obj", initPos, 5.0F);
|
|
||||||
waterFloors[0]->shouldBeFrustumCulled = true;
|
|
||||||
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();
|
|
||||||
Vector3 nextPos = Vector3(10.0F * spirals[i].x, 8.0F, 10.0F * spirals[i].y);
|
|
||||||
waterFloors[i]->setObj(nextPos, waterFloors[0]->obj, waterFloors[0]->spec);
|
|
||||||
waterFloors[i]->shouldBeFrustumCulled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 currentTexI = 0;
|
|
||||||
|
|
||||||
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]); // TODO
|
|
||||||
}
|
|
||||||
@@ -1,45 +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;
|
|
||||||
Vector3 initPos = Vector3(0.0F, 8.0F, 0.0F);
|
|
||||||
this->mesh.loadMD2("ari/", "ari.md2", initPos, 0.0001F);
|
|
||||||
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()
|
|
||||||
{
|
|
||||||
delete[] this->spec;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----
|
|
||||||
// Methods
|
|
||||||
// ----
|
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user