remove tyrav1 stuff

This commit is contained in:
h4570
2022-07-17 10:15:37 +02:00
parent 7f619ec829
commit 44c1ee4fe8
136 changed files with 0 additions and 30389 deletions
-60
View File
@@ -1,60 +0,0 @@
# 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: ./
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: ./
env:
TYRA: ${GITHUB_WORKSPACE}
run: |
make tests
- name: Compile cube project
working-directory: ./
env:
TYRA: ${GITHUB_WORKSPACE}
run: |
make cube
- name: Compile floors project
working-directory: ./
env:
TYRA: ${GITHUB_WORKSPACE}
run: |
make floors
- name: Compile dolphin project
working-directory: ./
env:
TYRA: ${GITHUB_WORKSPACE}
run: |
make dolphin
-38
View File
@@ -1,38 +0,0 @@
.vscode/
.idea/
# ---
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
*.erl
*.elf
-134
View File
@@ -1,134 +0,0 @@
# 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
-201
View File
@@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-97
View File
@@ -1,97 +0,0 @@
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2021, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# André Guilherme <andregui17@outlook.com>
TYRA_DIR = ./
LIB_NAME = libtyra.a
# ENGINE OBJECTS
ENGINE_OBJS = src/engine/engine.o \
src/engine/modules/audio.o \
src/engine/modules/camera_base.o \
src/engine/modules/file_service.o \
src/engine/modules/gif_sender.o \
src/engine/modules/light.o \
src/engine/modules/pad.o \
src/engine/modules/renderer.o \
src/engine/modules/texture_repository.o \
src/engine/modules/timer.o \
src/engine/modules/vif_sender.o \
src/engine/models/math/matrix.o \
src/engine/models/math/plane.o \
src/engine/models/math/point.o \
src/engine/models/math/vector3.o \
src/engine/models/mesh_frame.o \
src/engine/models/bounding_box.o \
src/engine/models/mesh_material.o \
src/engine/models/mesh.o \
src/engine/models/sprite.o \
src/engine/models/texture.o \
src/engine/utils/math.o \
src/engine/utils/string.o \
src/engine/loaders/bmp_loader.o \
src/engine/loaders/dff_loader.o \
src/engine/loaders/md2_loader.o \
src/engine/loaders/obj_loader.o \
src/engine/loaders/png_loader.o \
src/engine/vu1_progs/draw3D.o \
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
all: $(ENGINE_OBJS)
ar rcs $(LIB_NAME) $(ENGINE_OBJS)
cp -f $(LIB_NAME) $(PS2SDK)/ee/lib
rm -f $(ENGINE_OBJS)
# Cube example
cube:
$(MAKE) -C src/samples/cube all clean
# Dolphin example
dolphin:
$(MAKE) -C src/samples/dolphin all clean
# Floors example
floors:
$(MAKE) -C src/samples/floors all clean
# Rebuild the engine
rebuild-engine:
$(MAKE) -C src/engine && make && make EE_CXXFLAGS="-DNDEBUG $(EE_CXXFLAGS)"
# Rebuild debug engine
rebuild-dbg-engine:
$(MAKE) -C src/engine && make && make
# Unit tests folder
tests:
$(MAKE) -C src/unit_tests all clean
# %.vcl: %.vclpp
# $(EE_VCLPP) $< $@
# %.vsm: %.vcl
# $(EE_VCL) $< >> $@
%.o: %.vsm
$(EE_DVP) $< -o $@
include $(PS2SDK)/samples/Makefile.pref
include $(PS2SDK)/samples/Makefile.eeglobal
-190
View File
@@ -1,190 +0,0 @@
[![Contributors][contributors-shield]][contributors-url]
[![MIT License][license-shield]][license-url]
[![Discord](https://img.shields.io/badge/discord-Tyra-brightgreen?logo=discord)](https://discord.gg/NhhTmg3Gm5)
[![Discord](https://img.shields.io/badge/discord-PS2--Scene-brightgreen?logo=discord)](https://discord.gg/7dCr6ThSN5)
<br />
<p align="center">
<a href="https://github.com/h4570/tyra">
<img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/github-splash.png" alt="Logo" width="100%" height="auto">
</a>
<h3 align="center">Tyra - alpha 1.36.3</h3>
<p align="center">
Open source game engine for PlayStation 2™
<br />
<a href="https://github.com/h4570/tyra/tree/master/src/samples/dolphin"><strong>Dolphin sample »</strong></a>
&nbsp;
<a href="https://github.com/h4570/tyra/tree/master/src/samples/floors"><strong>Floors sample »</strong></a>
<br />
<br />
<a href="https://github.com/h4570/tyra/issues">Report Bug</a>
·
<a href="https://github.com/h4570/tyra/issues">Request Feature</a>
</p>
</p>
[![Stargazers repo roster for h4570/tyra](https://reporoster.com/stars/h4570/tyra)](https://github.com/h4570/tyra/stargazers)
## Table of Contents
* [About the Project](#about-the-project)
* [Samples](#samples)
* [Description](#description)
* [Features](#features)
* [Branches](#branches)
* [Getting Started](#getting-started)
* [Installation](#installation)
* [Prerequisites](#prerequisites)
* [Roadmap](#roadmap)
* [Contributing](#contributing)
* [License](#license)
* [Built With](#built-with)
* [Acronyms](#acronyms)
* [Thanks](#thanks)
<br />
## About the Project
<img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/tyra.gif" alt="Sample code" width="600" height="auto">
<img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/dolphin.gif " alt="Sample game" width="500" height="auto">
### Samples
* [Dolphin](https://github.com/h4570/tyra/tree/master/src/samples/dolphin)
* [Floors](https://github.com/h4570/tyra/tree/master/src/samples/floors)
* [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
* 3D support - VU1 "Path 1 rendering"
* 2D support - PNG & BMP
* Frustum culling, backface culling
* OpenGL adaptions: Perspective projection, lookAt camera
* Texture support - .bmp and png
* Mesh loaders: ".obj", ".dff" (RenderWare, GTA:SA) and ".md2" (Quake II)
* Threading support
* Animation support for obj and md2
* Audio support - .wav and .adpcm
* Pad support
### Branches
* Master - monthly releases - tested on PS2 & PCSX2.
* Develop - daily builds - can be unstable.
<br />
## Getting Started
### 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:
[![Discord](https://img.shields.io/badge/discord-Tyra-brightgreen?logo=discord)](https://discord.gg/NhhTmg3Gm5)
### Prerequisites
* PS2 DEV environment - [PS2DEV](https://github.com/ps2dev/ps2dev)
* At least #58ffb33 PS2SDK (28.05.2021) - [PS2SDK](https://github.com/ps2dev/ps2sdk)
* PS2 Emulator. For example [PCSX2](https://pcsx2.net/)
<br />
## Extra info
* If you want to use your own .obj file, please check "triangulate faces" in blender.
PS2 is supporting only triangle primitive type.
<br />
## Roadmap
### Roadmap for next master release:
[Next release roadmap](https://github.com/h4570/tyra/projects/4)
See the [open issues](https://github.com/h4570/tyra/issues) for a list of proposed features (and known issues).
<br />
## 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**.
1. Fork the Project
2. Create your Feature Branch (`git checkout -b feature/amazing-feature`)
3. Commit your Changes (`git commit -m 'Add some amazing-feature'`)
4. Push to the Branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
<br />
## License
Distributed under the Apache License 2.0 License. See `LICENSE` for more information.
<br />
## 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)
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-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
[license-shield]: https://img.shields.io/github/license/h4570/tyra.svg?style=flat-square
[license-url]: https://github.com/h4570/tyra/blob/master/LICENSE
-254
View File
@@ -1,254 +0,0 @@
# 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
unset ZLIB
unset LIBTIFF
unset LIBJPEG
unset LIBPNG
./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
- Just hit make all on the root of tyra folder or you can go via `cd /src/engine` and hit `make all` there.
- If you wanna build the debug build or rebuild the engine, just `make rebuild-engine ` on the root of tyra or `make rebuild-dbg-engine` to build debug version or go to one of the samples via `cd /repos/tyra/src/samples/floors `and do the same process above
<br/>
## Install & configure PCSX2
- Download & install PCSX2 from (1.6+ version)https://pcsx2.net/
- Extract bios files fromhttps://romsmania.cc/bios/pcsx2-playstation-2-bios-3to `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 - Method 1
- 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 PCSX2 via `make run-pcsx2`
## Run one of the samples Method 2
- Run `make floors` on the root of tyra project or change directory to the sampels via `cd src/samples/floors` and do the `make install` command
---
<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`
-51
View File
@@ -1,51 +0,0 @@
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
-11
View File
@@ -1,11 +0,0 @@
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
-100
View File
@@ -1,100 +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/engine.hpp"
#include <kernel.h>
#include <stdio.h>
#include <sifrpc.h>
#include <time.h>
#include <cstdlib>
#include "include/utils/debug.hpp"
// ----
// Constructors/Destructors
// ----
Engine::Engine()
{
setDefaultScreen();
firePS2();
}
Engine::Engine(const ScreenSettings &t_screen)
{
screen = t_screen;
firePS2();
}
Engine::~Engine() {}
// ----
// Methods
// ----
void Engine::setDefaultScreen()
{
screen.nearPlaneDist = 2.0F;
screen.farPlaneDist = 2000.0F;
screen.fov = 60.0F;
screen.width = 640.0F;
screen.height = 480.0F;
screen.aspectRatio = screen.width / screen.height;
screen.projectionScale = 4096.0F; // PS2 have 4k drawing area
}
void Engine::init(Game *t_game, u32 t_gifPacketSize)
{
assertMsg(!isInitialized, "Engine was already initialized!");
game = t_game;
renderer = new Renderer(t_gifPacketSize, &screen);
isInitialized = true;
game->onInit();
gameLoop();
}
/** Do not call this method. This is used in gameLoop() to maintain multithreading */
void Engine::wakeup(s32 t_alarmId, u16 t_time, void *t_common)
{
(void)t_alarmId;
(void)t_time;
iWakeupThread(*(int *)t_common);
ExitHandler();
}
void Engine::firePS2()
{
SifInitRpc(0);
srand(time(NULL));
// fileService.startThread();
// audio.startThread(&fileService);
audio.startThread(NULL);
isInitialized = 0;
mainThreadId = GetThreadId();
}
void Engine::gameLoop()
{
for (;;)
{
pad.update();
game->onUpdate();
if (fpsDelayer++ >= 4)
{
fps = timer.getFPS();
fpsDelayer = 0;
}
timer.prime();
renderer->endFrame(fps);
/** -6~ FPS */
SetAlarm(150, &Engine::wakeup, &mainThreadId);
SleepThread();
}
}
-52
View File
@@ -1,52 +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_ENGINE_
#define _TYRA_ENGINE_
#include <tamtypes.h>
#include "game.hpp"
#include "models/screen_settings.hpp"
#include "models/math/matrix.hpp"
#include "modules/renderer.hpp"
#include "modules/timer.hpp"
#include "modules/pad.hpp"
#include "modules/audio.hpp"
#include "modules/file_service.hpp"
class Engine
{
public:
Engine(const ScreenSettings &screen);
Engine();
~Engine();
void init(Game *t_game, u32 t_gifPacketSize);
void setDefaultScreen();
Renderer *renderer;
// FileService fileService;
Audio audio;
ScreenSettings screen;
Pad pad;
float fps;
private:
void firePS2();
u8 fpsDelayer;
Timer timer;
u8 isInitialized;
void gameLoop();
Game *game;
s32 mainThreadId;
static void wakeup(s32 t_alarmId, u16 t_time, void *t_common);
};
#endif
-27
View File
@@ -1,27 +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_GAME_
#define _TYRA_GAME_
#include <tamtypes.h>
class Game
{
public:
virtual ~Game(){};
virtual void onInit() = 0;
virtual void onUpdate() = 0;
private:
};
#endif
-183
View File
@@ -1,183 +0,0 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _TYRA_ANORMS_
#define _TYRA_ANORMS_
const float ANORMS[162][3] = {
{-0.525731f, 0.000000f, 0.850651f},
{-0.442863f, 0.238856f, 0.864188f},
{-0.295242f, 0.000000f, 0.955423f},
{-0.309017f, 0.500000f, 0.809017f},
{-0.162460f, 0.262866f, 0.951056f},
{0.000000f, 0.000000f, 1.000000f},
{0.000000f, 0.850651f, 0.525731f},
{-0.147621f, 0.716567f, 0.681718f},
{0.147621f, 0.716567f, 0.681718f},
{0.000000f, 0.525731f, 0.850651f},
{0.309017f, 0.500000f, 0.809017f},
{0.525731f, 0.000000f, 0.850651f},
{0.295242f, 0.000000f, 0.955423f},
{0.442863f, 0.238856f, 0.864188f},
{0.162460f, 0.262866f, 0.951056f},
{-0.681718f, 0.147621f, 0.716567f},
{-0.809017f, 0.309017f, 0.500000f},
{-0.587785f, 0.425325f, 0.688191f},
{-0.850651f, 0.525731f, 0.000000f},
{-0.864188f, 0.442863f, 0.238856f},
{-0.716567f, 0.681718f, 0.147621f},
{-0.688191f, 0.587785f, 0.425325f},
{-0.500000f, 0.809017f, 0.309017f},
{-0.238856f, 0.864188f, 0.442863f},
{-0.425325f, 0.688191f, 0.587785f},
{-0.716567f, 0.681718f, -0.147621f},
{-0.500000f, 0.809017f, -0.309017f},
{-0.525731f, 0.850651f, 0.000000f},
{0.000000f, 0.850651f, -0.525731f},
{-0.238856f, 0.864188f, -0.442863f},
{0.000000f, 0.955423f, -0.295242f},
{-0.262866f, 0.951056f, -0.162460f},
{0.000000f, 1.000000f, 0.000000f},
{0.000000f, 0.955423f, 0.295242f},
{-0.262866f, 0.951056f, 0.162460f},
{0.238856f, 0.864188f, 0.442863f},
{0.262866f, 0.951056f, 0.162460f},
{0.500000f, 0.809017f, 0.309017f},
{0.238856f, 0.864188f, -0.442863f},
{0.262866f, 0.951056f, -0.162460f},
{0.500000f, 0.809017f, -0.309017f},
{0.850651f, 0.525731f, 0.000000f},
{0.716567f, 0.681718f, 0.147621f},
{0.716567f, 0.681718f, -0.147621f},
{0.525731f, 0.850651f, 0.000000f},
{0.425325f, 0.688191f, 0.587785f},
{0.864188f, 0.442863f, 0.238856f},
{0.688191f, 0.587785f, 0.425325f},
{0.809017f, 0.309017f, 0.500000f},
{0.681718f, 0.147621f, 0.716567f},
{0.587785f, 0.425325f, 0.688191f},
{0.955423f, 0.295242f, 0.000000f},
{1.000000f, 0.000000f, 0.000000f},
{0.951056f, 0.162460f, 0.262866f},
{0.850651f, -0.525731f, 0.000000f},
{0.955423f, -0.295242f, 0.000000f},
{0.864188f, -0.442863f, 0.238856f},
{0.951056f, -0.162460f, 0.262866f},
{0.809017f, -0.309017f, 0.500000f},
{0.681718f, -0.147621f, 0.716567f},
{0.850651f, 0.000000f, 0.525731f},
{0.864188f, 0.442863f, -0.238856f},
{0.809017f, 0.309017f, -0.500000f},
{0.951056f, 0.162460f, -0.262866f},
{0.525731f, 0.000000f, -0.850651f},
{0.681718f, 0.147621f, -0.716567f},
{0.681718f, -0.147621f, -0.716567f},
{0.850651f, 0.000000f, -0.525731f},
{0.809017f, -0.309017f, -0.500000f},
{0.864188f, -0.442863f, -0.238856f},
{0.951056f, -0.162460f, -0.262866f},
{0.147621f, 0.716567f, -0.681718f},
{0.309017f, 0.500000f, -0.809017f},
{0.425325f, 0.688191f, -0.587785f},
{0.442863f, 0.238856f, -0.864188f},
{0.587785f, 0.425325f, -0.688191f},
{0.688191f, 0.587785f, -0.425325f},
{-0.147621f, 0.716567f, -0.681718f},
{-0.309017f, 0.500000f, -0.809017f},
{0.000000f, 0.525731f, -0.850651f},
{-0.525731f, 0.000000f, -0.850651f},
{-0.442863f, 0.238856f, -0.864188f},
{-0.295242f, 0.000000f, -0.955423f},
{-0.162460f, 0.262866f, -0.951056f},
{0.000000f, 0.000000f, -1.000000f},
{0.295242f, 0.000000f, -0.955423f},
{0.162460f, 0.262866f, -0.951056f},
{-0.442863f, -0.238856f, -0.864188f},
{-0.309017f, -0.500000f, -0.809017f},
{-0.162460f, -0.262866f, -0.951056f},
{0.000000f, -0.850651f, -0.525731f},
{-0.147621f, -0.716567f, -0.681718f},
{0.147621f, -0.716567f, -0.681718f},
{0.000000f, -0.525731f, -0.850651f},
{0.309017f, -0.500000f, -0.809017f},
{0.442863f, -0.238856f, -0.864188f},
{0.162460f, -0.262866f, -0.951056f},
{0.238856f, -0.864188f, -0.442863f},
{0.500000f, -0.809017f, -0.309017f},
{0.425325f, -0.688191f, -0.587785f},
{0.716567f, -0.681718f, -0.147621f},
{0.688191f, -0.587785f, -0.425325f},
{0.587785f, -0.425325f, -0.688191f},
{0.000000f, -0.955423f, -0.295242f},
{0.000000f, -1.000000f, 0.000000f},
{0.262866f, -0.951056f, -0.162460f},
{0.000000f, -0.850651f, 0.525731f},
{0.000000f, -0.955423f, 0.295242f},
{0.238856f, -0.864188f, 0.442863f},
{0.262866f, -0.951056f, 0.162460f},
{0.500000f, -0.809017f, 0.309017f},
{0.716567f, -0.681718f, 0.147621f},
{0.525731f, -0.850651f, 0.000000f},
{-0.238856f, -0.864188f, -0.442863f},
{-0.500000f, -0.809017f, -0.309017f},
{-0.262866f, -0.951056f, -0.162460f},
{-0.850651f, -0.525731f, 0.000000f},
{-0.716567f, -0.681718f, -0.147621f},
{-0.716567f, -0.681718f, 0.147621f},
{-0.525731f, -0.850651f, 0.000000f},
{-0.500000f, -0.809017f, 0.309017f},
{-0.238856f, -0.864188f, 0.442863f},
{-0.262866f, -0.951056f, 0.162460f},
{-0.864188f, -0.442863f, 0.238856f},
{-0.809017f, -0.309017f, 0.500000f},
{-0.688191f, -0.587785f, 0.425325f},
{-0.681718f, -0.147621f, 0.716567f},
{-0.442863f, -0.238856f, 0.864188f},
{-0.587785f, -0.425325f, 0.688191f},
{-0.309017f, -0.500000f, 0.809017f},
{-0.147621f, -0.716567f, 0.681718f},
{-0.425325f, -0.688191f, 0.587785f},
{-0.162460f, -0.262866f, 0.951056f},
{0.442863f, -0.238856f, 0.864188f},
{0.162460f, -0.262866f, 0.951056f},
{0.309017f, -0.500000f, 0.809017f},
{0.147621f, -0.716567f, 0.681718f},
{0.000000f, -0.525731f, 0.850651f},
{0.425325f, -0.688191f, 0.587785f},
{0.587785f, -0.425325f, 0.688191f},
{0.688191f, -0.587785f, 0.425325f},
{-0.955423f, 0.295242f, 0.000000f},
{-0.951056f, 0.162460f, 0.262866f},
{-1.000000f, 0.000000f, 0.000000f},
{-0.850651f, 0.000000f, 0.525731f},
{-0.955423f, -0.295242f, 0.000000f},
{-0.951056f, -0.162460f, 0.262866f},
{-0.864188f, 0.442863f, -0.238856f},
{-0.951056f, 0.162460f, -0.262866f},
{-0.809017f, 0.309017f, -0.500000f},
{-0.864188f, -0.442863f, -0.238856f},
{-0.951056f, -0.162460f, -0.262866f},
{-0.809017f, -0.309017f, -0.500000f},
{-0.681718f, 0.147621f, -0.716567f},
{-0.681718f, -0.147621f, -0.716567f},
{-0.850651f, 0.000000f, -0.525731f},
{-0.688191f, 0.587785f, -0.425325f},
{-0.587785f, 0.425325f, -0.688191f},
{-0.425325f, 0.688191f, -0.587785f},
{-0.425325f, -0.688191f, -0.587785f},
{-0.587785f, -0.425325f, -0.688191f},
{-0.688191f, -0.587785f, -0.425325f}};
#endif
-29
View File
@@ -1,29 +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_BMP_LOADER_
#define _TYRA_BMP_LOADER_
#include <stdio.h>
#include <tamtypes.h>
#include "../models/texture.hpp"
/** Class responsible for loading images in bmp format */
class BmpLoader
{
public:
BmpLoader();
~BmpLoader();
void load(Texture &o_texture, char *t_subfolder, char *t_name, char *t_extension);
};
#endif
-49
View File
@@ -1,49 +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_LOADER_
#define _TYRA_DFF_LOADER_
#include "../models/mesh_frame.hpp"
#include "./dff_structure.hpp"
/** Class responsible for loading&parsing .obj 3D files */
class DffLoader
{
public:
DffLoader();
~DffLoader();
// void im_not_used_anywhere(MeshFrame *o_result, char *t_fileName, float t_scale, u8 t_invertT);
void load(MeshFrame *o_result, char *t_fileName, float t_scale, u8 t_invertT);
void serialize(MeshFrame *o_result, u8 t_invertT, u8 *t_data, float t_scale);
private:
// ---
void readFrameListData(RwFrameListData &t_frd, 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 readGeometryExtension(MeshFrame *o_frame, char **materialNames, u8 *t_buffer, u32 &t_ptrPos);
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 readMaterialData(RwMaterialData &t_md, 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 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
@@ -1,342 +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_STRUCTURE_
#define _TYRA_DFF_STRUCTURE_
#include <tamtypes.h>
#include "../models/math/vector3.hpp"
enum RwGeometryDataFlags
{
rwOBJECT_VERTEX_TRISTRIP = 0x01,
rwOBJECT_VERTEX_POS = 0x02,
rwOBJECT_VERTEX_TEXTURED = 0x04,
rwOBJECT_VERTEX_PRELIT = 0x08,
rwOBJECT_VERTEX_NORMALS = 0x10,
rwOBJECT_VERTEX_LIGHT = 0x20,
rwOBJECT_VERTEX_MODULATE_MATERIAL_COLOR = 0x40,
rwOBJECT_VERTEX_TEXTURED_2 = 0x80
};
class RwSectionHeader
{
public:
u32 sectionType;
u32 sectionSize;
u32 versionNumber;
};
class RwFrameListChunk
{
public:
~RwFrameListChunk() {}
float *rotationalMatrix; // [ROT_MAT_DIM]
float coordinatesOffsetX;
float coordinatesOffsetY;
float coordinatesOffsetZ;
u32 parentFrame; // 0xFFFFFFFF = NONE
u32 unk1;
};
// Section: Frame List
class RwFrameListData : public RwSectionHeader
{
public:
~RwFrameListData() {}
static const u32 ROT_MAT_DIM = 9;
u32 frameCount;
RwFrameListChunk *frameInformation; // [frameCount]
};
class RwFrame : public RwSectionHeader
{
public:
~RwFrame() {}
u8 *frameName; // [sectionSize] - should be interpreted as string
};
class RwFrameListExtension : public RwSectionHeader
{
public:
RwFrame frame;
};
class RwFrameList : public RwSectionHeader
{
public:
RwFrameListData data;
~RwFrameList() {}
RwFrameListExtension *extensions;
};
// ---
class RwGeometryDataHeader
{
public:
u16 flags;
u16 unk1;
u32 triangleCount;
u32 vertexCount;
u32 morphTargetCount;
};
struct RwGeometryDataLightingHeader
{ // IF versionNumber = 4099 - according to not complete documentation
float ambient;
float diffuse;
float specular;
};
struct RwGeometryDataColorInformationChunk
{ // if rwOBJECT_VERTEX_PREILIT in flags
u8 red;
u8 green;
u8 blue;
u8 alpha;
};
struct RwGeometryDataTextureMappingInformationChunk
{ // if rwOBJECT_VERTEX_TEXTURED in flags
float u;
float v;
};
struct RwGeometryDataFaceInformation
{
u16 vertex2; // this
u16 vertex1; // is
u16 flags; // weird
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
class RwGeometryData : public RwSectionHeader
{
public:
~RwGeometryData()
{
// if (dataHeader.flags & rwOBJECT_VERTEX_NORMALS)
// delete[] normalInformation;
// delete[] vertexInformation;
// free(vertexInformation);
// delete[] faceInformation;
// if (dataHeader.flags & rwOBJECT_VERTEX_PRELIT)
// delete[] colorInformation;
// if (dataHeader.flags & rwOBJECT_VERTEX_TEXTURED)
// delete[] textureMappingInformation;
}
RwGeometryDataHeader dataHeader;
RwGeometryDataLightingHeader lightingHeader;
RwGeometryDataColorInformationChunk *colorInformation; // [vertexCount]
RwGeometryDataTextureMappingInformationChunk *textureMappingInformation; // [vertexCount]
RwGeometryDataFaceInformation *faceInformation; // [triangleCount]
RwGeometryDataNonameInfo nonameInfo;
Vector3 *vertexInformation; // [vertexCount]
Vector3 *normalInformation; // [vertexCount]
};
class RwMaterialData : public RwSectionHeader
{
public:
u32 unk1;
u8 R;
u8 G;
u8 B;
u8 A;
u32 unk2;
u32 textureCount;
float unkPosX;
float unkPosY;
float unkPosZ;
};
class RwTextureData : public RwSectionHeader
{
public:
u16 textureFilterModeFlags;
u16 unk;
};
class RwString : public RwSectionHeader
{
public:
~RwString() { delete[] text; }
char *text;
};
class RwTextureExtension : public RwSectionHeader
{
// May contain Sky Mipmap Val
};
class RwTexture : public RwSectionHeader
{
public:
RwTextureData data;
RwString textureName;
RwString textureAlphaName;
RwTextureExtension extension;
};
class RwMaterialExtension : public RwSectionHeader
{
// meant to be void.. don't ask
};
class RwMaterial : public RwSectionHeader
{
public:
~RwMaterial() {}
RwMaterialData data;
RwTexture *textures;
RwMaterialExtension extension;
};
class RwMaterialListData : public RwSectionHeader
{
public:
~RwMaterialListData() {}
u32 materialCount;
u32 *arrayOfUnks; // Filled with '-1's, [materialCount] - it wasn't mentioned in docs.
};
class RwMaterialList : public RwSectionHeader
{
public:
~RwMaterialList() {}
RwMaterialListData data;
RwMaterial *materials;
};
class RwGeometryListVertexInfoChunk
{
public:
u32 vertex1;
};
class RwGeometryListInfoChunk
{
public:
~RwGeometryListInfoChunk() {}
u32 faceIndex;
u32 materialIndex;
RwGeometryListVertexInfoChunk *vertexInformation; // [faceIndex]
};
class RwMaterialSplitHeader
{
public:
u32 triangleStrip;
u32 splitCount;
u32 faceCount;
};
class RwMaterialSplit
{
public:
~RwMaterialSplit() {}
RwMaterialSplitHeader header;
RwGeometryListInfoChunk *splitInformation; // [splitCount]
};
class RwGeometryExtension : public RwSectionHeader
{
public:
RwMaterialSplit materialSplit;
};
class RwGeometry : public RwSectionHeader
{
public:
RwGeometryData data;
RwMaterialList materialList;
RwGeometryExtension extension;
};
// ---
// Section: Geometry List
class RwGeometryListData : public RwSectionHeader
{
public:
u32 geometryCount;
};
class RwGeometryList : public RwSectionHeader
{
public:
~RwGeometryList() {}
RwGeometryListData data;
RwGeometry *geometries;
};
// ---
// Section: Atomic
class RwAtomicData : public RwSectionHeader
{
public:
u32 frameNumber;
u32 geometryNumber;
u32 unk1;
u32 unk2;
};
class RwAtomic : public RwSectionHeader
{
public:
RwAtomicData data;
};
// ---
// Section: Clump
class RwClumpData : public RwSectionHeader
{
public:
u32 objectCount;
u32 unk1;
u32 unk2;
};
class RwClump : public RwSectionHeader
{
public:
RwClumpData data;
RwFrameList frameList;
RwGeometryList geometryList;
RwAtomic atomic; //multiple?? but how many
};
// ---
#endif
-91
View File
@@ -1,91 +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_LOADER_
#define _TYRA_MD2_LOADER_
#include "../models/mesh_frame.hpp"
#include <stdio.h>
// magic number "IDP2" or 844121161
#define MD2_IDENT (('2' << 24) + ('P' << 16) + ('D' << 8) + 'I')
// model version
#define MD2_VERSION 8
typedef struct
{
int ident; // magic number. must be equal to "IDP2"
int version; // md2 version. must be equal to 8
int skinwidth; // width of the texture
int skinheight; // height of the texture
int framesize; // size of one frame in bytes
int num_skins; // number of textures
int num_xyz; // number of vertices
int num_st; // number of texture coordinates
int num_tris; // number of triangles
int num_glcmds; // number of opengl commands
int num_frames; // total number of frames
int ofs_skins; // offset to skin names (64 bytes each)
int ofs_st; // offset to s-t texture coordinates
int ofs_tris; // offset to triangles
int ofs_frames; // offset to frame data
int ofs_glcmds; // offset to opengl commands
int ofs_end; // offset to end of file
} md2_t;
typedef struct
{
unsigned char v[3]; // compressed vertex (x, y, z) coordinates
unsigned char lightnormalindex; // index to a normal vector for the lighting
} mvertex_t;
typedef struct
{
float scale[3]; // scale values
float translate[3]; // translation vector
char name[16]; // frame name
mvertex_t verts[1]; // first vertex of this frame
} frame_t;
typedef float vec3_t[3];
typedef struct
{
short index_xyz[3]; // indexes to triangle's vertices
short index_st[3]; // indexes to vertices' texture coorinates
} triangle_t;
typedef struct
{
short s;
short t;
} texCoord_t;
/** Class responsible for loading&parsing Quake's II ".md2" 3D files */
class MD2Loader
{
public:
MD2Loader();
~MD2Loader();
MeshFrame *load(u32 &o_framesCount, char *t_subpath, char *t_nameWithoutExtension, float t_scale, u8 t_invertT);
private:
};
#endif
-35
View File
@@ -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_OBJ_LOADER_
#define _TYRA_OBJ_LOADER_
#include "../models/mesh_frame.hpp"
#include <stdio.h>
/** Class responsible for loading&parsing .obj 3D files */
class ObjLoader
{
public:
ObjLoader();
~ObjLoader();
/** 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:
void allocateObjMemory(FILE *t_file, MeshFrame *t_result);
};
#endif
-29
View File
@@ -1,29 +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_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
-30
View File
@@ -1,30 +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_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
@@ -1,25 +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_AUDIO_LISTENER_
#define _TYRA_AUDIO_LISTENER_
class AudioListener
{
public:
virtual ~AudioListener(){};
virtual void onAudioTick() = 0;
virtual void onAudioFinish() = 0;
private:
};
#endif
@@ -1,94 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# 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
-23
View File
@@ -1,23 +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_LIGHT_BULB_
#define _TYRA_LIGHT_BULB_
#include "math/vector3.hpp"
#include <tamtypes.h>
struct LightBulb
{
Vector3 position;
u8 intensity;
};
#endif
-186
View File
@@ -1,186 +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_MATRIX_
#define _TYRA_MATRIX_
#include "vector3.hpp"
#include "../screen_settings.hpp"
#include <string.h>
/** 4x4 Matrix class. */
class Matrix
{
public:
float data[16] __attribute__((aligned(64)));
// ----
// Constructors/Destructors
// ----
/** Create empty matrix. */
Matrix();
/**
* Create identity/empty matrix.
* @param t_do_identity Identity matrix if true, random matrix values otherwise
*/
Matrix(const u8 &t_do_identity)
{
if (t_do_identity)
identity();
}
/** Init matrix with given values. */
Matrix(const float &m11, const float &m12, const float &m13, const float &m14,
const float &m21, const float &m22, const float &m23, const float &m24,
const float &m31, const float &m32, const float &m33, const float &m34,
const float &m41, const float &m42, const float &m43, const float &m44);
/** Init matrix with other matrix values. */
Matrix(const Matrix &v) { memcpy(data, v.data, 16 * sizeof(float)); }
// ----
// Operators
// ----
Vector3 operator*(const Vector3 &v) const;
Matrix operator*(const Matrix &v) const
{
Matrix result;
cross(result.data, this->data, v.data);
return result;
}
inline void operator*=(const Matrix &v) { cross(this->data, this->data, v.data); }
float &operator[](const u8 &t_index) { return data[t_index]; }
// ----
// Functions
// ----
/**
* 1 0 0 0
* 0 1 0 0
* 0 0 1 0
* 0 0 0 1
*/
void identity();
/**
* 1 0 0 0
* 0 1 0 0
* 0 0 1 0
* 0 0 0 1
*/
inline void unit() { identity(); };
/** 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
-33
View File
@@ -1,33 +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_PLANE_
#define _TYRA_PLANE_
#include "vector3.hpp"
/** https://en.wikipedia.org/wiki/Plane_(geometry) */
class Plane
{
public:
Vector3 normal;
float distance;
Plane();
Plane(Vector3 &a, Vector3 &b, Vector3 &c);
~Plane();
void update(Vector3 &a, Vector3 &b, Vector3 &c);
inline float distanceTo(Vector3 &t_vec) { return this->distance + this->normal.innerProduct(t_vec); }
const void print() const;
};
#endif
-40
View File
@@ -1,40 +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_POINT_
#define _TYRA_POINT_
/** https://en.wikipedia.org/wiki/Point_(geometry) */
class Point
{
public:
union
{
struct
{
float x;
float y;
};
float xy[2] __attribute__((__aligned__(16)));
};
Point(const float &t_x, const float &t_y);
Point(const Point &v);
Point();
~Point();
void set(const float &t_x, const float &t_y);
void rotate(const float &t_angle, const float &t_x, const float &t_y);
void set(const Point &v);
const void print() const;
};
#endif
-123
View File
@@ -1,123 +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_VECTOR3_
#define _TYRA_VECTOR3_
#include <tamtypes.h>
#include <stdio.h>
class Math; // Forward definition
/** https://en.wikipedia.org/wiki/Vector_(mathematics_and_physics) */
class Vector3
{
public:
/** This trick will allow use to use vec.x and vex[0] */
union
{
struct
{
float x;
float y;
float z;
};
float xyz[3] __attribute__((__aligned__(16)));
};
// ----
// Constructors/Destructors
// ----
/** Create empty vector. */
Vector3();
/** Create vector with given vector values. */
Vector3(const Vector3 &t_v) { set(t_v); }
/** Create vector with given values. */
Vector3(const float &t_x, const float &t_y, const float &t_z) { set(t_x, t_y, t_z); }
// ----
// Operators
// ----
Vector3 operator+(const Vector3 &v) const;
Vector3 operator-(const Vector3 &v) const;
/** Also called "cross product" */
Vector3 operator*(const Vector3 &v) const;
Vector3 operator*(const float &t) const;
Vector3 operator/(const float &t) const;
Vector3 operator-(void) const { return Vector3(-x, -y, -z); }
void operator+=(const Vector3 &t);
void operator*=(const float &t);
// ----
// 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();
/** Returns distance between two vectors */
float distanceTo(const Vector3 &v) const;
/**
* Checks intersection with given box
* @param t_min Opposite min vertex (ex. near, left, down vertex of bounding box)
* @param t_max Opposite max vertex (ex. far, right, up vertex of bounding box)
*/
u8 collidesBox(const Vector3 &t_min, const Vector3 &t_max) const
{
return ((this->x <= t_max.x && this->x >= t_min.x) && (this->y < t_max.y && this->y >= t_min.y) && (this->z <= t_max.z && this->z >= t_min.z)) ? 1 : 0;
}
/**
* Checks if this vector is on given box (this->y >= box.y)
* @param t_min Opposite min vertex (ex. near, left, down vertex of bounding box)
* @param t_max Opposite max vertex (ex. far, right, up vertex of bounding box)
*/
u8 isOnBox(const Vector3 &t_min, const Vector3 &t_max) const
{
return ((this->x <= t_max.x && this->x >= t_min.x) && (this->y >= t_max.y) && (this->z <= t_max.z && this->z >= t_min.z)) ? 1 : 0;
}
/** Check if given triangle should be backface culled. */
static u8 shouldBeBackfaceCulled(const Vector3 *t_cameraPos, const Vector3 *t_v0, const Vector3 *t_v1, const Vector3 *t_v2);
/**
* Set by linear interpolation between two vertices (animation).
* @param t_v1 Before vertex
* @param t_v2 After vertex
* @param t_interp State of interpolation
* @param t_scale Scale
*/
void setByLerp(const Vector3 &t_v1, const Vector3 &t_v2, const float &t_interp, const float &t_scale);
const void print() const
{
printf("Vector3(%f, %f, %f)\n", x, y, z);
}
};
#endif
-215
View File
@@ -1,215 +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_MESH_
#define _TYRA_MESH_
#include "math/vector3.hpp"
#include "math/plane.hpp"
#include "./texture.hpp"
#include "./mesh_frame.hpp"
#include <tamtypes.h>
#include <draw_buffers.h>
#include <draw_sampling.h>
#include "./anim_state.hpp"
/**
* Class which have contain 3D object data.
* External data can be loaded via loadXXX() methods.
*/
class Mesh
{
public:
Mesh();
~Mesh();
Vector3 position, rotation;
float scale;
u8 shouldBeLighted;
/**
* When true, invisible triangles of mesh materials are not drawn.
*/
u8 shouldBeBackfaceCulled;
/**
* When true, mesh materials are not drawn when they are outside of view frustum.
*/
u8 shouldBeFrustumCulled;
clutbuffer_t clut;
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);
/**
* 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:
AnimState animState;
MeshFrame *frames;
u32 id, framesCount;
u8 _isMother, _areFramesAllocated;
Vector3 calc3Vectors[3];
void setDefaultLODAndClut();
};
#endif
-182
View File
@@ -1,182 +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_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
-176
View File
@@ -1,176 +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_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
-42
View File
@@ -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_RENDER_DATA_
#define _TYRA_RENDER_DATA_
#include "light_bulb.hpp"
#include <draw_primitives.h>
#include "math/matrix.hpp"
#include "math/plane.hpp"
struct RenderData
{
LightBulb *bulbs;
u16 bulbsCount;
/**
* Camera matrix (glLookAt)
* OpenGL name: View
* Sony name: World view
*/
Matrix *view;
/**
* Projection matrix (glPerspective)
* OpenGL name: Projection
* Sony name: View screen
*/
Matrix *projection;
Vector3 *cameraPosition;
Plane *frustumPlanes;
prim_t *prim;
};
#endif
@@ -1,27 +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_SCREEN_SETTINGS_
#define _TYRA_SCREEN_SETTINGS_
struct ScreenSettings
{
float fov;
float width;
float height;
float aspectRatio;
float nearPlaneDist;
float farPlaneDist;
float projectionScale;
};
#endif
-80
View File
@@ -1,80 +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_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
-186
View File
@@ -1,186 +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_TEXTURE_
#define _TYRA_TEXTURE_
#include <tamtypes.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>
enum TextureType
{
TEX_TYPE_RGB = GS_PSM_24, // BMP
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;
char *name;
TextureType _type;
std::vector<TextureLink> texLinks;
u32 id;
u16 width, height;
u8 _isNameSet, _isSizeSet;
unsigned char *data;
};
#endif
@@ -1,25 +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_TEXTURE_USAGE_
#define _TYRA_TEXTURE_USAGE_
#include <tamtypes.h>
struct TextureLink
{
/**
* For 3D: Mesh material id.
* For 2D: Sprite id.
*/
u32 id;
};
#endif
@@ -1,22 +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_TEXTURE_WRAP_SETTINGS_
#define _TYRA_TEXTURE_WRAP_SETTINGS_
enum WrapSettings
{
Repeat = 0,
Clamp = 1,
RegionClamp = 2,
RegionRepeat = 3
};
#endif
-157
View File
@@ -1,157 +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_AUDIO_
#define _TYRA_AUDIO_
#include "../models/audio_listener.hpp"
#include "./file_service.hpp"
#include <tamtypes.h>
#include <stdio.h>
#include <audsrv.h>
#include <kernel.h>
#include <vector>
struct AudioListenerRef
{
AudioListener *listener;
u32 id;
};
/**
* Class responsible for audio playing.
* There are two main features:
* - WAV song (background music)
* - ADPCM samples
*/
class Audio
{
public:
/** Constructor is called by the engine. */
Audio();
~Audio();
// Song
/**
* Load 24bit 22050Hz Stereo WAV.
* Can be used multiple times for song switching.
* @param t_path Example: "song.wav" or "folder/song.wav"
*/
void loadSong(char *t_path);
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:
u8 songLoaded, volume, realVolume, songPlaying, songInLoop, songFinished;
u8 hack; // TODO
std::vector<AudioListenerRef *> songListeners;
FILE *wav;
audsrv_fmt_t format;
FileService *fileService;
char wavChunk[2 * 1024] __attribute__((aligned(16)));
s32 chunkReadStatus;
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();
void initSema();
void loadModules();
void initAUDSRV();
void threadLoop();
static void mainThread();
};
#endif
@@ -1,65 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#ifndef _TYRA_CAMERA_BASE_
#define _TYRA_CAMERA_BASE_
#include "../models/math/plane.hpp"
#include "../models/math/matrix.hpp"
#include "../models/math/vector3.hpp"
#include "../models/screen_settings.hpp"
/** Class responsible for frustum culling */
class CameraBase
{
public:
CameraBase(ScreenSettings *t_screen, Vector3 *t_position);
virtual ~CameraBase(){};
/**
* Frustum planes.
* Set by lookAt() method.
*/
Plane planes[6];
/**
* View matrix
* Set by lookAt() method.
*/
Matrix view;
protected:
/** Pointer to screen settings */
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:
Vector3 *p_position;
float farPlaneDist, nearPlaneDist, nearHeight, nearWidth, farHeight, farWidth;
Vector3 ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr;
Vector3 up; // always 0.0F, 1.0F, 0.0F
};
#endif
-115
View File
@@ -1,115 +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_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
-62
View File
@@ -1,62 +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_GIF_SENDER_
#define _TYRA_GIF_SENDER_
#include <tamtypes.h>
#include <draw_buffers.h>
#include <draw_types.h>
#include <draw_primitives.h>
#include <math3d.h>
#include <packet2.h>
#include "./light.hpp"
#include "../models/mesh.hpp"
#include "../models/math/matrix.hpp"
#include "../models/screen_settings.hpp"
#include "../models/light_bulb.hpp"
#include "../models/render_data.hpp"
#include "../models/texture.hpp"
/** Class responsible for sending data packets via GIF (PATH3) */
class GifSender
{
public:
GifSender(u32 t_packetSize, ScreenSettings *t_screen, Light *t_light);
~GifSender();
void initPacket(u8 context);
void addObject(RenderData *t_renderData, Mesh &t_mesh, u32 vertexCount, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer, color_t *t_color);
void addClear(zbuffer_t *t_zBuffer, color_t *t_rgb);
void sendPacket();
void sendClear(zbuffer_t *t_zBuffer, color_t *t_rgb);
static void sendTexture(Texture &texture, texbuffer_t *t_texBuffer);
private:
Light *light;
xyz_t *xyz;
color_t *rgbaq;
texel_t *st;
u8 isAnyObjectAdded;
ScreenSettings *screen;
packet2_t *packets[2];
packet2_t *currentPacket;
u8 packetsCount;
int packetSize;
float halfScreenW, halfScreenH;
MATRIX localWorld, localScreen, localLight;
void calc3DObject(Matrix t_perspective, Mesh &t_mesh, u32 vertexCount, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, RenderData *t_renderData, LightBulb *t_bulbs, u16 t_bulbsCount, color_t *t_color);
void convertCalcs(u32 t_vertCount, VECTOR *t_vertices, VECTOR *t_colors, VECTOR *t_sts, color_t &t_color);
void addCurrentCalcs(u32 &t_vertexCount);
};
#endif
-36
View File
@@ -1,36 +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_LIGHT_
#define _TYRA_LIGHT_
#include <math3d.h>
#include <tamtypes.h>
#include "../models/math/vector3.hpp"
#include "../models/light_bulb.hpp"
class Light
{
public:
Light();
~Light();
u16 getLightsCount(u32 t_bulbsCount);
/** Values from 0.0000F to 1.0000F */
void setAmbientLight(const Vector3 &t_rgb);
void calculateLight(VECTOR *t_lightDirections, VECTOR *t_lightColors, int *t_lightTypes, LightBulb *t_bulbs, u32 t_lightsCount, Vector3 t_objPosition);
private:
Vector3 ambientLight;
};
#endif
-43
View File
@@ -1,43 +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_PAD_
#define _TYRA_PAD_
#include <tamtypes.h>
#include <libpad.h>
/** Class responsible for player pad */
class Pad
{
public:
u8 isCrossClicked, isSquareClicked, isTriangleClicked, isCircleClicked;
u8 isDpadUpPressed, isDpadDownPressed, isDpadLeftPressed, isDpadRightPressed;
u8 lJoyH, lJoyV, rJoyH, rJoyV;
Pad();
~Pad();
void update();
private:
char padBuf[256] __attribute__((aligned(64)));
char actAlign[6];
int actuators, ret, port, slot;
padButtonStatus buttons;
u32 padData, oldPad, newPad;
void reset();
void loadModules();
int waitPadReady();
int initPad();
};
#endif
-171
View File
@@ -1,171 +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_RENDERER_
#define _TYRA_RENDERER_
#include <draw_buffers.h>
#include <draw_primitives.h>
#include <gs_privileged.h>
#include <draw.h>
#include <packet2.h>
#include "gif_sender.hpp"
#include "vif_sender.hpp"
#include "light.hpp"
#include "../models/math/plane.hpp"
#include "../models/sprite.hpp"
#include "../models/screen_settings.hpp"
#include "../models/render_data.hpp"
#include "./texture_repository.hpp"
/** Class responsible for intializing draw env, textures and buffers */
class Renderer
{
public:
Renderer(u32 t_packetSize, ScreenSettings *t_screen);
~Renderer();
framebuffer_t frameBuffers[2];
u8 context; // TODO
zbuffer_t zBuffer;
prim_t prim;
void enableVSync() { isVSyncEnabled = true; }
void disableVSync() { isVSyncEnabled = false; }
/** 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);
/**
* 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);
/**
* 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 setWorldColor(const color_t &t_rgb);
void endFrame(float fps);
void setAmbientLight(const Vector3 &t_rgb) { light.setAmbientLight(t_rgb); }
TextureRepository *getTextureRepository()
{
return &textureRepo;
};
private:
// We have some GCC bug here. Just try to reorder declarations. For example move worldColor up - game will crash.
void changeTexture(Texture *t_tex);
u32 lastTextureId;
texbuffer_t textureBuffer;
u8 isTextureVRAMAllocated, isVSyncEnabled;
void allocateTextureBuffer(Texture *t_texture);
void deallocateTextureBuffer();
void flipBuffers();
void beginFrameIfNeeded();
u8 isFrameEmpty;
Matrix perspective, camRotation;
Light light;
RenderData renderData;
TextureRepository textureRepo;
ScreenSettings *screen;
GifSender *gifSender;
VifSender *vifSender;
packet2_t *flipPacket;
color_t worldColor;
void allocateBuffers(int t_screenW, int t_screenH);
void initDrawingEnv();
void setPrim();
};
#endif
@@ -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>
*/
#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
-33
View File
@@ -1,33 +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_TIMER_
#define _TYRA_TIMER_
#include <tamtypes.h>
#include <timer.h>
/** Class responsible for fps counting */
class Timer
{
public:
Timer();
~Timer();
u32 getTimeDelta();
inline void prime() { lastTime = *T3_COUNT; }
float getFPS();
private:
u32 lastTime, time, change;
};
#endif
-63
View File
@@ -1,63 +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_VIF_SENDER_
#define _TYRA_VIF_SENDER_
#include <tamtypes.h>
#include <packet2_utils.h>
#include "../models/render_data.hpp"
#include "./light.hpp"
#include "../models/light_bulb.hpp"
#include "../models/mesh.hpp"
#include "../models/math/matrix.hpp"
#include "../models/math/vector3.hpp"
/** Class responsible for sending 3D objects via VIF (PATH 1) */
class VifSender
{
public:
VifSender(Light *t_light);
~VifSender();
// TODO refactor
void drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 vertCount2, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer, color_t *t_color, u8 t_rgbaOnly);
void calcMatrix(const RenderData &t_renderData, const Vector3 &t_position, const Vector3 &t_rotation);
void drawTheSameWithOtherMatrices(const RenderData &t_renderData, Mesh **t_meshes, const u32 &t_skip, const u32 &t_count);
void enableWait() { isDrawWaitEnabled = true; }
void disableWait() { isDrawWaitEnabled = false; }
private:
u32 lastVertCount; // needed for drawTheSameWithOtherMatrices()
u8 isLastRGBAOnly; // needed for drawTheSameWithOtherMatrices()
u8 isDrawWaitEnabled;
Light *light;
void uploadMicroProgram();
void 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;
u32 vertCount;
};
#endif
-40
View File
@@ -1,40 +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_DEBUG_
#define _TYRA_DEBUG_
#ifdef NDEBUG
#define consoleLog(message) ((void)0)
#define assertMsg(condition, message) ((void)0)
#else // IF Debug
#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
#endif // _TYRA_DEBUG_
-49
View File
@@ -1,49 +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_MATH_
#define _TYRA_MATH_
#include <tamtypes.h>
#include <math3d.h>
#include "../models/math/vector3.hpp"
#include <fastmath.h>
class Vector3; // Forward definition
void manyVec3ToNative(VECTOR *t_result, Vector3 *t_vec, int t_amount, float t_fourthVal);
void vec3ToNative(VECTOR t_result, const Vector3 &t_vec, float t_fourthVal);
class Math
{
public:
constexpr static float HALF_ANG2RAD = 3.14159265358979323846F / 360.0F;
constexpr static float ANG2RAD = 3.14159265358979323846F / 180.0F;
constexpr static float PI = 3.1415926535897932384626433832795F;
constexpr static float HALF_PI = 1.5707963267948966192313216916398F;
static float cos(float x);
static float asin(float x);
static float mod(float x, float y);
static inline float sin(float x) { return cos(x - HALF_PI); };
static inline float tan(float x) { return sin(x) / cos(x); }
static float invSqrt(float x);
static inline u32 max(u32 a, u32 b) { return (a > b) ? a : b; }
static inline s32 max(s32 a, s32 b) { return (a > b) ? a : b; }
static inline float max(float a, float b) { return (a > b) ? a : b; }
static inline u32 min(u32 a, u32 b) { return (a < b) ? a : b; }
static inline s32 min(s32 a, s32 b) { return (a < b) ? a : b; }
static inline float min(float a, float b) { return (a < b) ? a : b; }
private:
Math();
};
#endif
-28
View File
@@ -1,28 +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_STRING_
#define _TYRA_STRING_
#include <tamtypes.h>
class String
{
public:
static char *createU32ToString(const u32 a);
static char *createWithLeadingZeros(const char *a);
static char *createCopy(const char *source);
static u32 getLength(const char *a);
static char *createConcatenated(const char *a, const char *b);
static char *createWithoutExtension(const char *source);
};
#endif
-78
View File
@@ -1,78 +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/loaders/bmp_loader.hpp"
#include "../include/utils/debug.hpp"
#include "../include/utils/string.hpp"
#include <cstdlib>
// ----
// Constructors/Destructors
// ----
BmpLoader::BmpLoader() {}
BmpLoader::~BmpLoader() {}
// ----
// Methods
// ----
/**
* @param t_name Without extension. Example "skyfall2"
* @param t_extension With dot and extension. Example ".BMP"
*/
void BmpLoader::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 load .bmp file!");
unsigned char header[54];
fread(header, sizeof(unsigned char), 54, file);
u32 width = (u32)header[18];
u32 height = (u32)header[22];
u32 bits = (u32)header[28];
u32 dataOffset = (u32)header[10];
assertMsg(bits == 24, "Invalid bits per pixel in .bmp file - expected 24!");
o_texture.setSize(width, height, TEX_TYPE_RGB);
printf("BMPLoader - width: %d | height: %d | bits: %d\n", width, height, bits);
u64 rowPadded = (width * 3 + 3) & (~3);
unsigned char row[rowPadded];
//Offset file stream to raster data
fseek(file, dataOffset, SEEK_SET);
u32 x = 0;
for (u32 i = 0; i < height; i++)
{
fread(&row, sizeof(unsigned char), rowPadded, file);
for (u32 j = 0; j < width * 3; j += 3)
{
// Convert (B, G, R) to (R, G, B)
o_texture.setData(x, row[j + 2]);
o_texture.setData(x + 1, row[j + 1]);
o_texture.setData(x + 2, row[j]);
x += 3;
}
}
delete[] path;
fclose(file);
}
-413
View File
@@ -1,413 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
/*
* NOTICE: Based on
* https://github.com/mrqo/rw_parse/blob/master/rw_utils/rw_utils.cpp
* rw_utils.cpp Written by Marek Iwaniuk (c).
* Dff structure documentation http://www.chronetal.co.uk/gta/index.php?page=dff
* Created on 02/04/2017 (MM/DD/YYYY)
*/
#include "../include/loaders/dff_loader.hpp"
#include "../include/utils/debug.hpp"
#include "../include/utils/math.hpp"
#include "../include/utils/string.hpp"
#include <cstring>
// ----
// Constructors/Destructors
// ----
DffLoader::DffLoader() {}
DffLoader::~DffLoader() {}
// ----
// Methods
// ----
void DffLoader::load(MeshFrame *o_result, char *t_filename, float t_scale, u8 t_invertT)
{
consoleLog("Loading dff file");
char *path = String::createConcatenated("host:", t_filename);
FILE *file = fopen(path, "rb");
assertMsg(file != NULL, "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;
consoleLog("Dff file loaded!");
}
// void DffLoader::im_not_used_anywhere(MeshFrame *o_result, char *t_filename, float t_scale, u8 t_invertT)
// {
// PRINT_LOG("Loading dff file");
// char *path = String::createConcatenated("host:", t_filename);
// FILE *file = fopen(path, "rb");
// if (file == NULL)
// PRINT_ERR("Failed to load .dff file!");
// fseek(file, 0L, SEEK_END);
// long fileSize = ftell(file);
// u8 data[fileSize];
// rewind(file);
// fread(&data, sizeof(u8), fileSize, file);
// fclose(file);
// serialize(o_result, t_invertT, data, t_scale);
// o_result->calculateBoundingBoxes();
// delete[] path;
// PRINT_LOG("Dff file loaded!");
// }
void DffLoader::serialize(MeshFrame *o_result, u8 t_invertT, u8 *t_data, float t_scale)
{
u32 ptrPos = 0;
// readSectionHeader(t_clump, t_data, ptrPos);
// readSectionHeader(t_clump.data, t_data, ptrPos);
// readClumpData(t_clump.data, t_data, ptrPos);
for (u8 i = 0; i < 3 * 3; i++)
ptrPos += sizeof(u32);
// 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];
// 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;
// readSectionHeader(t_clump.geometryList, t_data, ptrPos);
// readSectionHeader(t_clump.geometryList.data, t_data, ptrPos);
for (u8 i = 0; i < 2 * 3; i++)
ptrPos += sizeof(u32);
// readGeometryListData(t_clump.geometryList.data, t_data, ptrPos);
ptrPos += sizeof(u32);
// readSectionHeader(geometry, t_data, ptrPos);
// readSectionHeader(geometry.data, t_data, ptrPos);
for (size_t i = 0; i < 2 * 3; i++)
ptrPos += sizeof(u32);
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++)
{
// readSectionHeader(geometry.materialList.materials[j], t_data, ptrPos);
for (size_t i = 0; i < 3; i++)
ptrPos += sizeof(u32);
// RwMaterialData materialData = RwMaterialData();
// readSectionHeader(materialData, t_data, ptrPos);
// readMaterialData(materialData, t_data, ptrPos);
RwSectionHeader header1 = RwSectionHeader();
readSectionHeader(header1, t_data, ptrPos);
ptrPos += header1.sectionSize;
// for (u32 k = 0; k < textureCount; k++)
// {
// 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
// readSectionHeader(geometry.materialList.materials[j].textures[k].extension, t_data, ptrPos);
RwSectionHeader header3 = RwSectionHeader();
readSectionHeader(header3, t_data, ptrPos);
ptrPos += header3.sectionSize;
// }
// Probably always void extension
// readSectionHeader(geometry.materialList.materials[j].extension, t_data, ptrPos);
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)
{
t_sh.sectionType = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
t_sh.sectionSize = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
t_sh.versionNumber = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
}
// ---
void DffLoader::readFrameListData(RwFrameListData &t_frd, u8 *t_buffer, u32 &t_ptrPos)
{
// t_frd.frameCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
// printf("Frame count:%d\n", t_frd.frameCount);
// t_frd.frameInformation = new RwFrameListChunk[t_frd.frameCount];
// for (u32 i = 0; i < t_frd.frameCount; i++)
// {
// t_frd.frameInformation[i].rotationalMatrix = new float[t_frd.ROT_MAT_DIM];
// 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].coordinatesOffsetX = 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]
// .parentFrame = 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)
{
// t_cd.objectCount = readDwordFromArrayLE(t_buffer, t_ptrPos);
// t_cd.unk1 = 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)
{
// t_gld.geometryCount = readDwordFromArrayLE(t_buffer, t_ptrPos);
}
void DffLoader::readGeometryExtension(MeshFrame *o_frame, char **materialNames, u8 *t_buffer, u32 &t_ptrPos)
{
for (u8 i = 0; i < 3; i++)
t_ptrPos += sizeof(u32);
RwMaterialSplitHeader header = RwMaterialSplitHeader();
header.triangleStrip = readDwordFromArrayLE(t_buffer, t_ptrPos);
header.splitCount = readDwordFromArrayLE(t_buffer, t_ptrPos);
header.faceCount = readDwordFromArrayLE(t_buffer, t_ptrPos);
o_frame->allocateMaterials(header.splitCount);
for (u32 i = 0; i < header.splitCount; i++)
{
u32 facesCount = readDwordFromArrayLE(t_buffer, t_ptrPos);
u32 materialIndex = readDwordFromArrayLE(t_buffer, t_ptrPos);
o_frame->getMaterial(i).setSTsPresent(true);
o_frame->getMaterial(i).setNormalsPresent(true);
o_frame->getMaterial(i).allocateFaces(facesCount);
o_frame->getMaterial(i).setName(materialNames[materialIndex]);
for (u32 j = 0; j < facesCount; j++)
{
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(MeshFrame *o_frame, u8 t_invertT, u8 *t_buffer, u32 &t_ptrPos, float t_scale)
{
Vector3 tempVec = Vector3();
Point tempPoint = Point();
RwGeometryDataHeader header;
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)
{ // version equals 4099 according to old documentation, disabled as for now
readDwordFromArrayLE(t_buffer, t_ptrPos); // ambient
readDwordFromArrayLE(t_buffer, t_ptrPos); // diffuse
readDwordFromArrayLE(t_buffer, t_ptrPos); // specular
}
if (header.flags & rwOBJECT_VERTEX_PRELIT)
for (u32 i = 0; i < header.vertexCount; i++)
{
readByteFromArrayLE(t_buffer, t_ptrPos); // r
readByteFromArrayLE(t_buffer, t_ptrPos); // g
readByteFromArrayLE(t_buffer, t_ptrPos); // b
readByteFromArrayLE(t_buffer, t_ptrPos); // a
}
if (header.flags & rwOBJECT_VERTEX_TEXTURED)
{
o_frame->allocateSTs(header.vertexCount);
for (u32 i = 0; i < header.vertexCount; i++)
{
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);
}
}
for (u32 i = 0; i < header.triangleCount; i++)
{
readWordFromArrayLE(t_buffer, t_ptrPos); // vert2
readWordFromArrayLE(t_buffer, t_ptrPos); // vert1
readWordFromArrayLE(t_buffer, t_ptrPos); // flags
readWordFromArrayLE(t_buffer, t_ptrPos); // vert3
}
for (size_t i = 0; i < 6; 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++)
{
float x = readFloatFromArrayLE(t_buffer, t_ptrPos) * t_scale;
float y = readFloatFromArrayLE(t_buffer, t_ptrPos) * t_scale;
float z = readFloatFromArrayLE(t_buffer, t_ptrPos) * t_scale;
tempVec.set(x, y, z);
o_frame->setVertex(i, tempVec);
}
o_frame->allocateNormals(header.vertexCount);
for (u32 i = 0; i < header.vertexCount; i++)
{
float x = readFloatFromArrayLE(t_buffer, t_ptrPos);
float y = readFloatFromArrayLE(t_buffer, t_ptrPos);
float z = readFloatFromArrayLE(t_buffer, t_ptrPos);
tempVec.set(x, y, z);
o_frame->setNormal(i, tempVec);
}
}
void DffLoader::readMaterialListData(RwMaterialListData &t_mld, u8 *t_buffer, u32 &t_ptrPos)
{
t_mld.materialCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
// t_mld.arrayOfUnks = new u32[t_mld.materialCount];
for (u32 i = 0; i < t_mld.materialCount; i++)
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)
{
t_md.unk1 = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
t_md.R = readByteFromArrayLE(t_buffer, t_ptrPos);
t_md.G = readByteFromArrayLE(t_buffer, t_ptrPos);
t_md.B = readByteFromArrayLE(t_buffer, t_ptrPos);
t_md.A = readByteFromArrayLE(t_buffer, t_ptrPos);
t_md.unk2 = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
t_md.textureCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
t_md.unkPosX = readFloatFromArrayLE(t_buffer, t_ptrPos);
t_md.unkPosY = readFloatFromArrayLE(t_buffer, t_ptrPos);
t_md.unkPosZ = readFloatFromArrayLE(t_buffer, t_ptrPos);
}
void DffLoader::readTextureData(RwTextureData &t_td, u8 *t_buffer, u32 &t_ptrPos)
{
t_td.textureFilterModeFlags = readWordFromArrayLE(t_buffer, t_ptrPos);
t_td.unk = readWordFromArrayLE(t_buffer, t_ptrPos);
}
void DffLoader::readStringData(RwString &t_s, u8 *t_buffer, u32 &t_ptrPos)
{
t_s.text = readString(t_buffer, t_ptrPos, t_s.sectionSize);
}
// ---
u8 DffLoader::readByteFromArrayLE(u8 *t_buffer, u32 &t_ptrPos)
{
return t_buffer[t_ptrPos++];
}
u16 DffLoader::readWordFromArrayLE(u8 *t_buffer, u32 &t_ptrPos)
{
u16 res = (t_buffer[t_ptrPos + 1] << 8) + (t_buffer[t_ptrPos]);
t_ptrPos += sizeof(u16);
return res;
}
u32 DffLoader::readDwordFromArrayLE(u8 *t_buffer, u32 &t_ptrPos)
{
u32 res = (t_buffer[t_ptrPos + 3] << 24) + (t_buffer[t_ptrPos + 2] << 16) + (t_buffer[t_ptrPos + 1] << 8) + (t_buffer[t_ptrPos]);
t_ptrPos += sizeof(u32);
return res;
}
float DffLoader::readFloatFromArrayLE(u8 *t_buffer, u32 &t_ptrPos)
{
float res;
memcpy(&res, t_buffer + t_ptrPos, sizeof(float));
t_ptrPos += sizeof(float);
return res;
}
char *DffLoader::readString(u8 *t_buffer, u32 &t_ptrPos, u32 t_dataSize)
{
u32 strLength = String::getLength((char *)&t_buffer[t_ptrPos]);
char *result = new char[strLength + 1];
for (u32 i = 0; i < strLength; i++)
result[i] = (char)t_buffer[t_ptrPos + i];
result[strLength] = '\0';
t_ptrPos += t_dataSize;
return result;
}
-147
View File
@@ -1,147 +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/loaders/md2_loader.hpp"
#include "../include/utils/string.hpp"
#include "../include/utils/debug.hpp"
#include "../include/loaders/anorms.hpp"
#include "../include/models/math/vector3.hpp"
#include "../include/models/math/point.hpp"
#include <string.h>
// ----
// Constructors/Destructors
// ----
MD2Loader::MD2Loader() {}
MD2Loader::~MD2Loader() {}
// ----
// Methods
// ----
int MEM_fread(char *buf, size_t size, size_t n, const FILE *f)
{
memcpy(buf, f, size * n);
f += size * n;
return n;
}
/**
* 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;
FILE *file = fopen(finalPath, "rb");
assertMsg(file != NULL, "Failed to load .md2 file!");
fread((char *)&header, sizeof(md2_t), 1, file);
assertMsg((header.ident == MD2_IDENT) && (header.version == MD2_VERSION), "This MD2 file was not in correct format!");
u32 framesCount = header.num_frames;
u32 vertexCount = header.num_xyz;
u32 stsCount = header.num_st;
u32 trianglesCount = header.num_tris;
char framesBuffer[framesCount * header.framesize];
fseek(file, header.ofs_frames, SEEK_SET);
fread(&framesBuffer, framesCount * header.framesize, 1, file);
char stsBuffer[stsCount * sizeof(texCoord_t)];
fseek(file, header.ofs_st, SEEK_SET);
fread(&stsBuffer, stsCount * sizeof(texCoord_t), 1, file);
char trianglesBuffer[trianglesCount * sizeof(triangle_t)];
fseek(file, header.ofs_tris, SEEK_SET);
fread(&trianglesBuffer, trianglesCount * sizeof(triangle_t), 1, file);
fclose(file);
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;
}
-244
View File
@@ -1,244 +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/loaders/obj_loader.hpp"
#include "../include/utils/debug.hpp"
#include "../include/utils/string.hpp"
#include <string.h>
// ----
// Constructors/Destructors
// ----
ObjLoader::ObjLoader() {}
ObjLoader::~ObjLoader() {}
// ----
// Methods
// ----
void ObjLoader::load(MeshFrame *o_result, char *t_filename, float t_scale, u8 t_invertT)
{
char *path = String::createConcatenated("host:", t_filename);
FILE *file = fopen(path, "rb");
assertMsg(file != NULL, "Failed to load .obj file!");
allocateObjMemory(file, o_result);
fseek(file, 0, SEEK_SET);
u32 verticesI = 0, cordsI = 0, normalsI = 0, faceI = 0, vertexIndex[3], coordIndex[3], normalIndex[3];
s16 materialsI = -1;
Vector3 vector = Vector3();
Point point = Point();
while (1)
{
char lineHeader[128]; // read the first word of the line
int res = fscanf(file, "%s", lineHeader);
if (res != EOF)
{
if (strcmp(lineHeader, "v") == 0)
{
fscanf(file, "%f %f %f\n", &vector.x, &vector.y, &vector.z);
o_result->setVertex(verticesI++, vector * t_scale);
}
else if (strcmp(lineHeader, "vt") == 0)
{
fscanf(file, "%f %f\n", &point.x, &point.y);
if (t_invertT)
point.y = 1.0F - point.y;
o_result->setST(cordsI++, point);
}
else if (strcmp(lineHeader, "vn") == 0)
{
fscanf(file, "%f %f %f\n", &vector.x, &vector.y, &vector.z);
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)
{
int *x = &res; // random assignment, to disable compilation warning
fpos_t start;
fgetpos(file, &start);
int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", x, x, x, x, x, x, x, x, x);
fsetpos(file, &start);
int newerMatches = 0;
switch (matches)
{
/** Vs, VTs and VNs all set */
case 9:
{
fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n",
&vertexIndex[0], &coordIndex[0], &normalIndex[0],
&vertexIndex[1], &coordIndex[1], &normalIndex[1],
&vertexIndex[2], &coordIndex[2], &normalIndex[2]);
}
break;
/** Loaded only two digits (V, VT) succesfuly. Not setting VN. */
case 3:
{
fscanf(file, "%d/%d/ %d/%d/ %d/%d/\n",
&vertexIndex[0], &coordIndex[0],
&vertexIndex[1], &coordIndex[1],
&vertexIndex[2], &coordIndex[2]);
}
break;
/** Only V set. Checking for existance of VT or VN. */
case 1:
{
/** Check for existance of V/// configuration.. */
newerMatches = fscanf(file, "%d// %d// %d//\n", x, x, x);
fsetpos(file, &start);
if (newerMatches == 3)
{
/** Configuration confirmed. */
fscanf(file, "%d// %d// %d//\n", &vertexIndex[0], &vertexIndex[1], &vertexIndex[2]);
}
else
{
/** Failed, checking configuration V//VN */
newerMatches = fscanf(file, "%d//%d %d//%d %d//%d", x, x, x, x, x, x);
fsetpos(file, &start);
assertMsg(newerMatches == 6, "Unknown .obj face for .obj file!");
/** Configuration confirmed. */
newerMatches = fscanf(file, "%d//%d %d//%d %d//%d",
&vertexIndex[0], &normalIndex[0],
&vertexIndex[1], &normalIndex[1],
&vertexIndex[2], &normalIndex[2]);
}
break;
}
break;
default:
{
assertMsg(true == false, "Unknown faces format in .obj file!");
break;
}
}
if (matches == 9 || matches == 2 || matches == 1)
{
o_result->getMaterial(materialsI).setVertexFace(faceI, vertexIndex[0] - 1);
o_result->getMaterial(materialsI).setVertexFace(faceI + 1, vertexIndex[1] - 1);
o_result->getMaterial(materialsI).setVertexFace(faceI + 2, vertexIndex[2] - 1);
}
if (matches == 9 || matches == 2)
{
o_result->getMaterial(materialsI).setSTFace(faceI, coordIndex[0] - 1);
o_result->getMaterial(materialsI).setSTFace(faceI + 1, coordIndex[1] - 1);
o_result->getMaterial(materialsI).setSTFace(faceI + 2, coordIndex[2] - 1);
o_result->getMaterial(materialsI).setSTsPresent(true);
}
if (matches == 9)
{
o_result->getMaterial(materialsI).setNormalFace(faceI, normalIndex[0] - 1);
o_result->getMaterial(materialsI).setNormalFace(faceI + 1, normalIndex[1] - 1);
o_result->getMaterial(materialsI).setNormalFace(faceI + 2, normalIndex[2] - 1);
o_result->getMaterial(materialsI).setNormalsPresent(true);
faceI += 3;
}
else if (matches == 2)
{
faceI += 2;
}
else if (matches == 1)
{
if (newerMatches == 3)
{
faceI += 1;
}
else if (newerMatches == 6)
{
o_result->getMaterial(materialsI).setNormalFace(faceI, normalIndex[0] - 1);
o_result->getMaterial(materialsI).setNormalFace(faceI + 1, normalIndex[1] - 1);
o_result->getMaterial(materialsI).setNormalFace(faceI + 2, normalIndex[2] - 1);
o_result->getMaterial(materialsI).setNormalsPresent(true);
faceI += 2;
}
}
}
}
else
break;
}
o_result->calculateBoundingBoxes();
fclose(file);
delete[] path;
}
/** Calculate how many vertices(v), coordinates(vt), normals(vn) and faces(f) have .obj file */
void ObjLoader::allocateObjMemory(FILE *t_file, MeshFrame *o_result)
{
u32 vertexCount = 0;
u32 stsCount = 0;
u32 normalsCount = 0;
u32 materialsCount = 0;
while (1)
{
char lineHeader[128];
int res = fscanf(t_file, "%s", lineHeader);
if (res != EOF)
{
if (strcmp(lineHeader, "v") == 0)
vertexCount += 1;
else if (strcmp(lineHeader, "vt") == 0)
stsCount += 1;
else if (strcmp(lineHeader, "vn") == 0)
normalsCount += 1;
else if (strcmp(lineHeader, "usemtl") == 0)
materialsCount += 1;
}
else
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);
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;
}
-126
View File
@@ -1,126 +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/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);
}
-49
View File
@@ -1,49 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# 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()
{
}
-371
View File
@@ -1,371 +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/math/matrix.hpp"
#include "../../include/utils/math.hpp"
#include <stdio.h>
// ----
// Constructors/Destructors
// ----
Matrix::Matrix()
{
for (u8 i = 0; i < 16; i++)
data[i] = 0.0F;
}
Matrix::Matrix(const float &m11, const float &m12, const float &m13, const float &m14,
const float &m21, const float &m22, const float &m23, const float &m24,
const float &m31, const float &m32, const float &m33, const float &m34,
const float &m41, const float &m42, const float &m43, const float &m44)
{
data[0] = m11;
data[1] = m12;
data[2] = m13;
data[3] = m14;
data[4] = m21;
data[5] = m22;
data[6] = m23;
data[7] = m24;
data[8] = m31;
data[9] = m32;
data[10] = m33;
data[11] = m34;
data[12] = m41;
data[13] = m42;
data[14] = m43;
data[15] = m44;
}
// ----
// Operators
// ----
Vector3 Matrix::operator*(const Vector3 &v) const
{
float a[4] = {v.x, v.y, v.z, 1.0F};
float res[4];
asm volatile(
"lqc2 $vf4, 0x00(%1) \n\t"
"lqc2 $vf5, 0x10(%1) \n\t"
"lqc2 $vf6, 0x20(%1) \n\t"
"lqc2 $vf7, 0x30(%1) \n\t"
"lqc2 $vf8, 0x00(%2) \n\t"
"vmulax.xyzw $ACC, $vf4, $vf8 \n\t"
"vmadday.xyzw $ACC, $vf5, $vf8 \n\t"
"vmaddaz.xyzw $ACC, $vf6, $vf8 \n\t"
"vmaddw.xyzw $vf9, $vf7, $vf8 \n\t"
"sqc2 $vf9, 0x00(%0) \n\t"
:
: "r"(res), "r"(this->data), "r"(a));
return Vector3(res[0], res[1], res[2]);
}
// ----
// Functions
// ----
void Matrix::identity()
{
asm volatile(
"vsub.xyzw $vf4, $vf0, $vf0 \n\t"
"vadd.w $vf4, $vf4, $vf0 \n\t"
"vmr32.xyzw $vf5, $vf4 \n\t"
"vmr32.xyzw $vf6, $vf5 \n\t"
"vmr32.xyzw $vf7, $vf6 \n\t"
"sqc2 $vf4, 0x30(%0) \n\t"
"sqc2 $vf5, 0x20(%0) \n\t"
"sqc2 $vf6, 0x10(%0) \n\t"
"sqc2 $vf7, 0x0(%0) \n\t"
:
: "r"(this->data));
}
void Matrix::setPerspective(const ScreenSettings &t_screen)
{
float fovYdiv2 = Math::HALF_ANG2RAD * t_screen.fov;
float cotFOV = 1.0F / (Math::sin(fovYdiv2) / Math::cos(fovYdiv2));
float w = cotFOV * (t_screen.width / t_screen.projectionScale) / t_screen.aspectRatio;
float h = cotFOV * (t_screen.height / t_screen.projectionScale);
this->data[0] = w;
this->data[1] = 0.0F;
this->data[2] = 0.0F;
this->data[3] = 0.0F;
this->data[4] = 0.0F;
this->data[5] = -h;
this->data[6] = 0.0F;
this->data[7] = 0.0F;
this->data[8] = 0.0F;
this->data[9] = 0.0F;
this->data[10] =
(t_screen.farPlaneDist + t_screen.nearPlaneDist) /
(t_screen.farPlaneDist - t_screen.nearPlaneDist);
this->data[11] = -1.0F;
this->data[12] = 0.0F;
this->data[13] = 0.0F;
this->data[14] =
(2.0F * t_screen.farPlaneDist * t_screen.nearPlaneDist) /
(t_screen.farPlaneDist - t_screen.nearPlaneDist);
this->data[15] = 0.0F;
}
void Matrix::lookAt(const Vector3 &t_position, const Vector3 &t_target)
{
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);
// Vector3 camForward, camUp, camRight;
// Vector3 t_up = Vector3(0.0F, 1.0F, 0.0F);
// camForward = t_position - t_target;
// camForward.normalize();
// camRight = t_up * camForward;
// camRight.normalize();
// camUp = camForward * camRight;
// data[0] = camRight.x;
// data[4] = camRight.y;
// data[8] = camRight.z;
// data[12] = -camRight.innerProduct(t_position);
// data[1] = camUp.x;
// data[5] = camUp.y;
// data[9] = camUp.z;
// data[13] = -camUp.innerProduct(t_position);
// data[2] = camForward.x;
// data[6] = camForward.y;
// data[10] = camForward.z;
// data[14] = -camForward.innerProduct(t_position);
// data[3] = 0;
// data[7] = 0;
// data[11] = 0;
// data[15] = 1;
}
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",
data[0], data[1], data[2], data[3],
data[4], data[5], data[6], data[7],
data[8], data[9], data[10], data[11],
data[12], data[13], data[14], data[15]);
}
// ----
// Private
// ----
void Matrix::rotationX(const float &t_radians)
{
float c = Math::cos(t_radians);
float s = Math::sin(t_radians);
this->data[5] = c; // 1,1
this->data[6] = s; // 1,2
this->data[9] = -s; // 2,1
this->data[10] = c; // 2,2
}
void Matrix::rotationY(const float &t_radians)
{
float c = Math::cos(t_radians);
float s = Math::sin(t_radians);
this->data[0] = c; // 0,0
this->data[2] = -s; // 0,3
this->data[8] = s; // 2,0
this->data[10] = c; // 2,2
}
void Matrix::rotationZ(const float &t_radians)
{
float c = Math::cos(t_radians);
float s = Math::sin(t_radians);
this->data[0] = c; // 0,0
this->data[1] = s; // 0,1
this->data[4] = -s; // 1,0
this->data[5] = c; // 1,1
}
void Matrix::rotationByAngle(const float &t_angle, const Vector3 &t_axis)
{
Vector3 localAxis = Vector3(t_axis);
localAxis.normalize();
float x = localAxis.x;
float y = localAxis.y;
float z = localAxis.z;
float c = Math::cos(t_angle);
float s = Math::sin(t_angle);
this->data[0] = x * x * (1 - c) + c;
this->data[1] = y * x * (1 - c) + z * s;
this->data[2] = x * z * (1 - c) - y * s;
this->data[3] = 0.0F;
this->data[4] = x * y * (1 - c) - z * s;
this->data[5] = y * y * (1 - c) + c;
this->data[6] = y * z * (1 - c) + x * s;
this->data[7] = 0.0F;
this->data[8] = x * z * (1 - c) + y * s;
this->data[9] = y * z * (1 - c) - x * s;
this->data[10] = z * z * (1 - c) + c;
this->data[11] = 0.0F;
this->data[12] = 0.0F;
this->data[13] = 0.0F;
this->data[14] = 0.0F;
this->data[15] = 1.0F;
}
void Matrix::translation(const Vector3 &t_val)
{
this->data[12] = t_val.x; // 3,0
this->data[13] = t_val.y; // 3,1
this->data[14] = t_val.z; // 3,2
}
void Matrix::setScale(const Vector3 &t_val)
{
this->data[0] = t_val.x;
this->data[5] = t_val.y;
this->data[10] = t_val.z;
this->data[15] = 1.0F;
}
void Matrix::setCamera(const float t_pos[4], const float t_vz[4], const float t_vy[4])
{
// Matrix $vf4, $vf5, $vf6, $vf7
// t_pos $vf8
// t_vz $vf9
// t_vy $vf10
// vtmp $vf11
asm volatile(
"lqc2 $vf9, 0x00(%2) \n\t"
"lqc2 $vf10, 0x00(%3) \n\t"
// mtmp.unit()
"vsub.w $vf5, $vf0, $vf0 # mtmp[1][PW] = 0.0F \n\t"
// vtmp.outerProduct(vy, vz);
"vopmula.xyz $ACC, $vf10, $vf9 \n\t"
"vopmsub.xyz $vf11, $vf9, $vf10 \n\t"
// mtmp[0] = vtmp.normalize();
"vmul.xyz $vf12, $vf11, $vf11 \n\t"
"vaddy.x $vf12, $vf12, $vf12 \n\t"
"vaddz.x $vf12, $vf12, $vf12 \n\t"
"vrsqrt $Q, $vf0w, $vf12x \n\t"
"vsub.xyzw $vf4, $vf0, $vf0 \n\t"
"vwaitq \n\t"
"vmulq.xyz $vf4, $vf11, $Q \n\t"
// mtmp[2] = vz.normalize();
"vmul.xyz $vf12, $vf9, $vf9 \n\t"
"vaddy.x $vf12, $vf12, $vf12 \n\t"
"vaddz.x $vf12, $vf12, $vf12 \n\t"
"vrsqrt $Q, $vf0w, $vf12x \n\t"
"vsub.xyzw $vf6, $vf0, $vf0 \n\t"
"vwaitq \n\t"
"vmulq.xyz $vf6, $vf9, $Q \n\t"
// mtmp[1].outerProduct(mtmp[2], mtmp[0]);
"vopmula.xyz $ACC, $vf6, $vf4 \n\t"
"vopmsub.xyz $vf5, $vf4, $vf6 \n\t"
// mtmp.transpose(pos);
"lqc2 $vf7, 0x00(%1) \n\t"
// m = mtmp.inverse();
"qmfc2.ni $11, $vf0 \n\t"
"qmfc2.ni $8, $vf4 \n\t"
"qmfc2.ni $9, $vf5 \n\t"
"qmfc2.ni $10, $vf6 \n\t"
"pextlw $12, $9, $8 \n\t"
"pextuw $13, $9, $8 \n\t"
"pextlw $14, $11, $10 \n\t"
"pextuw $15, $11, $10 \n\t"
"pcpyld $8, $14, $12 \n\t"
"pcpyud $9, $12, $14 \n\t"
"pcpyld $10, $15, $13 \n\t"
"qmtc2.ni $8, $vf16 \n\t"
"qmtc2.ni $9, $vf17 \n\t"
"qmtc2.ni $10, $vf18 \n\t"
"vmulax.xyz $ACC, $vf16, $vf7 \n\t"
"vmadday.xyz $ACC, $vf17, $vf7 \n\t"
"vmaddz.xyz $vf5, $vf18, $vf7 \n\t"
"vsub.xyzw $vf5, $vf0, $vf5 \n\t"
"sq $8, 0x00(%0) \n\t"
"sq $9, 0x10(%0) \n\t"
"sq $10, 0x20(%0) \n\t"
"sqc2 $vf5, 0x30(%0) \n\t"
:
: "r"(this->data), "r"(t_pos), "r"(t_vz), "r"(t_vy));
}
void Matrix::cross(float res[16], const float a[16], const float b[16]) const
{
asm volatile(
"lqc2 $vf1, 0x00(%1) \n\t"
"lqc2 $vf2, 0x10(%1) \n\t"
"lqc2 $vf3, 0x20(%1) \n\t"
"lqc2 $vf4, 0x30(%1) \n\t"
"lqc2 $vf5, 0x00(%2) \n\t"
"lqc2 $vf6, 0x10(%2) \n\t"
"lqc2 $vf7, 0x20(%2) \n\t"
"lqc2 $vf8, 0x30(%2) \n\t"
"vmulax.xyzw $ACC, $vf5, $vf1 \n\t"
"vmadday.xyzw $ACC, $vf6, $vf1 \n\t"
"vmaddaz.xyzw $ACC, $vf7, $vf1 \n\t"
"vmaddw.xyzw $vf1, $vf8, $vf1 \n\t"
"vmulax.xyzw $ACC, $vf5, $vf2 \n\t"
"vmadday.xyzw $ACC, $vf6, $vf2 \n\t"
"vmaddaz.xyzw $ACC, $vf7, $vf2 \n\t"
"vmaddw.xyzw $vf2, $vf8, $vf2 \n\t"
"vmulax.xyzw $ACC, $vf5, $vf3 \n\t"
"vmadday.xyzw $ACC, $vf6, $vf3 \n\t"
"vmaddaz.xyzw $ACC, $vf7, $vf3 \n\t"
"vmaddw.xyzw $vf3, $vf8, $vf3 \n\t"
"vmulax.xyzw $ACC, $vf5, $vf4 \n\t"
"vmadday.xyzw $ACC, $vf6, $vf4 \n\t"
"vmaddaz.xyzw $ACC, $vf7, $vf4 \n\t"
"vmaddw.xyzw $vf4, $vf8, $vf4 \n\t"
"sqc2 $vf1, 0x00(%0) \n\t"
"sqc2 $vf2, 0x10(%0) \n\t"
"sqc2 $vf3, 0x20(%0) \n\t"
"sqc2 $vf4, 0x30(%0) \n\t"
:
: "r"(res), "r"(b), "r"(a)
: "memory");
}
-50
View File
@@ -1,50 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "../../include/models/math/plane.hpp"
#include <stdio.h>
// ----
// Constructors/Destructors
// ----
/** Create empty plane */
Plane::Plane() { this->distance = 0; }
/** Create by specyfying 3 points.
* This function assumes that the points
* are given in counter clockwise order
*/
Plane::Plane(Vector3 &a, Vector3 &b, Vector3 &c) { this->update(a, b, c); }
Plane::~Plane() {}
// ----
// Methods
// ----
/** Set plane by specyfying 3 points.
* This function assumes that the points
* are given in counter clockwise order
*/
void Plane::update(Vector3 &a, Vector3 &b, Vector3 &c)
{
Vector3 aux1 = a - b;
Vector3 aux2 = c - b;
this->normal = aux2 * aux1;
this->normal.normalize();
this->distance = -this->normal.innerProduct(b);
}
const void Plane::print() const
{
printf("Plane(Vector3(%f, %f, %f), %f)\n", this->normal.x, this->normal.y, this->normal.z, this->distance);
}
-77
View File
@@ -1,77 +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/math/point.hpp"
#include "../../include/utils/math.hpp"
#include <stdio.h>
// ----
// Constructors/Destructors
// ----
/** Create by specifying values */
Point::Point(const float &t_x, const float &t_y)
{
x = t_x;
y = t_y;
}
/** Create with other point values */
Point::Point(const Point &v)
{
x = v.x;
y = v.y;
}
/** Create empty point */
Point::Point()
{
x = 0;
y = 0;
}
Point::~Point() {}
// ----
// Methods
// ----
void Point::set(const float &t_x, const float &t_y)
{
x = t_x;
y = t_y;
}
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);
}
-254
View File
@@ -1,254 +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/math/vector3.hpp"
#include "../../include/utils/math.hpp"
// ----
// Constructors/Destructors
// ----
Vector3::Vector3()
{
x = 0.0F;
y = 0.0F;
z = 0.0F;
}
// ----
// Operators
// ----
Vector3 Vector3::operator+(const Vector3 &v) const
{
Vector3 result;
asm volatile( // VU0 Macro program
"lqc2 $vf4, 0x0(%1) \n\t"
"lqc2 $vf5, 0x0(%2) \n\t"
"vadd.xyz $vf6, $vf4, $vf5 \n\t"
"sqc2 $vf6, 0x0(%0) \n\t"
:
: "r"(result.xyz), "r"(this->xyz), "r"(v.xyz));
return result;
}
Vector3 Vector3::operator-(const Vector3 &v) const
{
Vector3 result;
asm volatile( // VU0 Macro program
"lqc2 $vf4, 0x0(%1) \n\t"
"lqc2 $vf5, 0x0(%2) \n\t"
"vsub.xyz $vf6, $vf4, $vf5 \n\t"
"sqc2 $vf6, 0x0(%0) \n\t"
:
: "r"(result.xyz), "r"(this->xyz), "r"(v.xyz));
return result;
}
Vector3 Vector3::operator*(const Vector3 &v) const
{
Vector3 res;
asm volatile( // VU0 Macro program
"lqc2 $vf4, 0x0(%1) \n\t" // $vf4 = this
"lqc2 $vf5, 0x0(%2) \n\t" // $vf5 = v
"vopmula.xyz $ACC, $vf4, $vf5 \n\t"
"vopmsub.xyz $vf8, $vf5, $vf4 \n\t"
"vsub.w $vf8, $vf0, $vf0 \n\t"
"sqc2 $vf8, 0x0(%0) \n\t" // $vf8 = res
:
: "r"(res.xyz), "r"(this->xyz), "r"(v.xyz));
// result.x = y * v.z - z * v.y;
// result.y = z * v.x - x * v.z;
// result.z = x * v.y - y * v.x;
return res;
}
Vector3 Vector3::operator*(const float &t) const
{
Vector3 result;
asm volatile(
"lqc2 $vf4, 0x0(%1) \n\t"
"mfc1 $8, %2 \n\t"
"qmtc2 $8, $vf5 \n\t"
"vmulx.xyz $vf6, $vf4, $vf5 \n\t"
"sqc2 $vf6, 0x0(%0) \n\t"
:
: "r"(result.xyz), "r"(this->xyz), "f"(t));
return result;
}
Vector3 Vector3::operator/(const float &t) const
{
Vector3 result;
result.x = x / t;
result.y = y / t;
result.z = z / t;
return result;
}
void Vector3::operator+=(const Vector3 &t)
{
asm volatile( // VU0 Macro program
"lqc2 $vf4, 0x0(%0) \n\t"
"lqc2 $vf5, 0x0(%1) \n\t"
"vadd.xyz $vf4, $vf4, $vf5 \n\t"
"sqc2 $vf4, 0x0(%0) \n\t"
:
: "r"(this->xyz), "r"(t.xyz));
}
void Vector3::operator*=(const float &t)
{
asm volatile(
"lqc2 $vf4, 0x0(%0) \n\t"
"mfc1 $8, %1 \n\t"
"qmtc2 $8, $vf5 \n\t"
"vmulx.xyz $vf4, $vf4, $vf5 \n\t"
"sqc2 $vf4, 0x0(%0) \n\t"
:
: "r"(this->xyz), "f"(t));
}
// ----
// Functions
// ----
void Vector3::set(const Vector3 &v)
{
asm volatile( // VU0 Macro program
"lq $6, 0x0(%1) \n\t"
"sq $6, 0x0(%0) \n\t"
:
: "r"(this->xyz), "r"(v.xyz));
}
void Vector3::set(const float &t_x, const float &t_y, const float &t_z)
{
x = t_x;
y = t_y;
z = t_z;
}
float Vector3::innerProduct(const Vector3 &v) const
{
float result;
asm volatile( // VU0 Macro program
"lqc2 $vf4, 0x0(%1) \n\t"
"lqc2 $vf5, 0x0(%2) \n\t"
"vmul.xyz $vf6, $vf4, $vf5 \n\t"
"vaddy.x $vf6, $vf6, $vf6 \n\t"
"vaddz.x $vf6, $vf6, $vf6 \n\t"
"qmfc2 $2, $vf6 \n\t"
"mtc1 $2, %0 \n\t"
: "=f"(result)
: "r"(this->xyz), "r"(v.xyz));
return result;
// return (x * v.x + y * v.y + z * v.z);
}
float Vector3::length() const
{
float result;
asm volatile( // VU0 Macro program
"lqc2 $vf4, 0x0(%1) \n\t"
"vmul.xyz $vf5, $vf4, $vf4 \n\t"
"vaddy.x $vf5, $vf5, $vf5 \n\t"
"vaddz.x $vf5, $vf5, $vf5 \n\t"
"vsqrt $Q , $vf5x \n\t"
"vwaitq \n\t"
"vaddq.x $vf8, $vf0, $Q \n\t"
"qmfc2 $2, $vf8 \n\t"
"mtc1 $2, %0 \n\t"
: "=f"(result)
: "r"(this->xyz));
return result;
// return Math::sqrt(x * x + y * y + z * z);
}
void Vector3::normalize()
{
asm volatile( // VU0 Macro program
"lqc2 $vf4, 0x0(%0) \n\t"
"vmul.xyz $vf5, $vf4, $vf4 \n\t"
"vaddy.x $vf5, $vf5, $vf5 \n\t"
"vaddz.x $vf5, $vf5, $vf5 \n\t"
"vrsqrt $Q, $vf0w, $vf5x \n\t"
"vwaitq \n\t"
"vsub.xyz $vf6, $vf0, $vf0 \n\t"
"vaddw.xyz $vf6, $vf6, $vf4 \n\t"
"vwaitq \n\t"
"vmulq.xyz $vf6, $vf4, $Q \n\t"
"sqc2 $vf6, 0x0(%0) \n\t"
:
: "r"(this->xyz));
}
float Vector3::distanceTo(const Vector3 &v) const
{
register float result;
asm volatile( // VU0 Macro program
"lqc2 $vf4, 0x0(%1) \n\t"
"lqc2 $vf5, 0x0(%2) \n\t"
"vsub.xyz $vf6, $vf4, $vf5 \n\t"
"vmul.xyz $vf7, $vf6, $vf6 \n\t"
"vaddy.x $vf7, $vf7, $vf7 \n\t"
"vaddz.x $vf7, $vf7, $vf7 \n\t"
"vsqrt $Q , $vf7x \n\t"
"vwaitq \n\t"
"vaddq.x $vf8, $vf0, $Q \n\t"
"qmfc2 $2, $vf8 \n\t"
"mtc1 $2, %0 \n\t"
: "=f"(result)
: "r"(this->xyz), "r"(v.xyz));
return result;
// return Math::sqrt((this->x - v.x) * (this->x - v.x) +
// (this->y - v.y) * (this->y - v.y) +
// (this->z - v.z) * (this->z - v.z));
}
u8 Vector3::shouldBeBackfaceCulled(const Vector3 *t_cameraPos, const Vector3 *t_v0, const Vector3 *t_v1, const Vector3 *t_v2)
{
register float dot;
asm volatile(
"lqc2 $vf4, 0x0(%1) \n\t" // $vf4 = cameraPos
"lqc2 $vf5, 0x0(%2) \n\t" // $vf5 = v0
"lqc2 $vf6, 0x0(%3) \n\t" // $vf6 = v1
"lqc2 $vf7, 0x0(%4) \n\t" // $vf7 = v2
"vsub.xyz $vf8, $vf7, $vf5 \n\t" // $vf8 = $vf7(v2) - $vf5(v0)
"vsub.xyz $vf9, $vf6, $vf5 \n\t" // $vf9 = $vf6(v1) - $vf5(v0)
"vopmula.xyz $ACC, $vf8, $vf9 \n\t" // $vf6 = cross($vf8, $vf9)
"vopmsub.xyz $vf6, $vf9, $vf8 \n\t"
"vsub.w $vf6, $vf6, $vf6 \n\t"
"vsub.xyz $vf7, $vf5, $vf4 \n\t" // $vf7 = $vf5(v0) - $vf4(cameraPos)
"vmul.xyz $vf5, $vf7, $vf6 \n\t" // $vf5 = dot($vf7, $vf6)
"vaddy.x $vf5, $vf5, $vf5 \n\t"
"vaddz.x $vf5, $vf5, $vf5 \n\t"
"qmfc2 $2, $vf5 \n\t" // store result on `dot` variable
"mtc1 $2, %0 \n\t"
: "=f"(dot)
: "r"(t_cameraPos->xyz), "r"(t_v0->xyz), "r"(t_v1->xyz), "r"(t_v2->xyz));
return dot <= 0.0F;
}
void Vector3::setByLerp(const Vector3 &t_v1, const Vector3 &t_v2, const float &t_interp, const float &t_scale)
{
asm volatile(
"lqc2 $vf4, 0x0(%1) \n\t" // $vf4 = v1
"lqc2 $vf5, 0x0(%2) \n\t" // $vf5 = v2
"mfc1 $8, %3 \n\t" // $vf6 = t
"qmtc2 $8, $vf6 \n\t" // lerp:
"vsub.xyz $vf7, $vf5, $vf4 \n\t" // $vf7 = v2 - v1
"vmulx.xyz $vf8, $vf7, $vf6 \n\t" // $vf8 = $vf7 * t
"vadd.xyz $vf9, $vf8, $vf4 \n\t" // $vf9 = $vf8 + $vf4
"sqc2 $vf9, 0x0(%0) \n\t" // v0 = $vf9
:
: "r"(&this->xyz), "r"(&t_v1.xyz), "r"(&t_v2.xyz), "f"(t_interp));
operator*=(t_scale);
}
-386
View File
@@ -1,386 +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.hpp"
#include "../include/loaders/obj_loader.hpp"
#include "../include/loaders/md2_loader.hpp"
#include "../include/loaders/dff_loader.hpp"
#include "../include/loaders/bmp_loader.hpp"
#include "../include/models/texture.hpp"
#include "../include/utils/debug.hpp"
#include "../include/utils/string.hpp"
#include <cstdlib>
// ----
// Constructors/Destructors
// ----
Mesh::Mesh()
{
id = rand() % 1000000;
shouldBeFrustumCulled = true;
shouldBeBackfaceCulled = false;
shouldBeLighted = false;
_areFramesAllocated = false;
_isMother = false;
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()
{
if (_areFramesAllocated)
delete[] frames;
}
// ----
// Methods
// ----
void Mesh::loadObj(char *t_subfolder, char *t_objFile, const float &t_scale, const u8 &t_invertT)
{
ObjLoader loader = ObjLoader();
framesCount = 1;
frames = new MeshFrame[framesCount];
_areFramesAllocated = true;
char *part1 = String::createConcatenated(t_subfolder, t_objFile); // "folder/object"
char *finalPath = String::createConcatenated(part1, ".obj"); // "folder/object.obj"
loader.load(&frames[0], finalPath, t_scale, t_invertT);
delete[] part1;
delete[] finalPath;
_isMother = true;
}
void Mesh::loadObj(char *t_subfolder, char *t_objFile, const float &t_scale, const u32 &t_framesCount, const u8 &t_invertT)
{
assertMsg(t_framesCount != 0, "Frames count cannot be 0!");
if (t_framesCount == 1)
loadObj(t_subfolder, t_objFile, t_scale, t_invertT);
else
{
ObjLoader loader = ObjLoader();
framesCount = t_framesCount;
frames = new MeshFrame[framesCount];
_areFramesAllocated = true;
char *part1 = String::createConcatenated(t_subfolder, t_objFile); // "folder/object"
char *part2 = String::createConcatenated(part1, "_"); // "folder/object_"
for (u32 i = 0; i < framesCount; i++)
{
char *part3 = String::createU32ToString(i + 1); // 0 -> "1"
char *part4 = String::createWithLeadingZeros(part3); // "000001"
char *part5 = String::createConcatenated(part2, part4); // "folder/object_000001"
char *finalPath = String::createConcatenated(part5, ".obj"); // "folder/object_000001.obj"
loader.load(&frames[i], finalPath, t_scale, t_invertT);
delete[] part3;
delete[] part4;
delete[] part5;
delete[] finalPath;
}
delete[] part2;
delete[] part1;
_isMother = true;
}
}
void Mesh::loadDff(char *t_subfolder, char *t_dffFile, const float &t_scale, const u8 &t_invertT)
{
DffLoader loader = DffLoader();
char *part1 = String::createConcatenated(t_subfolder, t_dffFile);
char *dffPath = String::createConcatenated(part1, ".dff");
framesCount = 1;
frames = new MeshFrame[1];
_areFramesAllocated = true;
loader.load(frames, dffPath, t_scale, t_invertT);
delete[] part1;
delete[] dffPath;
_isMother = true;
}
void Mesh::loadMD2(char *t_subfolder, char *t_md2File, const float &t_scale, const u8 &t_invertT)
{
MD2Loader loader = MD2Loader();
frames = loader.load(framesCount, t_subfolder, t_md2File, t_scale, t_invertT);
_isMother = true;
}
void Mesh::loadFrom(const Mesh &t_mesh)
{
framesCount = t_mesh.framesCount;
frames = new MeshFrame[framesCount];
_areFramesAllocated = true;
for (u32 i = 0; i < framesCount; i++)
frames[i].copyFrom(&t_mesh.getFrame(i));
}
void Mesh::playAnimation(const u32 &t_startFrame, const u32 &t_endFrame)
{
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;
if (animState.currentFrame == t_startFrame)
animState.nextFrame = t_endFrame;
else
animState.nextFrame = t_startFrame;
}
void Mesh::playAnimation(const u32 &t_startFrame, const u32 &t_endFrame, const u32 &t_stayFrame)
{
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)
{
animState.interpolation = 0.0F;
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
animState.nextFrame = animState.startFrame;
}
}
}
u32 Mesh::getDrawData(u32 t_materialIndex, VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, Vector3 &t_cameraPos)
{
VECTOR ONE_VEC = {1.0F, 1.0F, 1.0F, 1.0F};
asm volatile(
// VU0 macro program:
// Load vector with 1.0F values to VF21
"lqc2 $vf21, 0x0(%0) \n\t" // load "one vec"
:
: "r"(ONE_VEC));
u32 addedFaces = 0;
#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;
}
u8 Mesh::isInFrustum(Plane *t_frustumPlanes)
{
Vector3 boxCalcTemp;
u8 boxResult = 1, boxIn = 0, boxOut = 0;
const Vector3 *currentBoundingBox = getCurrentBoundingBoxVertices();
for (int 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 (int y = 0; y < 8 && (boxIn == 0 || boxOut == 0); 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)
boxOut++;
else
boxIn++;
}
//if all corners are out
if (boxIn == 0)
return 0;
else if (boxOut)
boxResult = 1;
}
return boxResult;
}
/** Sets texture level of details settings and CLUT settings */
void Mesh::setDefaultLODAndClut()
{
lod.calculation = LOD_USE_K;
lod.max_level = 0;
lod.mag_filter = LOD_MAG_NEAREST;
lod.min_filter = LOD_MIN_NEAREST;
lod.l = 0;
lod.k = 0.0F;
clut.storage_mode = CLUT_STORAGE_MODE1;
clut.start = 0;
clut.psm = 0;
clut.load_method = CLUT_NO_LOAD;
clut.address = 0;
}
-151
View File
@@ -1,151 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# 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[i].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;
}
-170
View File
@@ -1,170 +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_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;
}
-56
View File
@@ -1,56 +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/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;
}
-81
View File
@@ -1,81 +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/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);
}
-308
View File
@@ -1,308 +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/audio.hpp"
#include "../include/utils/string.hpp"
#include "../include/utils/debug.hpp"
#include <loadfile.h>
#include <cstdlib>
// ----
// Constructors/Destructors
// ----
Audio *audioRef;
Audio::Audio()
{
// We must set it to 0 on songStop();
realVolume = 100;
volume = 100;
chunkReadStatus = 0;
songLoaded = false;
songPlaying = false;
songInLoop = false;
songFinished = false;
audioRef = this;
initSema();
loadModules();
initAUDSRV();
setSongFormat();
}
Audio::~Audio() {}
// ----
// Methods
// ----
void Audio::loadSong(char *t_path)
{
if (songLoaded)
unloadSong();
char *fullFilename = String::createConcatenated("host:", t_path);
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::unloadSong()
{
songLoaded = false;
fclose(wav);
}
/** Set WAV format to 16bit, 22050Hz, stereo. */
void Audio::setSongFormat()
{
format.bits = 16;
format.freq = 22050;
format.channels = 2;
audsrv_set_format(&format);
}
/** 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()
{
consoleLog("Creating audio semaphore");
sema.init_count = 0;
sema.max_count = 1;
sema.option = 0;
fillbufferSema = CreateSema(&sema);
consoleLog("Audio semaphore created");
}
/** Load LIBSD and AUDSRV modules */
void Audio::loadModules()
{
consoleLog("Modules loading started (LIBSD, AUDSRV)");
int ret = SifLoadModule("rom0:LIBSD", 0, NULL);
assertMsg(ret != -203, "LIBSD loading failed!");
ret = SifLoadModule("host:AUDSRV.IRX", 0, NULL);
assertMsg(ret != -203, "AUDSRV.IRX loading failed!");
consoleLog("Audio modules loaded");
}
/**
* Initialize AUDSRV main and ADPCM module.
* Install AUDSRV callback.
*/
void Audio::initAUDSRV()
{
consoleLog("Initializing AUDSRV");
int ret = audsrv_init();
if (ret != 0)
{
printf("AUDSRV returned error string: %s", audsrv_get_error_string());
assertMsg(true == false, "Failed to initialize AUDSRV!");
}
ret = audsrv_adpcm_init();
if (ret != 0)
{
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!");
}
/**
* Do not call this function.
* This is a audio thread, runned by engine
*/
void Audio::mainThread()
{
while (true)
audioRef->threadLoop();
}
-78
View File
@@ -1,78 +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/camera_base.hpp"
#include <fastmath.h>
#include "../include/utils/debug.hpp"
#include "../include/utils/math.hpp"
// ----
// Constructors/Destructors
// ----
CameraBase::CameraBase(ScreenSettings *t_screen, Vector3 *t_position)
: screen(t_screen)
{
consoleLog("Initializing frustum");
farPlaneDist = screen->farPlaneDist;
nearPlaneDist = screen->nearPlaneDist;
float tang = tanf(screen->fov * Math::HALF_ANG2RAD);
nearHeight = tang * nearPlaneDist;
nearWidth = nearHeight * screen->aspectRatio;
farHeight = tang * farPlaneDist;
farWidth = farHeight * screen->aspectRatio;
p_position = t_position;
up.set(0.0F, 1.0F, 0.0F);
consoleLog("CameraBase initialized!");
}
// ----
// Methods
// ----
void CameraBase::lookAt(Vector3 &t_target)
{
updatePlanes(t_target);
view.lookAt(*p_position, t_target);
}
void CameraBase::updatePlanes(Vector3 t_target)
{
Vector3 nearCenter, farCenter, X, Y, Z;
// compute the Z axis of camera
Z = *p_position - t_target;
Z.normalize();
// X axis of camera of given "up" vector and Z axis
X = up * Z;
X.normalize();
// the real "up" vector is the cross product of Z and X
Y = Z * X;
// compute the center of the near and far planes
nearCenter = *p_position - Z * nearPlaneDist;
farCenter = *p_position - Z * farPlaneDist;
// compute the 8 corners of the frustum
ntl = nearCenter + Y * nearHeight - X * nearWidth;
ntr = nearCenter + Y * nearHeight + X * nearWidth;
nbl = nearCenter - Y * nearHeight - X * nearWidth;
nbr = nearCenter - Y * nearHeight + X * nearWidth;
ftl = farCenter + Y * farHeight - X * farWidth;
fbr = farCenter - Y * farHeight + X * farWidth;
ftr = farCenter + Y * farHeight + X * farWidth;
fbl = farCenter - Y * farHeight - X * farWidth;
planes[0].update(ntr, ntl, ftl); // Top
planes[1].update(nbl, nbr, fbr); // BOTTOM
planes[2].update(ntl, nbl, fbl); // LEFT
planes[3].update(nbr, ntr, fbr); // RIGHT
planes[4].update(ntl, ntr, nbr); // NEAR
planes[5].update(ftr, ftl, fbl); // FAR
}
-114
View File
@@ -1,114 +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/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();
}
-255
View File
@@ -1,255 +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/gif_sender.hpp"
#include "../include/utils/math.hpp"
#include "../include/utils/debug.hpp"
#include <packet2_chain.h>
#include <kernel.h>
#include <dma.h>
#include <draw.h>
#include <stdio.h>
#include <malloc.h>
#include <dma_tags.h>
#include <gs_psm.h>
// ----
// Constructors/Destructors
// ----
/** Initializes vars and creates data transfer packets
* @param packetSize Size of data packet, should be increased when more data will be rendered
*/
GifSender::GifSender(u32 t_packetSize, ScreenSettings *t_screen, Light *t_light) : screen(t_screen)
{
consoleLog("Initializing GifSender");
light = t_light;
packetSize = t_packetSize;
packets[0] = packet2_create(t_packetSize, P2_TYPE_NORMAL, P2_MODE_CHAIN, false);
packets[1] = packet2_create(t_packetSize, P2_TYPE_NORMAL, P2_MODE_CHAIN, false);
consoleLog("GifSender initialized!");
}
/** Releases packets memory */
GifSender::~GifSender()
{
packet2_free(packets[0]);
packet2_free(packets[1]);
}
// ----
// Methods
// ----
#include <gif_tags.h>
#include <gs_gp.h>
/** Send texture via GIF */
void GifSender::sendTexture(Texture &texture, texbuffer_t *t_texBuffer)
{
packet2_t *packet2 = packet2_create(15, P2_TYPE_NORMAL, P2_MODE_CHAIN, false);
packet2_update(
packet2,
draw_texture_transfer(
packet2->base,
texture.getData(),
texture.getWidth(),
texture.getHeight(),
texture.getType(),
t_texBuffer->address,
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, color_t *t_rgb)
{
packet2_t *packet2 = packet2_create(36, P2_TYPE_NORMAL, P2_MODE_CHAIN, false);
packet2_chain_open_end(packet2, 0, 0);
packet2_update(packet2, draw_disable_tests(packet2->next, 0, t_zBuffer));
packet2_update(packet2, draw_clear(packet2->next, 0,
2048.0F - (screen->width / 2), 2048.0F - (screen->height / 2),
screen->width, screen->height,
t_rgb->r, t_rgb->g, t_rgb->b));
packet2_update(packet2, draw_enable_tests(packet2->next, 0, t_zBuffer));
packet2_update(packet2, draw_finish(packet2->next));
packet2_chain_close_tag(packet2);
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);
}
/** Used in game loop.
* Switches current packet to next one
*/
void GifSender::initPacket(u8 t_context)
{
currentPacket = packets[t_context];
packet2_reset(currentPacket, false);
isAnyObjectAdded = false;
}
/** Sends packet to GIF. */
void GifSender::sendPacket()
{
if (isAnyObjectAdded)
{
packet2_chain_open_end(currentPacket, 0, 0);
packet2_update(currentPacket, draw_finish(currentPacket->next));
packet2_chain_close_tag(currentPacket);
}
dma_channel_wait(DMA_CHANNEL_GIF, 0);
dma_channel_send_packet2(currentPacket, DMA_CHANNEL_GIF, true);
}
/** Adds clear screen to current packet */
void GifSender::addClear(zbuffer_t *t_zBuffer, color_t *t_rgb)
{
packet2_chain_open_cnt(currentPacket, 0, 0, 0);
packet2_update(currentPacket, draw_disable_tests(currentPacket->next, 0, t_zBuffer));
packet2_update(currentPacket, draw_clear(currentPacket->next, 0,
2048.0F - (screen->width / 2), 2048.0F - (screen->height / 2),
screen->width, screen->height,
t_rgb->r, t_rgb->g, t_rgb->b));
packet2_update(currentPacket, draw_enable_tests(currentPacket->next, 0, t_zBuffer));
packet2_chain_close_tag(currentPacket);
}
/** Adds meshes to current packet */
void GifSender::addObject(RenderData *t_renderData, Mesh &t_mesh, u32 vertexCount, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer, color_t *t_color)
{
packet2_chain_open_cnt(currentPacket, 0, 0, 0);
packet2_update(currentPacket, draw_texture_sampling(currentPacket->next, 0, &t_mesh.lod));
packet2_update(currentPacket, draw_texturebuffer(currentPacket->next, 0, textureBuffer, &t_mesh.clut));
packet2_update(currentPacket, draw_prim_start(currentPacket->next, 0, t_renderData->prim, t_color));
xyz = new xyz_t[vertexCount];
rgbaq = new color_t[vertexCount];
st = new texel_t[vertexCount];
calc3DObject(*t_renderData->projection, t_mesh, vertexCount, vertices, normals, coordinates, t_renderData, t_bulbs, t_bulbsCount, t_color);
addCurrentCalcs(vertexCount);
delete[] xyz;
delete[] rgbaq;
delete[] st;
packet2_update(currentPacket, draw_prim_end(currentPacket->next, 3, DRAW_STQ_REGLIST));
packet2_chain_close_tag(currentPacket);
}
/** Calculates 3D object data into xyz, rgbq, st
* After it addCurrentCalcs() can be done
*/
void GifSender::calc3DObject(Matrix t_perspective, Mesh &t_mesh, u32 vertexCount, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, RenderData *t_renderData, LightBulb *t_bulbs, u16 t_bulbsCount, color_t *t_color)
{
VECTOR *colors = new VECTOR[vertexCount];
VECTOR position, rotation;
vec3ToNative(position, t_mesh.position, 1.0F);
vec3ToNative(rotation, t_mesh.rotation, 1.0F);
create_local_world(localWorld, position, rotation);
const u8 SHOULD_BE_LIGHTED = t_bulbs != NULL && t_mesh.shouldBeLighted;
if (SHOULD_BE_LIGHTED)
create_local_light(localLight, rotation);
// I cant put perspective from renderData here. ee-gcc bug?
create_local_screen(localScreen, localWorld, t_renderData->view->data, t_perspective.data);
if (SHOULD_BE_LIGHTED)
{
const u16 lightsCount = light->getLightsCount(t_bulbsCount);
VECTOR *lightDirections = new VECTOR[lightsCount];
VECTOR *lightColors = new VECTOR[lightsCount];
int *lightTypes = new int[lightsCount];
VECTOR *lights = new VECTOR[vertexCount];
calculate_normals(normals, vertexCount, normals, localLight);
light->calculateLight(lightDirections, lightColors, lightTypes, t_bulbs, lightsCount, t_mesh.position);
calculate_lights(lights, vertexCount, normals, lightDirections, lightColors, lightTypes, lightsCount);
for (u32 i = 0; i < vertexCount; i++)
{
// Apply the light value to the colour.
colors[i][0] = (t_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[] lightColors;
delete[] lightTypes;
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);
convertCalcs(vertexCount, vertices, colors, coordinates, *t_color);
delete[] colors;
}
void GifSender::convertCalcs(u32 t_vertexCount, VECTOR *t_vertices, VECTOR *t_colors, VECTOR *t_sts, color_t &t_color)
{
// TODO get this via screensettings
const s32 centerX = ftoi4(2048);
const s32 centerY = ftoi4(2048);
const u32 maxZ = ftoi4(((float)0xFFFFFF) / 32.0F);
float q = 1.00F;
for (u32 i = 0; i < t_vertexCount; i++)
{
xyz[i].x = (u16)((t_vertices[i][0] + 1.0F) * centerX);
xyz[i].y = (u16)((t_vertices[i][1] + 1.0F) * centerY);
xyz[i].z = (u32)((t_vertices[i][2] + 1.0F) * maxZ);
if (t_vertices[i][3])
q = 1 / t_vertices[i][3];
st[i].s = t_sts[i][0] * q;
st[i].t = t_sts[i][1] * q;
rgbaq[i].r = (u8)(t_colors[i][0] * 128.0F);
rgbaq[i].g = (u8)(t_colors[i][1] * 128.0F);
rgbaq[i].b = (u8)(t_colors[i][2] * 128.0F);
rgbaq[i].a = t_color.a;
rgbaq[i].q = q;
}
}
/** Update q's double words. It may look strange, but this workaround
* use's a 64-bit pointer to simplify adding data to the packet.
*/
void GifSender::addCurrentCalcs(u32 &t_vertexCount)
{
for (u32 i = 0; i < t_vertexCount; i++)
{
packet2_add_u64(currentPacket, rgbaq[i].rgbaq);
packet2_add_u64(currentPacket, st[i].uv);
packet2_add_u64(currentPacket, xyz[i].xyz);
}
packet2_pad128(currentPacket, 0);
}
-78
View File
@@ -1,78 +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/light.hpp"
// ----
// Constructors/Destructors
// ----
Light::Light() {}
Light::~Light() {}
// ----
// Methods
// ----
const u8 ADDITIONAL_LIGHTS = 1; // Ambient
const float LIGHT_MAX = 255.0F;
const float LIGHT_DIS_MOD = 4.0F;
void Light::setAmbientLight(const Vector3 &t_rgb) { ambientLight.set(t_rgb); }
u16 Light::getLightsCount(u32 t_bulbsCount) { return t_bulbsCount + ADDITIONAL_LIGHTS; }
/** Calculates lighting. Used in gifSender in object 3D calculations */
void Light::calculateLight(VECTOR *t_lightDirections, VECTOR *t_lightColors, int *t_lightTypes, LightBulb *t_bulbs, u32 t_lightsCount, Vector3 t_objPosition)
{
// --- Ambient light
t_lightTypes[0] = LIGHT_AMBIENT;
t_lightDirections[0][0] = 0.0F;
t_lightDirections[0][1] = 0.0F;
t_lightDirections[0][2] = 0.0F;
t_lightDirections[0][3] = 1.0F;
t_lightColors[0][0] = ambientLight.x;
t_lightColors[0][1] = ambientLight.y;
t_lightColors[0][2] = ambientLight.z;
t_lightColors[0][3] = 1.0F;
// ---
for (u8 i = 1; i < t_lightsCount; i++)
{
t_lightTypes[i] = LIGHT_DIRECTIONAL;
Vector3 newLight = Vector3(t_objPosition.x - t_bulbs[i - 1].position.x,
t_objPosition.y - t_bulbs[i - 1].position.y,
t_objPosition.z - t_bulbs[i - 1].position.z);
newLight.normalize();
t_lightDirections[i][0] = newLight.x;
t_lightDirections[i][1] = newLight.y;
t_lightDirections[i][2] = newLight.z;
t_lightDirections[i][3] = 1.0F;
// Intensity range 0.0F - 1.0F
float intensity = t_bulbs[i - 1].intensity / LIGHT_MAX;
// Distance range 0.0F - LIGHT_MAX * LIGHT_DIS_MOD (1020.0F at this time)
float distance = t_bulbs[i - 1].position.distanceTo(t_objPosition);
// printf("Distance:%f\n", distance);
distance = distance > (LIGHT_MAX - LIGHT_DIS_MOD) * LIGHT_DIS_MOD ? LIGHT_MAX - LIGHT_DIS_MOD : distance;
intensity /= 1.0F + (distance / LIGHT_DIS_MOD); // intensity /= 1.0F - 251.0F
intensity /= 3.0F; // it looks better
t_lightColors[i][0] = intensity;
t_lightColors[i][1] = intensity;
t_lightColors[i][2] = intensity;
t_lightColors[i][3] = 1.0F;
}
}
-208
View File
@@ -1,208 +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/pad.hpp"
#include "../include/utils/debug.hpp"
#include <kernel.h>
#include <loadfile.h>
#include <string.h>
#include <stdio.h>
// ----
// Constructors/Destructors
// ----
/** Init vars, load modules, opens pad port and initializes pad */
Pad::Pad()
{
this->oldPad = 0;
this->loadModules();
padInit(0);
this->port = 0; // 0 -> Connector 1, 1 -> Connector 2
this->slot = 0; // Always zero if not using multitap
if ((this->ret = padPortOpen(this->port, this->slot, padBuf)) == 0)
{
printf("padPortOpen returned: %d\n", this->ret);
assertMsg(true == false, "padPortOpen failed!");
}
assertMsg(this->initPad(), "initPad failed!");
}
Pad::~Pad() {}
// ----
// Methods
// ----
/** Load SIO2MAN and PADMAN modules */
void Pad::loadModules()
{
consoleLog("Loading pad modules");
this->ret = SifLoadModule("rom0:SIO2MAN", 0, NULL);
if (this->ret < 0)
{
printf("SifLoadModule returned: %d\n", this->ret);
assertMsg(true == false, "SifLoadModule (SIO2MAN) failed!");
}
this->ret = SifLoadModule("rom0:PADMAN", 0, NULL);
if (this->ret < 0)
{
printf("SifLoadModule returned: %d\n", this->ret);
assertMsg(true == false, "SifLoadModule (PADMAN) failed!");
}
consoleLog("Pad modules loaded!");
}
/** Wait when pad will be ready (stable and ready) */
int Pad::waitPadReady()
{
int state;
int lastState;
char stateString[16];
state = padGetState(this->port, this->slot);
lastState = -1;
while ((state != PAD_STATE_STABLE) && (state != PAD_STATE_FINDCTP1))
{
if (state != lastState)
{
padStateInt2String(state, stateString);
consoleLog("Pad state changed");
printf("Curent pad(%d,%d) status: %s\n", this->port, this->slot, stateString);
}
lastState = state;
state = padGetState(this->port, this->slot);
}
// Were the pad ever 'out of sync'?
if (lastState != -1)
consoleLog("Pad is ready!");
return 0;
}
/** Initializes and checks type of pad */
int Pad::initPad()
{
consoleLog("Initializing pad");
this->waitPadReady();
// How many different modes can this device operate in?
// i.e. get # entrys in the modetable
int modes = padInfoMode(this->port, this->slot, PAD_MODETABLE, -1);
assertMsg(modes, "Connected device is not a dual shock controller!"); // (it has no actuator engines)
// Verify that the controller has a DUAL SHOCK mode
int i = 0;
do
{
if (padInfoMode(this->port, this->slot, PAD_MODETABLE, i) == PAD_TYPE_DUALSHOCK)
break;
i++;
} while (i < modes);
assertMsg(i < modes, "Connected device is not a dual shock controller!");
// If ExId != 0x0 => This controller has actuator engines
// This check should always pass if the Dual Shock test above passed
this->ret = padInfoMode(this->port, this->slot, PAD_MODECUREXID, 0);
assertMsg(this->ret, "Connected device is not a dual shock controller!");
consoleLog("Enabling dual shock functions.");
// When using MMODE_LOCK, user cant change mode with Select button
padSetMainMode(this->port, this->slot, PAD_MMODE_DUALSHOCK, PAD_MMODE_LOCK);
this->waitPadReady();
printf("Pad has pressure sensitive buttons? %d\n", padInfoPressMode(this->port, this->slot));
this->waitPadReady();
padEnterPressMode(this->port, this->slot); // Set pressure sensitive mode
this->waitPadReady();
this->actuators = padInfoAct(this->port, this->slot, -1, 0);
printf("# of actuators: %d\n", this->actuators);
if (actuators != 0)
{
this->actAlign[0] = 0; // Enable small engine
this->actAlign[1] = 1; // Enable big engine
this->actAlign[2] = 0xff;
this->actAlign[3] = 0xff;
this->actAlign[4] = 0xff;
this->actAlign[5] = 0xff;
this->waitPadReady();
printf("padSetActAlign: %d\n", padSetActAlign(this->port, this->slot, actAlign));
}
else
printf("Did not find any actuators.\n");
this->waitPadReady();
consoleLog("Pad initialized!");
return 1;
}
/** Updates state of joys/buttons */
void Pad::update()
{
int x = 0;
this->ret = padGetState(this->port, this->slot);
while ((this->ret != PAD_STATE_STABLE) && (this->ret != PAD_STATE_FINDCTP1))
{
if (this->ret == PAD_STATE_DISCONN)
printf("Pad(%d, %d) is disconnected\n", this->port, this->slot);
this->ret = padGetState(this->port, this->slot);
}
if (x == 1)
printf("Pad: OK!\n");
this->ret = padRead(this->port, this->slot, &this->buttons); // this->port, this->slot, this->buttons
if (this->ret != 0)
{
this->padData = 0xffff ^ this->buttons.btns;
this->newPad = this->padData & ~this->oldPad;
this->oldPad = this->padData;
this->reset();
this->rJoyH = this->buttons.rjoy_h;
this->rJoyV = this->buttons.rjoy_v;
this->lJoyH = this->buttons.ljoy_h;
this->lJoyV = this->buttons.ljoy_v;
if (this->newPad & PAD_CROSS)
this->isCrossClicked = 1;
if (this->newPad & PAD_SQUARE)
this->isSquareClicked = 1;
if (this->newPad & PAD_TRIANGLE)
this->isTriangleClicked = 1;
if (this->newPad & PAD_CIRCLE)
this->isCircleClicked = 1;
if (this->buttons.up_p > 0)
this->isDpadUpPressed = 1;
if (this->buttons.down_p > 0)
this->isDpadDownPressed = 1;
if (this->buttons.left_p)
this->isDpadLeftPressed = 1;
if (this->buttons.right_p)
this->isDpadRightPressed = 1;
}
}
/** Resets state of joys/buttons */
void Pad::reset()
{
this->isCrossClicked = 0;
this->isSquareClicked = 0;
this->isTriangleClicked = 0;
this->isCircleClicked = 0;
this->isDpadUpPressed = 0;
this->isDpadDownPressed = 0;
this->isDpadLeftPressed = 0;
this->isDpadRightPressed = 0;
this->lJoyH = 0;
this->lJoyV = 0;
this->rJoyH = 0;
this->rJoyV = 0;
}
-379
View File
@@ -1,379 +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/renderer.hpp"
#include <dma.h>
#include <graph.h>
#include <packet.h>
#include "../include/utils/debug.hpp"
#include "../include/utils/math.hpp"
// ----
// Constructors/Destructors
// ----
static const float GS_CENTER = 4096.0F;
static const float SCREEN_CENTER = GS_CENTER / 2.0F;
/** Initialize DMA<->GIF channel
* Allocate buffers
* Initialize screen
* Initialize drawing environment
* Load/setup textures
* @param screenW Half of screen width
* @param screenH Half of screen height
*/
Renderer::Renderer(u32 t_packetSize, ScreenSettings *t_screen)
{
consoleLog("Initializing renderer");
dma_channel_initialize(DMA_CHANNEL_GIF, NULL, 0); // Initialize DMA to enable data transfer
dma_channel_fast_waits(DMA_CHANNEL_GIF);
screen = t_screen;
context = 0;
isTextureVRAMAllocated = false;
isVSyncEnabled = true;
isFrameEmpty = false;
lastTextureId = 0;
flipPacket = packet2_create(4, P2_TYPE_UNCACHED_ACCL, P2_MODE_NORMAL, 0);
allocateBuffers((int)t_screen->width, (int)t_screen->height);
initDrawingEnv();
setPrim();
worldColor.r = 0x10;
worldColor.g = 0x10;
worldColor.b = 0x10;
gifSender = new GifSender(t_packetSize, t_screen, &light);
vifSender = new VifSender(&light);
perspective.setPerspective(*t_screen);
renderData.projection = &perspective;
consoleLog("Renderer initialized!");
}
Renderer::~Renderer() {}
// ----
// Methods
// ----
/** Configure and allocate vRAM for texture buffer */
void Renderer::allocateTextureBuffer(Texture *t_texture)
{
textureBuffer.width = t_texture->getWidth();
textureBuffer.psm = t_texture->getType();
textureBuffer.info.components = textureBuffer.psm == TEX_TYPE_RGBA ? TEXTURE_COMPONENTS_RGBA : TEXTURE_COMPONENTS_RGB;
textureBuffer.address = graph_vram_allocate(t_texture->getWidth(), t_texture->getHeight(), textureBuffer.psm, GRAPH_ALIGN_BLOCK);
assertMsg(textureBuffer.address > 1, "Texture buffer allocation error. No memory!");
textureBuffer.info.width = draw_log2(t_texture->getWidth());
textureBuffer.info.height = draw_log2(t_texture->getHeight());
textureBuffer.info.function = TEXTURE_FUNCTION_MODULATE;
isTextureVRAMAllocated = true;
}
/** Configure and allocate vRAM for texture buffer */
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 */
void Renderer::setPrim()
{
prim.type = PRIM_TRIANGLE;
prim.shading = PRIM_SHADE_FLAT;
prim.mapping = DRAW_ENABLE;
prim.fogging = DRAW_DISABLE;
prim.blending = DRAW_ENABLE;
prim.antialiasing = DRAW_DISABLE;
prim.mapping_type = PRIM_MAP_ST;
prim.colorfix = PRIM_UNFIXED;
renderData.prim = &prim;
consoleLog("Prim set!");
}
void Renderer::setWorldColor(const color_t &t_rgb)
{
worldColor.r = t_rgb.r;
worldColor.g = t_rgb.g;
worldColor.b = t_rgb.b;
}
/** Defines and allocates framebuffers and zbuffer */
void Renderer::allocateBuffers(int t_screenW, int t_screenH)
{
frameBuffers[0].width = (unsigned int)t_screenW;
frameBuffers[0].height = (unsigned int)t_screenH;
frameBuffers[0].mask = 0;
frameBuffers[0].psm = GS_PSM_32;
frameBuffers[0].address = graph_vram_allocate(t_screenW, t_screenH, frameBuffers[0].psm, GRAPH_ALIGN_PAGE);
frameBuffers[1].width = (unsigned int)t_screenW;
frameBuffers[1].height = (unsigned int)t_screenH;
frameBuffers[1].mask = 0;
frameBuffers[1].psm = GS_PSM_32;
frameBuffers[1].address = graph_vram_allocate(t_screenW, t_screenH, frameBuffers[1].psm, GRAPH_ALIGN_PAGE);
zBuffer.enable = DRAW_ENABLE;
zBuffer.mask = 0;
zBuffer.method = ZTEST_METHOD_GREATER_EQUAL;
zBuffer.zsm = GS_ZBUF_24;
zBuffer.address = graph_vram_allocate(t_screenW, t_screenH, zBuffer.zsm, GRAPH_ALIGN_PAGE);
consoleLog("Framebuffers, zBuffer set and allocated!");
// Initialize the screen and tie the first framebuffer to the read circuits.
graph_initialize(frameBuffers[0].address, frameBuffers[0].width, frameBuffers[0].height, frameBuffers[0].psm, 0, 0);
}
/// --- Draw: PATH3
// Obsolete
// void Renderer::drawByPath3(Mesh *t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount)
// {
// for (u16 i = 0; i < t_amount; i++)
// drawByPath3(t_meshes[i], t_bulbs, t_bulbsCount);
// }
// Obsolete
// void Renderer::drawByPath3(Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount)
// {
// beginFrameIfNeeded();
// if (!t_mesh.isDataLoaded())
// PRINT_ERR("Can't draw, because no mesh data was loaded!");
// if (t_mesh.getCurrentAnimationFrame() != t_mesh.getNextAnimationFrame())
// t_mesh.animate();
// for (u32 i = 0; i < t_mesh.getMaterialsCount(); i++)
// {
// MeshMaterial *material = &t_mesh.getMaterial(i);
// if (t_mesh.shouldBeFrustumCulled && !material->isInFrustum(renderData.frustumPlanes, t_mesh.position))
// return;
// Texture *tex = textureRepo.getBySpriteOrMesh(material->getId());
// changeTexture(tex);
// gifSender->initPacket(context);
// u32 vertCount = material->getFacesCount();
// VECTOR *vertices = new VECTOR[vertCount];
// VECTOR *normals = new VECTOR[vertCount];
// VECTOR *coordinates = new VECTOR[vertCount];
// vertCount = t_mesh.getDrawData(i, vertices, normals, coordinates, *renderData.cameraPosition);
// gifSender->addObject(&renderData, t_mesh, vertCount, vertices, normals, coordinates, t_bulbs, t_bulbsCount, &textureBuffer, &material->color);
// gifSender->sendPacket();
// delete[] vertices;
// delete[] normals;
// delete[] coordinates;
// }
// }
// Obsolete
// void Renderer::drawByPath3(Mesh *t_meshes, u16 t_amount) { drawByPath3(t_meshes, t_amount, NULL, 0); }
// Obsolete
// void Renderer::drawByPath3(Mesh &t_mesh) { drawByPath3(t_mesh, NULL, 0); }
/// --- Draw: PATH1
void Renderer::draw(Mesh **t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount)
{
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++)
if (t_meshes[i]->getMaterial(0).isInFrustum(renderData.frustumPlanes, t_meshes[i]->position))
meshesInFrustum[addedMeshes++] = t_meshes[i];
draw(*meshesInFrustum[0], t_bulbs, t_bulbsCount);
draw(*meshesInFrustum[1], t_bulbs, t_bulbsCount);
vifSender->enableWait();
resetWaitFlag();
vifSender->drawTheSameWithOtherMatrices(renderData, meshesInFrustum, 2, addedMeshes);
if (isWaitFlagSet())
resetWaitFlag();
else
waitForRender();
delete[] meshesInFrustum;
}
else
for (u16 i = 0; i < t_amount; i++)
draw(*t_meshes[i], t_bulbs, t_bulbsCount);
}
void Renderer::draw(Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount)
{
beginFrameIfNeeded();
vifSender->calcMatrix(renderData, t_mesh.position, t_mesh.rotation);
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;
u32 vertCount = material->getFacesCount();
VECTOR vertices[vertCount] __attribute__((aligned(16)));
VECTOR normals[vertCount] __attribute__((aligned(16)));
VECTOR coordinates[vertCount] __attribute__((aligned(16)));
Texture *tex = textureRepo.getBySpriteOrMesh(material->getId());
changeTexture(tex);
vertCount = t_mesh.getDrawData(i, vertices, normals, coordinates, rotatedCamera);
vifSender->drawMesh(&renderData, perspective, vertCount, vertices, normals, coordinates, t_mesh, t_bulbs, t_bulbsCount, &textureBuffer, &material->color, !material->areSTsPresent());
}
}
void Renderer::draw(Mesh **t_meshes, u16 t_amount) { draw(t_meshes, t_amount, NULL, 0); }
void Renderer::draw(Mesh &t_mesh) { draw(t_mesh, NULL, 0); }
/// ---
void Renderer::setCameraDefinitions(Matrix *t_worldView, Vector3 *t_cameraPos, Plane *t_planes)
{
renderData.view = t_worldView;
renderData.cameraPosition = t_cameraPos;
renderData.frustumPlanes = t_planes;
}
void Renderer::beginFrameIfNeeded()
{
if (isFrameEmpty)
{
isFrameEmpty = false;
gifSender->sendClear(&zBuffer, &worldColor);
}
}
void Renderer::endFrame(float fps)
{
if (!isFrameEmpty)
{
if (fps > 49.0F && isVSyncEnabled)
graph_wait_vsync();
flipBuffers();
}
}
/** We need to flip buffers outside of the chain, for some reason,
* so we use a separate small packet
* Do not use this method. This is called via packetManager
*/
void Renderer::flipBuffers()
{
graph_set_framebuffer_filtered(
frameBuffers[context].address,
frameBuffers[context].width,
frameBuffers[context].psm,
0,
0);
context ^= 1;
isFrameEmpty = 1;
packet2_update(flipPacket, draw_framebuffer(flipPacket->base, 0, &frameBuffers[context]));
packet2_update(flipPacket, draw_finish(flipPacket->next));
dma_channel_send_packet2(flipPacket, DMA_CHANNEL_GIF, true);
draw_wait_finish();
}
-63
View File
@@ -1,63 +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/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);
}
}
-44
View File
@@ -1,44 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "../include/modules/timer.hpp"
// ----
// Constructors/Destructors
// ----
Timer::Timer() { prime(); }
Timer::~Timer() {}
// ----
// Methods
// ----
u32 Timer::getTimeDelta()
{
time = *T3_COUNT;
if (time < lastTime) // The counter has wrapped
change = time + (65536 - lastTime);
else
change = time - lastTime;
return change;
}
float Timer::getFPS()
{
u32 timeDelta = this->getTimeDelta();
if (timeDelta == 0)
return -1.0F;
return 15625.0F / (float)timeDelta; // PAL
}
-250
View File
@@ -1,250 +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/vif_sender.hpp"
#include <gs_gp.h>
#include <dma.h>
#include <gif_tags.h>
#include "../include/utils/math.hpp"
#include "../include/utils/debug.hpp"
const u32 VU1_PACKAGE_VERTS_PER_BUFF = 96; // Remember to modify buffer size in vu1 also
const u32 VU1_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
// ----
// VU1 micro program
extern u32 VU1Draw3D_CodeStart __attribute__((section(".vudata")));
extern u32 VU1Draw3D_CodeEnd __attribute__((section(".vudata")));
//
VifSender::VifSender(Light *t_light)
{
consoleLog("Initializing VifSender");
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()
{
packet2_free(packets[0]);
packet2_free(packets[1]);
}
// ----
// Methods
// ----
void VifSender::uploadMicroProgram()
{
packet2_t *packet2 = packet2_create(
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);
}
void VifSender::calcMatrix(const RenderData &t_renderData, const Vector3 &t_position, const Vector3 &t_rotation)
{
model.identity();
model.rotate(t_rotation);
model.translate(t_position);
modelViewProj.identity();
modelViewProj = model * modelViewProj;
modelViewProj = *t_renderData.view * modelViewProj;
modelViewProj = *t_renderData.projection * modelViewProj;
}
void VifSender::drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 vertCount2, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer, color_t *t_color, u8 t_rgbaOnly)
{
// we have to split 3D object into small parts, because of small memory of VU1
for (u32 i = 0; i < vertCount2;)
{
currPacket = packets[context];
packet2_reset(currPacket, false);
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
i -= 3;
const u32 endI = i + (VU1_PACKAGE_VERTS_PER_BUFF - 1) > vertCount2 ? vertCount2 : i + (VU1_PACKAGE_VERTS_PER_BUFF - 1);
drawVertices(t_mesh, i, endI, vertices, coordinates, t_renderData->prim, textureBuffer, isDrawWaitEnabled ? endI == vertCount2 : false, t_color, t_rgbaOnly);
if (endI == vertCount2) // if there are no more vertices to draw, break
{
i = vertCount2;
break;
}
i += (VU1_PACKAGE_VERTS_PER_BUFF - 1);
i++;
}
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 */
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;
lastVertCount = vertCount;
isLastRGBAOnly = t_rgbaOnly;
packet2_utils_vu_open_unpack(currPacket, 0, true);
packet2_add_data(currPacket, modelViewProj.data, 4);
packet2_add_u32(currPacket, t_addDrawWait); // Draw finish?
packet2_add_u32(currPacket, vertCount); // Vertex count
packet2_add_u32(currPacket, vertCount / 3); // Triangles count
packet2_add_u32(currPacket, t_rgbaOnly); // 0 = STQ+RGBA, 1 = RGBA
packet2_utils_gs_add_lod(currPacket, &t_mesh.lod);
packet2_utils_gs_add_texbuff_clut(currPacket, t_texBuff, &t_mesh.clut);
if (t_rgbaOnly)
packet2_utils_gs_add_prim_giftag(currPacket, t_prim, vertCount, DRAW_RGBAQ_REGLIST, 2, 0);
else
packet2_utils_gs_add_prim_giftag(currPacket, t_prim, vertCount, DRAW_STQ2_REGLIST, 3, 0);
packet2_add_u32(currPacket, t_color->r);
packet2_add_u32(currPacket, t_color->g);
packet2_add_u32(currPacket, t_color->b);
packet2_add_u32(currPacket, t_color->a);
u32 vif_added_bytes = packet2_utils_vu_close_unpack(currPacket);
packet2_utils_vu_add_unpack_data(currPacket, vif_added_bytes, t_vertices + t_start, vertCount, true);
if (!t_rgbaOnly)
{
vif_added_bytes += vertCount;
packet2_utils_vu_add_unpack_data(currPacket, vif_added_bytes, t_coordinates + t_start, vertCount, true);
}
packet2_utils_vu_add_start_program(currPacket, 0);
}
void VifSender::drawTheSameWithOtherMatrices(const RenderData &t_renderData, Mesh **t_meshes, const u32 &t_skip, const u32 &t_count)
{
// Standard double buffering (packets)
packet2_t *packet1 = packet2_create(300, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
packet2_t *packet2 = packet2_create(300, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
packet2_t *currMPacket = packet1;
u8 currPacketIndex = 1;
// We are sending 32 matrices max per one VU1 send
u8 switchCounter = 0;
for (u32 i = t_skip; i < t_count; i++)
{
model.identity();
model.rotate(t_meshes[i]->rotation);
model.translate(t_meshes[i]->position);
modelViewProj.identity();
modelViewProj = model * modelViewProj;
modelViewProj = *t_renderData.view * modelViewProj;
modelViewProj = *t_renderData.projection * modelViewProj;
packet2_utils_vu_open_unpack(currMPacket, 0, true);
{
packet2_add_data(currMPacket, modelViewProj.data, 4);
}
packet2_utils_vu_close_unpack(currMPacket);
packet2_utils_vu_open_unpack(currMPacket, VU1_RGBA_ADDRESS, true);
{
packet2_add_u32(currMPacket, t_meshes[i]->getMaterial(0).color.r);
packet2_add_u32(currMPacket, t_meshes[i]->getMaterial(0).color.g);
packet2_add_u32(currMPacket, t_meshes[i]->getMaterial(0).color.b);
packet2_add_u32(currMPacket, t_meshes[i]->getMaterial(0).color.a);
}
packet2_utils_vu_close_unpack(currMPacket);
if (i != t_count - 1) // if it is last, we must also add draw wait finish interrupt.
packet2_utils_vu_add_start_program(currMPacket, 0);
if (switchCounter++ >= 32)
{
switchCounter = 0;
if (i == t_count - 1) // is last
{
packet2_utils_vu_open_unpack(currMPacket, VU1_PARAMS_ADDRESS, true);
{
packet2_add_u32(currMPacket, true); // Draw wait finish?
packet2_add_u32(currMPacket, lastVertCount); // Vertex count
packet2_add_u32(currMPacket, lastVertCount / 3); // Triangles count
packet2_add_u32(currMPacket, isLastRGBAOnly); // 0 = STQ+RGBA, 1 = RGBA
}
packet2_utils_vu_close_unpack(currMPacket);
packet2_utils_vu_add_start_program(currMPacket, 0); // and start program
}
packet2_utils_vu_add_end_tag(currMPacket);
dma_channel_wait(DMA_CHANNEL_VIF1, 0);
dma_channel_send_packet2(currMPacket, DMA_CHANNEL_VIF1, 1);
if (currPacketIndex == 1) // Switch double buffer (packets)
{
currPacketIndex = 2;
currMPacket = packet2;
}
else
{
currPacketIndex = 1;
currMPacket = packet1;
}
packet2_reset(currMPacket, false);
}
}
if (switchCounter != 0) // if there are any not sended matrices
{
packet2_utils_vu_open_unpack(currMPacket, VU1_PARAMS_ADDRESS, true);
{
packet2_add_u32(currMPacket, true); // Draw wait finish?
packet2_add_u32(currMPacket, lastVertCount); // Vertex count
packet2_add_u32(currMPacket, lastVertCount / 3); // Triangles count
packet2_add_u32(currMPacket, isLastRGBAOnly); // 0 = STQ+RGBA, 1 = RGBA
}
packet2_utils_vu_close_unpack(currMPacket);
packet2_utils_vu_add_start_program(currMPacket, 0);
packet2_utils_vu_add_end_tag(currMPacket);
dma_channel_wait(DMA_CHANNEL_VIF1, 0);
dma_channel_send_packet2(currMPacket, DMA_CHANNEL_VIF1, 1);
}
packet2_free(packet1);
packet2_free(packet2);
}
-174
View File
@@ -1,174 +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/utils/math.hpp"
#include <math.h>
float Math::cos(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::invSqrt(float x) { return 1.0F / sqrt(x); }
/** Converts Vector3 to PS2SDK's Vector4 */
void vec3ToNative(VECTOR o_result, const Vector3 &t_vec, float t_fourthVal)
{
o_result[0] = t_vec.x;
o_result[1] = t_vec.y;
o_result[2] = t_vec.z;
o_result[3] = t_fourthVal;
}
/** Converts array of Vector3 to array of PS2SDK's Vector4 */
void manyVec3ToNative(VECTOR *o_result, Vector3 *t_vec, int t_amount, float t_fourthVal)
{
for (int i = 0; i < t_amount; i++)
vec3ToNative(o_result[i], t_vec[i], t_fourthVal);
}
float Math::asin(float x)
{
float r;
asm volatile(
"lui $9, 0x3f00 \n\t"
".set noreorder \n\t"
".align 3 \n\t"
"abs.s %0, %1 \n\t"
"lui $8, 0xbe22 \n\t"
"mtc1 $9, $f1 \n\t"
"ori $8, $8, 0xf983 \n\t"
"mtc1 $8, $f8 \n\t"
"lui $9, 0x4b00 \n\t"
"mtc1 $9, $f3 \n\t"
"lui $8, 0x3f80 \n\t"
"mtc1 $8, $f2 \n\t"
"mula.s %0, $f8 \n\t"
"msuba.s $f3, $f2 \n\t"
"madda.s $f3, $f2 \n\t"
"lui $8, 0x40c9 \n\t"
"msuba.s %0, $f8 \n\t"
"ori $8, 0x0fdb \n\t"
"msub.s %0, $f1, $f2 \n\t"
"lui $9, 0xc225 \n\t"
"abs.s %0, %0 \n\t"
"lui $10, 0x3e80 \n\t"
"mtc1 $10, $f7 \n\t"
"ori $9, 0x5de1 \n\t"
"sub.s %0, %0, $f7 \n\t"
"lui $10, 0x42a3 \n\t"
"mtc1 $8, $f3 \n\t"
"ori $10, 0x3458 \n\t"
"mtc1 $9, $f4 \n\t"
"lui $8, 0xc299 \n\t"
"mtc1 $10, $f5 \n\t"
"ori $8, 0x2663 \n\t"
"mul.s $f8, %0, %0 \n\t"
"lui $9, 0x421e \n\t"
"mtc1 $8, $f6 \n\t"
"ori $9, 0xd7bb \n\t"
"mtc1 $9, $f7 \n\t"
"nop \n\t"
"mul.s $f1, %0, $f8 \n\t"
"mul.s $f9, $f8, $f8 \n\t"
"mula.s $f3, %0 \n\t"
"mul.s $f2, $f1, $f8 \n\t"
"madda.s $f4, $f1 \n\t"
"mul.s $f1, $f1, $f9 \n\t"
"mul.s %0, $f2, $f9 \n\t"
"madda.s $f5, $f2 \n\t"
"madda.s $f6, $f1 \n\t"
"madd.s %0, $f7, %0 \n\t"
".set reorder \n\t"
: "=&f"(r)
: "f"(x)
: "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", "$f9", "$8", "$9", "$10");
return r;
}
float Math::mod(float x, float y)
{
/*
* Portable fmod(x,y) implementation for systems
* that don't have it. Adapted from code found here:
* http://www.opensource.apple.com/source/python/python-3/python/Python/fmod.c
*/
float i, f;
if (y == 0.0f)
{
return 0.0f;
}
i = floorf(x / y);
f = x - i * y;
if ((x < 0.0f) != (y < 0.0f))
{
f = f - y;
}
return f;
}
-82
View File
@@ -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/utils/string.hpp"
#include "../include/utils/debug.hpp"
#include <stdio.h>
#define CHAR_BIT 8
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;
for (;; length++)
if (source[length] == '.')
break;
char *res = new char[length + 1];
for (u32 i = 0; i < length; i++)
res[i] = source[i];
res[length] = '\0';
return res;
}
char *String::createCopy(const char *source)
{
u32 srcLength = getLength(source);
char *res = new char[srcLength + 1];
for (u32 i = 0; i < srcLength; i++)
res[i] = source[i];
res[srcLength] = '\0';
return res;
}
// For test\0 will return 4
u32 String::getLength(const char *a)
{
if (a == NULL)
return 0;
for (u32 i = 0;; i++)
if (a[i] == '\0')
return i;
}
char *String::createConcatenated(const char *a, const char *b)
{
u32 aLength = getLength(a);
u32 bLength = getLength(b);
char *res = new char[aLength + bLength + 1]; // + '\0'
for (u32 i = 0; i < aLength; i++)
res[i] = a[i];
for (u32 i = 0; i < bLength; i++)
res[aLength + i] = b[i];
res[aLength + bLength] = '\0';
return res;
}
-190
View File
@@ -1,190 +0,0 @@
; ______ ____ ___
; | \/ ____| |___|
; | | | \ | |
;---------------------------
; 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
-149
View File
@@ -1,149 +0,0 @@
;-------------------------
;-------------------------
;-----VCL CODE------------
;-------------------------
;-------------------------
; =================================================
; flowMon::Emit() vcl 1.4beta7 produced this code:
.vu
.align 4
.global VU1Draw3D_CodeStart
.global VU1Draw3D_CodeEnd
VU1Draw3D_CodeStart:
__v_draw3D_vcl_4:
; _LNOPT_w=[ normal2 ] 27 [27 0] 27 [__v_draw3D_vcl_4]
NOP xtop VI06
NOP lq VF02,1(VI00)
NOP lq VF01,0(VI00)
NOP ilw.x VI01,4(VI06)
NOP ilw.y VI08,4(VI06)
NOP lq VF03,0(VI06)
NOP lq VF04,1(VI06)
NOP lq VF08,5(VI06)
NOP lq VF10,6(VI06)
NOP lq VF05,2(VI06)
NOP lq VF06,3(VI06)
NOP iaddiu VI04,VI06,0x00000009
NOP iadd VI05,VI04,VI08
NOP ilw.z VI02,4(VI06)
NOP iadd VI07,VI05,VI08
NOP loi 0x44fff000
NOP ilw.w VI03,4(VI06)
NOP lq VF07,7(VI06)
NOP sqi VF02,(VI07++)
NOP sqi VF08,(VI07++)
NOP sqi VF02,(VI07++)
NOP lq VF08,8(VI06)
NOP iadd VI06,VI05,VI08
addi.xy VF09,VF00,I loi 0x492aaaaa
NOP fcset 0
NOP iblez VI01,prim_tag_l
addi.z VF09,VF00,I sqi VF10,(VI07++)
; _LNOPT_w=[ normal2 ] 2 [2 0] 2 [__v_draw3D_vcl_5]
NOP sqi VF02,(VI07++)
NOP sqi VF01,(VI07++)
prim_tag_l:
; _LNOPT_w=[ normal2 ] 4 [4 0] 4 [prim_tag_l]
NOP iaddiu VI08,VI00,0x00007fff
NOP sqi VF07,(VI07++)
NOP iaddiu VI08,VI08,0x00000001
NOP iaddiu VI09,VI00,0
triangle_loop:
; _LNOPT_w=[ normal2 ] 11 [27 0] 27 [triangle_loop]
NOP lq VF02,0(VI04)
mulax ACC,VF03,VF02x mfir.w VF01,VI08 ; STALL_LATENCY ?3
madday ACC,VF04,VF02y NOP
maddaz ACC,VF05,VF02z NOP
maddw VF02,VF06,VF02w NOP
clipw.xyz VF02xyz,VF02w div Q,VF00w,VF02w ; STALL_LATENCY ?3
mulq.xyz VF02,VF02,Q waitq ; STALL_LATENCY ?6
mulaw.xyz ACC,VF09,VF00w NOP
madd.xyz VF02,VF02,VF09 NOP ; STALL_LATENCY ?2
NOP ibgtz VI03,vec_1_rgba
ftoi4.xyz VF01,VF02 NOP ; STALL_LATENCY ?2
; _LNOPT_w=[ normal2 ] 5 [9 0] 9 [vec_1_stq_rgba]
NOP lq VF02,0(VI05)
mulq VF01,VF02,Q sq VF01,2(VI07) ; STALL_LATENCY ?3
NOP sq VF08,1(VI07)
NOP b vec2
NOP sq VF01,0(VI07) ; STALL_LATENCY ?1
vec_1_rgba:
; _LNOPT_w=[ normal2 ] 4 [2 0] 4 [vec_1_rgba]
NOP NOP
NOP NOP
NOP sq VF08,0(VI07)
NOP sq VF01,1(VI07)
vec2:
; _LNOPT_w=[ normal2 ] 11 [27 0] 27 [vec2]
NOP lq VF02,1(VI04)
mulax ACC,VF03,VF02x mfir.w VF01,VI08 ; STALL_LATENCY ?3
madday ACC,VF04,VF02y NOP
maddaz ACC,VF05,VF02z NOP
maddw VF02,VF06,VF02w NOP
clipw.xyz VF02xyz,VF02w div Q,VF00w,VF02w ; STALL_LATENCY ?3
mulq.xyz VF02,VF02,Q waitq ; STALL_LATENCY ?6
mulaw.xyz ACC,VF09,VF00w NOP
madd.xyz VF02,VF02,VF09 NOP ; STALL_LATENCY ?2
NOP ibgtz VI03,vec_2_rgba
ftoi4.xyz VF01,VF02 NOP ; STALL_LATENCY ?2
; _LNOPT_w=[ normal2 ] 5 [9 0] 9 [vec_2_stq_rgba]
NOP lq VF02,1(VI05)
mulq VF01,VF02,Q sq VF01,5(VI07) ; STALL_LATENCY ?3
NOP sq VF08,4(VI07)
NOP b vec3
NOP sq VF01,3(VI07) ; STALL_LATENCY ?1
vec_2_rgba:
; _LNOPT_w=[ normal2 ] 4 [2 0] 4 [vec_2_rgba]
NOP NOP
NOP NOP
NOP sq VF08,2(VI07)
NOP sq VF01,3(VI07)
vec3:
; _LNOPT_w=[ normal2 ] 13 [27 0] 27 [vec3]
NOP lq VF01,2(VI04)
mulax ACC,VF03,VF01x NOP ; STALL_LATENCY ?3
madday ACC,VF04,VF01y NOP
maddaz ACC,VF05,VF01z NOP
maddw VF01,VF06,VF01w NOP
clipw.xyz VF01xyz,VF01w div Q,VF00w,VF01w ; STALL_LATENCY ?3
mulq.xyz VF01,VF01,Q waitq ; STALL_LATENCY ?6
mulaw.xyz ACC,VF09,VF00w NOP
madd.xyz VF01,VF01,VF09 fcand VI01,262143 ; STALL_LATENCY ?2
NOP iaddiu VI01,VI01,0x00007fff
NOP mfir.w VF01,VI01
NOP ibgtz VI03,vec_3_rgba
ftoi4.xyz VF01,VF01 NOP
; _LNOPT_w=[ normal2 ] 6 [9 0] 9 [vec_3_stq_rgba]
NOP lq VF02,2(VI05)
mulq VF01,VF02,Q sq VF01,8(VI07) ; STALL_LATENCY ?3
NOP sq VF08,7(VI07)
NOP iaddiu VI07,VI07,0x00000009
NOP b loop_ctrl
NOP sq VF01,-3(VI07)
vec_3_rgba:
; _LNOPT_w=[ normal2 ] 4 [3 0] 4 [vec_3_rgba]
NOP NOP
NOP sq VF08,4(VI07)
NOP iaddiu VI07,VI07,0x00000006
NOP sq VF01,-1(VI07)
loop_ctrl:
; _LNOPT_w=[ normal2 ] 4 [4 0] 4 [loop_ctrl]
NOP iaddiu VI09,VI09,0x00000001
NOP iaddiu VI04,VI04,0x00000003
NOP ibne VI09,VI02,triangle_loop
NOP iaddiu VI05,VI05,0x00000003
; _LNOPT_w=[ normal2 ] 3 [1 0] 3 [__v_draw3D_vcl_21]
NOP xgkick VI06
NOP[E] NOP
NOP NOP
.align 4
VU1Draw3D_CodeEnd:
; iCount=103
; register stats:
; 10 VU User integer
; 11 VU User floating point
;-------------------------
;-------------------------
;-------------------------
;-------------------------
;-------------------------
-7
View File
@@ -1,7 +0,0 @@
; Load GS offsets to center xformed vertex in gs coord space and color clamping constant
#macro LoadScaleConstant: gs_scale
loi 2047.5
addi.xy gs_scale, vf00, i
loi 699050.625000 // ((float)0xFFFFFF) / 24.0F
addi.z gs_scale, vf00, i
#endmacro
-13
View File
@@ -1,13 +0,0 @@
#macro MatrixLoad: matrix, offset, vumem
lq matrix[0], offset+0(vumem)
lq matrix[1], offset+1(vumem)
lq matrix[2], offset+2(vumem)
lq matrix[3], offset+3(vumem)
#endmacro
#macro MatrixXForm: output_vertex, matrix, input_vertex
mul acc, matrix[0], input_vertex[x]
madd acc, matrix[1], input_vertex[y]
madd acc, matrix[2], input_vertex[z]
madd output_vertex, matrix[3], input_vertex[w]
#endmacro
-27
View File
@@ -1,27 +0,0 @@
#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
-2
View File
@@ -1,2 +0,0 @@
.vscode/
fonts/**
-39
View File
@@ -1,39 +0,0 @@
# 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
-15
View File
@@ -1,15 +0,0 @@
## 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
-4
View File
@@ -1,4 +0,0 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore
-67
View File
@@ -1,67 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Wellington Carvalho <wellcoj@gmail.com>
*/
#include "camera.hpp"
#include <utils/debug.hpp>
#include <fastmath.h>
const float CAMERA_Y = 30.0F;
// ----
// Constructors/Destructors
// ----
Camera::Camera(ScreenSettings *t_screen) : CameraBase(t_screen, &position)
{
consoleLog("Initializing camera");
verticalLevel = 80.0F;
consoleLog("Camera initialized!");
}
Camera::~Camera() {}
// ----
// Methods
// ----
void Camera::update(Pad &t_pad, Mesh &t_mesh)
{
rotate(t_pad);
followBy(t_mesh);
lookAt(t_mesh.position);
}
/** Set camera rotation by pad right joy and update unit circle
* https://en.wikipedia.org/wiki/Unit_circle
* https://www.desmos.com/calculator/3e7iypw4ow
*/
void Camera::rotate(Pad &t_pad)
{
if (t_pad.rJoyH <= 100)
horizontalLevel -= 0.08;
else if (t_pad.rJoyH >= 200)
horizontalLevel += 0.08;
if (t_pad.rJoyV <= 50 && verticalLevel > 25.0F)
verticalLevel -= 0.9F;
else if (t_pad.rJoyV >= 200 && verticalLevel < 80.0F)
verticalLevel += 0.9F;
unitCirclePosition.x = (sin(horizontalLevel) * verticalLevel);
unitCirclePosition.y = CAMERA_Y;
unitCirclePosition.z = (cos(horizontalLevel) * verticalLevel);
}
/** Rotate camera around 3D object */
void Camera::followBy(Mesh &t_mesh)
{
position.x = unitCirclePosition.x + t_mesh.position.x;
position.y = unitCirclePosition.y + t_mesh.position.y;
position.z = unitCirclePosition.z + t_mesh.position.z;
}
-41
View File
@@ -1,41 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Wellington Carvalho <wellcoj@gmail.com>
*/
#ifndef _CAMERA_
#define _CAMERA_
#include <modules/pad.hpp>
#include <models/mesh.hpp>
#include <models/math/vector3.hpp>
#include <models/screen_settings.hpp>
#include <modules/camera_base.hpp>
#include <tamtypes.h>
/** 3D camera which follow by 3D object. Can be rotated via pad */
class Camera : public CameraBase
{
public:
Vector3 up, position, unitCirclePosition;
float horizontalLevel, verticalLevel;
Camera(ScreenSettings *t_screen);
~Camera();
void update(Pad &t_pad, Mesh &t_mesh);
void rotate(Pad &t_pad);
void followBy(Mesh &t_mesh);
protected:
Vector3 *getPosition() { return &position; };
ScreenSettings screen;
};
#endif
-48
View File
@@ -1,48 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# 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);
}
-40
View File
@@ -1,40 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# 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
-20
View File
@@ -1,20 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Wellington Carvalho <wellcoj@gmail.com>
*/
#include "cubes.hpp"
int main()
{
Engine engine = Engine();
Cubes game = Cubes(&engine);
game.engine->init(&game, 128);
SleepThread();
return 0;
}
-78
View File
@@ -1,78 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Wellington Carvalho <wellcoj@gmail.com>
*/
#include "cube.hpp"
#include <models/mesh.hpp>
#include <loaders/obj_loader.hpp>
#include <utils/debug.hpp>
// ----
// Constructors/Destructors
// ----
Cube::Cube(TextureRepository *t_texRepo)
{
consoleLog("Creating cube");
texRepo = t_texRepo;
speed = 1.2F;
mesh.loadObj("meshes/cube/", "cube", 10.0F, true);
mesh.position.set(20.00F, 40.00F, 10.00F);
mesh.rotation.x = -1.566F;
mesh.rotation.z = 1.566F;
texRepo->addByMesh("meshes/cube/", mesh, PNG);
consoleLog("Cube object created!");
}
void Cube::update(const Pad &t_pad, const Camera &t_camera)
{
rotate(t_pad);
Vector3 *nextPos = getNextPosition(t_pad, t_camera);
}
Vector3 *Cube::getNextPosition(const Pad &t_pad, const Camera &t_camera)
{
Vector3 *result = new Vector3(mesh.position);
Vector3 normalizedCamera = Vector3(t_camera.unitCirclePosition);
normalizedCamera.normalize();
normalizedCamera *= speed;
if (t_pad.lJoyV <= 100)
{
result->x += -normalizedCamera.x;
result->z += -normalizedCamera.z;
}
else if (t_pad.lJoyV >= 200)
{
result->x += normalizedCamera.x;
result->z += normalizedCamera.z;
}
if (t_pad.lJoyH <= 100)
{
result->x += -normalizedCamera.z;
result->z += normalizedCamera.x;
}
else if (t_pad.lJoyH >= 200)
{
result->x += normalizedCamera.z;
result->z += -normalizedCamera.x;
}
return result;
}
void Cube::rotate(const Pad &t_pad)
{
//if (t_pad.rJoyH >= 200)
//else if (t_pad.rJoyH <= 100)
mesh.rotation.x += (0.01 * speed);
mesh.rotation.y += (0.01 * speed);
mesh.rotation.z += (0.01 * speed);
}
-37
View File
@@ -1,37 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Wellington Carvalho <wellcoj@gmail.com>
*/
#ifndef _CUBE_
#define _CUBE_
#include "../camera.hpp"
#include <tamtypes.h>
#include <modules/pad.hpp>
#include <modules/timer.hpp>
#include "modules/texture_repository.hpp"
/** Cube 3D object class */
class Cube
{
public:
Mesh mesh;
Cube( TextureRepository *t_texRepo );
~Cube();
void update(const Pad &t_pad, const Camera &t_camera);
private:
TextureRepository *texRepo;
Vector3 *getNextPosition(const Pad &t_pad, const Camera &t_camera);
void rotate(const Pad &t_pad);
float speed;
};
#endif
-2
View File
@@ -1,2 +0,0 @@
.vscode/
fonts/**
-41
View File
@@ -1,41 +0,0 @@
# Project settings
DIR_NAME = dolphin
EE_LIBS = -ltyra
EE_OBJS = \
camera.o \
objects/player.o \
objects/collectible.o \
objects/mine.o \
dolphin.o \
main.o
# ----------------
# Other
EE_BIN = $(DIR_NAME).elf
all: $(EE_BIN)
$(EE_STRIP) --strip-all $(EE_BIN)
mv $(EE_BIN) bin/$(EE_BIN)
rebuild-engine:
cd $(TYRA)/src/engine && make clean && make EE_CXXFLAGS="-DNDEBUG $(EE_CXXFLAGS)"
rebuild-dbg-engine:
cd $(TYRA)/src/engine && make clean && make
clean:
rm -f $(EE_OBJS)
run:
killall -v ps2client || true
ps2client reset
ps2client reset
cd bin/ && ps2client execee host:$(EE_BIN)
run-pcsx2:
taskkill.exe /f /t /im pcsx2.exe || true
$(WSL_LINUX_PCSX2)/pcsx2.exe --elf=$(WSL_MAKE_WINDOWS)\\repos\\tyra\\src\\samples\\$(DIR_NAME)\\bin\\$(EE_BIN)
include $(TYRA)/src/engine/Makefile.pref
-20
View File
@@ -1,20 +0,0 @@
## Dolphin sample
### Features
- Animated character
- Collectibles and mines
- Big DFF mesh
- Background songs
- Overlay
- Audio effects (ADPCM)
- Transparent 2D UI
- Usage of draw() in array mode (for water tiles, very fast)
### Assets
You can download assets from [latest release](https://github.com/h4570/tyra/releases/latest) (unpack to `/repos/tyra/src/samples/dolphin/bin`)
### Screenshot
[![Dolphin screenshot][dolphin-screenshot]](#)
[dolphin-screenshot]: http://apgcglz.cluster028.hosting.ovh.net/tyra/dolphin.gif
-4
View File
@@ -1,4 +0,0 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore
-54
View File
@@ -1,54 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Michał Mostowik <mostek3pl@gmail.com>
*/
#include "camera.hpp"
#include <utils/math.hpp>
const float CAMERA_Y = 25.0F;
Camera::Camera(ScreenSettings *t_screen) : CameraBase(t_screen, &position)
{
verticalLevel = 30.0F;
}
Camera::~Camera() {}
void Camera::update(Pad &t_pad, Mesh &t_mesh)
{
float cameraRot = (t_mesh.rotation.z * 180 / Math::PI) - (horizontalLevel * 180 / Math::PI);
cameraRot += 180;
cameraRot /= 15;
horizontalLevel += cameraRot / (180 / Math::PI);
rotate(t_pad);
followBy(t_mesh);
Vector3 lookPos = Vector3(t_mesh.position.x, t_mesh.position.y + 10.0F, t_mesh.position.z);
lookAt(lookPos);
}
void Camera::rotate(Pad &t_pad)
{
if (t_pad.rJoyH <= 100)
horizontalLevel -= 0.08;
else if (t_pad.rJoyH >= 200)
horizontalLevel += 0.08;
unitCirclePosition.x = (Math::sin(horizontalLevel) * verticalLevel);
unitCirclePosition.y = CAMERA_Y;
unitCirclePosition.z = (Math::cos(horizontalLevel) * verticalLevel);
}
void Camera::followBy(Mesh &t_mesh)
{
position.x = unitCirclePosition.x + t_mesh.position.x;
position.y = unitCirclePosition.y + t_mesh.position.y;
position.z = unitCirclePosition.z + t_mesh.position.z;
}
-40
View File
@@ -1,40 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Michał Mostowik <mostek3pl@gmail.com>
*/
#ifndef _CAMERA_
#define _CAMERA_
#include <modules/pad.hpp>
#include <models/mesh.hpp>
#include <models/math/vector3.hpp>
#include <models/screen_settings.hpp>
#include <modules/camera_base.hpp>
#include <tamtypes.h>
class Camera : public CameraBase
{
public:
Vector3 position, up, unitCirclePosition;
float horizontalLevel, verticalLevel;
Camera(ScreenSettings *t_screen);
~Camera();
void update(Pad &t_pad, Mesh &t_mesh);
void rotate(Pad &t_pad);
void followBy(Mesh &t_mesh);
protected:
Vector3 *getPosition() { return &position; };
ScreenSettings screen;
};
#endif
-296
View File
@@ -1,296 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Michał Mostowik <mostek3pl@gmail.com>
*/
#include "dolphin.hpp"
#include "utils/math.hpp"
float Dolphin::engineFPS = 60.0F;
const float WATER_TILE_SCALE = 6.0F;
const u8 WATER_SIZE = 4;
const u8 MINES_COUNT = 15;
const u8 OYSTERS_COUNT = 5;
Dolphin::Dolphin(Engine *t_engine) : engine(t_engine), camera(&engine->screen)
{
oysters = new Collectible[OYSTERS_COUNT];
mines = new Mine[MINES_COUNT];
}
Dolphin::~Dolphin()
{
delete[] oysters;
delete[] mines;
delete[] waterDrawList;
}
void Dolphin::onInit()
{
player.init(engine);
engine->renderer->setCameraDefinitions(&camera.view, &camera.position, camera.planes);
engine->audio.loadSong("sound/dirediredocks.wav");
engine->audio.playSong();
engine->audio.setSongVolume(60);
surfaceAmbient = engine->audio.loadADPCM("sound/surface.sad");
underwaterAmbient = engine->audio.loadADPCM("sound/underwater.sad");
pickupSound = engine->audio.loadADPCM("sound/pickup.sad");
boomSound = engine->audio.loadADPCM("sound/boom.sad");
engine->audio.playADPCM(surfaceAmbient, 0);
engine->audio.playADPCM(underwaterAmbient, 1);
texRepo = engine->renderer->getTextureRepository();
engine->renderer->disableVSync();
printf("loading island..\n");
island.loadDff("sunnyisl/", "sunnyisl", 5.0F, false);
printf("Loaded..\n");
island.rotation.x = -1.6F;
island.position.set(0.0F, 60.0F, 20.0F);
island.shouldBeBackfaceCulled = true;
island.shouldBeFrustumCulled = false;
gameOver.size.set(640.0F, 480.0F);
Texture *gameOverTex = texRepo->add("2d/", "gameover", PNG);
gameOver.setMode(MODE_STRETCH);
gameOverTex->addLink(gameOver.getId());
printf("Loading water overlay...\n");
waterOverlay.size.set(640.0F, 480.0F);
Texture *watOverlayTex = texRepo->add("2d/", "underwater_overlay", PNG);
waterOverlay.setMode(MODE_STRETCH);
watOverlayTex->addLink(waterOverlay.getId());
printf("Loaded.\n");
printf("Loading water...\n");
u32 spiralOffset = (u32)sqrt(WATER_TILES_COUNT);
waterDrawList = new Mesh *[WATER_TILES_COUNT];
calcSpiral(spiralOffset, spiralOffset);
water[0].loadObj("water/", "water", WATER_TILE_SCALE, false);
water[0].position.set(0.0F, WATER_LEVEL, 0.0F);
texRepo->addByMesh("water/", water[0], BMP);
water[0].shouldBeFrustumCulled = true;
water[0].shouldBeBackfaceCulled = false;
waterDrawList[0] = &water[0];
for (size_t i = 1; i < WATER_TILES_COUNT; i++)
{
water[i].loadFrom(water[0]);
water[i].shouldBeFrustumCulled = true;
water[i].shouldBeBackfaceCulled = false;
water[i].position.set(WATER_TILE_SCALE * 2.0F * spirals[i].x, WATER_LEVEL, WATER_TILE_SCALE * 2.0F * spirals[i].y);
texRepo->getBySpriteOrMesh(water[0].getMaterial(0).getId())->addLink(water[i].getMaterial(0).getId());
waterDrawList[i] = &water[i];
}
printf("Loading seabed...\n");
seabed.loadObj("seabed/", "seabed", 10.0F, false);
seabed.position.set(0, -250.0F, 0);
texRepo->addByMesh("seabed/", seabed, BMP);
seabed.shouldBeBackfaceCulled = false;
seabed.shouldBeFrustumCulled = false;
skybox.loadObj("skybox/", "skybox", 400.0F, false);
skybox.shouldBeFrustumCulled = false;
waterbox.loadObj("waterbox/", "waterbox", 250.0F, false);
waterbox.shouldBeFrustumCulled = false;
waterbox.shouldBeBackfaceCulled = false;
waterbox.rotation.x = Math::PI;
waterbox.position.y = -100.F;
printf("Loading oyster dff\n");
oysters[0].mesh.loadObj("oyster/", "oyster", 10.F, false);
printf("Loaded.");
oysters[0].mesh.shouldBeBackfaceCulled = false;
oysters[0].mesh.shouldBeFrustumCulled = false;
oysters[0].mesh.position.set(15, 0, 15);
texRepo->addByMesh("oyster/", oysters[0].mesh, BMP);
printf("Adding oyster texture.\n");
for (int i = 1; i < OYSTERS_COUNT; i++)
{
printf("Processing oyster %d\n", i);
oysters[i].mesh.loadFrom(oysters[0].mesh);
oysters[i].mesh.shouldBeBackfaceCulled = false;
oysters[i].mesh.shouldBeFrustumCulled = false;
texRepo->getBySpriteOrMesh(oysters[0].mesh.getMaterial(0).getId())->addLink(oysters[i].mesh.getMaterial(0).getId());
oysters[i].mesh.position.set(i * -100, 5.0F, i * -100);
}
printf("Loading mine .obj\n");
mines[0].mesh.loadObj("mine/", "mine", 10.F, false);
mines[0].mesh.shouldBeBackfaceCulled = false;
mines[0].mesh.shouldBeFrustumCulled = false;
mines[0].mesh.position.set(5, -15, 32);
texRepo->addByMesh("mine/", mines[0].mesh, BMP);
printf("Adding mine texture.\n");
for (int i = 1; i < MINES_COUNT; i++)
{
printf("Processing mine %d\n", i);
mines[i].mesh.loadFrom(mines[0].mesh);
mines[i].mesh.shouldBeBackfaceCulled = false;
mines[i].mesh.shouldBeFrustumCulled = false;
texRepo->getBySpriteOrMesh(mines[0].mesh.getMaterial(0).getId())->addLink(mines[i].mesh.getMaterial(0).getId());
mines[i].mesh.position.set(i * -10, 0.0F, i * -68);
}
Texture *pLifeTex = texRepo->add("2d/", "life", PNG);
// pLifeTex->addLink(lifeSprites[0].getId());
for (int i = 0; i < 3; i++)
{
lifeSprites[i].size.set(64.0F, 64.0F);
lifeSprites[i].setMode(MODE_STRETCH);
lifeSprites[i].position.set(395 + (64 * i), 0);
pLifeTex->addLink(lifeSprites[i].getId());
}
texRepo->addByMesh("dolphin/", player.mesh, BMP);
texRepo->addByMesh("sunnyisl/", island, BMP);
texRepo->addByMesh("skybox/", skybox, BMP);
texRepo->addByMesh("waterbox/", waterbox, BMP);
bulb.intensity = 55;
bulb.position.set(5.0F, 10.0F, 10.0f);
printf("Finished initialization\n");
}
void Dolphin::onUpdate()
{
if (player.getLifes() <= 0)
{
engine->audio.stopSong();
engine->audio.setADPCMVolume(0, 0);
engine->audio.setADPCMVolume(75, 1);
engine->renderer->draw(gameOver);
return;
}
Dolphin::engineFPS = engine->fps;
// if (engine->pad.isCrossClicked)
// printf("Delta multiplier: %f\n", 60.0F / engine->fps);
float xDist = player.mesh.position.x - water[0].position.x;
float zDist = player.mesh.position.z - water[0].position.z;
if (xDist < 0)
xDist *= -1;
if (zDist < 0)
zDist *= -1;
if (xDist > WATER_SIZE * WATER_TILE_SCALE / 4 ||
zDist > WATER_SIZE * WATER_TILE_SCALE / 4)
{
for (size_t i = 0; i < WATER_TILES_COUNT; i++)
{
water[i].position.x = player.mesh.position.x + (WATER_TILE_SCALE * 2.0F * spirals[i].x);
water[i].position.z = player.mesh.position.z + (WATER_TILE_SCALE * 2.0F * spirals[i].y);
}
}
for (int i = 0; i < OYSTERS_COUNT; i++)
{
oysters[i].update();
Vector3 vecDist = oysters[i].mesh.position - player.mesh.position;
float dist = vecDist.length();
if (dist < 20.F && player.isJumping() && oysters[i].isActive())
{
printf("Pickup:%d Dist:%f\n", i, dist);
oysters[i].disappear();
player.setLife(player.getLifes() + 1);
engine->audio.setADPCMVolume(30, 3);
engine->audio.playADPCM(pickupSound, 3);
}
}
for (int i = 0; i < MINES_COUNT; i++)
{
mines[i].update();
Vector3 vecDist = mines[i].mesh.position - player.mesh.position;
float dist = vecDist.length();
if (dist < 20.F && !mines[i].getExplosionTicks())
{
printf("Vecdist: %f,%f,%f\n", vecDist.x, vecDist.y, vecDist.z);
printf("Explode:%d Dist:%f\n", i, dist);
mines[i].explode();
player.setLife(player.getLifes() - 1);
// Buffer switching to prevent playing two sounds on one buffer
engine->audio.setADPCMVolume(65, Mine::lastSoundBuffer);
engine->audio.playADPCM(boomSound, Mine::lastSoundBuffer);
Mine::lastSoundBuffer = Mine::lastSoundBuffer == 4 ? 5 : 4;
}
}
if (player.mesh.position.y > WATER_LEVEL - 5)
player.mesh.position.y = WATER_LEVEL - 5;
player.update(engine->pad);
camera.update(engine->pad, player.mesh);
skybox.position.set(player.mesh.position.x, +200.0F, player.mesh.position.z);
waterbox.position.set(player.mesh.position.x, -260.0F, player.mesh.position.z);
engine->renderer->draw(island);
engine->renderer->draw(waterDrawList, WATER_TILES_COUNT);
engine->renderer->draw(skybox);
engine->renderer->draw(waterbox);
engine->renderer->draw(seabed);
for (u8 i = 0; i < OYSTERS_COUNT; i++)
if (oysters[i].isActive())
engine->renderer->draw(oysters[i].mesh);
for (u8 i = 0; i < MINES_COUNT; i++)
if (mines[i].getExplosionTicks() < MINE_EXPLOSION_TICKS)
engine->renderer->draw(mines[i].mesh);
for (u8 i = 0; i < player.getLifes(); i++)
engine->renderer->draw(lifeSprites[i]);
engine->renderer->draw(player.mesh);
if (camera.position.y < WATER_LEVEL)
{
engine->renderer->draw(waterOverlay);
engine->audio.setADPCMVolume(0, 0); // Surface ambient
engine->audio.setADPCMVolume(65, 1); // Underwater ambient
}
else
{
engine->audio.setADPCMVolume(50, 0); //Surface ambient
engine->audio.setADPCMVolume(0, 1); //Underwater ambient
}
}
void Dolphin::calcSpiral(int X, int Y)
{
int x, y, dx;
x = y = dx = 0;
int dy = -1;
int t = X > Y ? X : Y;
int maxI = t * t;
for (int i = 0; i < maxI; i++)
{
if ((-X / 2 <= x) && (x <= X / 2) && (-Y / 2 <= y) && (y <= Y / 2))
{
spirals[i].x = x;
spirals[i].y = y;
}
if ((x == y) || ((x < 0) && (x == -y)) || ((x > 0) && (x == 1 - y)))
{
t = dx;
dx = -dy;
dy = t;
}
x += dx;
y += dy;
}
}
-69
View File
@@ -1,69 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Michał Mostowik <mostek3pl@gmail.com>
*/
#ifndef _DRIVER_
#define _DRIVER_
#include <tamtypes.h>
#include <audsrv.h>
#include <game.hpp>
#include <engine.hpp>
#include <models/light_bulb.hpp>
#include <models/sprite.hpp>
#include <modules/texture_repository.hpp>
#include "./camera.hpp"
#include "./objects/player.hpp"
#include "./objects/collectible.hpp"
#include "./objects/mine.hpp"
class Dolphin : public Game
{
public:
Dolphin(Engine *t_engine);
~Dolphin();
void onInit();
void onUpdate();
Engine *engine;
static float engineFPS;
private:
void calcSpiral(int X, int Y);
static const u16 WATER_TILES_COUNT = 1024;
Point spirals[WATER_TILES_COUNT];
Mesh **waterDrawList;
/**
* DO NOT TOUCH ORDER OF DECLARATION!
* GCC BUG CAUSES RENDERING TO FAIL IN ANY OTHER ORDER OF DECLARATION!
*/
Mesh seabed;
Mesh island;
Mesh skybox;
Mesh mine;
LightBulb bulb;
Player player;
Camera camera;
Collectible *oysters;
TextureRepository *texRepo;
Sprite waterOverlay;
Mesh water[WATER_TILES_COUNT];
Mesh waterbox;
Sprite lifeSprites[3];
Sprite gameOver;
audsrv_adpcm_t *underwaterAmbient, *surfaceAmbient;
audsrv_adpcm_t *pickupSound;
audsrv_adpcm_t *boomSound;
Mine *mines;
};
#endif

Some files were not shown because too many files have changed in this diff Show More