Compare commits
569 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e63ae14792 | |||
| 87b983153a | |||
| cab934763f | |||
| 20d2291a88 | |||
| 4f6e55c0b0 | |||
| fbcb38d37a | |||
| a25594b95c | |||
| 86c0ab74f1 | |||
| e3726600fd | |||
| 8b8500a1c9 | |||
| 789c795c14 | |||
| a0be9022ff | |||
| 77c6702f80 | |||
| d54cba9e58 | |||
| 958ddb4ab7 | |||
| edff3a85d5 | |||
| 165cc4221e | |||
| cc42bbf56b | |||
| a340540d55 | |||
| d790349ab9 | |||
| 0cecbf0a7d | |||
| f46b058ecf | |||
| c833f93db2 | |||
| 6dc73982f9 | |||
| 1fe12962b8 | |||
| e359bcbe2b | |||
| 13f4b5e626 | |||
| 2ae1ccd761 | |||
| d7013f302b | |||
| b3fe92c996 | |||
| 822663f95e | |||
| 3f9bb33177 | |||
| fa173f1e87 | |||
| f08da7b358 | |||
| 945b9c462b | |||
| c9535412a7 | |||
| 2c41930cb2 | |||
| 2a4e2a2109 | |||
| 286b9e43a7 | |||
| f62eaff37b | |||
| 48fa642cef | |||
| cad720a399 | |||
| cf3f5b3443 | |||
| 48a0eec86b | |||
| 6a9f3c6683 | |||
| 325fea1a8b | |||
| ce00f58b89 | |||
| 5d4d2b0f06 | |||
| ca25a6de03 | |||
| a6c8eb5bce | |||
| 73b0cd90b4 | |||
| b69504c9b0 | |||
| 293113c4d0 | |||
| ac335baa75 | |||
| 0fd2478049 | |||
| a21bcee671 | |||
| 5c375dd24f | |||
| b5147bba3a | |||
| 989d2702e8 | |||
| 9f831c7a6f | |||
| 3bbf3202ac | |||
| d469e78747 | |||
| 4fa65fc535 | |||
| 409ee294eb | |||
| 4303cc2c97 | |||
| b4b48ae479 | |||
| d251df8704 | |||
| 57767eee72 | |||
| 405d5afd35 | |||
| 8eb01d34da | |||
| 1456a79135 | |||
| 3817eadc14 | |||
| 385849e3b2 | |||
| 1ba2cb55b7 | |||
| b9cde6346f | |||
| a464fac9dc | |||
| 36098c9b62 | |||
| 2e41332dca | |||
| fea2398699 | |||
| 4fb0ab3b6c | |||
| 2c3055c5a2 | |||
| 60e3804c15 | |||
| 3af2493068 | |||
| ae0d5c52fd | |||
| 83f07f4789 | |||
| 0d15d0c7c8 | |||
| 0558dd7612 | |||
| 7a4ca89b14 | |||
| 74c684fff8 | |||
| d0085e834e | |||
| 26596fa2c3 | |||
| 37257b253a | |||
| d5261dbb0c | |||
| 156973714b | |||
| 65f40091db | |||
| 6e5b75e39b | |||
| 5c2ae9770e | |||
| 7ef0e73543 | |||
| a78f430a6e | |||
| b8aa40cba8 | |||
| 58f45833fe | |||
| 03eaf726ed | |||
| 15391a81e0 | |||
| a9c91db594 | |||
| 8829bf3035 | |||
| 2054dba4ec | |||
| d65561487c | |||
| cbe346900d | |||
| 00216da1cd | |||
| 472ab5c2ad | |||
| 74c642bd83 | |||
| 5316abce42 | |||
| b6ffc11be3 | |||
| 5f5f28b3fb | |||
| 0a2d19b2d0 | |||
| 10e0f52d44 | |||
| 0df43e5a08 | |||
| 5cc5862810 | |||
| a0898e7b4c | |||
| 725c17f9d4 | |||
| 420a2d3eae | |||
| 2dad96d396 | |||
| 6b45629595 | |||
| 0c4fff4f0c | |||
| a3e4ee8496 | |||
| 599d44a491 | |||
| 5d632c36bf | |||
| 01f4121242 | |||
| 153ebb52a5 | |||
| 689c8132d1 | |||
| 82e5e87822 | |||
| 0a024e745f | |||
| da958cb094 | |||
| 5aae7cff7e | |||
| cdadb932b7 | |||
| 74668fba34 | |||
| 4a9042b129 | |||
| 34b2956c08 | |||
| 47c323ec9e | |||
| 4f3b731ad7 | |||
| b94ef8c416 | |||
| 12dd72f15e | |||
| 834d57ea32 | |||
| 347fdb240b | |||
| bc1ac1b4a3 | |||
| 927c10e82a | |||
| 1bdb33e1a6 | |||
| ff2967c7e5 | |||
| b7b32fb35a | |||
| 52a19f11a5 | |||
| 1a2f7026e5 | |||
| 8591e35c4f | |||
| d435d08cf8 | |||
| b2f538bf1c | |||
| 97946e1c6d | |||
| 7ec6bb71b8 | |||
| 19e99eee56 | |||
| 4366d6d6fb | |||
| 960f4dd0c4 | |||
| 59077bcfe9 | |||
| e894039959 | |||
| 0107e888c7 | |||
| 01e1d6adbf | |||
| 31b7626bea | |||
| 440f25d7d8 | |||
| 7a80c15ac8 | |||
| dfb8bc73c3 | |||
| cf553b7376 | |||
| af843fba87 | |||
| 21073a8a99 | |||
| b2c0bfbe11 | |||
| 10164beadf | |||
| 97e44507ff | |||
| 7a9b294945 | |||
| 70028a8f18 | |||
| ff5757bf9b | |||
| 237066bfd4 | |||
| 0c63de8ac9 | |||
| 819a7c3de3 | |||
| c1f88d2f15 | |||
| 7c1ab0bfaa | |||
| 9d18a81c2a | |||
| cf8ca23ba9 | |||
| f5a7b7519e | |||
| 9a5993232a | |||
| 91e425e0f8 | |||
| 91ba265310 | |||
| 1e2560c566 | |||
| 23e98afe91 | |||
| e7a9230b59 | |||
| 1ffba47119 | |||
| 17d7634f1d | |||
| 1ae7939cc3 | |||
| 22998fbbef | |||
| c5aea0d50f | |||
| c8592e0c67 | |||
| 0b60aa0f6d | |||
| aad634a241 | |||
| 2c72abe081 | |||
| 04e89fd3a2 | |||
| a9975c9da2 | |||
| 81686a8033 | |||
| e7e4f375ba | |||
| 4e0785754e | |||
| 86c11034bf | |||
| 07d7db97c2 | |||
| 7fd2926d1d | |||
| dfd79a307e | |||
| 2fe40c8d90 | |||
| f08fc1c8d3 | |||
| 0953ce3f19 | |||
| efdec2c52e | |||
| 9850028811 | |||
| a5e1a28164 | |||
| 95c01afa01 | |||
| 34c553af04 | |||
| 85f4f2e666 | |||
| f651ec76ac | |||
| f249936981 | |||
| c56c3d76db | |||
| ecfaef1b85 | |||
| bb02a3d9bf | |||
| 632be84ceb | |||
| 2797d71618 | |||
| c8b22ff331 | |||
| 44c1ee4fe8 | |||
| 7f619ec829 | |||
| 94a77267a8 | |||
| 950d0fc052 | |||
| e11af10ba1 | |||
| 4b0f2862d3 | |||
| bb6956576b | |||
| 288d27f97b | |||
| 12de377525 | |||
| 0afd450c63 | |||
| e9ff711c38 | |||
| 9a0504f94a | |||
| 3ee31276ef | |||
| 3a68de50cb | |||
| 7f9addbeb9 | |||
| 3f3e6a0df4 | |||
| 7bfe7675cb | |||
| c7f210706d | |||
| 3a06ac548d | |||
| 8225abf328 | |||
| 2e23914c17 | |||
| e7c2f8a7c7 | |||
| 756fb216a4 | |||
| de4ce28839 | |||
| ed59d6b254 | |||
| 3fe9715958 | |||
| cba177f2db | |||
| 781c97eb73 | |||
| 5245ba3f55 | |||
| f0b5d25a27 | |||
| 5f22c02d2e | |||
| d63bd6cb0e | |||
| 921f34eb4c | |||
| 385e553e5a | |||
| e4230f1b62 | |||
| 94a353cdb8 | |||
| 8a162be036 | |||
| 1d273de455 | |||
| eecfc0b6c2 | |||
| 7ff8153086 | |||
| 9cb52ff620 | |||
| 3023bb7501 | |||
| 762e7eada2 | |||
| 70ea8e47ba | |||
| dd8499abad | |||
| 0816f522bb | |||
| fafc66d35c | |||
| d8458b98e0 | |||
| d0d7ed85e5 | |||
| a80f62e843 | |||
| 8b0233a45d | |||
| 10b275055c | |||
| 164d9f558c | |||
| 247e71a407 | |||
| ea49543542 | |||
| 20de0dc17d | |||
| 1090801f4e | |||
| 7b43c0c90f | |||
| b0ae873a88 | |||
| 7b3a28065b | |||
| 589b3b03a4 | |||
| 611d4f76be | |||
| bf0c65a14c | |||
| ab0c999117 | |||
| 28599512e4 | |||
| db6c84ba11 | |||
| b0c94a1602 | |||
| f34284591f | |||
| 7203f6f5c4 | |||
| 94f6e9fbf2 | |||
| 18ba08dc7a | |||
| 9dd69317e3 | |||
| 24509f7f20 | |||
| 9268628ccd | |||
| 4160bddc4b | |||
| e022fcdafe | |||
| 444990a262 | |||
| b749a80a25 | |||
| e43fae88e8 | |||
| 11717f42eb | |||
| 142bf60a6d | |||
| 9efd8ab3e1 | |||
| 7b2e411a13 | |||
| 8bd5476d61 | |||
| 4146df48a9 | |||
| 35fc8aea73 | |||
| c0bb78f1c9 | |||
| e5c2aa1548 | |||
| c72393b236 | |||
| a973c47321 | |||
| bc41afdf89 | |||
| 67bbe2e674 | |||
| 69b3621215 | |||
| b053504623 | |||
| ad43a4bfd3 | |||
| 1b6e1e94ee | |||
| 6e09741d19 | |||
| 152bc7d6cf | |||
| 25255c1c22 | |||
| afa98e8bdf | |||
| 55bc876dfb | |||
| 6432fc183e | |||
| a971309e2d | |||
| b94fa40eac | |||
| c1ed10eb3b | |||
| 07ba692009 | |||
| 64a2ccd6f3 | |||
| ea0d47e09c | |||
| 913f52ec6f | |||
| 55f476e9ed | |||
| 1d7730504b | |||
| c7fe915174 | |||
| 92d5ad7ad0 | |||
| e987089df0 | |||
| 89295ff27a | |||
| d0c2dfcaa3 | |||
| 7f9f86d7c3 | |||
| 91772a905c | |||
| 8a8d453ee0 | |||
| 8406dcee72 | |||
| 4c8ead755b | |||
| aeb25ad398 | |||
| d60d42cac6 | |||
| c0ece7206c | |||
| 096f2490ec | |||
| b4fe16dccc | |||
| 469ef48051 | |||
| 91934df5e8 | |||
| e39c8c5de8 | |||
| 8589a298da | |||
| 5a932b35ca | |||
| 7dd8947612 | |||
| 4b2deb8b39 | |||
| e0ad58f72f | |||
| f95e805d33 | |||
| b935d4da13 | |||
| f6cbac7c20 | |||
| 3af3576203 | |||
| ae3dd737e5 | |||
| 23ea1a28f6 | |||
| 115dac21bc | |||
| f8f91c6b49 | |||
| 8137bd56d8 | |||
| cf07cf78c8 | |||
| 13f6a2ecb7 | |||
| 9e1a9e8b3c | |||
| 5c232aebce | |||
| 586fe136ea | |||
| 02d7916925 | |||
| 1cc1e62ed6 | |||
| 1765885bec | |||
| d835f83e51 | |||
| 974138d64e | |||
| ae15906c99 | |||
| 71ce30a8fc | |||
| 55d8e445db | |||
| 11a4e2ee76 | |||
| 596bf2d89a | |||
| 53c134b0d5 | |||
| 9b2d39505b | |||
| 44776f7aba | |||
| bb0ec257b2 | |||
| a8a649d723 | |||
| 73a3d1d7e5 | |||
| dfee1ab25f | |||
| fcf03b27fa | |||
| b8d31fc1cc | |||
| 249c2431a2 | |||
| 2d1d36ddcc | |||
| bd11955fd4 | |||
| 3c827a407b | |||
| 607c2abc0c | |||
| 49713dc145 | |||
| 18db9875ad | |||
| 37703e69d0 | |||
| d4f2a1e1a2 | |||
| 91e8f791b0 | |||
| 12ef639516 | |||
| 552f2c6e4a | |||
| ea6d5215d1 | |||
| 4a1bca12aa | |||
| 0156d4444f | |||
| 623576a387 | |||
| 3f4d2c5521 | |||
| 206ccdf415 | |||
| 7025f5371b | |||
| 2455ce82dd | |||
| 2ce2e76663 | |||
| f4e699025a | |||
| b050e4643b | |||
| e38f569bc4 | |||
| 3dd51607f0 | |||
| b7618c014a | |||
| 8256efa7c8 | |||
| ac36012545 | |||
| 968718a549 | |||
| 24bab8464a | |||
| 4bee938106 | |||
| 86c48eeca4 | |||
| 97151ffc78 | |||
| bc44f598c1 | |||
| 5129d53b27 | |||
| 1539aa4108 | |||
| 083c041973 | |||
| 0c0512b37f | |||
| e7aa4d13cc | |||
| 1c9351e5e9 | |||
| f86a1bf190 | |||
| 36a637e5e6 | |||
| c4fc52b043 | |||
| 70efbcad46 | |||
| db635c09ea | |||
| edf5bd1e55 | |||
| f4421b659d | |||
| a017c3a3b6 | |||
| 220caba84a | |||
| 921b482e61 | |||
| 45edf7aedb | |||
| d9b5f8a4aa | |||
| 4557485cab | |||
| 582b42c29e | |||
| 6e1c94a112 | |||
| 62cff819ff | |||
| 729bcff954 | |||
| 8a0f5f7b84 | |||
| 5787b6a920 | |||
| 6d9b93998a | |||
| 96fe7c380e | |||
| 11a92c32ee | |||
| 87ae4b0507 | |||
| ad855a13d2 | |||
| 14b688c6cb | |||
| 0474fc07a5 | |||
| e00e677d1e | |||
| 3284c5a598 | |||
| dd49fc165e | |||
| 83dce5cb92 | |||
| 32422b87eb | |||
| 6292c27c50 | |||
| 4b158781af | |||
| cad2623649 | |||
| d94f51623c | |||
| 18f3398687 | |||
| 1c3edb3887 | |||
| 5fb6858678 | |||
| 8a1bc254c5 | |||
| 0423e484a5 | |||
| ed6c20e5df | |||
| f95794c181 | |||
| 9f4f6f4b18 | |||
| fbbb41580c | |||
| d15cdecd97 | |||
| 8b9ea4696e | |||
| 9fb2cb385a | |||
| 97c9a5cd90 | |||
| f080a97dc5 | |||
| 55cee63ace | |||
| 69d4cf81ec | |||
| bcad6f7941 | |||
| 94e4f8ea3a | |||
| d0017f26f1 | |||
| 9a94d93747 | |||
| 67a10cb724 | |||
| b8552330bd | |||
| 20b14a5168 | |||
| c0ab97585c | |||
| d61396866d | |||
| b547de9cbb | |||
| a05b4fbd0f | |||
| 3e385f7c84 | |||
| fd29a11579 | |||
| 82361e4619 | |||
| b48d342adf | |||
| d22d125afa | |||
| 513ae84577 | |||
| db23acddd7 | |||
| 17ef6b9fbc | |||
| e5eb57e587 | |||
| f45f5c39c7 | |||
| bae834e599 | |||
| 72266d0c25 | |||
| a6f8bb9b36 | |||
| 940271fe8c | |||
| 7e676916a0 | |||
| d58163d75b | |||
| 56e1d7d5d8 | |||
| 945aeb1bec | |||
| c662307942 | |||
| 389a5ee608 | |||
| ade89bbdd1 | |||
| ca7846f60b | |||
| 510199164c | |||
| 3841487388 | |||
| 51702d5ef7 | |||
| 6f1d0e2e33 | |||
| eed34a17bc | |||
| 2fad5f67f1 | |||
| 7d2f354085 | |||
| 7233e6a4f4 | |||
| 94db15da9b | |||
| d1f16cf9b3 | |||
| 25b5fb4295 | |||
| 3cbea1877a | |||
| e9febb5d8d | |||
| 756f69d160 | |||
| 1e4022171d | |||
| 66f67b0d22 | |||
| 82cab6f78b | |||
| 5e811b78cd | |||
| 3d755e9983 | |||
| 6b821afd86 | |||
| 8a3485e671 | |||
| 33d7f9648d | |||
| 2b42bc53cb | |||
| 4112e6d327 | |||
| d2ce2eb7b2 | |||
| 00c171d6b9 | |||
| 7e442bcf5c | |||
| c1ad6effbd | |||
| 6c82beb383 | |||
| fb0df1537e | |||
| c6af82943a | |||
| f3a1bcb47d | |||
| ac7a04b669 | |||
| a3a6150ecb | |||
| 3b5fb1b670 | |||
| 3dc304b829 | |||
| b11df0262e | |||
| eba254f13b | |||
| 3fdbda4a4a | |||
| 1868b714bc | |||
| bfd75003a4 | |||
| 1757ef67dc | |||
| efe34c677d | |||
| d2013d4467 | |||
| b48fa16274 | |||
| 1f11c9f8e5 | |||
| ef16f1dbe2 | |||
| aa6b2d314b | |||
| 4d53c6c5fe | |||
| 02560f2d6f | |||
| 5399b1744f | |||
| 52518540f3 | |||
| 9e3ed74b45 |
@@ -0,0 +1,40 @@
|
||||
# Use the Google style in this project.
|
||||
BasedOnStyle: Google
|
||||
|
||||
# Some folks prefer to write "int& foo" while others prefer "int &foo". The
|
||||
# Google Style Guide only asks for consistency within a project, we chose
|
||||
# "int& foo" for this project:
|
||||
DerivePointerAlignment: false
|
||||
PointerAlignment: Left
|
||||
|
||||
SortIncludes: false
|
||||
|
||||
IncludeBlocks: Merge
|
||||
IncludeCategories:
|
||||
# Matches common headers first, but sorts them after project includes
|
||||
- Regex: '^\"google/cloud/internal/disable_deprecation_warnings.inc\"$'
|
||||
Priority: -1
|
||||
- Regex: '^\"google/cloud/(internal/|grpc_utils/|testing_util/|[^/]+\.h)'
|
||||
Priority: 1000
|
||||
- Regex: '^\"google/cloud/' # project includes should sort first
|
||||
Priority: 500
|
||||
- Regex: '^\"'
|
||||
Priority: 1500
|
||||
- Regex: '^<grpc/'
|
||||
Priority: 2000
|
||||
- Regex: '^<google/*'
|
||||
Priority: 3000
|
||||
- Regex: '^<.*/.*'
|
||||
Priority: 4000
|
||||
- Regex: '^<[^/]*>'
|
||||
Priority: 5000
|
||||
|
||||
# Format raw string literals with a `pb` or `proto` tag as proto.
|
||||
RawStringFormats:
|
||||
- Language: TextProto
|
||||
Delimiters:
|
||||
- 'pb'
|
||||
- 'proto'
|
||||
BasedOnStyle: Google
|
||||
|
||||
CommentPragmas: '(@copydoc)'
|
||||
@@ -0,0 +1,5 @@
|
||||
*.elf
|
||||
.git/
|
||||
.vscode/
|
||||
docs/
|
||||
tools/
|
||||
@@ -0,0 +1,2 @@
|
||||
# Ignore all differences in line endings
|
||||
* -crlf
|
||||
@@ -0,0 +1,35 @@
|
||||
#This is a modified version of the clang format check used on Open-PS2-Loader
|
||||
name: CI-cpp-check
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- '**.hpp'
|
||||
- '**.cpp'
|
||||
- '**.'
|
||||
- '**.h'
|
||||
- './engine/inc/tyra'
|
||||
- '.github/workflows/check-format.yml'
|
||||
- '.clang-format'
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.hpp'
|
||||
- '**.cpp'
|
||||
- '**.'
|
||||
- '**.h'
|
||||
- './engine/inc/tyra'
|
||||
- '.github/workflows/check-format.yml'
|
||||
- '.clang-format'
|
||||
|
||||
jobs:
|
||||
check-format:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: DoozyX/clang-format-lint-action@v0.12
|
||||
with:
|
||||
source: '.'
|
||||
extensions: 'hpp, cpp, h'
|
||||
clangFormatVersion: 12
|
||||
inplace: False
|
||||
+33
-44
@@ -1,44 +1,33 @@
|
||||
.vscode/
|
||||
|
||||
*.[Bb][Mm][Pp]
|
||||
*.[Oo][Bb][Jj]
|
||||
*.[Ww][Aa][Vv]
|
||||
*.[Dd][Ff][Ff]
|
||||
*.[Ii][Rr][Xx]
|
||||
*.[Mm][Dd]2
|
||||
|
||||
# ---
|
||||
|
||||
# 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
|
||||
# ---
|
||||
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.vsm
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
*.erl
|
||||
*.elf
|
||||
*.irx
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
*.log
|
||||
|
||||
# Configuration files
|
||||
/c_cpp_properties.json
|
||||
/tasks.json
|
||||
/settings.json
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Docker PS2SDK",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**",
|
||||
"C:/Users/YOUR-INTELLISENSE-PATH/ps2dev-intellisense/ps2sdk/common/include/**",
|
||||
"C:/Users/YOUR-INTELLISENSE-PATH/ps2dev-intellisense/ps2sdk/ee/include/**",
|
||||
"C:/Users/YOUR-INTELLISENSE-PATH/ps2dev-intellisense/ps2sdk/iop/include/**",
|
||||
"C:/Users/YOUR-INTELLISENSE-PATH/ps2dev-intellisense/ps2sdk/ports/include/**",
|
||||
"C:/Users/YOUR-INTELLISENSE-PATH/ps2dev-intellisense/ee/include/**",
|
||||
"C:/Users/YOUR-INTELLISENSE-PATH/ps2dev-intellisense/ee/lib/gcc/mips64r5900el-ps2-elf/11.3.0/include/**",
|
||||
"C:/Users/YOUR-INTELLISENSE-PATH/ps2dev-intellisense/ee/lib/gcc/mips64r5900el-ps2-elf/11.3.0/include-fixed/**",
|
||||
"C:/Users/YOUR-INTELLISENSE-PATH/ps2dev-intellisense/ee/lib/gcc/mips64r5900el-ps2-elf/11.3.0/install-tools/include/**",
|
||||
"C:/Users/YOUR-INTELLISENSE-PATH/ps2dev-intellisense/ee/lib/gcc/mips64r5900el-ps2-elf/11.3.0/plugin/include/**",
|
||||
"C:/Users/YOUR-INTELLISENSE-PATH/ps2dev-intellisense/ee/mips64r5900el-ps2-elf/include/**",
|
||||
"C:/Users/YOUR-INTELLISENSE-PATH/ps2dev-intellisense/ee/mips64r5900el-ps2-elf/sys-include/**",
|
||||
"C:/Users/YOUR-INTELLISENSE-PATH/ps2dev-intellisense/gsKit/include/**",
|
||||
"C:/Users/YOUR-INTELLISENSE-PATH/ps2dev-intellisense/iop/lib/gcc/mipsel-ps2-elf/11.3.0/include/**",
|
||||
"C:/Users/YOUR-INTELLISENSE-PATH/ps2dev-intellisense/iop/lib/gcc/mipsel-ps2-elf/11.3.0/install-tools/include/**",
|
||||
"C:/Users/YOUR-INTELLISENSE-PATH/ps2dev-intellisense/iop/lib/gcc/mipsel-ps2-elf/11.3.0/plugin/include/**",
|
||||
"C:/Users/YOUR-INTELLISENSE-PATH/ps2dev-intellisense/iop/lib/gcc/mipsel-ps2-elf/11.3.0/include-fixed/**",
|
||||
"C:/Users/YOUR-INTELLISENSE-PATH/ps2dev-intellisense/iop/lib/gcc/mipsel-ps2-irx/11.3.0/include/**",
|
||||
"C:/Users/YOUR-INTELLISENSE-PATH/ps2dev-intellisense/iop/lib/gcc/mipsel-ps2-irx/11.3.0/install-tools/include/**",
|
||||
"C:/Users/YOUR-INTELLISENSE-PATH/ps2dev-intellisense/iop/lib/gcc/mipsel-ps2-irx/11.3.0/plugin/include/**",
|
||||
"C:/Users/YOUR-INTELLISENSE-PATH/ps2dev-intellisense/iop/lib/gcc/mipsel-ps2-irx/11.3.0/include-fixed/**"
|
||||
],
|
||||
"defines": [
|
||||
"_EE",
|
||||
"_IOP",
|
||||
"__SPU__",
|
||||
"INTELLISENSE"
|
||||
],
|
||||
"cppStandard": "c++20",
|
||||
"compilerPath": "", // Should be empty
|
||||
"intelliSenseMode": "linux-gcc-x86",
|
||||
"configurationProvider": "ms-vscode.cpptools"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"buildDirectory": "demo",
|
||||
"C_Cpp.default.intelliSenseMode": "gcc-x86",
|
||||
"files.associations": {
|
||||
"*.vcl": "asm-collection",
|
||||
"*.i": "asm-collection",
|
||||
"*.vsm": "asm-collection",
|
||||
"*.vclpp": "asm-collection",
|
||||
"*.hpp": "cpp",
|
||||
"*.cpp": "cpp",
|
||||
"*.h": "c",
|
||||
"*.c": "c"
|
||||
}
|
||||
}
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Build & run",
|
||||
"dependsOrder": "sequence",
|
||||
"dependsOn": [
|
||||
"1. Copy source code to docker volume",
|
||||
"2. Compile via docker container",
|
||||
"3. Copy binaries to host",
|
||||
"4. Run PCSX2"
|
||||
],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"label": "1. Copy source code to docker volume",
|
||||
"command": "docker exec -t tyra-compiler sh -c 'rsync -ac --delete --exclude \".git\" --exclude \"docs\" --exclude \".vscode\" --exclude \"tools\" --exclude \"obj\" --exclude \"bin\" /host/ /src/'"
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"label": "2. Compile via docker container",
|
||||
"command": "docker exec -t tyra-compiler sh -c 'cd ${config:buildDirectory} && make build-engine all'",
|
||||
"problemMatcher": {
|
||||
"base": "$gcc",
|
||||
"fileLocation": [
|
||||
"autoDetect"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"label": "3. Copy binaries to host",
|
||||
"command": "docker exec -t tyra-compiler sh -c 'rsync -zac --include=\"*/\" --include=\"bin/**\" --exclude=\"*\" /src/ /host/'"
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"label": "4. Run PCSX2",
|
||||
"options": {
|
||||
"cwd": "${config:buildDirectory}"
|
||||
},
|
||||
"command": "./run.ps1"
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"label": "Convert WAV to ADPCM",
|
||||
"dependsOn": [
|
||||
"1. Copy source code to docker volume"
|
||||
],
|
||||
"command": "docker exec -t tyra-compiler sh -c 'adpenc ${input:wav2adpcmSource} ${input:wav2adpcmTarget} && rsync -zac /src/${input:wav2adpcmTarget} /host/${input:wav2adpcmTarget}'"
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"label": "Cleanup",
|
||||
"command": "docker exec -t tyra-compiler sh -c 'rm -rf /src/*'"
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"label": "Send to PS2",
|
||||
"command": "docker exec -t tyra-compiler sh -c 'cd ${config:buildDirectory}/bin && killall -v ps2client || $true && ps2client -h ${input:ps2Ip} reset && ps2client -h ${input:ps2Ip} reset && ps2client -h ${input:ps2Ip} execee host:$(find . -maxdepth 1 -type f -name \"*.elf\")'"
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"label": "Open PS2 output logger",
|
||||
"command": "docker stop ps2-logs || $true && docker run -t --rm --name=ps2-logs -p ${input:local2Ip}:18194:18194/udp h4570/tyra sh -c 'ps2client -h ${input:ps2Ip} listen'",
|
||||
"runOptions": {
|
||||
"instanceLimit": 1
|
||||
},
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "new"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"label": "Start docker container",
|
||||
"command": "docker compose up -d"
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"label": "Stop docker container",
|
||||
"command": "docker compose down"
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"label": "[Debug] Copy obj directory to host",
|
||||
"command": "docker exec -t tyra-compiler sh -c 'rsync -zac --include=\"*/\" --include=\"obj/**\" --exclude=\"*\" /src/ /host/'"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"id": "wav2adpcmSource",
|
||||
"description": "Source file path (ex. ):",
|
||||
"default": "demo/res/sound.wav",
|
||||
"type": "promptString"
|
||||
},
|
||||
{
|
||||
"id": "wav2adpcmTarget",
|
||||
"description": "Target file path (ex. ):",
|
||||
"default": "demo/res/sound.adpcm",
|
||||
"type": "promptString"
|
||||
},
|
||||
{
|
||||
"id": "ps2Ip",
|
||||
"description": "PS2link ip address:",
|
||||
"default": "192.168.1.200",
|
||||
"type": "promptString"
|
||||
},
|
||||
{
|
||||
"id": "local2Ip",
|
||||
"description": "Local ip address:",
|
||||
"default": "192.168.1.245",
|
||||
"type": "promptString"
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"ms-vscode.cpptools-extension-pack",
|
||||
"ryzngard.vscode-header-source",
|
||||
"maziac.asm-code-lens",
|
||||
"dmnsgn.vscode-wavefront",
|
||||
"spmeesseman.vscode-taskexplorer"
|
||||
]
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM ubuntu:20.04
|
||||
|
||||
# Install necessary packages for PS2DEV, VCLPP and VCL.
|
||||
RUN apt-get update
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
RUN apt-get install -y git make g++ texinfo bison flex gettext libgmp3-dev \
|
||||
libmpfr-dev libmpc-dev gcc binutils cmake wget patch zlib1g-dev libgsl-dev \
|
||||
unzip
|
||||
|
||||
# Setup PS2DEV env
|
||||
ENV PS2DEV /usr/local/ps2dev
|
||||
RUN mkdir -p $PS2DEV
|
||||
RUN chown -R $USER: $PS2DEV
|
||||
ENV PS2SDK $PS2DEV/ps2sdk
|
||||
ENV GSKIT $PS2DEV/gsKit
|
||||
ENV PATH $PATH:${PS2DEV}/bin:${PS2DEV}/ee/bin:${PS2DEV}/iop/bin:${PS2DEV}/dvp/bin:${PS2SDK}/bin
|
||||
|
||||
# Compile PS2DEV
|
||||
RUN mkdir -p /temp/ps2dev
|
||||
RUN git clone https://github.com/ps2dev/ps2dev.git /temp/ps2dev
|
||||
WORKDIR "/temp/ps2dev"
|
||||
RUN ./build-all.sh
|
||||
|
||||
# Compile VCLPP
|
||||
RUN mkdir -p /temp/vclpp
|
||||
RUN git clone https://github.com/glampert/vclpp.git /temp/vclpp
|
||||
WORKDIR "/temp/vclpp"
|
||||
RUN make
|
||||
|
||||
# Download VCL
|
||||
RUN mkdir -p /temp/vcl
|
||||
WORKDIR "/temp/vcl"
|
||||
RUN wget http://apgcglz.cluster028.hosting.ovh.net/tyra/vcl.zip
|
||||
RUN unzip vcl.zip
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Start from clean image
|
||||
FROM ubuntu:20.04
|
||||
|
||||
# Set ENV variables
|
||||
ENV PS2DEV /usr/local/ps2dev
|
||||
ENV PS2SDK $PS2DEV/ps2sdk
|
||||
ENV PATH $PATH:${PS2DEV}/bin:${PS2DEV}/ee/bin:${PS2DEV}/iop/bin:${PS2DEV}/dvp/bin:${PS2SDK}/bin
|
||||
|
||||
# Copy stuff from previous stage
|
||||
COPY --from=0 ${PS2DEV} ${PS2DEV}
|
||||
COPY --from=0 /temp/vcl/vcl /usr/bin/vcl
|
||||
COPY --from=0 /temp/vclpp/vclpp /usr/bin/vclpp
|
||||
|
||||
# Install packages for emulating x86 and Tyra (make, libmpc, psmisc)
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y make rsync libmpc-dev qemu qemu-user-static binfmt-support psmisc
|
||||
|
||||
# Add 32bit executables support for VCL
|
||||
RUN dpkg --add-architecture i386
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y libstdc++5:i386
|
||||
RUN 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'
|
||||
|
||||
# Set chmod
|
||||
RUN chmod 755 /usr/bin/vclpp
|
||||
RUN chmod 755 /usr/bin/vcl
|
||||
|
||||
WORKDIR /src
|
||||
CMD ["/bin/bash"]
|
||||
@@ -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.
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
#Compiler and Linker
|
||||
EE_PREFIX := mips64r5900el-ps2-elf-
|
||||
AR := $(EE_PREFIX)ar
|
||||
AS := $(EE_PREFIX)as
|
||||
CC := $(EE_PREFIX)gcc
|
||||
CXX := $(EE_PREFIX)g++
|
||||
STRIP := $(EE_PREFIX)strip
|
||||
BIN2S := $(PS2SDK)/bin/bin2s
|
||||
VCL := vcl
|
||||
VCLPP := vclpp
|
||||
DVP := dvp-as
|
||||
|
||||
IRXEMBEDDEDEXT := irx-em
|
||||
|
||||
#Flags, Libraries and Includes
|
||||
CFLAGS += -D_EE -Wall -O3
|
||||
LINKFLAGS += -O3 -Wl,-zmax-page-size=128
|
||||
ASFLAGS += -O3
|
||||
LIB += -lstdc++ -ldma -lpacket2 -lgraph -ldraw -lmath3d -lpng -lz -lpad -laudsrv -lpatches -lcdvd
|
||||
INC += -I$(PS2DEV)/ps2sdk/ee/include -I$(PS2DEV)/ps2sdk/common/include -I$(PS2DEV)/ps2sdk/ports/include
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
#DO NOT EDIT BELOW THIS LINE
|
||||
#---------------------------------------------------------------------------------
|
||||
SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))
|
||||
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.$(OBJEXT)))
|
||||
|
||||
IRXEM_SOURCES := $(shell find $(SRCDIR) -type f -name *.$(IRXEMBEDDEDEXT))
|
||||
IRXEM_OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(IRXEM_SOURCES:.$(IRXEMBEDDEDEXT)=.$(OBJEXT)))
|
||||
|
||||
VU_SOURCES_VCL := $(shell find $(SRCDIR) -type f -name *.$(VCLEXT))
|
||||
VU_OBJECTS_VCL := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(VU_SOURCES_VCL:.$(VCLEXT)=.$(OBJEXT)))
|
||||
|
||||
VU_SOURCES_VSM := $(shell find $(SRCDIR) -type f -name *.$(VSMEXT))
|
||||
VU_OBJECTS_VSM := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(VU_SOURCES_VSM:.$(VSMEXT)=.$(OBJEXT)))
|
||||
|
||||
VCL_SOURCES := $(shell find $(SRCDIR) -type f -name *.$(VCLPPEXT))
|
||||
VCL_OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(VCL_SOURCES:.$(VCLPPEXT)=.$(OBJEXT)))
|
||||
|
||||
#Default Make
|
||||
all: resources $(TARGET)
|
||||
#all: resources irxcopy $(TARGET)
|
||||
|
||||
release:
|
||||
$(MAKE) CFLAGS="-DNDEBUG $(CFLAGS)"
|
||||
|
||||
#Remake
|
||||
remake: cleaner all
|
||||
|
||||
#Copy Resources from Resources Directory to Target Directory
|
||||
resources: directories
|
||||
@cp -r $(RESDIR)/* $(TARGETDIR)/ || true
|
||||
|
||||
#Make the Directories
|
||||
directories:
|
||||
@mkdir -p $(TARGETDIR)
|
||||
@mkdir -p $(BUILDDIR)
|
||||
|
||||
#Clean only Objects
|
||||
clean:
|
||||
@$(RM) -rf $(BUILDDIR)
|
||||
|
||||
#Full Clean, Objects and Binaries
|
||||
cleaner: clean
|
||||
@$(RM) -rf $(TARGETDIR)
|
||||
@$(RM) -rf $(BUILDDIR)
|
||||
|
||||
#irxcopy:
|
||||
# @cp $(PS2SDK)/iop/irx/audsrv.irx $(TARGETDIR)/audsrv.irx
|
||||
|
||||
#Pull in dependency info for *existing* .o files
|
||||
-include $(OBJECTS:.$(OBJEXT)=.$(DEPEXT))
|
||||
|
||||
#Link
|
||||
$(TARGET): $(OBJECTS) $(VCL_OBJECTS) $(VU_OBJECTS_VCL) $(VU_OBJECTS_VSM) $(IRXEM_OBJECTS)
|
||||
$(CXX) -T$(PS2DEV)/ps2sdk/ee/startup/linkfile -o $(TARGETDIR)/$(TARGET) $^ -L$(PS2DEV)/ps2sdk/ee/lib -L$(PS2SDK)/ports/lib $(LINKFLAGS) $(LIBDIRS) $(LIB)
|
||||
$(STRIP) --strip-all $(TARGETDIR)/$(TARGET)
|
||||
|
||||
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(IRXEMBEDDEDEXT)
|
||||
@mkdir -p $(dir $@)
|
||||
@rm -f $@.s
|
||||
$(BIN2S) $(shell head -1 $<) $@.s $(shell sed -n '2p' $<)
|
||||
$(AS) $(ASFLAGS) $@.s -o $@
|
||||
|
||||
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT)
|
||||
@mkdir -p $(dir $@)
|
||||
$(CXX) $(CFLAGS) $(INC) -c -o $@ $<
|
||||
@$(CXX) $(CFLAGS) $(INCDEP) -MM $(SRCDIR)/$*.$(SRCEXT) > $(BUILDDIR)/$*.$(DEPEXT)
|
||||
@cp -f $(BUILDDIR)/$*.$(DEPEXT) $(BUILDDIR)/$*.$(DEPEXT).tmp
|
||||
@sed -e 's|.*:|$(BUILDDIR)/$*.$(OBJEXT):|' < $(BUILDDIR)/$*.$(DEPEXT).tmp > $(BUILDDIR)/$*.$(DEPEXT)
|
||||
@sed -e 's/.*://' -e 's/\\$$//' < $(BUILDDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(BUILDDIR)/$*.$(DEPEXT)
|
||||
@rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp
|
||||
|
||||
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(VCLEXT)
|
||||
@mkdir -p $(dir $@)
|
||||
@rm -f $@.vsm
|
||||
$(VCL) $< >> $@.vsm
|
||||
$(DVP) $@.vsm -o $@
|
||||
|
||||
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(VSMEXT)
|
||||
@mkdir -p $(dir $@)
|
||||
$(DVP) $< -o $@
|
||||
|
||||
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(VCLPPEXT)
|
||||
@mkdir -p $(dir $@)
|
||||
@rm -f $@.vcl
|
||||
@rm -f $@.vsm
|
||||
$(VCLPP) $< $@.vcl
|
||||
$(VCL) $@.vcl > $@.vsm
|
||||
$(DVP) $@.vsm -o $@
|
||||
|
||||
run-pcsx2:
|
||||
taskkill.exe /f /t /im pcsx2x64.exe || true
|
||||
$(WSL_LINUX_PCSX2)/pcsx2x64.exe --elf=$(WSL_MAKE_WINDOWS)$(CURDIR)/$(TARGETDIR)/$(TARGET)
|
||||
|
||||
#Non-File Targets
|
||||
.PHONY: all remake clean cleaner resources
|
||||
@@ -1,157 +1,171 @@
|
||||
[![Contributors][contributors-shield]][contributors-url]
|
||||
[![MIT License][license-shield]][license-url]
|
||||
|
||||
<br />
|
||||
<p align="center">
|
||||
<a href="https://github.com/ps2-tyra/tyra">
|
||||
<img src="http://allvectorlogo.com/img/2016/05/ps2-logo.png" alt="Logo" width="230" height="125">
|
||||
</a>
|
||||
|
||||
<h3 align="center">Tyra alpha 1.1.0</h3>
|
||||
|
||||
<p align="center">
|
||||
First open source renderer and game engine for PS2 (PlayStation 2™).
|
||||
<br />
|
||||
<a href="https://www.youtube.com/"><strong>View Demo (soon) »</strong></a>
|
||||
<br />
|
||||
<br />
|
||||
<a href="https://github.com/ps2-tyra/tyra/issues">Report Bug</a>
|
||||
·
|
||||
<a href="https://github.com/ps2-tyra/tyra/issues">Request Feature</a>
|
||||
</p>
|
||||
</p>
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [About the Project](#about-the-project)
|
||||
* [Samples](#samples)
|
||||
* [About project](#about-project)
|
||||
* [Acronyms](#acronyms)
|
||||
* [Tyra features](#tyra-features)
|
||||
* [Built With](#built-with)
|
||||
* [Getting Started](#getting-started)
|
||||
* [Prerequisites](#prerequisites)
|
||||
* [Installation](#installation)
|
||||
* [Roadmap](#roadmap)
|
||||
* [Contributing](#contributing)
|
||||
* [License](#license)
|
||||
* [Contact](#contact)
|
||||
* [Thanks](#thanks)
|
||||
|
||||
## About The Project
|
||||
|
||||
<img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/1.1.0/tyra.gif" alt="sample" width="600" height="auto">
|
||||
|
||||
### Samples
|
||||
* [Floors](https://github.com/ps2-tyra/tyra/tree/master/src/samples/floors)
|
||||
* [Ari (WIP)](https://github.com/ps2-tyra/tyra/tree/master/src/samples/ari)
|
||||
|
||||
### Contributors wanted
|
||||
#### I will be grateful for any help, Discord: Sandro#3402
|
||||
|
||||
### About project
|
||||
Goal of Tyra project is to provide simple API for PS2 (PlayStation 2™) game creation. So you can just run PS2 emulator, grab your .obj file, and put it into live in a seconds. Project is on early stage, so a lot of stuff is changing from release to release.
|
||||
|
||||
YouTube tutorials soon!
|
||||
|
||||
**Why PS2 game dev is so different?** Raw PS2 development can be a big challenge. PS2 it's pretty low-level and there are a lot of stuff that you must do from scratch.
|
||||
Tyra takes care for you, and rendering, coprocessors communication and many more low-level stuff is already done.
|
||||
|
||||
### Acronyms
|
||||
* EE (Emotion Engine) - whole set of processors and subsystems that make up the PlayStation 2
|
||||
* GS (Graphic synthesizer) - configurable rasterizer and texture mapper. Has only 2MB~ memory for textures, but for the opposite have very high transfer rate, so you can switch textures in the blink
|
||||
* VU0 - programmable (ASM) vector processor that is accessed by inline assembly code injected into C program.
|
||||
* VU1 - programmable (ASM) vector processor, which is similar to vertex shader. Accessed via DMA.
|
||||
* IOP - I/O processor which enables access to peripheral devices, such the game controller
|
||||
|
||||
### Tyra features
|
||||
* VU1 rendering (PATH 1), double-buffered
|
||||
* GIF rendering (PATH 3), double-buffered
|
||||
* Frustum culling, backface culling
|
||||
* OpenGL adaptions: Perspective projection, lookAt camera
|
||||
* Texture support (.bmp loader)
|
||||
* Mesh loaders: ".obj", ".dff" (RenderWare, GTA:SA) and ".md2" (Quake II)
|
||||
* Threading support
|
||||
* Lighting support (now PATH3 only)
|
||||
* Animation support
|
||||
* Audio support
|
||||
* Pad support
|
||||
* TODO: physics, ADPCM and many more!
|
||||
|
||||
### Built With
|
||||
|
||||
* [PS2SDK](https://github.com/ps2dev/ps2sdk)
|
||||
|
||||
## Getting Started
|
||||
|
||||
To get a local copy up and running follow these simple steps.
|
||||
YouTube tutorials soon!
|
||||
|
||||
### Prerequisites
|
||||
|
||||
This is an example of how to list things you need to use the software and how to install them.
|
||||
* PS2 DEV environment - [PS2DEV](https://github.com/ps2dev/ps2dev)
|
||||
* At least #1a4587d PS2SDK - [PS2SDK](https://github.com/ps2dev/ps2sdk)
|
||||
* PS2 Emulator. For example [PCSX2](https://pcsx2.net/)
|
||||
|
||||
### Installation
|
||||
|
||||
1. Clone the repo
|
||||
```sh
|
||||
git clone https://github.com/ps2-tyra/tyra.git
|
||||
```
|
||||
2. Get into src folder and compile it!
|
||||
```sh
|
||||
make
|
||||
```
|
||||
|
||||
## Extra info
|
||||
* Textures can be saved using GIMP. Just replace red with green color, and when exporting select .bmp, 24bit: RGB888, without saving information about colors
|
||||
* If you want to run .elf in PCSX2, be sure that you have version >=1.6 and **Host access** enabled in PCSX2 configuration file.
|
||||
* If you want to use your own .obj file, please check "triangulate faces" in blender. PS2 is supporting only trinagle primitive type.
|
||||
|
||||
## Roadmap
|
||||
|
||||
### Roadmap moved to github kanban:
|
||||
[https://github.com/ps2-tyra/tyra/projects/1](https://github.com/ps2-tyra/tyra/projects/1)
|
||||
|
||||
|
||||
See the [open issues](https://github.com/ps2-tyra/tyra/issues) for a list of proposed features (and known issues).
|
||||
|
||||
## 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
|
||||
|
||||
## License
|
||||
|
||||
Distributed under the Apache License 2.0 License. See `LICENSE` for more information.
|
||||
|
||||
## Contact
|
||||
|
||||
Sandro Sobczyński - sandro.sobczynski@gmail.com
|
||||
[![LinkedIn][linkedin-shield]][linkedin-url]
|
||||
|
||||
## Thanks
|
||||
|
||||
Without these guys, everything would be harder:
|
||||
* Dr Henry Fortuna - Abertay University (code sources)
|
||||
* Lukasz D.K. (huge archive of PS2 stuff)
|
||||
* Guilherme Lampert - PlayStation London (code sources)
|
||||
* Jesper Svennevid, Daniel Collin - Microcode (openvcl, code samples)
|
||||
* Whole PS2SDK/PS2Scene team
|
||||
* And so many other guys. Thanks!
|
||||
|
||||
Project Link: [https://github.com/ps2-tyra/tyra](https://github.com/ps2-tyra/tyra)
|
||||
|
||||
[contributors-shield]: https://img.shields.io/github/contributors/ps2-tyra/tyra.svg?style=flat-square
|
||||
[contributors-url]: https://github.com/ps2-tyra/tyra/graphs/contributors
|
||||
[linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=flat-square&logo=linkedin&colorB=555
|
||||
[linkedin-url]: https://linkedin.com/in/sandro-sobczyński-28820b15a/
|
||||
[license-shield]: https://img.shields.io/github/license/ps2-tyra/tyra.svg?style=flat-square
|
||||
[license-url]: https://github.com/ps2-tyra/tyra/blob/master/LICENSE
|
||||
[](https://www.codacy.com/gh/h4570/tyra/dashboard?utm_source=github.com&utm_medium=referral&utm_content=h4570/tyra&utm_campaign=Badge_Grade)
|
||||
[![Contributors][contributors-shield]][contributors-url]
|
||||
[![MIT License][license-shield]][license-url]
|
||||
[](https://discord.gg/NhhTmg3Gm5)
|
||||
[](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</h3>
|
||||
|
||||
<p align="center">
|
||||
Open source game engine for PlayStation 2™
|
||||
<br />
|
||||
<a href="https://www.youtube.com/watch?v=DGR4vWDjkmc"><strong>Showcase video »</strong></a>
|
||||
|
||||
<a href="https://youtube.com/playlist?list=PLdQVLBcXRRWvtMi-OqccDWLTEFEisD5RH"><strong>YouTube tutorials »</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>
|
||||
|
||||
[](https://github.com/h4570/tyra/stargazers)
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [About the project](#about-the-project)
|
||||
* [Description](#description)
|
||||
* [Tutorials](#tutorials)
|
||||
* [Features](#features)
|
||||
* [Branches](#branches)
|
||||
* [Contributing](#contributing)
|
||||
* [Games](#games)
|
||||
* [License](#license)
|
||||
* [Built With](#built-with)
|
||||
* [Acronyms](#acronyms)
|
||||
* [Credits](#credits)
|
||||
|
||||
## About the Project
|
||||
<p align="center">
|
||||
<img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/tyra_code.gif" alt="Sample code" width="500" height="auto">
|
||||
<img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/showcase.gif " alt="Sample game" width="500" height="auto">
|
||||
</p>
|
||||
|
||||
---
|
||||
### Description
|
||||
Tyra is a project that allows you to easily create games for the PlayStation 2 console.
|
||||
When I tried to make a game for PS2 a few years ago, I realized how many things had to be done to tame this exotic console architecture.
|
||||
Decision was simple - I need to create an engine which will handle 3D file loading, 2D/3D rendering, animation, audio, handling between PS2 CPUs, synchronization.. It should be simple as possible - so people with no experience can create a simple game in a few hours.
|
||||
**And that's what Tyra is all about.**
|
||||
|
||||
### Tutorials
|
||||
* 01 - Setup environment - [Text tutorial](https://github.com/h4570/tyra/tree/master/docs/install) or [Video](https://www.youtube.com/watch?v=9IXOU1SPdzc)
|
||||
* 02 - Cooking game assets - [Video](https://www.youtube.com/watch?v=hpVDeTTLyjI)
|
||||
* 03 - Create a game repository - [Video](https://www.youtube.com/watch?v=DKfIKar3GUM)
|
||||
* 04 - Run game from USB in PS2 - [Video](https://www.youtube.com/watch?v=ZX8fTQqiNho)
|
||||
---
|
||||
* 01 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/01-hello) - Hello world
|
||||
* 02 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/02-sprite) - 2D rendering
|
||||
* 03 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/03-minecraft) - 3D minecraft blocks
|
||||
* 04 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/04-de_dust2) - `de_dust2.obj` rendering
|
||||
* 05 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/05-animation) - 3D animation
|
||||
* 06 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/06-audio) - Background music and sound effects
|
||||
* 07 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/07-lighting) - Static lightmap and dynamic directional lights
|
||||
* 08 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/08-skybox-debug) - Skybox and debug rendering
|
||||
* 09 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/09-manual-mode) - Manual rendering (a'la OpenGL)
|
||||
* Demo game - [Code](https://github.com/h4570/tyra/tree/master/demo)
|
||||
---
|
||||
|
||||
### Features
|
||||
* Docker image with Tyra, all tools and `PS2DEV` C++20 compiler
|
||||
* 3D rendering via `VU1` coprocessor:
|
||||
* Static rendering
|
||||
* Morph animation rendering
|
||||
* Super optimized, custom minecraft block renderer
|
||||
* Debug rendering (lines, boxes, bboxes)
|
||||
* Manual rendering (a'la `OpenGL`)
|
||||
* 2D rendering
|
||||
* Frustum culling:
|
||||
* Simple - culling whole mesh
|
||||
* Precise - culling only visible parts of mesh
|
||||
* Clipping:
|
||||
* Standard "fake", but fast PS2 clipping done in `VU1`
|
||||
* Software clipping done in `EE Core`
|
||||
* Optimized math functions via `VU0` coprocessor
|
||||
* Background music and sound effects support
|
||||
* Pad support
|
||||
* USB support
|
||||
* Memory card support
|
||||
* `.wav` Audio file support
|
||||
* `.obj` 3D file support
|
||||
* `.md2` 3D file support
|
||||
* `.png` Texture file support
|
||||
|
||||
### Branches
|
||||
* `master` - stable releases - tested on PS2 & PCSX2.
|
||||
* `develop` - daily builds.
|
||||
|
||||
See the [open issues](https://github.com/h4570/tyra/issues) for a list of proposed features (and known issues).
|
||||
|
||||
## 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
|
||||
|
||||
## Games
|
||||
|
||||
List of games developed with Tyra.
|
||||
If you created one, please contact me - I will add it to the list :)
|
||||
|
||||
* [Tyracraft](https://github.com/Wellinator/tyracraft) by [Wellinator](https://github.com/Wellinator)
|
||||
* [Rock, paper, scissors](https://github.com/GuidoDQR/my-ps2-game) by [GuidoDQR](https://github.com/GuidoDQR)
|
||||
* [TyraTale](https://github.com/Br4k2n/TyraTale) by [Br4k2n](https://github.com/Br4k2n)
|
||||
|
||||
## License
|
||||
|
||||
Distributed under the Apache License 2.0 License. See `LICENSE` for more information.
|
||||
|
||||
## Built With
|
||||
|
||||
* [PS2DEV](https://github.com/ps2dev/ps2dev)
|
||||
* [VCLPP](https://github.com/glampert/vclpp)
|
||||
* Sony VCL
|
||||
|
||||
## Acronyms
|
||||
* EE (Emotion Engine) - whole set of processors and subsystems that make up the PlayStation 2
|
||||
* EE Core - main PS2 CPU (c++ done here)
|
||||
* 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
|
||||
|
||||
## Credits
|
||||
|
||||
Without these guys, Tyra would not happen:
|
||||
* [Dr Henry Fortuna](http://ps2-edu.tensioncore.com/index.html) - for code sources, PS2 academy tutorials
|
||||
* Whole [PS2DEV](https://github.com/ps2dev) team, and specially to [Rick Gaiser](https://github.com/rickgaiser), [fjtrujy](https://github.com/fjtrujy) - for a lot of good tips!
|
||||
* [Wellington Carvalho](https://github.com/Wellinator), [André Guilheme](https://github.com/wolfysdl) - for testing, contributing to Tyra and sharing cool ideas!
|
||||
* [Leonardo Ono](https://github.com/leonardo-ono) - for software renderer example (with clipping!)
|
||||
* [Lukasz D.K.](https://github.com/lukaszdk) - for huge archive of PS2 stuff
|
||||
* [Guilherme Lampert](https://github.com/glampert) - for code sources
|
||||
* [Jesper Svennevid](https://github.com/jsvennevid), [Daniel Collin](https://github.com/emoon) - for openvcl's code samples
|
||||
* [Manieq](https://www.facebook.com/mvnieq) - 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
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
TARGET := demo.elf
|
||||
ENGINEDIR := ../engine
|
||||
|
||||
#The Directories, Source, Includes, Objects, Binary and Resources
|
||||
SRCDIR := src
|
||||
INCDIR := inc
|
||||
BUILDDIR := obj
|
||||
TARGETDIR := bin
|
||||
RESDIR := res
|
||||
SRCEXT := cpp
|
||||
VSMEXT := vsm
|
||||
VCLEXT := vcl
|
||||
VCLPPEXT := vclpp
|
||||
DEPEXT := d
|
||||
OBJEXT := o
|
||||
|
||||
#Flags, Libraries and Includes
|
||||
CFLAGS :=
|
||||
LIB := -ltyra
|
||||
LIBDIRS := -L$(ENGINEDIR)/bin
|
||||
INC := -I$(INCDIR) -I$(ENGINEDIR)/inc
|
||||
INCDEP := -I$(INCDIR) -I$(ENGINEDIR)/inc
|
||||
|
||||
include ../Makefile.base
|
||||
|
||||
clean-engine:
|
||||
cd $(ENGINEDIR) && $(MAKE) cleaner
|
||||
|
||||
build-engine:
|
||||
cd $(ENGINEDIR) && $(MAKE)
|
||||
|
||||
build-release-engine:
|
||||
cd $(ENGINEDIR) && $(MAKE) release
|
||||
@@ -0,0 +1,4 @@
|
||||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file
|
||||
!.gitignore
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tyra>
|
||||
#include "state/state_manager.hpp"
|
||||
|
||||
using Tyra::Engine;
|
||||
using Tyra::Game;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
class DemoGame : public Game {
|
||||
public:
|
||||
DemoGame(Engine* engine);
|
||||
~DemoGame();
|
||||
|
||||
void init();
|
||||
void loop();
|
||||
|
||||
private:
|
||||
Engine* engine;
|
||||
StateManager<GlobalStateType> stateManager;
|
||||
};
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Demo {
|
||||
|
||||
const bool IS_REAL_PS2_VIA_USB = false;
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Demo {
|
||||
|
||||
enum GlobalStateType { STATE_INTRO, STATE_LOADING, STATE_GAME, STATE_EXIT };
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <engine.hpp>
|
||||
|
||||
using Tyra::Engine;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
template <typename StateTypeT>
|
||||
class State {
|
||||
public:
|
||||
State(Engine* t_engine) : engine(t_engine) {}
|
||||
virtual ~State() {}
|
||||
|
||||
virtual const StateTypeT& getState() const = 0;
|
||||
|
||||
virtual const bool& wantFinish() const = 0;
|
||||
|
||||
virtual void onStart() = 0;
|
||||
|
||||
virtual void update() = 0;
|
||||
|
||||
/** @return Next game state */
|
||||
virtual StateTypeT onFinish() = 0;
|
||||
|
||||
protected:
|
||||
Engine* engine;
|
||||
};
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "./state.hpp"
|
||||
#include "./global_state_type.hpp"
|
||||
|
||||
namespace Demo {
|
||||
|
||||
template <typename StateTypeT>
|
||||
class StateManager {
|
||||
public:
|
||||
StateManager(const StateTypeT& t_initialState,
|
||||
const StateTypeT& t_exitState) {
|
||||
stateInitialized = false;
|
||||
currentState = t_initialState;
|
||||
exitState = t_exitState;
|
||||
}
|
||||
|
||||
~StateManager() { freeAll(); }
|
||||
|
||||
const StateTypeT& getCurrentState() const { return currentState; }
|
||||
|
||||
const StateTypeT& getExitState() const { return exitState; }
|
||||
|
||||
bool finished() const { return currentState == exitState; }
|
||||
|
||||
std::vector<State<StateTypeT>*>* getAll() { return &states; }
|
||||
|
||||
State<StateTypeT>* get(const StateTypeT& stateType) {
|
||||
for (auto& state : states) {
|
||||
if (state->getState() == stateType) {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void add(State<StateTypeT>* state) { states.push_back(state); }
|
||||
|
||||
/** remove (without free) */
|
||||
void remove(const State<StateTypeT>* state) {
|
||||
states.erase(std::remove(states.begin(), states.end(), state),
|
||||
states.end());
|
||||
}
|
||||
|
||||
/** free and remove */
|
||||
void free(const State<StateTypeT>* state) {
|
||||
auto* found = get(state);
|
||||
if (!found) return;
|
||||
|
||||
remove(found);
|
||||
delete found;
|
||||
}
|
||||
|
||||
/** free and remove all */
|
||||
void freeAll() {
|
||||
for (auto& state : states) {
|
||||
delete state;
|
||||
}
|
||||
states.clear();
|
||||
}
|
||||
|
||||
void update() {
|
||||
for (auto& state : states) {
|
||||
if (state->getState() == currentState) {
|
||||
if (state->wantFinish()) {
|
||||
currentState = state->onFinish();
|
||||
stateInitialized = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!stateInitialized) {
|
||||
state->onStart();
|
||||
stateInitialized = true;
|
||||
}
|
||||
|
||||
state->update();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool stateInitialized;
|
||||
std::vector<State<StateTypeT>*> states;
|
||||
StateTypeT currentState, exitState;
|
||||
};
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tyra>
|
||||
#include "states/game/renderer/renderer_dynamic_pair.hpp"
|
||||
#include "states/game/terrain/heightmap.hpp"
|
||||
#include "states/game/player/player_shoot_action.hpp"
|
||||
#include "./enemy_info.hpp"
|
||||
|
||||
using Tyra::AnimationSequenceCallback;
|
||||
using Tyra::Audio;
|
||||
using Tyra::DynamicMesh;
|
||||
using Tyra::DynPipOptions;
|
||||
using Tyra::Engine;
|
||||
using Tyra::Renderer;
|
||||
using Tyra::Renderer3DUtility;
|
||||
using Tyra::TextureRepository;
|
||||
using Tyra::Vec4;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
class Enemy {
|
||||
public:
|
||||
Enemy(Engine* engine, const EnemyInfo& info);
|
||||
~Enemy();
|
||||
|
||||
DynamicMesh* mesh;
|
||||
DynPipOptions* options;
|
||||
RendererDynamicPair* pair;
|
||||
|
||||
void update(const Heightmap& heightmap, const Vec4& playerPosition,
|
||||
const PlayerShootAction& shootAction);
|
||||
|
||||
private:
|
||||
std::vector<u32> walkSequence;
|
||||
std::vector<u32> fightSequence;
|
||||
|
||||
void allocateOptions();
|
||||
void walk(const Heightmap& heightmap, const Vec4& positionDiff);
|
||||
void animationCallback(const AnimationSequenceCallback& callback);
|
||||
void fight();
|
||||
void handlePlayerShoot(const PlayerShootAction& shootAction);
|
||||
void setMeshToSpawn();
|
||||
|
||||
bool isWalking = true;
|
||||
bool isFighting = false;
|
||||
Vec4 terrainLeftUp;
|
||||
Vec4 terrainRightDown;
|
||||
|
||||
Audio* audio;
|
||||
EnemyInfo info;
|
||||
};
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tyra>
|
||||
#include <audsrv.h>
|
||||
|
||||
using Tyra::DynamicMesh;
|
||||
using Tyra::Texture;
|
||||
using Tyra::Vec4;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
struct EnemyInfo {
|
||||
u8 adpcmChannel;
|
||||
audsrv_adpcm_t* adpcmPunch;
|
||||
audsrv_adpcm_t* adpcmDeath;
|
||||
DynamicMesh* motherMesh;
|
||||
Texture* bodyTexture;
|
||||
Texture* clothTexture;
|
||||
Vec4 terrainLeftUp;
|
||||
Vec4 terrainRightDown;
|
||||
};
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tyra>
|
||||
#include <vector>
|
||||
#include "states/game/terrain/heightmap.hpp"
|
||||
#include "states/game/player/player_shoot_action.hpp"
|
||||
#include "./enemy.hpp"
|
||||
|
||||
using Tyra::DynamicMesh;
|
||||
using Tyra::Engine;
|
||||
using Tyra::Texture;
|
||||
using Tyra::TextureRepository;
|
||||
using Tyra::Vec4;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
class EnemyManager {
|
||||
public:
|
||||
EnemyManager(Engine* engine, const Heightmap& heightmap);
|
||||
~EnemyManager();
|
||||
|
||||
void update(const Heightmap& heightmap, const Vec4& playerPosition,
|
||||
const PlayerShootAction& shootAction);
|
||||
|
||||
std::vector<RendererDynamicPair*> getPairs() const;
|
||||
|
||||
private:
|
||||
TextureRepository* textureRepo;
|
||||
std::vector<Enemy*> enemies;
|
||||
DynamicMesh* motherMesh;
|
||||
Texture* bodyTexture;
|
||||
Texture* clothTexture;
|
||||
};
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "state/state.hpp"
|
||||
#include "state/global_state_type.hpp"
|
||||
#include "./player/player.hpp"
|
||||
#include "./renderer/game_renderer.hpp"
|
||||
#include "./terrain/terrain.hpp"
|
||||
#include "./skybox/skybox.hpp"
|
||||
#include "./ship/ship.hpp"
|
||||
#include "./hud/hud.hpp"
|
||||
#include "./enemy/enemy_manager.hpp"
|
||||
|
||||
using std::unique_ptr;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
class GameState : public State<GlobalStateType> {
|
||||
public:
|
||||
GameState(Engine* t_engine);
|
||||
~GameState();
|
||||
|
||||
const GlobalStateType& getState() const { return state; }
|
||||
|
||||
const bool& wantFinish() const { return _wantFinish; };
|
||||
|
||||
void onStart();
|
||||
|
||||
void update();
|
||||
|
||||
/** @return Next game state */
|
||||
GlobalStateType onFinish();
|
||||
|
||||
private:
|
||||
GlobalStateType state;
|
||||
bool _wantFinish;
|
||||
bool initialized;
|
||||
u8 fpsChecker;
|
||||
|
||||
GameRenderer renderer;
|
||||
unique_ptr<Player> player;
|
||||
unique_ptr<EnemyManager> enemyManager;
|
||||
unique_ptr<Terrain> terrain;
|
||||
unique_ptr<Skybox> skybox;
|
||||
unique_ptr<Ship> ship;
|
||||
unique_ptr<Hud> hud;
|
||||
};
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tyra>
|
||||
#include <memory>
|
||||
|
||||
using std::unique_ptr;
|
||||
using Tyra::Sprite;
|
||||
using Tyra::Texture;
|
||||
using Tyra::TextureRepository;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
class Hud {
|
||||
public:
|
||||
Hud(TextureRepository* repo);
|
||||
~Hud();
|
||||
|
||||
TextureRepository* repo;
|
||||
|
||||
unique_ptr<Sprite> hpSprite;
|
||||
unique_ptr<Sprite> crosshairSprite;
|
||||
unique_ptr<Sprite> soldierSprite;
|
||||
|
||||
Texture* hpTexture;
|
||||
Texture* crosshairTexture;
|
||||
Texture* soldierTexture;
|
||||
};
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tyra>
|
||||
|
||||
using Tyra::CameraInfo3D;
|
||||
using Tyra::Pad;
|
||||
using Tyra::Vec4;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
class Camera {
|
||||
public:
|
||||
Camera(Pad* pad);
|
||||
~Camera();
|
||||
|
||||
Vec4 lookAt;
|
||||
Vec4 position;
|
||||
Vec4 unitCircle;
|
||||
|
||||
CameraInfo3D getCameraInfo() { return CameraInfo3D(&position, &lookAt); }
|
||||
|
||||
void update(const Vec4& playerPosition, const float& terrainHeight);
|
||||
|
||||
private:
|
||||
float circleRotation, lengthFromOrigin, height;
|
||||
|
||||
Pad* pad;
|
||||
};
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "states/game/renderer/renderer_dynamic_pair.hpp"
|
||||
#include "states/game/renderer/renderer_static_pair.hpp"
|
||||
#include "states/game/terrain/heightmap.hpp"
|
||||
#include "./weapon.hpp"
|
||||
#include "./camera.hpp"
|
||||
#include "./player_shoot_action.hpp"
|
||||
#include <tyra>
|
||||
|
||||
using Tyra::Engine;
|
||||
using Tyra::Pad;
|
||||
using Tyra::Renderer3DUtility;
|
||||
using Tyra::Vec4;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
class Player {
|
||||
public:
|
||||
Player(Engine* engine);
|
||||
~Player();
|
||||
|
||||
const Vec4& getPosition() const { return position; }
|
||||
CameraInfo3D getCameraInfo() { return camera.getCameraInfo(); }
|
||||
|
||||
RendererStaticPair* pair;
|
||||
|
||||
void update(const Heightmap& heightmap);
|
||||
|
||||
PlayerShootAction getShootAction() const;
|
||||
|
||||
private:
|
||||
void handlePlayerPosition(const Heightmap& heightmap,
|
||||
const float& terrainHeight);
|
||||
|
||||
float speed;
|
||||
Pad* pad;
|
||||
Vec4 position;
|
||||
Weapon weapon;
|
||||
Camera camera;
|
||||
};
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tyra>
|
||||
#include <optional>
|
||||
|
||||
using Tyra::Ray;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
struct PlayerShootAction {
|
||||
bool isShooting = false;
|
||||
std::optional<Ray> ray;
|
||||
};
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tyra>
|
||||
|
||||
using Tyra::Audio;
|
||||
using Tyra::Engine;
|
||||
using Tyra::Pad;
|
||||
using Tyra::Renderer;
|
||||
using Tyra::StaPipOptions;
|
||||
using Tyra::StaticMesh;
|
||||
using Tyra::TextureRepository;
|
||||
using Tyra::Timer;
|
||||
using Tyra::Vec4;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
class Weapon {
|
||||
public:
|
||||
Weapon(Engine* engine);
|
||||
~Weapon();
|
||||
|
||||
StaticMesh* mesh;
|
||||
StaPipOptions* options;
|
||||
bool isShooting = false;
|
||||
|
||||
void update();
|
||||
|
||||
private:
|
||||
bool isShootAnimation1, isShootAnimation2;
|
||||
Pad* pad;
|
||||
Audio* audio;
|
||||
Timer shootTimer;
|
||||
Vec4 initialPosition;
|
||||
u8 adpcmCurrentChannel;
|
||||
u8 adpcmChannelsCount;
|
||||
|
||||
audsrv_adpcm_t* shootAdpcm;
|
||||
|
||||
void shoot();
|
||||
void allocateOptions();
|
||||
u8 getShootChannel();
|
||||
};
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tyra>
|
||||
#include "./renderer_static_pair.hpp"
|
||||
#include "./renderer_dynamic_pair.hpp"
|
||||
|
||||
using Tyra::CoreBBox;
|
||||
using Tyra::DynamicPipeline;
|
||||
using Tyra::Renderer;
|
||||
using Tyra::Sprite;
|
||||
using Tyra::StaticPipeline;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
class GameRenderer {
|
||||
public:
|
||||
GameRenderer(Renderer* renderer);
|
||||
~GameRenderer();
|
||||
|
||||
void add(std::vector<RendererStaticPair*> staticPairs);
|
||||
void add(std::vector<RendererDynamicPair*> dynamicPairs);
|
||||
void add(RendererStaticPair* staticPair);
|
||||
void add(RendererDynamicPair* dynamicPair);
|
||||
void add(Sprite* sprite);
|
||||
void add(const CoreBBox& bbox);
|
||||
|
||||
void clear();
|
||||
void render();
|
||||
|
||||
private:
|
||||
Renderer* renderer;
|
||||
|
||||
StaticPipeline stpip;
|
||||
DynamicPipeline dypip;
|
||||
|
||||
std::vector<RendererStaticPair*> staticPairs;
|
||||
std::vector<RendererDynamicPair*> dynamicPairs;
|
||||
std::vector<Sprite*> sprites;
|
||||
std::vector<CoreBBox> bboxes;
|
||||
};
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tyra>
|
||||
|
||||
using Tyra::DynamicMesh;
|
||||
using Tyra::DynPipOptions;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
struct RendererDynamicPair {
|
||||
DynamicMesh* mesh;
|
||||
DynPipOptions* options;
|
||||
};
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tyra>
|
||||
|
||||
using Tyra::StaPipOptions;
|
||||
using Tyra::StaticMesh;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
struct RendererStaticPair {
|
||||
StaticMesh* mesh;
|
||||
StaPipOptions* options;
|
||||
};
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tyra>
|
||||
#include "states/game/renderer/renderer_static_pair.hpp"
|
||||
|
||||
using Tyra::Renderer;
|
||||
using Tyra::StaPipOptions;
|
||||
using Tyra::StaticMesh;
|
||||
using Tyra::TextureRepository;
|
||||
using Tyra::Vec4;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
class Ship {
|
||||
public:
|
||||
Ship(TextureRepository* repo);
|
||||
~Ship();
|
||||
|
||||
StaticMesh* mesh;
|
||||
StaPipOptions* options;
|
||||
RendererStaticPair* pair;
|
||||
|
||||
private:
|
||||
void allocateOptions();
|
||||
};
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tyra>
|
||||
#include "states/game/renderer/renderer_static_pair.hpp"
|
||||
|
||||
using Tyra::Renderer;
|
||||
using Tyra::StaPipOptions;
|
||||
using Tyra::StaticMesh;
|
||||
using Tyra::TextureRepository;
|
||||
using Tyra::Vec4;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
class Skybox {
|
||||
public:
|
||||
Skybox(TextureRepository* repo);
|
||||
~Skybox();
|
||||
|
||||
StaticMesh* mesh;
|
||||
StaPipOptions* options;
|
||||
RendererStaticPair* pair;
|
||||
|
||||
void update(const Vec4& playerPosition);
|
||||
|
||||
private:
|
||||
void allocateOptions();
|
||||
};
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tyra>
|
||||
|
||||
using Tyra::Vec4;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
class Heightmap {
|
||||
public:
|
||||
Heightmap(const float& minHeight, const float& maxHeight, const Vec4& leftUp,
|
||||
const Vec4& rightDown);
|
||||
~Heightmap();
|
||||
|
||||
const float& getHeightOffset(const Vec4& playerPosition) const;
|
||||
|
||||
bool isOutside(const Vec4& position) const;
|
||||
|
||||
float** map;
|
||||
s16 mapWidth, mapHeight;
|
||||
float minHeight, maxHeight;
|
||||
Vec4 leftUp, rightDown;
|
||||
|
||||
private:
|
||||
float getWidthPercentage(const Vec4& playerPosition) const;
|
||||
float getHeightPercentage(const Vec4& playerPosition) const;
|
||||
void allocateMap(const unsigned char* data, const int& width,
|
||||
const int& height);
|
||||
float getGameHeight(const u8& inputColor, const u8& minColor,
|
||||
const u8& maxColor) const;
|
||||
};
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tyra>
|
||||
#include "states/game/renderer/renderer_static_pair.hpp"
|
||||
#include "./heightmap.hpp"
|
||||
|
||||
using Tyra::StaPipOptions;
|
||||
using Tyra::StaticMesh;
|
||||
using Tyra::TextureRepository;
|
||||
using Tyra::Vec4;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
class Terrain {
|
||||
public:
|
||||
Terrain(TextureRepository* repo);
|
||||
~Terrain();
|
||||
|
||||
Heightmap heightmap;
|
||||
StaticMesh* mesh;
|
||||
StaPipOptions* options;
|
||||
RendererStaticPair* pair;
|
||||
|
||||
float getHeightOffset(const Vec4& playerPosition);
|
||||
|
||||
private:
|
||||
void allocateOptions();
|
||||
};
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "state/state.hpp"
|
||||
#include "state/global_state_type.hpp"
|
||||
#include "state/state_manager.hpp"
|
||||
#include "./intro_state_type.hpp"
|
||||
|
||||
namespace Demo {
|
||||
|
||||
class IntroState : public State<GlobalStateType> {
|
||||
public:
|
||||
IntroState(Engine* t_engine);
|
||||
~IntroState();
|
||||
|
||||
const GlobalStateType& getState() const { return state; }
|
||||
|
||||
const bool& wantFinish() const { return _wantFinish; };
|
||||
|
||||
void onStart();
|
||||
|
||||
void update();
|
||||
|
||||
/** @return Next game state */
|
||||
GlobalStateType onFinish();
|
||||
|
||||
private:
|
||||
GlobalStateType state;
|
||||
bool _wantFinish;
|
||||
bool initialized;
|
||||
|
||||
StateManager<IntroStateType> stateManager;
|
||||
};
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Demo {
|
||||
|
||||
enum IntroStateType {
|
||||
STATE_PS2DEV,
|
||||
STATE_TYRA,
|
||||
STATE_PRESS_KEY,
|
||||
STATE_INTRO_END
|
||||
};
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "state/state.hpp"
|
||||
#include "../intro_state_type.hpp"
|
||||
#include <tyra>
|
||||
|
||||
using Tyra::Sprite;
|
||||
using Tyra::Texture;
|
||||
using Tyra::Timer;
|
||||
using Tyra::Vec2;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
class IntroPressKeyState : public State<IntroStateType> {
|
||||
public:
|
||||
IntroPressKeyState(Engine* t_engine);
|
||||
~IntroPressKeyState();
|
||||
|
||||
const IntroStateType& getState() const { return state; }
|
||||
|
||||
const bool& wantFinish() const { return _wantFinish; };
|
||||
|
||||
void onStart();
|
||||
|
||||
/** @return Next game state */
|
||||
IntroStateType onFinish();
|
||||
|
||||
void update();
|
||||
|
||||
private:
|
||||
void renderFiller();
|
||||
void updateMap();
|
||||
|
||||
IntroStateType state;
|
||||
bool _wantFinish;
|
||||
bool initialized;
|
||||
bool mapFadeIn;
|
||||
bool fillerFadeIn;
|
||||
bool showPressKey;
|
||||
bool pressKeyAlphaToggle;
|
||||
u8 pressKeyAlphaDelayer;
|
||||
|
||||
float fillersOffset;
|
||||
constexpr static float textureWidthHeight = 512.0F;
|
||||
const static u8 mapRows = 3;
|
||||
const static u8 mapCols = 3;
|
||||
|
||||
Vec2 mapPosition;
|
||||
u8 mapDirection;
|
||||
|
||||
Texture* fillerTexture;
|
||||
Sprite* fillerSprite;
|
||||
|
||||
Texture* logoTexture;
|
||||
Sprite* logoSprite;
|
||||
|
||||
Texture* pressKeyTexture;
|
||||
Sprite* pressKeySprite;
|
||||
|
||||
Texture* mapTextures[mapRows][mapCols];
|
||||
Sprite* mapSprites[mapRows][mapCols];
|
||||
};
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "state/state.hpp"
|
||||
#include "../intro_state_type.hpp"
|
||||
#include <tyra>
|
||||
|
||||
using Tyra::Sprite;
|
||||
using Tyra::Texture;
|
||||
using Tyra::Timer;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
class IntroPs2DevState : public State<IntroStateType> {
|
||||
public:
|
||||
IntroPs2DevState(Engine* t_engine);
|
||||
~IntroPs2DevState();
|
||||
|
||||
const IntroStateType& getState() const { return state; }
|
||||
|
||||
const bool& wantFinish() const { return _wantFinish; };
|
||||
|
||||
void onStart();
|
||||
|
||||
void update();
|
||||
|
||||
/** @return Next game state */
|
||||
IntroStateType onFinish();
|
||||
|
||||
private:
|
||||
IntroStateType state;
|
||||
bool _wantFinish;
|
||||
|
||||
Texture* texture;
|
||||
Timer initialDelayTimer;
|
||||
bool initialized;
|
||||
bool initialDelayElapsed;
|
||||
bool fadeinActivated;
|
||||
bool fadeoutActivated;
|
||||
u8 frameSkipper;
|
||||
|
||||
Sprite* sprite;
|
||||
};
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "state/state.hpp"
|
||||
#include "../intro_state_type.hpp"
|
||||
#include <tyra>
|
||||
|
||||
using Tyra::Sprite;
|
||||
using Tyra::Texture;
|
||||
using Tyra::Timer;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
class IntroTyraState : public State<IntroStateType> {
|
||||
public:
|
||||
IntroTyraState(Engine* t_engine);
|
||||
~IntroTyraState();
|
||||
|
||||
const IntroStateType& getState() const { return state; }
|
||||
|
||||
const bool& wantFinish() const { return _wantFinish; };
|
||||
|
||||
void onStart();
|
||||
|
||||
void update();
|
||||
|
||||
/** @return Next game state */
|
||||
IntroStateType onFinish();
|
||||
|
||||
private:
|
||||
IntroStateType state;
|
||||
bool _wantFinish;
|
||||
|
||||
Texture* tyraTexture;
|
||||
Texture* bgTexture;
|
||||
Texture* bg2Texture;
|
||||
Texture* fillerTexture;
|
||||
|
||||
Timer initialDelayTimer;
|
||||
bool initialized;
|
||||
bool initialDelayElapsed;
|
||||
bool animActivated;
|
||||
bool fadeoutActivated;
|
||||
u8 frameSkipper;
|
||||
|
||||
Sprite* tyraSprite;
|
||||
Sprite* bgSprite;
|
||||
Sprite* bg2Sprite;
|
||||
Sprite* fillerSprite;
|
||||
|
||||
void renderFillers();
|
||||
};
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "state/state.hpp"
|
||||
#include "state/global_state_type.hpp"
|
||||
#include "state/state_manager.hpp"
|
||||
|
||||
namespace Demo {
|
||||
|
||||
class LoadingState : public State<GlobalStateType> {
|
||||
public:
|
||||
LoadingState(Engine* t_engine);
|
||||
~LoadingState();
|
||||
|
||||
const GlobalStateType& getState() const { return state; }
|
||||
|
||||
const bool& wantFinish() const { return _wantFinish; };
|
||||
|
||||
void onStart();
|
||||
|
||||
void update();
|
||||
|
||||
/** @return Next game state */
|
||||
GlobalStateType onFinish();
|
||||
|
||||
private:
|
||||
GlobalStateType state;
|
||||
bool _wantFinish;
|
||||
bool initialized;
|
||||
};
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,4 @@
|
||||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file
|
||||
!.gitignore
|
||||
@@ -0,0 +1,4 @@
|
||||
$ConfigFile = Join-Path $PSScriptRoot '../windows-pcsx2.ps1'
|
||||
. $ConfigFile
|
||||
|
||||
RunPCSX2
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "demo_game.hpp"
|
||||
#include "states/intro/intro_state.hpp"
|
||||
#include "states/loading/loading_state.hpp"
|
||||
#include "states/game/game_state.hpp"
|
||||
|
||||
namespace Demo {
|
||||
|
||||
DemoGame::DemoGame(Engine* t_engine)
|
||||
: engine(t_engine), stateManager(STATE_INTRO, STATE_EXIT) {}
|
||||
DemoGame::~DemoGame() {}
|
||||
|
||||
void DemoGame::init() {
|
||||
stateManager.add(new IntroState(engine));
|
||||
stateManager.add(new LoadingState(engine));
|
||||
stateManager.add(new GameState(engine));
|
||||
}
|
||||
void DemoGame::loop() {
|
||||
stateManager.update();
|
||||
|
||||
if (stateManager.finished()) {
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include <tyra>
|
||||
#include "demo_game.hpp"
|
||||
#include "game_settings.hpp"
|
||||
|
||||
int main() {
|
||||
Tyra::EngineOptions options;
|
||||
|
||||
if (Demo::IS_REAL_PS2_VIA_USB) {
|
||||
options.writeLogsToFile = true;
|
||||
options.loadUsbDriver = true;
|
||||
}
|
||||
|
||||
Tyra::Engine engine(options);
|
||||
|
||||
Demo::DemoGame game(&engine);
|
||||
engine.run(&game);
|
||||
SleepThread();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "states/game/enemy/enemy.hpp"
|
||||
#include <functional>
|
||||
|
||||
using Tyra::Color;
|
||||
using Tyra::Math;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
Enemy::Enemy(Engine* engine, const EnemyInfo& t_info) {
|
||||
info = t_info;
|
||||
|
||||
mesh = new DynamicMesh(*info.motherMesh);
|
||||
|
||||
auto* bodyMaterial = mesh->getMaterialByName("BodyMaterial");
|
||||
auto* clothMaterial = mesh->getMaterialByName("ClothMaterial");
|
||||
|
||||
TYRA_ASSERT(bodyMaterial != nullptr && clothMaterial != nullptr,
|
||||
"Body and cloth materials not found!");
|
||||
|
||||
info.bodyTexture->addLink(bodyMaterial->id);
|
||||
info.clothTexture->addLink(clothMaterial->id);
|
||||
|
||||
float r = Math::randomf(75.0F, 128.0F);
|
||||
float g = Math::randomf(75.0F, 128.0F);
|
||||
float b = Math::randomf(75.0F, 128.0F);
|
||||
|
||||
bodyMaterial->ambient.set(r, g, b);
|
||||
clothMaterial->ambient.set(r, g, b);
|
||||
|
||||
walkSequence = {0, 1, 2};
|
||||
fightSequence = {3, 4, 5};
|
||||
|
||||
terrainLeftUp = info.terrainLeftUp;
|
||||
terrainRightDown = info.terrainRightDown;
|
||||
|
||||
setMeshToSpawn();
|
||||
|
||||
mesh->animation.setSequence(walkSequence);
|
||||
mesh->animation.loop = true;
|
||||
mesh->animation.setCallback(
|
||||
std::bind(&Enemy::animationCallback, this, std::placeholders::_1));
|
||||
mesh->translation.translateY(-5.0F);
|
||||
|
||||
audio = &engine->audio;
|
||||
audio->adpcm.setVolume(30, info.adpcmChannel);
|
||||
|
||||
allocateOptions();
|
||||
|
||||
pair = new RendererDynamicPair{mesh, options};
|
||||
}
|
||||
|
||||
Enemy::~Enemy() {
|
||||
delete mesh;
|
||||
delete options;
|
||||
delete pair;
|
||||
}
|
||||
|
||||
void Enemy::setMeshToSpawn() {
|
||||
auto spawnPoint =
|
||||
Vec4(Math::randomf(terrainLeftUp.x, terrainRightDown.x), 0.0F,
|
||||
Math::randomf(terrainLeftUp.z, terrainRightDown.z), 1.0F);
|
||||
|
||||
mesh->setPosition(spawnPoint);
|
||||
}
|
||||
|
||||
void Enemy::update(const Heightmap& heightmap, const Vec4& playerPosition,
|
||||
const PlayerShootAction& shootAction) {
|
||||
auto* enemyPosition = mesh->getPosition();
|
||||
|
||||
handlePlayerShoot(shootAction);
|
||||
|
||||
auto diff = *enemyPosition - playerPosition;
|
||||
auto ang = Math::atan2(diff.x, diff.z);
|
||||
|
||||
if (diff.length() > 150.0F) {
|
||||
walk(heightmap, diff);
|
||||
} else {
|
||||
fight();
|
||||
}
|
||||
|
||||
const float naturalRotation = 3.1F;
|
||||
mesh->rotation.identity();
|
||||
ang += naturalRotation;
|
||||
mesh->rotation.rotateByAngle(ang, Vec4(0.0F, 1.0F, 0.0F, 0.0F));
|
||||
|
||||
mesh->update();
|
||||
}
|
||||
|
||||
void Enemy::handlePlayerShoot(const PlayerShootAction& shootAction) {
|
||||
if (!shootAction.isShooting) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& ray = shootAction.ray.value();
|
||||
|
||||
auto bbox =
|
||||
mesh->getCurrentBoundingBox().getTransformed(mesh->getModelMatrix());
|
||||
|
||||
auto isOnEnemy = ray.intersectBox(bbox.min(), bbox.max());
|
||||
|
||||
if (isOnEnemy) {
|
||||
setMeshToSpawn();
|
||||
audio->adpcm.tryPlay(info.adpcmDeath, info.adpcmChannel);
|
||||
}
|
||||
}
|
||||
|
||||
void Enemy::walk(const Heightmap& heightmap, const Vec4& positionDiff) {
|
||||
if (isFighting) {
|
||||
mesh->animation.setSequence(walkSequence);
|
||||
}
|
||||
|
||||
isFighting = false;
|
||||
isWalking = true;
|
||||
|
||||
auto* enemyPosition = mesh->getPosition();
|
||||
auto normalized = positionDiff;
|
||||
normalized.normalize();
|
||||
const float speed = 2.5F;
|
||||
auto nextPos = *enemyPosition - normalized * speed;
|
||||
nextPos.y = heightmap.getHeightOffset(nextPos) - 60.0F;
|
||||
|
||||
mesh->translation.identity();
|
||||
mesh->translation.translate(nextPos);
|
||||
}
|
||||
|
||||
void Enemy::fight() {
|
||||
if (isWalking) {
|
||||
mesh->animation.setSequence(fightSequence);
|
||||
}
|
||||
|
||||
isFighting = true;
|
||||
isWalking = false;
|
||||
}
|
||||
|
||||
void Enemy::animationCallback(const AnimationSequenceCallback& callback) {
|
||||
if (callback == AnimationSequenceCallback::AnimationSequenceCallback_Loop) {
|
||||
if (isFighting) {
|
||||
audio->adpcm.tryPlay(info.adpcmPunch, info.adpcmChannel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Enemy::allocateOptions() {
|
||||
options = new DynPipOptions();
|
||||
options->frustumCulling =
|
||||
Tyra::PipelineFrustumCulling::PipelineFrustumCulling_None;
|
||||
}
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "states/game/enemy/enemy_manager.hpp"
|
||||
#include <functional>
|
||||
#include "game_settings.hpp"
|
||||
|
||||
using Tyra::FileUtils;
|
||||
using Tyra::Math;
|
||||
using Tyra::ObjLoader;
|
||||
using Tyra::ObjLoaderOptions;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
EnemyManager::EnemyManager(Engine* engine, const Heightmap& heightmap) {
|
||||
textureRepo = &engine->renderer.core.texture.repository;
|
||||
|
||||
ObjLoader loader;
|
||||
ObjLoaderOptions objOptions;
|
||||
objOptions.animation.count = 6;
|
||||
objOptions.flipUVs = true;
|
||||
objOptions.scale = 250.0F;
|
||||
|
||||
auto data = loader.load(FileUtils::fromCwd("game/models/zombie/zombie.obj"),
|
||||
objOptions);
|
||||
data->loadNormals = false;
|
||||
motherMesh = new DynamicMesh(data.get());
|
||||
|
||||
bodyTexture = textureRepo->add(
|
||||
FileUtils::fromCwd("game/models/zombie/BodyMaterial.png"));
|
||||
|
||||
clothTexture = textureRepo->add(
|
||||
FileUtils::fromCwd("game/models/zombie/ClothMaterial.png"));
|
||||
|
||||
auto* punch = engine->audio.adpcm.load(
|
||||
FileUtils::fromCwd("game/models/zombie/punch.adpcm"));
|
||||
|
||||
auto* death = engine->audio.adpcm.load(
|
||||
FileUtils::fromCwd("game/models/zombie/death.adpcm"));
|
||||
|
||||
const int enemyCount = IS_REAL_PS2_VIA_USB ? 8 : 12;
|
||||
for (int i = 0; i < enemyCount; i++) {
|
||||
EnemyInfo info;
|
||||
info.adpcmChannel = 9 + i;
|
||||
info.adpcmPunch = punch;
|
||||
info.adpcmDeath = death;
|
||||
info.motherMesh = motherMesh;
|
||||
info.clothTexture = clothTexture;
|
||||
info.bodyTexture = bodyTexture;
|
||||
info.terrainLeftUp = heightmap.leftUp;
|
||||
info.terrainRightDown = heightmap.rightDown;
|
||||
enemies.push_back(new Enemy(engine, info));
|
||||
}
|
||||
}
|
||||
|
||||
EnemyManager::~EnemyManager() {
|
||||
for (auto* enemy : enemies) {
|
||||
delete enemy;
|
||||
}
|
||||
|
||||
delete motherMesh;
|
||||
|
||||
textureRepo->free(bodyTexture->id);
|
||||
textureRepo->free(clothTexture->id);
|
||||
}
|
||||
|
||||
std::vector<RendererDynamicPair*> EnemyManager::getPairs() const {
|
||||
std::vector<RendererDynamicPair*> result;
|
||||
|
||||
for (auto* enemy : enemies) {
|
||||
result.push_back(enemy->pair);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void EnemyManager::update(const Heightmap& heightmap,
|
||||
const Vec4& playerPosition,
|
||||
const PlayerShootAction& shootAction) {
|
||||
for (auto* enemy : enemies) {
|
||||
enemy->update(heightmap, playerPosition, shootAction);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "states/game/game_state.hpp"
|
||||
#include "game_settings.hpp"
|
||||
|
||||
using std::make_unique;
|
||||
using Tyra::FileUtils;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
GameState::GameState(Engine* t_engine)
|
||||
: State(t_engine), renderer(&t_engine->renderer) {
|
||||
state = STATE_GAME;
|
||||
_wantFinish = false;
|
||||
initialized = false;
|
||||
fpsChecker = 0;
|
||||
}
|
||||
|
||||
GameState::~GameState() {}
|
||||
|
||||
void GameState::onStart() {
|
||||
TYRA_LOG("Game. RAM: ", engine->info.getAvailableRAM(), "MB");
|
||||
|
||||
engine->audio.song.stop();
|
||||
engine->audio.song.inLoop = true;
|
||||
engine->audio.song.load(FileUtils::fromCwd("game/game-audio.wav"));
|
||||
engine->audio.song.setVolume(0);
|
||||
engine->audio.song.play();
|
||||
|
||||
auto* repository = &engine->renderer.core.texture.repository;
|
||||
player = make_unique<Player>(engine);
|
||||
terrain = make_unique<Terrain>(repository);
|
||||
enemyManager = make_unique<EnemyManager>(engine, terrain->heightmap);
|
||||
ship = make_unique<Ship>(repository);
|
||||
skybox = make_unique<Skybox>(repository);
|
||||
hud = make_unique<Hud>(repository);
|
||||
|
||||
engine->audio.song.setVolume(85);
|
||||
|
||||
if (IS_REAL_PS2_VIA_USB) engine->renderer.setFrameLimit(false);
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
GlobalStateType GameState::onFinish() {
|
||||
if (!initialized) return STATE_EXIT;
|
||||
|
||||
initialized = false;
|
||||
|
||||
return STATE_EXIT;
|
||||
}
|
||||
|
||||
void GameState::update() {
|
||||
// Check fps
|
||||
if (fpsChecker++ > 50) {
|
||||
TYRA_LOG("FPS: ", engine->info.getFps(),
|
||||
" RAM: ", engine->info.getAvailableRAM());
|
||||
fpsChecker = 0;
|
||||
}
|
||||
|
||||
// Game logic
|
||||
player->update(terrain->heightmap);
|
||||
skybox->update(player->getPosition());
|
||||
auto shootAction = player->getShootAction();
|
||||
enemyManager->update(terrain->heightmap, player->getPosition(), shootAction);
|
||||
auto* firstEnemyMesh = enemyManager->getPairs().front()->mesh;
|
||||
|
||||
// Render
|
||||
engine->renderer.beginFrame(player->getCameraInfo());
|
||||
{
|
||||
renderer.clear();
|
||||
{
|
||||
renderer.add(skybox->pair); // First, because of ALLPASS
|
||||
renderer.add(ship->pair);
|
||||
renderer.add(player->pair);
|
||||
renderer.add(enemyManager->getPairs());
|
||||
renderer.add(terrain->pair);
|
||||
renderer.add(firstEnemyMesh->getCurrentBoundingBox().getTransformed(
|
||||
firstEnemyMesh->getModelMatrix()));
|
||||
renderer.add(hud->crosshairSprite.get());
|
||||
renderer.add(hud->hpSprite.get());
|
||||
renderer.add(hud->soldierSprite.get());
|
||||
}
|
||||
renderer.render();
|
||||
}
|
||||
engine->renderer.endFrame();
|
||||
}
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "states/game/hud/hud.hpp"
|
||||
|
||||
using Tyra::FileUtils;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
Hud::Hud(TextureRepository* t_repo) {
|
||||
repo = t_repo;
|
||||
|
||||
soldierSprite = std::make_unique<Sprite>();
|
||||
soldierSprite->mode = Tyra::MODE_STRETCH;
|
||||
soldierSprite->size.set(64.0F, 64.0F);
|
||||
soldierSprite->position.set(5.0F, 448.0F - 64.0F - 5.0F);
|
||||
|
||||
soldierTexture = repo->add(FileUtils::fromCwd("game/soldier.png"));
|
||||
soldierTexture->addLink(soldierSprite->id);
|
||||
|
||||
hpSprite = std::make_unique<Sprite>();
|
||||
hpSprite->mode = Tyra::MODE_STRETCH;
|
||||
hpSprite->size.set(128.0F, 64.0F);
|
||||
hpSprite->position.set(70.0F, 448.0F - 64.0F - 5.0F);
|
||||
|
||||
hpTexture = repo->add(FileUtils::fromCwd("game/health_bar.png"));
|
||||
hpTexture->addLink(hpSprite->id);
|
||||
|
||||
crosshairSprite = std::make_unique<Sprite>();
|
||||
crosshairSprite->mode = Tyra::MODE_STRETCH;
|
||||
crosshairSprite->size.set(16.0F, 16.0F);
|
||||
crosshairSprite->position.set(512.0F / 2.0F - 16.0F / 2,
|
||||
448.0F / 2.0F - 16.0F / 2);
|
||||
|
||||
crosshairTexture = repo->add(FileUtils::fromCwd("game/crosshair.png"));
|
||||
crosshairTexture->addLink(crosshairSprite->id);
|
||||
}
|
||||
|
||||
Hud::~Hud() {
|
||||
repo->free(crosshairTexture->id);
|
||||
repo->free(hpTexture->id);
|
||||
}
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "states/game/player/camera.hpp"
|
||||
|
||||
namespace Demo {
|
||||
|
||||
Camera::Camera(Pad* t_pad) : lookAt(0.0F), position(0.0F), pad(t_pad) {
|
||||
lengthFromOrigin = 30.0F;
|
||||
circleRotation = -3.5F;
|
||||
height = 1.5F;
|
||||
}
|
||||
|
||||
Camera::~Camera() {}
|
||||
|
||||
void Camera::update(const Vec4& playerPosition, const float& terrainHeight) {
|
||||
const float rotationOffset = 0.045F;
|
||||
const float heightOffset = 0.5F;
|
||||
|
||||
const auto& rightJoy = pad->getRightJoyPad();
|
||||
|
||||
if (rightJoy.h <= 100) {
|
||||
circleRotation -= rotationOffset;
|
||||
} else if (rightJoy.h >= 200) {
|
||||
circleRotation += rotationOffset;
|
||||
}
|
||||
|
||||
if (rightJoy.v <= 100) {
|
||||
height -= heightOffset;
|
||||
} else if (rightJoy.v >= 200) {
|
||||
height += heightOffset;
|
||||
}
|
||||
|
||||
unitCircle.x = (sin(circleRotation) * lengthFromOrigin);
|
||||
unitCircle.y = height;
|
||||
unitCircle.z = (cos(circleRotation) * lengthFromOrigin);
|
||||
|
||||
position = playerPosition;
|
||||
lookAt = unitCircle + playerPosition;
|
||||
}
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "states/game/player/player.hpp"
|
||||
|
||||
namespace Demo {
|
||||
|
||||
Player::Player(Engine* engine)
|
||||
: position(0.0F), weapon(engine), camera(&engine->pad) {
|
||||
pair = new RendererStaticPair{weapon.mesh, weapon.options};
|
||||
pad = &engine->pad;
|
||||
position = Vec4(3.0F, 50.0F, 0.0F);
|
||||
camera.lookAt = Vec4(0.0F, 0.0F, -30.0F);
|
||||
speed = 6.0F;
|
||||
}
|
||||
|
||||
Player::~Player() { delete pair; }
|
||||
|
||||
void Player::update(const Heightmap& heightmap) {
|
||||
float terrainHeight = heightmap.getHeightOffset(getPosition());
|
||||
|
||||
handlePlayerPosition(heightmap, terrainHeight);
|
||||
camera.update(position, terrainHeight);
|
||||
weapon.update();
|
||||
}
|
||||
|
||||
PlayerShootAction Player::getShootAction() const {
|
||||
PlayerShootAction action;
|
||||
action.isShooting = weapon.isShooting;
|
||||
|
||||
if (action.isShooting) {
|
||||
action.ray =
|
||||
Ray(camera.position, (camera.lookAt - camera.position).getNormalized());
|
||||
}
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
void Player::handlePlayerPosition(const Heightmap& heightmap,
|
||||
const float& terrainHeight) {
|
||||
const auto& leftJoy = pad->getLeftJoyPad();
|
||||
|
||||
auto normalizedCamera = Vec4(camera.unitCircle);
|
||||
normalizedCamera.normalize();
|
||||
normalizedCamera *= speed;
|
||||
|
||||
Vec4 nextPosition(position);
|
||||
nextPosition.y = terrainHeight + 50.0F;
|
||||
|
||||
if (leftJoy.v <= 100) {
|
||||
nextPosition.x += normalizedCamera.x;
|
||||
nextPosition.z += normalizedCamera.z;
|
||||
} else if (leftJoy.v >= 200) {
|
||||
nextPosition.x += -normalizedCamera.x;
|
||||
nextPosition.z += -normalizedCamera.z;
|
||||
}
|
||||
if (leftJoy.h <= 100) {
|
||||
nextPosition.x += normalizedCamera.z;
|
||||
nextPosition.z += -normalizedCamera.x;
|
||||
} else if (leftJoy.h >= 200) {
|
||||
nextPosition.x += -normalizedCamera.z;
|
||||
nextPosition.z += normalizedCamera.x;
|
||||
}
|
||||
|
||||
if (!heightmap.isOutside(nextPosition)) position = nextPosition;
|
||||
|
||||
camera.position = position;
|
||||
}
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "states/game/player/weapon.hpp"
|
||||
|
||||
using Tyra::FileUtils;
|
||||
using Tyra::ObjLoader;
|
||||
using Tyra::ObjLoaderOptions;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
Weapon::Weapon(Engine* engine) {
|
||||
ObjLoader loader;
|
||||
|
||||
ObjLoaderOptions objOptions;
|
||||
objOptions.flipUVs = true;
|
||||
objOptions.scale = .5F;
|
||||
|
||||
pad = &engine->pad;
|
||||
audio = &engine->audio;
|
||||
auto* repo = &engine->renderer.core.texture.repository;
|
||||
auto data =
|
||||
loader.load(FileUtils::fromCwd("game/models/ak47/ak47.obj"), objOptions);
|
||||
data->loadNormals = false;
|
||||
mesh = new StaticMesh(data.get());
|
||||
|
||||
mesh->translation.translateX(2.85F);
|
||||
mesh->translation.translateY(-3.40F);
|
||||
mesh->translation.translateZ(-10.50F);
|
||||
|
||||
mesh->rotation.rotateY(1.60F);
|
||||
mesh->rotation.rotateZ(-6.30F);
|
||||
|
||||
mesh->scale.scale(0.5F);
|
||||
|
||||
repo->addByMesh(mesh, FileUtils::fromCwd("game/models/ak47/"), "png");
|
||||
|
||||
initialPosition = *mesh->getPosition();
|
||||
|
||||
allocateOptions();
|
||||
|
||||
shootAdpcm =
|
||||
audio->adpcm.load(FileUtils::fromCwd("game/models/ak47/ak47.adpcm"));
|
||||
|
||||
isShootAnimation1 = isShootAnimation2 = false;
|
||||
|
||||
adpcmChannelsCount = 8;
|
||||
adpcmCurrentChannel = 0;
|
||||
|
||||
const u8 shootVolume = 25;
|
||||
for (u8 i = 0; i < adpcmChannelsCount; i++) {
|
||||
audio->adpcm.setVolume(shootVolume, i);
|
||||
}
|
||||
}
|
||||
|
||||
Weapon::~Weapon() {
|
||||
delete mesh;
|
||||
delete options;
|
||||
delete shootAdpcm;
|
||||
}
|
||||
|
||||
u8 Weapon::getShootChannel() {
|
||||
auto result = adpcmCurrentChannel++;
|
||||
|
||||
if (adpcmCurrentChannel >= adpcmChannelsCount) {
|
||||
adpcmCurrentChannel = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Weapon::update() {
|
||||
isShooting = false;
|
||||
|
||||
if (!isShootAnimation1 && !isShootAnimation2 && pad->getPressed().Cross) {
|
||||
shoot();
|
||||
}
|
||||
|
||||
auto* position = mesh->getPosition();
|
||||
|
||||
const float recoil = 0.5F;
|
||||
const float speed = 500;
|
||||
|
||||
if (isShootAnimation1) {
|
||||
position->z += recoil;
|
||||
position->y -= recoil / 4;
|
||||
if (shootTimer.getTimeDelta() > speed) {
|
||||
isShootAnimation1 = false;
|
||||
shootTimer.prime();
|
||||
isShootAnimation2 = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isShootAnimation2) {
|
||||
position->z -= recoil / 2;
|
||||
position->y += recoil / 8;
|
||||
if (shootTimer.getTimeDelta() > speed * 2) {
|
||||
isShootAnimation2 = false;
|
||||
*position = initialPosition;
|
||||
if (pad->getPressed().Cross) {
|
||||
shoot();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Weapon::shoot() {
|
||||
isShooting = true;
|
||||
shootTimer.prime();
|
||||
audio->adpcm.tryPlay(shootAdpcm, getShootChannel());
|
||||
isShootAnimation1 = true;
|
||||
}
|
||||
|
||||
void Weapon::allocateOptions() {
|
||||
options = new StaPipOptions();
|
||||
options->textureMappingType = Tyra::TyraNearest;
|
||||
options->shadingType = Tyra::TyraShadingFlat;
|
||||
options->blendingEnabled = false;
|
||||
options->fullClipChecks = false;
|
||||
options->frustumCulling = Tyra::PipelineFrustumCulling_None;
|
||||
options->transformationType = Tyra::TyraMP;
|
||||
options->antiAliasingEnabled = false;
|
||||
}
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "states/game/renderer/game_renderer.hpp"
|
||||
|
||||
using Tyra::Threading;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
GameRenderer::GameRenderer(Renderer* t_renderer) {
|
||||
renderer = t_renderer;
|
||||
|
||||
stpip.setRenderer(&renderer->core);
|
||||
dypip.setRenderer(&renderer->core);
|
||||
}
|
||||
|
||||
GameRenderer::~GameRenderer() {}
|
||||
|
||||
void GameRenderer::add(std::vector<RendererStaticPair*> t_staticPairs) {
|
||||
staticPairs.insert(staticPairs.end(), t_staticPairs.begin(),
|
||||
t_staticPairs.end());
|
||||
}
|
||||
|
||||
void GameRenderer::add(std::vector<RendererDynamicPair*> t_dynamicPairs) {
|
||||
dynamicPairs.insert(dynamicPairs.end(), t_dynamicPairs.begin(),
|
||||
t_dynamicPairs.end());
|
||||
}
|
||||
|
||||
void GameRenderer::add(Sprite* sprite) { sprites.push_back(sprite); }
|
||||
|
||||
void GameRenderer::add(const CoreBBox& bbox) { bboxes.push_back(bbox); }
|
||||
|
||||
void GameRenderer::add(RendererStaticPair* staticPair) {
|
||||
staticPairs.push_back(staticPair);
|
||||
}
|
||||
|
||||
void GameRenderer::add(RendererDynamicPair* dynamicPair) {
|
||||
dynamicPairs.push_back(dynamicPair);
|
||||
}
|
||||
|
||||
void GameRenderer::clear() {
|
||||
staticPairs.clear();
|
||||
dynamicPairs.clear();
|
||||
sprites.clear();
|
||||
bboxes.clear();
|
||||
}
|
||||
|
||||
void GameRenderer::render() {
|
||||
// Render static stuff
|
||||
if (staticPairs.size()) {
|
||||
renderer->renderer3D.usePipeline(&stpip);
|
||||
|
||||
for (auto& pair : staticPairs) {
|
||||
stpip.render(pair->mesh, pair->options);
|
||||
}
|
||||
}
|
||||
|
||||
Threading::switchThread(); // give some time for audio thread
|
||||
|
||||
// Render animated stuff
|
||||
if (dynamicPairs.size()) {
|
||||
renderer->renderer3D.usePipeline(&dypip);
|
||||
|
||||
for (auto& pair : dynamicPairs) {
|
||||
dypip.render(pair->mesh, pair->options);
|
||||
}
|
||||
}
|
||||
|
||||
Threading::switchThread();
|
||||
|
||||
// Render debug stuff after stapip/dynpip, otherwise it will not be visible
|
||||
for (auto& bbox : bboxes) {
|
||||
renderer->renderer3D.utility.drawBBox(bbox);
|
||||
}
|
||||
|
||||
// Render 2D
|
||||
for (auto& sprite : sprites) {
|
||||
renderer->renderer2D.render(sprite);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "states/game/ship/ship.hpp"
|
||||
|
||||
using Tyra::FileUtils;
|
||||
using Tyra::ObjLoader;
|
||||
using Tyra::ObjLoaderOptions;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
Ship::Ship(TextureRepository* repo) {
|
||||
ObjLoader loader;
|
||||
|
||||
ObjLoaderOptions objOptions;
|
||||
objOptions.flipUVs = true;
|
||||
objOptions.scale = 200.0F;
|
||||
|
||||
auto data =
|
||||
loader.load(FileUtils::fromCwd("game/models/ship/ship.obj"), objOptions);
|
||||
mesh = new StaticMesh(data.get());
|
||||
|
||||
for (std::size_t i = 0; i < mesh->materials.size(); i++) {
|
||||
mesh->materials[i]->ambient /= 2.0F;
|
||||
mesh->materials[i]->ambient.a = 128.0F;
|
||||
}
|
||||
|
||||
mesh->setPosition(Vec4(-800.0F, 10.0F, -2500.0F));
|
||||
|
||||
allocateOptions();
|
||||
|
||||
pair = new RendererStaticPair{mesh, options};
|
||||
}
|
||||
|
||||
Ship::~Ship() {
|
||||
delete mesh;
|
||||
delete options;
|
||||
delete pair;
|
||||
}
|
||||
|
||||
void Ship::allocateOptions() { options = new StaPipOptions(); }
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "states/game/skybox/skybox.hpp"
|
||||
|
||||
using Tyra::FileUtils;
|
||||
using Tyra::ObjLoader;
|
||||
using Tyra::ObjLoaderOptions;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
Skybox::Skybox(TextureRepository* repo) {
|
||||
ObjLoader loader;
|
||||
|
||||
ObjLoaderOptions objOptions;
|
||||
objOptions.flipUVs = true;
|
||||
objOptions.scale = 100.0F;
|
||||
|
||||
auto data = loader.load(FileUtils::fromCwd("game/models/skybox/skybox.obj"),
|
||||
objOptions);
|
||||
data->loadNormals = false;
|
||||
mesh = new StaticMesh(data.get());
|
||||
|
||||
repo->addByMesh(mesh, FileUtils::fromCwd("game/models/skybox/"), "png");
|
||||
|
||||
allocateOptions();
|
||||
|
||||
pair = new RendererStaticPair{mesh, options};
|
||||
}
|
||||
|
||||
Skybox::~Skybox() {
|
||||
delete mesh;
|
||||
delete options;
|
||||
delete pair;
|
||||
}
|
||||
|
||||
void Skybox::update(const Vec4& playerPosition) {
|
||||
mesh->translation.identity();
|
||||
mesh->translation.translate(playerPosition);
|
||||
}
|
||||
|
||||
void Skybox::allocateOptions() {
|
||||
options = new StaPipOptions();
|
||||
options->frustumCulling = Tyra::PipelineFrustumCulling_None;
|
||||
options->shadingType = Tyra::TyraShadingGouraud;
|
||||
options->zTestType = Tyra::PipelineZTest_AllPass;
|
||||
options->textureMappingType = Tyra::TyraNearest;
|
||||
options->blendingEnabled = true;
|
||||
options->antiAliasingEnabled = false;
|
||||
}
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "states/game/terrain/heightmap.hpp"
|
||||
|
||||
using Tyra::FileUtils;
|
||||
using Tyra::PngLoader;
|
||||
using Tyra::PngPixel3;
|
||||
using Tyra::Vec4;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
Heightmap::Heightmap(const float& t_minHeight, const float& t_maxHeight,
|
||||
const Vec4& t_leftUp, const Vec4& t_rightDown)
|
||||
: minHeight(t_minHeight),
|
||||
maxHeight(t_maxHeight),
|
||||
leftUp(t_leftUp),
|
||||
rightDown(t_rightDown) {
|
||||
PngLoader loader;
|
||||
auto* data =
|
||||
loader.load(FileUtils::fromCwd("game/models/terrain/heightmap.png"));
|
||||
|
||||
allocateMap(data->data, data->width, data->height);
|
||||
|
||||
delete data;
|
||||
}
|
||||
|
||||
bool Heightmap::isOutside(const Vec4& position) const {
|
||||
return position.x <= leftUp.x || position.x >= rightDown.x ||
|
||||
position.z <= leftUp.z || position.z >= rightDown.z;
|
||||
}
|
||||
|
||||
Heightmap::~Heightmap() {
|
||||
if (map) {
|
||||
for (int i = 0; i < mapHeight; i++) {
|
||||
delete[] map[i];
|
||||
}
|
||||
delete[] map;
|
||||
}
|
||||
}
|
||||
|
||||
const float& Heightmap::getHeightOffset(const Vec4& playerPosition) const {
|
||||
float widthPercentage = getWidthPercentage(playerPosition);
|
||||
float heightPercentage = getHeightPercentage(playerPosition);
|
||||
|
||||
auto x = static_cast<s16>(widthPercentage * mapWidth);
|
||||
auto y = static_cast<s16>(heightPercentage * mapHeight);
|
||||
|
||||
TYRA_ASSERT(x >= 0 && x < mapWidth, "x is out of range");
|
||||
TYRA_ASSERT(y >= 0 && y < mapHeight, "y is out of range");
|
||||
|
||||
return map[x][y];
|
||||
}
|
||||
|
||||
float Heightmap::getWidthPercentage(const Vec4& playerPosition) const {
|
||||
return (playerPosition.x - leftUp.x) / (rightDown.x - leftUp.x);
|
||||
}
|
||||
|
||||
float Heightmap::getHeightPercentage(const Vec4& playerPosition) const {
|
||||
return (playerPosition.z - leftUp.z) / (rightDown.z - leftUp.z);
|
||||
}
|
||||
|
||||
void Heightmap::allocateMap(const unsigned char* data, const int& width,
|
||||
const int& height) {
|
||||
auto* pixels = (struct PngPixel3*)data;
|
||||
|
||||
u8 min = pixels[0].r; // in grayscale every r,g,b is the same
|
||||
u8 max = pixels[0].r;
|
||||
|
||||
// Get min and max
|
||||
for (int i = 0; i < width * height; i++) {
|
||||
const auto& value = pixels[i].r;
|
||||
if (value < min) {
|
||||
min = value;
|
||||
}
|
||||
if (value > max) {
|
||||
max = value;
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate
|
||||
mapWidth = width;
|
||||
mapHeight = height;
|
||||
map = new float*[width];
|
||||
for (int i = 0; i < width; i++) {
|
||||
map[i] = new float[height];
|
||||
}
|
||||
|
||||
// Fill
|
||||
int k = 0;
|
||||
for (int j = 0; j < height; j++) {
|
||||
for (int i = 0; i < width; i++) {
|
||||
map[i][j] = getGameHeight(pixels[k++].r, min, max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float Heightmap::getGameHeight(const u8& inputColor, const u8& minColor,
|
||||
const u8& maxColor) const {
|
||||
const float mapRange = maxColor - minColor;
|
||||
const float gameRange = maxHeight - minHeight;
|
||||
|
||||
return (inputColor - minColor) / mapRange * gameRange + minHeight;
|
||||
}
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "states/game/terrain/terrain.hpp"
|
||||
|
||||
using Tyra::FileUtils;
|
||||
using Tyra::ObjLoader;
|
||||
using Tyra::ObjLoaderOptions;
|
||||
|
||||
namespace Demo {
|
||||
Terrain::Terrain(TextureRepository* repo)
|
||||
: heightmap(-70.0F, // Min height
|
||||
240.0F, // Max height
|
||||
Vec4(-750.0F, 0.0F, -1400.0F, 1.0F), // Left up
|
||||
Vec4(920.0F, 0.0F, 1520.0F, 1.0F) // Right down
|
||||
) {
|
||||
ObjLoader loader;
|
||||
|
||||
ObjLoaderOptions objOptions;
|
||||
objOptions.flipUVs = true;
|
||||
objOptions.scale = 100.0F;
|
||||
|
||||
auto data = loader.load(FileUtils::fromCwd("game/models/terrain/terrain.obj"),
|
||||
objOptions);
|
||||
data->loadNormals = false;
|
||||
mesh = new StaticMesh(data.get());
|
||||
|
||||
repo->addByMesh(mesh, FileUtils::fromCwd("game/models/terrain/"), "png");
|
||||
|
||||
allocateOptions();
|
||||
|
||||
pair = new RendererStaticPair{mesh, options};
|
||||
}
|
||||
|
||||
float Terrain::getHeightOffset(const Vec4& playerPosition) {
|
||||
return heightmap.getHeightOffset(playerPosition);
|
||||
}
|
||||
|
||||
Terrain::~Terrain() {
|
||||
delete mesh;
|
||||
delete options;
|
||||
delete pair;
|
||||
}
|
||||
|
||||
void Terrain::allocateOptions() {
|
||||
options = new StaPipOptions();
|
||||
options->frustumCulling = Tyra::PipelineFrustumCulling_None;
|
||||
options->shadingType = Tyra::TyraShadingGouraud;
|
||||
options->blendingEnabled = true;
|
||||
options->antiAliasingEnabled = false;
|
||||
}
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "states/intro/intro_state.hpp"
|
||||
|
||||
#include "states/intro/states/intro_ps2dev_state.hpp"
|
||||
#include "states/intro/states/intro_tyra_state.hpp"
|
||||
#include "states/intro/states/intro_press_key_state.hpp"
|
||||
|
||||
using Tyra::FileUtils;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
IntroState::IntroState(Engine* t_engine)
|
||||
: State(t_engine), stateManager(STATE_PS2DEV, STATE_INTRO_END) {
|
||||
state = STATE_INTRO;
|
||||
_wantFinish = false;
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
IntroState::~IntroState() {}
|
||||
|
||||
void IntroState::onStart() {
|
||||
TYRA_LOG("Intro. RAM: ", engine->info.getAvailableRAM(), "MB");
|
||||
|
||||
engine->audio.song.load(FileUtils::fromCwd("intro/intro.wav"));
|
||||
engine->audio.song.inLoop = false;
|
||||
engine->audio.song.setVolume(80);
|
||||
engine->audio.song.play();
|
||||
|
||||
stateManager.add(new IntroPs2DevState(engine));
|
||||
stateManager.add(new IntroTyraState(engine));
|
||||
stateManager.add(new IntroPressKeyState(engine));
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
GlobalStateType IntroState::onFinish() {
|
||||
if (!initialized) return STATE_LOADING;
|
||||
|
||||
stateManager.freeAll();
|
||||
|
||||
initialized = false;
|
||||
return STATE_LOADING;
|
||||
}
|
||||
|
||||
void IntroState::update() {
|
||||
stateManager.update();
|
||||
|
||||
if (stateManager.finished()) {
|
||||
_wantFinish = true;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "states/intro/states/intro_press_key_state.hpp"
|
||||
#include <string>
|
||||
|
||||
using Tyra::FileUtils;
|
||||
using Tyra::Math;
|
||||
using Tyra::PngLoader;
|
||||
using Tyra::SpriteMode;
|
||||
using Tyra::Threading;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
IntroPressKeyState::IntroPressKeyState(Engine* t_engine)
|
||||
: State(t_engine), mapPosition(0.0F, 0.0F) {
|
||||
state = STATE_PRESS_KEY;
|
||||
_wantFinish = false;
|
||||
mapDirection = 0;
|
||||
mapFadeIn = true;
|
||||
fillerFadeIn = false;
|
||||
showPressKey = false;
|
||||
pressKeyAlphaToggle = false;
|
||||
pressKeyAlphaDelayer = 0;
|
||||
fillersOffset = -512.0F;
|
||||
}
|
||||
|
||||
IntroPressKeyState::~IntroPressKeyState() {}
|
||||
|
||||
void IntroPressKeyState::onStart() {
|
||||
TYRA_LOG("Intro - presskey. RAM: ", engine->info.getAvailableRAM(), "MB");
|
||||
|
||||
for (u8 i = 0; i < mapRows; i++) {
|
||||
for (u8 j = 0; j < mapCols; j++) {
|
||||
mapSprites[i][j] = new Sprite;
|
||||
mapSprites[i][j]->color.a = 0.0F;
|
||||
mapSprites[i][j]->mode = SpriteMode::MODE_STRETCH;
|
||||
mapSprites[i][j]->size.set(textureWidthHeight, textureWidthHeight);
|
||||
mapSprites[i][j]->position.set(i * textureWidthHeight,
|
||||
j * textureWidthHeight);
|
||||
|
||||
std::string filename =
|
||||
"map-" + std::to_string(i) + "-" + std::to_string(j);
|
||||
std::string path = "intro/map/" + filename + ".png";
|
||||
|
||||
mapTextures[i][j] = engine->renderer.core.texture.repository.add(
|
||||
FileUtils::fromCwd(path));
|
||||
mapTextures[i][j]->addLink(mapSprites[i][j]->id);
|
||||
}
|
||||
}
|
||||
|
||||
fillerSprite = new Sprite;
|
||||
fillerSprite->size.set(256.0F, 50.0F);
|
||||
fillerSprite->position.set(0.0F, 224.0F - 25.0F);
|
||||
|
||||
fillerTexture = engine->renderer.core.texture.repository.add(
|
||||
FileUtils::fromCwd("intro/filler.png"));
|
||||
fillerTexture->addLink(fillerSprite->id);
|
||||
|
||||
pressKeySprite = new Sprite;
|
||||
pressKeySprite->size.set(256.0F, 64.0F);
|
||||
pressKeySprite->scale = 0.5F;
|
||||
pressKeySprite->position.set(192.0F, 380.0F);
|
||||
|
||||
pressKeyTexture = engine->renderer.core.texture.repository.add(
|
||||
FileUtils::fromCwd("intro/press-key.png"));
|
||||
pressKeyTexture->addLink(pressKeySprite->id);
|
||||
|
||||
logoSprite = new Sprite;
|
||||
logoSprite->size.set(256.0F, 128.0F);
|
||||
logoSprite->position.set(256.0F - 128.0F, 224.0F - 64.0F);
|
||||
|
||||
logoTexture = engine->renderer.core.texture.repository.add(
|
||||
FileUtils::fromCwd("intro/lastalive.png"));
|
||||
logoTexture->addLink(logoSprite->id);
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
IntroStateType IntroPressKeyState::onFinish() {
|
||||
if (!initialized) return STATE_INTRO_END;
|
||||
|
||||
for (u8 i = 0; i < mapRows; i++)
|
||||
for (u8 j = 0; j < mapCols; j++) {
|
||||
engine->renderer.core.texture.repository.free(mapTextures[i][j]->id);
|
||||
delete mapSprites[i][j];
|
||||
}
|
||||
|
||||
engine->renderer.core.texture.repository.free(fillerTexture->id);
|
||||
delete fillerSprite;
|
||||
|
||||
engine->renderer.core.texture.repository.free(logoTexture->id);
|
||||
delete logoSprite;
|
||||
|
||||
engine->renderer.core.texture.repository.free(pressKeyTexture->id);
|
||||
delete pressKeySprite;
|
||||
|
||||
initialized = false;
|
||||
return STATE_INTRO_END;
|
||||
}
|
||||
|
||||
void IntroPressKeyState::update() {
|
||||
engine->renderer.beginFrame();
|
||||
|
||||
if (mapDirection == 0 &&
|
||||
mapPosition.x >= textureWidthHeight * (mapRows - 1) &&
|
||||
mapPosition.y >= textureWidthHeight * (mapCols - 1)) {
|
||||
mapDirection = 1;
|
||||
} else if (mapDirection == 1 && mapPosition.x <= 0.0F &&
|
||||
mapPosition.y <= 0.0F) {
|
||||
mapDirection = 0;
|
||||
}
|
||||
|
||||
if (engine->pad.getClicked().Cross) {
|
||||
_wantFinish = true;
|
||||
}
|
||||
|
||||
const float offset = 0.1F;
|
||||
if (mapDirection == 0) {
|
||||
mapPosition += offset;
|
||||
} else if (mapDirection == 1) {
|
||||
mapPosition -= offset;
|
||||
}
|
||||
|
||||
if (mapFadeIn) {
|
||||
for (u8 i = 0; i < mapRows; i++) {
|
||||
for (u8 j = 0; j < mapCols; j++) {
|
||||
auto* sprite = mapSprites[i][j];
|
||||
if (sprite->color.a >= 16.0F && sprite->color.a < 32.0F) {
|
||||
fillerFadeIn = true;
|
||||
}
|
||||
if (sprite->color.a < 96.0F) {
|
||||
sprite->color.a += 0.2F;
|
||||
} else {
|
||||
mapFadeIn = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fillerFadeIn) {
|
||||
if (fillersOffset < -1.0F) {
|
||||
fillersOffset += 4.0F;
|
||||
} else {
|
||||
fillerFadeIn = false;
|
||||
showPressKey = true;
|
||||
}
|
||||
}
|
||||
|
||||
updateMap();
|
||||
|
||||
Threading::switchThread();
|
||||
|
||||
for (u8 i = 0; i < mapRows; i++)
|
||||
for (u8 j = 0; j < mapCols; j++)
|
||||
engine->renderer.renderer2D.render(mapSprites[i][j]);
|
||||
|
||||
renderFiller();
|
||||
engine->renderer.renderer2D.render(logoSprite);
|
||||
|
||||
if (showPressKey) {
|
||||
if (pressKeyAlphaDelayer++ > 50) {
|
||||
pressKeyAlphaToggle = !pressKeyAlphaToggle;
|
||||
pressKeyAlphaDelayer = 0;
|
||||
}
|
||||
|
||||
if (pressKeyAlphaToggle) {
|
||||
engine->renderer.renderer2D.render(pressKeySprite);
|
||||
}
|
||||
}
|
||||
|
||||
engine->renderer.endFrame();
|
||||
}
|
||||
|
||||
void IntroPressKeyState::renderFiller() {
|
||||
fillerSprite->position.x = -1.0F + fillersOffset;
|
||||
engine->renderer.renderer2D.render(fillerSprite);
|
||||
fillerSprite->position.x = 255.0F + fillersOffset;
|
||||
engine->renderer.renderer2D.render(fillerSprite);
|
||||
}
|
||||
|
||||
void IntroPressKeyState::updateMap() {
|
||||
for (u8 i = 0; i < mapRows; i++)
|
||||
for (u8 j = 0; j < mapCols; j++) {
|
||||
mapSprites[i][j]->position.x =
|
||||
i * (textureWidthHeight + 1.0F) - mapPosition.x;
|
||||
mapSprites[i][j]->position.y =
|
||||
j * (textureWidthHeight + 1.0F) - mapPosition.y;
|
||||
}
|
||||
}
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "states/intro/states/intro_ps2dev_state.hpp"
|
||||
|
||||
using Tyra::FileUtils;
|
||||
using Tyra::PngLoader;
|
||||
using Tyra::Threading;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
IntroPs2DevState::IntroPs2DevState(Engine* t_engine) : State(t_engine) {
|
||||
state = STATE_PS2DEV;
|
||||
_wantFinish = false;
|
||||
initialized = false;
|
||||
initialDelayElapsed = false;
|
||||
frameSkipper = 0;
|
||||
fadeinActivated = true;
|
||||
fadeoutActivated = false;
|
||||
}
|
||||
|
||||
IntroPs2DevState::~IntroPs2DevState() {}
|
||||
|
||||
void IntroPs2DevState::onStart() {
|
||||
TYRA_LOG("Intro - ps2dev. RAM: ", engine->info.getAvailableRAM(), "MB");
|
||||
|
||||
const auto& settings = engine->renderer.core.getSettings();
|
||||
|
||||
initialDelayTimer.prime();
|
||||
|
||||
sprite = new Sprite;
|
||||
sprite->size.set(256.0F, 64.0F);
|
||||
sprite->position.set(settings.getWidth() / 2 - sprite->size.x / 2,
|
||||
settings.getHeight() / 2 - sprite->size.y / 2);
|
||||
sprite->color.a = 0;
|
||||
|
||||
Threading::switchThread();
|
||||
|
||||
texture = engine->renderer.core.texture.repository.add(
|
||||
FileUtils::fromCwd("intro/ps2dev.png"));
|
||||
texture->addLink(sprite->id);
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
IntroStateType IntroPs2DevState::onFinish() {
|
||||
if (!initialized) return STATE_TYRA;
|
||||
|
||||
delete sprite;
|
||||
engine->renderer.core.texture.repository.free(texture->id);
|
||||
|
||||
initialized = false;
|
||||
return STATE_TYRA;
|
||||
}
|
||||
|
||||
void IntroPs2DevState::update() {
|
||||
engine->renderer.beginFrame();
|
||||
|
||||
if (initialDelayTimer.getTimeDelta() >= 60000) initialDelayElapsed = true;
|
||||
|
||||
if (engine->pad.getClicked().Cross) {
|
||||
_wantFinish = true;
|
||||
}
|
||||
|
||||
frameSkipper++;
|
||||
if (frameSkipper > 3) {
|
||||
frameSkipper = 0;
|
||||
}
|
||||
|
||||
if (fadeinActivated && initialDelayElapsed && frameSkipper == 0) {
|
||||
if (sprite->color.a < 128.0F)
|
||||
sprite->color.a += 2.0F;
|
||||
else {
|
||||
fadeoutActivated = true;
|
||||
fadeinActivated = false;
|
||||
}
|
||||
if (sprite->color.a >= 96.0F && sprite->color.a < 128.0F) {
|
||||
sprite->color.g -= 6.0F;
|
||||
sprite->color.b -= 6.0F;
|
||||
}
|
||||
}
|
||||
|
||||
Threading::switchThread();
|
||||
|
||||
if (fadeoutActivated && frameSkipper == 0) {
|
||||
if (sprite->color.a > 0)
|
||||
sprite->color.a -= 4;
|
||||
else
|
||||
_wantFinish = true;
|
||||
}
|
||||
|
||||
engine->renderer.renderer2D.render(sprite);
|
||||
|
||||
engine->renderer.endFrame();
|
||||
}
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "states/intro/states/intro_tyra_state.hpp"
|
||||
|
||||
using Tyra::FileUtils;
|
||||
using Tyra::Math;
|
||||
using Tyra::PngLoader;
|
||||
using Tyra::Threading;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
IntroTyraState::IntroTyraState(Engine* t_engine) : State(t_engine) {
|
||||
state = STATE_TYRA;
|
||||
_wantFinish = false;
|
||||
initialized = false;
|
||||
initialDelayElapsed = false;
|
||||
animActivated = true;
|
||||
fadeoutActivated = false;
|
||||
frameSkipper = 0;
|
||||
}
|
||||
|
||||
IntroTyraState::~IntroTyraState() {}
|
||||
|
||||
void IntroTyraState::onStart() {
|
||||
TYRA_LOG("Intro - tyra. RAM: ", engine->info.getAvailableRAM(), "MB");
|
||||
|
||||
const auto& settings = engine->renderer.core.getSettings();
|
||||
|
||||
initialDelayTimer.prime();
|
||||
|
||||
tyraSprite = new Sprite;
|
||||
tyraSprite->size.set(256.0F, 64.0F);
|
||||
tyraSprite->position.set(settings.getWidth() / 2 - tyraSprite->size.x / 2,
|
||||
settings.getHeight() / 2 - tyraSprite->size.y / 2);
|
||||
|
||||
bgSprite = new Sprite;
|
||||
bgSprite->size.set(256.0F, 256.0F);
|
||||
bgSprite->position.set(settings.getWidth() / 2 - bgSprite->size.x / 2,
|
||||
settings.getHeight() / 3 * 2.0F);
|
||||
|
||||
bg2Sprite = new Sprite;
|
||||
bg2Sprite->size.set(256.0F, 256.0F);
|
||||
bg2Sprite->position.set(
|
||||
settings.getWidth() / 2 - bg2Sprite->size.x / 2,
|
||||
(settings.getHeight() / 3 * 2.0F) + bg2Sprite->size.y + 1.0F);
|
||||
|
||||
fillerSprite = new Sprite;
|
||||
fillerSprite->size.set(256.0F, 256.0F);
|
||||
fillerSprite->position.set(0.0F, 0.0F);
|
||||
|
||||
tyraTexture = engine->renderer.core.texture.repository.add(
|
||||
FileUtils::fromCwd("intro/tyra.png"));
|
||||
tyraTexture->addLink(tyraSprite->id);
|
||||
|
||||
bgTexture = engine->renderer.core.texture.repository.add(
|
||||
FileUtils::fromCwd("intro/tyra_bg.png"));
|
||||
bgTexture->addLink(bgSprite->id);
|
||||
|
||||
Threading::switchThread();
|
||||
|
||||
bg2Texture = engine->renderer.core.texture.repository.add(
|
||||
FileUtils::fromCwd("intro/tyra_bg2.png"));
|
||||
bg2Texture->addLink(bg2Sprite->id);
|
||||
|
||||
fillerTexture = engine->renderer.core.texture.repository.add(
|
||||
FileUtils::fromCwd("intro/filler.png"));
|
||||
fillerTexture->addLink(fillerSprite->id);
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
IntroStateType IntroTyraState::onFinish() {
|
||||
if (!initialized) return STATE_PRESS_KEY;
|
||||
|
||||
engine->renderer.core.texture.repository.free(tyraTexture->id);
|
||||
engine->renderer.core.texture.repository.free(bgTexture->id);
|
||||
engine->renderer.core.texture.repository.free(bg2Texture->id);
|
||||
engine->renderer.core.texture.repository.free(fillerTexture->id);
|
||||
|
||||
delete tyraSprite;
|
||||
delete bgSprite;
|
||||
delete bg2Sprite;
|
||||
delete fillerSprite;
|
||||
|
||||
initialized = false;
|
||||
return STATE_PRESS_KEY;
|
||||
}
|
||||
|
||||
void IntroTyraState::update() {
|
||||
engine->renderer.beginFrame();
|
||||
|
||||
if (initialDelayTimer.getTimeDelta() >= 15000) initialDelayElapsed = true;
|
||||
|
||||
frameSkipper++;
|
||||
if (frameSkipper > 3) {
|
||||
frameSkipper = 0;
|
||||
}
|
||||
|
||||
if (engine->pad.getClicked().Cross) {
|
||||
_wantFinish = true;
|
||||
}
|
||||
|
||||
const float slideUpMaxPost = -128.0F;
|
||||
|
||||
if (initialDelayElapsed) {
|
||||
if (bgSprite->position.y <= 32.0F) fadeoutActivated = true;
|
||||
|
||||
float offset = 1.0F;
|
||||
if (bgSprite->position.y > slideUpMaxPost && bgSprite->position.y <= 64.0F)
|
||||
offset /= 1.6F;
|
||||
else if (bgSprite->position.y > 64.0F && bgSprite->position.y <= 128.0F)
|
||||
offset /= 1.2F;
|
||||
|
||||
if (bgSprite->position.y > 32.0F && bgSprite->position.y <= 64.0F &&
|
||||
bgSprite->color.g > 0.0F) {
|
||||
const float colorOffset = 1.5F;
|
||||
bgSprite->color.g -= colorOffset;
|
||||
bgSprite->color.b -= colorOffset;
|
||||
bg2Sprite->color.g -= colorOffset;
|
||||
bg2Sprite->color.b -= colorOffset;
|
||||
}
|
||||
|
||||
if (bgSprite->position.y > slideUpMaxPost) {
|
||||
bgSprite->position.y -= offset;
|
||||
bg2Sprite->position.y -= offset;
|
||||
}
|
||||
}
|
||||
|
||||
if (fadeoutActivated && frameSkipper == 0) {
|
||||
if (bgSprite->color.a > 0) {
|
||||
bgSprite->color.a -= 4.0F;
|
||||
bg2Sprite->color.a -= 4.0F;
|
||||
} else
|
||||
_wantFinish = true;
|
||||
}
|
||||
|
||||
Threading::switchThread();
|
||||
|
||||
engine->renderer.renderer2D.render(bgSprite);
|
||||
engine->renderer.renderer2D.render(bg2Sprite);
|
||||
engine->renderer.renderer2D.render(tyraSprite);
|
||||
|
||||
renderFillers();
|
||||
|
||||
engine->renderer.endFrame();
|
||||
}
|
||||
|
||||
void IntroTyraState::renderFillers() {
|
||||
// Up
|
||||
fillerSprite->position.set(0.0F, -63.0F);
|
||||
engine->renderer.renderer2D.render(fillerSprite);
|
||||
|
||||
fillerSprite->position.set(256.0F, -63.0F);
|
||||
engine->renderer.renderer2D.render(fillerSprite);
|
||||
|
||||
// Left
|
||||
fillerSprite->position.set(-124.0F, 128.0F);
|
||||
engine->renderer.renderer2D.render(fillerSprite);
|
||||
|
||||
// Down
|
||||
fillerSprite->position.set(0.0F, 256.0F);
|
||||
engine->renderer.renderer2D.render(fillerSprite);
|
||||
|
||||
fillerSprite->position.set(256.0F, 256.0F);
|
||||
engine->renderer.renderer2D.render(fillerSprite);
|
||||
|
||||
// Right
|
||||
fillerSprite->position.set(386.0F, 128.0F);
|
||||
engine->renderer.renderer2D.render(fillerSprite);
|
||||
}
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include <tyra>
|
||||
#include "states/loading/loading_state.hpp"
|
||||
#include <memory>
|
||||
|
||||
using std::make_unique;
|
||||
using std::unique_ptr;
|
||||
using Tyra::FileUtils;
|
||||
using Tyra::Sprite;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
LoadingState::LoadingState(Engine* t_engine) : State(t_engine) {
|
||||
state = STATE_LOADING;
|
||||
_wantFinish = false;
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
LoadingState::~LoadingState() {}
|
||||
|
||||
void LoadingState::onStart() {
|
||||
TYRA_LOG("Loading. RAM: ", engine->info.getAvailableRAM(), "MB");
|
||||
|
||||
auto* repo = &engine->renderer.core.texture.repository;
|
||||
|
||||
auto fillerTexture = repo->add(FileUtils::fromCwd("loading/filler.png"));
|
||||
auto loadingTexture = repo->add(FileUtils::fromCwd("loading/loading.png"));
|
||||
|
||||
auto fillerSprite = make_unique<Sprite>();
|
||||
auto loadingSprite = make_unique<Sprite>();
|
||||
|
||||
fillerSprite->position.set(0.0F, 0.0F);
|
||||
fillerSprite->size.set(600.0F, 600.0F);
|
||||
fillerSprite->mode = Tyra::MODE_STRETCH;
|
||||
|
||||
loadingSprite->size.set(128.0F, 64.0F);
|
||||
loadingSprite->mode = Tyra::MODE_STRETCH;
|
||||
loadingSprite->position.set(5.0F, 448.0F - 64.0F - 5.0F);
|
||||
|
||||
fillerTexture->addLink(fillerSprite->id);
|
||||
loadingTexture->addLink(loadingSprite->id);
|
||||
|
||||
engine->renderer.beginFrame();
|
||||
engine->renderer.renderer2D.render(fillerSprite.get());
|
||||
engine->renderer.renderer2D.render(loadingSprite.get());
|
||||
engine->renderer.endFrame();
|
||||
|
||||
repo->free(fillerTexture->id);
|
||||
repo->free(loadingTexture->id);
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
GlobalStateType LoadingState::onFinish() {
|
||||
if (!initialized) return STATE_GAME;
|
||||
|
||||
initialized = false;
|
||||
return STATE_GAME;
|
||||
}
|
||||
|
||||
void LoadingState::update() { _wantFinish = true; }
|
||||
|
||||
} // namespace Demo
|
||||
@@ -0,0 +1,14 @@
|
||||
version: "3.9"
|
||||
volumes:
|
||||
tyra-volume:
|
||||
services:
|
||||
compiler:
|
||||
environment:
|
||||
TERM: xterm-256color
|
||||
network_mode: host
|
||||
image: "h4570/tyra"
|
||||
tty: true
|
||||
container_name: tyra-compiler
|
||||
volumes:
|
||||
- tyra-volume:/src
|
||||
- ./:/host
|
||||
@@ -0,0 +1,26 @@
|
||||
# Installing Tyra
|
||||
|
||||
[](#)
|
||||
|
||||
## Prerequisites:
|
||||
1. Git
|
||||
2. VSCode
|
||||
3. Docker with PowerShell as a default terminal
|
||||
4. [PCSX2](https://github.com/h4570/tyra/blob/master/docs/install/pcsx2.md#)
|
||||
|
||||
---
|
||||
|
||||
## Steps:
|
||||
1. Download [intellisense package](https://github.com/h4570/tyra/releases) and unzip it somewhere in your computer.
|
||||
2. Open terminal in your favourite repositories directory and execute:
|
||||
```
|
||||
docker pull h4570/tyra
|
||||
git clone https://github.com/h4570/tyra.git
|
||||
```
|
||||
3. Download the [assets.zip](https://github.com/h4570/tyra/releases) file and unzip it into the tyra directory
|
||||
4. Open `VSCode` and open previously cloned directory.
|
||||
5. In `VSCode` open `.vscode/configurations/windows-docker` and copy configuration files into `.vscode/`
|
||||
6. In `c_cpp_properties.json` fix all `YOUR-INTELLISENSE-PATH` with path from point 2.
|
||||
7. Click `CTRL+SHIFT+P`, type `Tasks: Run task` and run `Start docker container` - Repeat this step every time you want to start working with Tyra (every reboot)
|
||||
8. Click `CTRL+SHIFT+P`, type `Tasks: Run build task`
|
||||
9. Tyra should automatically compile engine, `demo` game and run `PCSX2`. If you want to compile & run tutorials, please change `buildDirectory` in `settings.json` to example `tutorials/01-hello`
|
||||
@@ -0,0 +1,21 @@
|
||||
## Install & configure PCSX2
|
||||
|
||||
- Download & install PCSX2 (1.6+ version) from https://pcsx2.net/
|
||||
- Extract bios files from https://romsmania.cc/bios/pcsx2-playstation-2-bios-3 to `%UserProfile%\Documents\PCSX2\bios`
|
||||
- Close `PCSX2` if you have opened!
|
||||
- Open `%UserProfile%\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
|
||||
```
|
||||
|
||||
- Enable **"EE timing hack"** in PCSX2 hacks!
|
||||
@@ -0,0 +1,26 @@
|
||||
TARGET := libtyra.a
|
||||
|
||||
#The Directories, Source, Includes, Objects, Binary and Resources
|
||||
SRCDIR := src
|
||||
INCDIR := inc
|
||||
BUILDDIR := obj
|
||||
TARGETDIR := bin
|
||||
RESDIR := res
|
||||
SRCEXT := cpp
|
||||
VSMEXT := vsm
|
||||
VCLEXT := vcl
|
||||
VCLPPEXT := vclpp
|
||||
DEPEXT := d
|
||||
OBJEXT := o
|
||||
|
||||
#Flags, Libraries and Includes
|
||||
CFLAGS :=
|
||||
LIB :=
|
||||
LIBDIRS :=
|
||||
INC := -I$(INCDIR)
|
||||
INCDEP := -I$(INCDIR)
|
||||
|
||||
include ../Makefile.base
|
||||
|
||||
$(TARGET): $(OBJECTS) $(VCL_OBJECTS) $(VU_OBJECTS_VCL) $(VU_OBJECTS_VSM) $(IRXEM_OBJECTS)
|
||||
$(AR) rcs $(TARGETDIR)/$(TARGET) $(OBJECTS) $(VCL_OBJECTS) $(VU_OBJECTS_VCL) $(VU_OBJECTS_VSM) $(IRXEM_OBJECTS)
|
||||
@@ -0,0 +1,4 @@
|
||||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file
|
||||
!.gitignore
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022-2022, Tyra - https://github.com/h4570/tyrav2
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
# Wellinator Carvalho <wellcoj@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
enum AdpcmResult {
|
||||
ADPCM_OK,
|
||||
|
||||
/** When provided channel by user is currently in use */
|
||||
ADPCM_CHANNEL_USED,
|
||||
|
||||
/** When user did not provided channel and all are in use */
|
||||
ADPCM_NO_FREE_CHANNELS,
|
||||
|
||||
ADPCM_ERROR
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022-2022, Tyra - https://github.com/h4570/tyrav2
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
# Wellinator Carvalho <wellcoj@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "./audio_adpcm.hpp"
|
||||
#include "./audio_song.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
/** Class responsible for audio. */
|
||||
class Audio {
|
||||
public:
|
||||
Audio();
|
||||
~Audio();
|
||||
|
||||
void init();
|
||||
|
||||
AudioSong song;
|
||||
AudioAdpcm adpcm;
|
||||
|
||||
void work();
|
||||
|
||||
private:
|
||||
ee_thread_t thread;
|
||||
int threadId;
|
||||
static const u16 threadStackSize;
|
||||
u8* threadStack;
|
||||
|
||||
void initAUDSRV();
|
||||
void initThread();
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022-2022, Tyra - https://github.com/h4570/tyrav2
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
# Wellinator Carvalho <wellcoj@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "./audio_listener_ref.hpp"
|
||||
#include "./adpcm_result.hpp"
|
||||
#include <audsrv.h>
|
||||
#include <string>
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
/**
|
||||
* Class responsible for playing ADPCM samples.
|
||||
* ADPCM sample can't be stopped.
|
||||
*/
|
||||
class AudioAdpcm {
|
||||
public:
|
||||
AudioAdpcm();
|
||||
~AudioAdpcm();
|
||||
|
||||
void init();
|
||||
|
||||
/**
|
||||
* Load ADPCM sample.
|
||||
* ADPCM sample is an output from "Convert WAV to ADPCM" task (adpenc tool).
|
||||
* Adpenc expects 22kHz 16bit file.
|
||||
* @param t_path Example: "host:hit.adpcm" or "host:folder/jump.adpcm"
|
||||
*/
|
||||
audsrv_adpcm_t* load(const char* t_path);
|
||||
audsrv_adpcm_t* load(const std::string& t_path);
|
||||
|
||||
/**
|
||||
* Frees up all memory taken by samples, and stops all voices from
|
||||
* being played.
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* Try play ADPCM sample if channel(s) is not occupied.
|
||||
* @param t_adpcm ADPCM data, created by load();
|
||||
* @param t_ch Channel (0-23). Type -1 for use any free channel.
|
||||
*/
|
||||
AdpcmResult tryPlay(audsrv_adpcm_t* t_adpcm);
|
||||
AdpcmResult tryPlay(audsrv_adpcm_t* t_adpcm, const s8& t_ch);
|
||||
|
||||
/**
|
||||
* Play ADPCM sample, if channel is occupied, wait for it.
|
||||
* If not used properly, can hugely reduce performance.
|
||||
* @param t_adpcm ADPCM data, created by load();
|
||||
* @param t_ch Channel (0-23). Type -1 for use any free channel.
|
||||
*/
|
||||
void playWait(audsrv_adpcm_t* t_adpcm);
|
||||
void playWait(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 setVolume(const u8& t_vol, const s8& t_ch) {
|
||||
audsrv_adpcm_set_volume(t_ch, t_vol);
|
||||
}
|
||||
|
||||
private:
|
||||
void initAUDSRV();
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022-2022, Tyra - https://github.com/h4570/tyrav2
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
# Wellinator Carvalho <wellcoj@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
class AudioListener {
|
||||
public:
|
||||
virtual ~AudioListener(){};
|
||||
virtual void onAudioTick() = 0;
|
||||
virtual void onAudioFinish() = 0;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022-2022, Tyra - https://github.com/h4570/tyrav2
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
# Wellinator Carvalho <wellcoj@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "./audio_listener.hpp"
|
||||
#include <tamtypes.h>
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
struct AudioListenerRef {
|
||||
AudioListener* listener;
|
||||
u32 id;
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022-2022, Tyra - https://github.com/h4570/tyrav2
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
# Wellinator Carvalho <wellcoj@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "./audio_listener_ref.hpp"
|
||||
#include <audsrv.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <kernel.h>
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
/** Class responsible for background audio playing. */
|
||||
class AudioSong {
|
||||
public:
|
||||
AudioSong();
|
||||
~AudioSong();
|
||||
|
||||
void init();
|
||||
|
||||
bool inLoop;
|
||||
|
||||
/**
|
||||
* Load 16bit 22kHz Stereo WAV.
|
||||
* Can be used multiple times for song switching.
|
||||
* @param t_path Example: "host:song.wav" or "host:folder/song.wav"
|
||||
*/
|
||||
void load(const char* t_path);
|
||||
void load(const std::string& t_path);
|
||||
|
||||
void play();
|
||||
|
||||
void stop();
|
||||
|
||||
const bool& isPlaying() const;
|
||||
|
||||
const bool& isLoaded() const;
|
||||
|
||||
const u8& getVolume() const;
|
||||
|
||||
/**
|
||||
* Set song volume.
|
||||
* @param t_vol Value 0-100
|
||||
*/
|
||||
void setVolume(const u8& t_vol);
|
||||
|
||||
/**
|
||||
* If you want to synchronize some actions with
|
||||
* background song, add audio listener.
|
||||
* @returns Listener id.
|
||||
*/
|
||||
u32 addListener(AudioListener* t_listener);
|
||||
|
||||
/** Remove song listener. */
|
||||
void removeListener(const u32& t_id);
|
||||
|
||||
std::size_t getListenersCount() const;
|
||||
|
||||
void work();
|
||||
|
||||
private:
|
||||
bool songLoaded, songPlaying, songFinished;
|
||||
u8 tyraVolume, audsrvVolume;
|
||||
FILE* wav;
|
||||
audsrv_fmt_t format;
|
||||
std::vector<AudioListenerRef*> songListeners;
|
||||
|
||||
ee_sema_t sema;
|
||||
s32 fillbufferSema;
|
||||
static const u16 chunkSize;
|
||||
char* chunk;
|
||||
s32 chunkReadStatus;
|
||||
|
||||
void initSema();
|
||||
void initAUDSRV();
|
||||
void setSongFormat();
|
||||
void unloadSong();
|
||||
void rewindSongToStart();
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define TYRA_LOG(...) ((void)0)
|
||||
#define TYRA_WARN(...) ((void)0)
|
||||
#define TYRA_ERROR(...) ((void)0)
|
||||
#define TYRA_TRAP(...) ((void)0)
|
||||
#define TYRA_ASSERT(condition, ...) ((void)0)
|
||||
|
||||
#else // IF Debug
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
|
||||
#include "file/file_utils.hpp"
|
||||
#include "info/info.hpp"
|
||||
|
||||
#define TYRA_LOG(...) TyraDebug::writeLines("LOG: ", ##__VA_ARGS__, "\n")
|
||||
#define TYRA_WARN(...) TyraDebug::writeLines("==WARN: ", ##__VA_ARGS__, "\n")
|
||||
#define TYRA_ERROR(...) TyraDebug::writeLines("====ERR: ", ##__VA_ARGS__, "\n")
|
||||
#define TYRA_TRAP(...) TyraDebug::trap(__FILE__, __LINE__, ##__VA_ARGS__)
|
||||
#define TYRA_BREAKPOINT() TyraDebug::trap(__FILE__, __LINE__, "Breakpoint")
|
||||
#define TYRA_ASSERT(condition, ...) \
|
||||
if (!(condition)) TyraDebug::trap(__FILE__, __LINE__, ##__VA_ARGS__)
|
||||
|
||||
class TyraDebug {
|
||||
public:
|
||||
template <typename Arg, typename... Args>
|
||||
static void writeLines(Arg&& arg, Args&&... args) {
|
||||
std::stringstream ss;
|
||||
|
||||
ss << std::forward<Arg>(arg);
|
||||
using expander = int[];
|
||||
(void)expander{0, (void(ss << std::forward<Args>(args)), 0)...};
|
||||
|
||||
if (Tyra::Info::writeLogsToFile) {
|
||||
auto* logFile = getLogFile();
|
||||
*logFile << ss.str();
|
||||
logFile->flush();
|
||||
} else {
|
||||
printf("%s", ss.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
static void trap(const char* file, int line, Args... args) {
|
||||
std::stringstream ss1;
|
||||
ss1 << "\n";
|
||||
ss1 << "============== TYRA ==============\n";
|
||||
ss1 << "| Assertion failed!\n";
|
||||
ss1 << "|\n";
|
||||
|
||||
if (Tyra::Info::writeLogsToFile) {
|
||||
auto* logFile = getLogFile();
|
||||
*logFile << ss1.str();
|
||||
logFile->flush();
|
||||
} else {
|
||||
printf("%s", ss1.str().c_str());
|
||||
}
|
||||
|
||||
writeAssertLines(args...);
|
||||
|
||||
std::stringstream ss2;
|
||||
ss2 << "|\n";
|
||||
ss2 << "| File : " << file << ":" << line << "\n";
|
||||
ss2 << "====================================\n\n";
|
||||
|
||||
if (Tyra::Info::writeLogsToFile) {
|
||||
auto* logFile = getLogFile();
|
||||
*logFile << ss2.str();
|
||||
logFile->flush();
|
||||
} else {
|
||||
printf("%s", ss2.str().c_str());
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static std::unique_ptr<std::ofstream> logFile;
|
||||
static std::ofstream* getLogFile();
|
||||
|
||||
template <typename Arg, typename... Args>
|
||||
static void writeAssertLines(Arg&& arg, Args&&... args) {
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "| " << std::forward<Arg>(arg) << "\n";
|
||||
using expander = int[];
|
||||
(void)expander{
|
||||
0, (void(ss << "| " << std::forward<Args>(args) << "\n"), 0)...};
|
||||
|
||||
if (Tyra::Info::writeLogsToFile) {
|
||||
auto* logfile = getLogFile();
|
||||
*logfile << ss.str();
|
||||
logFile->flush();
|
||||
} else {
|
||||
printf("%s", ss.str().c_str());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // NDEBUG
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "./renderer/renderer.hpp"
|
||||
#include "./pad/pad.hpp"
|
||||
#include "./audio/audio.hpp"
|
||||
#include "./irx/irx_loader.hpp"
|
||||
#include "./info/info.hpp"
|
||||
#include "./info/banner.hpp"
|
||||
#include "./game.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
struct EngineOptions {
|
||||
/**
|
||||
* True -> logs will be written to file.
|
||||
* False -> logs will be displayed in console
|
||||
*/
|
||||
bool writeLogsToFile = false;
|
||||
|
||||
bool loadUsbDriver = false;
|
||||
};
|
||||
|
||||
class Engine {
|
||||
public:
|
||||
Engine();
|
||||
Engine(const EngineOptions& options);
|
||||
~Engine();
|
||||
|
||||
Renderer renderer;
|
||||
Pad pad;
|
||||
Audio audio;
|
||||
Info info;
|
||||
|
||||
void run(Game* t_game);
|
||||
|
||||
private:
|
||||
IrxLoader irx;
|
||||
|
||||
Game* game;
|
||||
Banner banner;
|
||||
|
||||
void realLoop();
|
||||
void initAll(const bool& loadUsbDriver);
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Wellington Carvalho <wellcoj@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
class FileUtils {
|
||||
public:
|
||||
FileUtils();
|
||||
~FileUtils();
|
||||
|
||||
/**
|
||||
* Get current working directory.
|
||||
* Example: "host:" or "mass:"
|
||||
*/
|
||||
static std::string getCwd();
|
||||
|
||||
/**
|
||||
* Add current working directory prefix to path
|
||||
* Example: "host:..." or "mass:..."
|
||||
*/
|
||||
static std::string fromCwd(const std::string& relativePath);
|
||||
static std::string fromCwd(const char* relativePath);
|
||||
|
||||
static std::string getFilenameFromPath(const std::string& path);
|
||||
static std::string getPathFromFilename(const std::string& path);
|
||||
static std::string getFilenameWithoutExtension(const std::string& filename);
|
||||
static std::string getExtensionOfFilename(const std::string& filename);
|
||||
|
||||
const char* getElfName() const { return elfName; };
|
||||
const char* getElfPath() const { return elfPath; };
|
||||
|
||||
private:
|
||||
// Argv name+path & just path
|
||||
char cwd[255];
|
||||
char elfName[255];
|
||||
char elfPath[255 - 14];
|
||||
|
||||
void setPathInfo(const char* path);
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
class Game {
|
||||
public:
|
||||
virtual void init() = 0;
|
||||
virtual void loop() = 0;
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Wellington Carvalho <wellcoj@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "renderer/renderer.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
class Banner {
|
||||
public:
|
||||
Banner();
|
||||
~Banner();
|
||||
|
||||
void show(Renderer* renderer);
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Wellington Carvalho <wellcoj@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tamtypes.h>
|
||||
#include <stddef.h>
|
||||
#include "time/timer.hpp"
|
||||
#include "./version.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
class Info {
|
||||
public:
|
||||
Info();
|
||||
~Info();
|
||||
|
||||
Version version;
|
||||
|
||||
static bool writeLogsToFile;
|
||||
|
||||
/** Called by engine */
|
||||
void update();
|
||||
|
||||
const u32& getFps() const { return fps; };
|
||||
|
||||
/** @return Available RAM in MB */
|
||||
float getAvailableRAM();
|
||||
|
||||
private:
|
||||
float calcFps();
|
||||
void* allocateLargestFreeRAMBlock(size_t* size);
|
||||
size_t getFreeRAMSize();
|
||||
|
||||
u8 fpsDelayer;
|
||||
u32 fps;
|
||||
Timer timer;
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# André Guilherme <andregui17@outlook.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tamtypes.h>
|
||||
#include <string>
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
class Version {
|
||||
public:
|
||||
Version() {}
|
||||
~Version() {}
|
||||
|
||||
static const u8 major = 2;
|
||||
static const u8 minor = 2;
|
||||
static const u8 patch = 0;
|
||||
|
||||
static std::string toString() {
|
||||
return std::to_string(major) + "." + std::to_string(minor) + "." +
|
||||
std::to_string(patch);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Wellington Carvalho <wellcoj@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tamtypes.h>
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
class IrxLoader {
|
||||
public:
|
||||
IrxLoader();
|
||||
~IrxLoader();
|
||||
|
||||
void loadAll(const bool& withUsb, const bool& isLoggingToFile);
|
||||
|
||||
private:
|
||||
static bool isLoaded;
|
||||
|
||||
void loadSio2man(const bool& verbose);
|
||||
void loadPadman(const bool& verbose);
|
||||
void loadLibsd(const bool& verbose);
|
||||
void loadUsbModules(const bool& verbose);
|
||||
void loadAudsrv(const bool& verbose);
|
||||
|
||||
int applyRpcPatches();
|
||||
void waitUntilUsbDeviceIsReady();
|
||||
void delay(int count);
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "./mesh_builder_material_data.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
/**
|
||||
* Data needed for constructing mesh class.
|
||||
* All dynamic data ownership is moved to mesh class, so
|
||||
* verts, coords.. are not deallocated!
|
||||
*/
|
||||
class MeshBuilderData {
|
||||
public:
|
||||
MeshBuilderData();
|
||||
~MeshBuilderData();
|
||||
|
||||
std::vector<MeshBuilderMaterialData*> materials;
|
||||
|
||||
bool loadNormals, loadLightmap;
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,33 @@
|
||||
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
#include "./mesh_builder_material_frame_data.hpp"
|
||||
#include "renderer/models/color.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
class MeshBuilderMaterialData {
|
||||
public:
|
||||
MeshBuilderMaterialData();
|
||||
~MeshBuilderMaterialData();
|
||||
|
||||
std::vector<MeshBuilderMaterialFrameData*> frames;
|
||||
std::string name;
|
||||
std::optional<std::string> texturePath;
|
||||
Color ambient;
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,30 @@
|
||||
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tamtypes.h>
|
||||
#include "math/vec4.hpp"
|
||||
#include "renderer/models/color.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
class MeshBuilderMaterialFrameData {
|
||||
public:
|
||||
MeshBuilderMaterialFrameData();
|
||||
~MeshBuilderMaterialFrameData();
|
||||
|
||||
u32 count;
|
||||
Vec4 *vertices, *textureCoords, *normals;
|
||||
Color* colors;
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
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}};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../builder/mesh_builder_data.hpp"
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
struct MD2LoaderOptions {
|
||||
bool flipUVs = false;
|
||||
float scale = 1.0F;
|
||||
};
|
||||
|
||||
/** Class responsible for loading & parsing Quake's II ".md2" 3D files */
|
||||
class MD2Loader {
|
||||
public:
|
||||
static std::unique_ptr<MeshBuilderData> load(const char* fullpath);
|
||||
static std::unique_ptr<MeshBuilderData> load(const char* fullpath,
|
||||
MD2LoaderOptions options);
|
||||
static std::unique_ptr<MeshBuilderData> load(const std::string& fullpath);
|
||||
static std::unique_ptr<MeshBuilderData> load(const std::string& fullpath,
|
||||
MD2LoaderOptions options);
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,853 @@
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace mapbox {
|
||||
|
||||
namespace util {
|
||||
|
||||
template <std::size_t I, typename T>
|
||||
struct nth {
|
||||
inline static typename std::tuple_element<I, T>::type get(const T& t) {
|
||||
return std::get<I>(t);
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace util
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename N = uint32_t>
|
||||
class Earcut {
|
||||
public:
|
||||
std::vector<N> indices;
|
||||
std::size_t vertices = 0;
|
||||
|
||||
template <typename Polygon>
|
||||
void operator()(const Polygon& points);
|
||||
|
||||
private:
|
||||
struct Node {
|
||||
Node(N index, double x_, double y_) : i(index), x(x_), y(y_) {}
|
||||
Node(const Node&) = delete;
|
||||
Node& operator=(const Node&) = delete;
|
||||
Node(Node&&) = delete;
|
||||
Node& operator=(Node&&) = delete;
|
||||
|
||||
const N i;
|
||||
const double x;
|
||||
const double y;
|
||||
|
||||
// previous and next vertice nodes in a polygon ring
|
||||
Node* prev = nullptr;
|
||||
Node* next = nullptr;
|
||||
|
||||
// z-order curve value
|
||||
int32_t z = 0;
|
||||
|
||||
// previous and next nodes in z-order
|
||||
Node* prevZ = nullptr;
|
||||
Node* nextZ = nullptr;
|
||||
|
||||
// indicates whether this is a steiner point
|
||||
bool steiner = false;
|
||||
};
|
||||
|
||||
template <typename Ring>
|
||||
Node* linkedList(const Ring& points, const bool clockwise);
|
||||
Node* filterPoints(Node* start, Node* end = nullptr);
|
||||
void earcutLinked(Node* ear, int pass = 0);
|
||||
bool isEar(Node* ear);
|
||||
bool isEarHashed(Node* ear);
|
||||
Node* cureLocalIntersections(Node* start);
|
||||
void splitEarcut(Node* start);
|
||||
template <typename Polygon>
|
||||
Node* eliminateHoles(const Polygon& points, Node* outerNode);
|
||||
Node* eliminateHole(Node* hole, Node* outerNode);
|
||||
Node* findHoleBridge(Node* hole, Node* outerNode);
|
||||
bool sectorContainsSector(const Node* m, const Node* p);
|
||||
void indexCurve(Node* start);
|
||||
Node* sortLinked(Node* list);
|
||||
int32_t zOrder(const double x_, const double y_);
|
||||
Node* getLeftmost(Node* start);
|
||||
bool pointInTriangle(double ax, double ay, double bx, double by, double cx,
|
||||
double cy, double px, double py) const;
|
||||
bool isValidDiagonal(Node* a, Node* b);
|
||||
double area(const Node* p, const Node* q, const Node* r) const;
|
||||
bool equals(const Node* p1, const Node* p2);
|
||||
bool intersects(const Node* p1, const Node* q1, const Node* p2,
|
||||
const Node* q2);
|
||||
bool onSegment(const Node* p, const Node* q, const Node* r);
|
||||
int sign(double val);
|
||||
bool intersectsPolygon(const Node* a, const Node* b);
|
||||
bool locallyInside(const Node* a, const Node* b);
|
||||
bool middleInside(const Node* a, const Node* b);
|
||||
Node* splitPolygon(Node* a, Node* b);
|
||||
template <typename Point>
|
||||
Node* insertNode(std::size_t i, const Point& p, Node* last);
|
||||
void removeNode(Node* p);
|
||||
|
||||
bool hashing;
|
||||
double minX, maxX;
|
||||
double minY, maxY;
|
||||
double inv_size = 0;
|
||||
|
||||
template <typename T, typename Alloc = std::allocator<T>>
|
||||
class ObjectPool {
|
||||
public:
|
||||
ObjectPool() {}
|
||||
ObjectPool(std::size_t blockSize_) { reset(blockSize_); }
|
||||
~ObjectPool() { clear(); }
|
||||
template <typename... Args>
|
||||
T* construct(Args&&... args) {
|
||||
if (currentIndex >= blockSize) {
|
||||
currentBlock = alloc_traits::allocate(alloc, blockSize);
|
||||
allocations.emplace_back(currentBlock);
|
||||
currentIndex = 0;
|
||||
}
|
||||
T* object = ¤tBlock[currentIndex++];
|
||||
alloc_traits::construct(alloc, object, std::forward<Args>(args)...);
|
||||
return object;
|
||||
}
|
||||
void reset(std::size_t newBlockSize) {
|
||||
for (auto allocation : allocations) {
|
||||
alloc_traits::deallocate(alloc, allocation, blockSize);
|
||||
}
|
||||
allocations.clear();
|
||||
blockSize = std::max<std::size_t>(1, newBlockSize);
|
||||
currentBlock = nullptr;
|
||||
currentIndex = blockSize;
|
||||
}
|
||||
void clear() { reset(blockSize); }
|
||||
|
||||
private:
|
||||
T* currentBlock = nullptr;
|
||||
std::size_t currentIndex = 1;
|
||||
std::size_t blockSize = 1;
|
||||
std::vector<T*> allocations;
|
||||
Alloc alloc;
|
||||
typedef typename std::allocator_traits<Alloc> alloc_traits;
|
||||
};
|
||||
ObjectPool<Node> nodes;
|
||||
};
|
||||
|
||||
template <typename N>
|
||||
template <typename Polygon>
|
||||
void Earcut<N>::operator()(const Polygon& points) {
|
||||
// reset
|
||||
indices.clear();
|
||||
vertices = 0;
|
||||
|
||||
if (points.empty()) return;
|
||||
|
||||
double x;
|
||||
double y;
|
||||
int threshold = 80;
|
||||
std::size_t len = 0;
|
||||
|
||||
for (size_t i = 0; threshold >= 0 && i < points.size(); i++) {
|
||||
threshold -= static_cast<int>(points[i].size());
|
||||
len += points[i].size();
|
||||
}
|
||||
|
||||
// estimate size of nodes and indices
|
||||
nodes.reset(len * 3 / 2);
|
||||
indices.reserve(len + points[0].size());
|
||||
|
||||
Node* outerNode = linkedList(points[0], true);
|
||||
if (!outerNode || outerNode->prev == outerNode->next) return;
|
||||
|
||||
if (points.size() > 1) outerNode = eliminateHoles(points, outerNode);
|
||||
|
||||
// if the shape is not too simple, we'll use z-order curve hash later;
|
||||
// calculate polygon bbox
|
||||
hashing = threshold < 0;
|
||||
if (hashing) {
|
||||
Node* p = outerNode->next;
|
||||
minX = maxX = outerNode->x;
|
||||
minY = maxY = outerNode->y;
|
||||
do {
|
||||
x = p->x;
|
||||
y = p->y;
|
||||
minX = std::min<double>(minX, x);
|
||||
minY = std::min<double>(minY, y);
|
||||
maxX = std::max<double>(maxX, x);
|
||||
maxY = std::max<double>(maxY, y);
|
||||
p = p->next;
|
||||
} while (p != outerNode);
|
||||
|
||||
// minX, minY and size are later used to transform coords into integers for
|
||||
// z-order calculation
|
||||
inv_size = std::max<double>(maxX - minX, maxY - minY);
|
||||
inv_size = inv_size != .0 ? (1. / inv_size) : .0;
|
||||
}
|
||||
|
||||
earcutLinked(outerNode);
|
||||
|
||||
nodes.clear();
|
||||
}
|
||||
|
||||
// create a circular doubly linked list from polygon points in the specified
|
||||
// winding order
|
||||
template <typename N>
|
||||
template <typename Ring>
|
||||
typename Earcut<N>::Node* Earcut<N>::linkedList(const Ring& points,
|
||||
const bool clockwise) {
|
||||
using Point = typename Ring::value_type;
|
||||
double sum = 0;
|
||||
const std::size_t len = points.size();
|
||||
std::size_t i, j;
|
||||
Node* last = nullptr;
|
||||
|
||||
// calculate original winding order of a polygon ring
|
||||
for (i = 0, j = len > 0 ? len - 1 : 0; i < len; j = i++) {
|
||||
const auto& p1 = points[i];
|
||||
const auto& p2 = points[j];
|
||||
const double p20 = util::nth<0, Point>::get(p2);
|
||||
const double p10 = util::nth<0, Point>::get(p1);
|
||||
const double p11 = util::nth<1, Point>::get(p1);
|
||||
const double p21 = util::nth<1, Point>::get(p2);
|
||||
sum += (p20 - p10) * (p11 + p21);
|
||||
}
|
||||
|
||||
// link points into circular doubly-linked list in the specified winding order
|
||||
if (clockwise == (sum > 0)) {
|
||||
for (i = 0; i < len; i++) last = insertNode(vertices + i, points[i], last);
|
||||
} else {
|
||||
for (i = len; i-- > 0;) last = insertNode(vertices + i, points[i], last);
|
||||
}
|
||||
|
||||
if (last && equals(last, last->next)) {
|
||||
removeNode(last);
|
||||
last = last->next;
|
||||
}
|
||||
|
||||
vertices += len;
|
||||
|
||||
return last;
|
||||
}
|
||||
|
||||
// eliminate colinear or duplicate points
|
||||
template <typename N>
|
||||
typename Earcut<N>::Node* Earcut<N>::filterPoints(Node* start, Node* end) {
|
||||
if (!end) end = start;
|
||||
|
||||
Node* p = start;
|
||||
bool again;
|
||||
do {
|
||||
again = false;
|
||||
|
||||
if (!p->steiner && (equals(p, p->next) || area(p->prev, p, p->next) == 0)) {
|
||||
removeNode(p);
|
||||
p = end = p->prev;
|
||||
|
||||
if (p == p->next) break;
|
||||
again = true;
|
||||
|
||||
} else {
|
||||
p = p->next;
|
||||
}
|
||||
} while (again || p != end);
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
// main ear slicing loop which triangulates a polygon (given as a linked list)
|
||||
template <typename N>
|
||||
void Earcut<N>::earcutLinked(Node* ear, int pass) {
|
||||
if (!ear) return;
|
||||
|
||||
// interlink polygon nodes in z-order
|
||||
if (!pass && hashing) indexCurve(ear);
|
||||
|
||||
Node* stop = ear;
|
||||
Node* prev;
|
||||
Node* next;
|
||||
|
||||
int iterations = 0;
|
||||
|
||||
// iterate through ears, slicing them one by one
|
||||
while (ear->prev != ear->next) {
|
||||
iterations++;
|
||||
prev = ear->prev;
|
||||
next = ear->next;
|
||||
|
||||
if (hashing ? isEarHashed(ear) : isEar(ear)) {
|
||||
// cut off the triangle
|
||||
indices.emplace_back(prev->i);
|
||||
indices.emplace_back(ear->i);
|
||||
indices.emplace_back(next->i);
|
||||
|
||||
removeNode(ear);
|
||||
|
||||
// skipping the next vertice leads to less sliver triangles
|
||||
ear = next->next;
|
||||
stop = next->next;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
ear = next;
|
||||
|
||||
// if we looped through the whole remaining polygon and can't find any more
|
||||
// ears
|
||||
if (ear == stop) {
|
||||
// try filtering points and slicing again
|
||||
if (!pass) earcutLinked(filterPoints(ear), 1);
|
||||
|
||||
// if this didn't work, try curing all small self-intersections locally
|
||||
else if (pass == 1) {
|
||||
ear = cureLocalIntersections(filterPoints(ear));
|
||||
earcutLinked(ear, 2);
|
||||
|
||||
// as a last resort, try splitting the remaining polygon into two
|
||||
} else if (pass == 2)
|
||||
splitEarcut(ear);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check whether a polygon node forms a valid ear with adjacent nodes
|
||||
template <typename N>
|
||||
bool Earcut<N>::isEar(Node* ear) {
|
||||
const Node* a = ear->prev;
|
||||
const Node* b = ear;
|
||||
const Node* c = ear->next;
|
||||
|
||||
if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
|
||||
|
||||
// now make sure we don't have other points inside the potential ear
|
||||
Node* p = ear->next->next;
|
||||
|
||||
while (p != ear->prev) {
|
||||
if (pointInTriangle(a->x, a->y, b->x, b->y, c->x, c->y, p->x, p->y) &&
|
||||
area(p->prev, p, p->next) >= 0)
|
||||
return false;
|
||||
p = p->next;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename N>
|
||||
bool Earcut<N>::isEarHashed(Node* ear) {
|
||||
const Node* a = ear->prev;
|
||||
const Node* b = ear;
|
||||
const Node* c = ear->next;
|
||||
|
||||
if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
|
||||
|
||||
// triangle bbox; min & max are calculated like this for speed
|
||||
const double minTX = std::min<double>(a->x, std::min<double>(b->x, c->x));
|
||||
const double minTY = std::min<double>(a->y, std::min<double>(b->y, c->y));
|
||||
const double maxTX = std::max<double>(a->x, std::max<double>(b->x, c->x));
|
||||
const double maxTY = std::max<double>(a->y, std::max<double>(b->y, c->y));
|
||||
|
||||
// z-order range for the current triangle bbox;
|
||||
const int32_t minZ = zOrder(minTX, minTY);
|
||||
const int32_t maxZ = zOrder(maxTX, maxTY);
|
||||
|
||||
// first look for points inside the triangle in increasing z-order
|
||||
Node* p = ear->nextZ;
|
||||
|
||||
while (p && p->z <= maxZ) {
|
||||
if (p != ear->prev && p != ear->next &&
|
||||
pointInTriangle(a->x, a->y, b->x, b->y, c->x, c->y, p->x, p->y) &&
|
||||
area(p->prev, p, p->next) >= 0)
|
||||
return false;
|
||||
p = p->nextZ;
|
||||
}
|
||||
|
||||
// then look for points in decreasing z-order
|
||||
p = ear->prevZ;
|
||||
|
||||
while (p && p->z >= minZ) {
|
||||
if (p != ear->prev && p != ear->next &&
|
||||
pointInTriangle(a->x, a->y, b->x, b->y, c->x, c->y, p->x, p->y) &&
|
||||
area(p->prev, p, p->next) >= 0)
|
||||
return false;
|
||||
p = p->prevZ;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// go through all polygon nodes and cure small local self-intersections
|
||||
template <typename N>
|
||||
typename Earcut<N>::Node* Earcut<N>::cureLocalIntersections(Node* start) {
|
||||
Node* p = start;
|
||||
do {
|
||||
Node* a = p->prev;
|
||||
Node* b = p->next->next;
|
||||
|
||||
// a self-intersection where edge (v[i-1],v[i]) intersects (v[i+1],v[i+2])
|
||||
if (!equals(a, b) && intersects(a, p, p->next, b) && locallyInside(a, b) &&
|
||||
locallyInside(b, a)) {
|
||||
indices.emplace_back(a->i);
|
||||
indices.emplace_back(p->i);
|
||||
indices.emplace_back(b->i);
|
||||
|
||||
// remove two nodes involved
|
||||
removeNode(p);
|
||||
removeNode(p->next);
|
||||
|
||||
p = start = b;
|
||||
}
|
||||
p = p->next;
|
||||
} while (p != start);
|
||||
|
||||
return filterPoints(p);
|
||||
}
|
||||
|
||||
// try splitting polygon into two and triangulate them independently
|
||||
template <typename N>
|
||||
void Earcut<N>::splitEarcut(Node* start) {
|
||||
// look for a valid diagonal that divides the polygon into two
|
||||
Node* a = start;
|
||||
do {
|
||||
Node* b = a->next->next;
|
||||
while (b != a->prev) {
|
||||
if (a->i != b->i && isValidDiagonal(a, b)) {
|
||||
// split the polygon in two by the diagonal
|
||||
Node* c = splitPolygon(a, b);
|
||||
|
||||
// filter colinear points around the cuts
|
||||
a = filterPoints(a, a->next);
|
||||
c = filterPoints(c, c->next);
|
||||
|
||||
// run earcut on each half
|
||||
earcutLinked(a);
|
||||
earcutLinked(c);
|
||||
return;
|
||||
}
|
||||
b = b->next;
|
||||
}
|
||||
a = a->next;
|
||||
} while (a != start);
|
||||
}
|
||||
|
||||
// link every hole into the outer loop, producing a single-ring polygon without
|
||||
// holes
|
||||
template <typename N>
|
||||
template <typename Polygon>
|
||||
typename Earcut<N>::Node* Earcut<N>::eliminateHoles(const Polygon& points,
|
||||
Node* outerNode) {
|
||||
const size_t len = points.size();
|
||||
|
||||
std::vector<Node*> queue;
|
||||
for (size_t i = 1; i < len; i++) {
|
||||
Node* list = linkedList(points[i], false);
|
||||
if (list) {
|
||||
if (list == list->next) list->steiner = true;
|
||||
queue.push_back(getLeftmost(list));
|
||||
}
|
||||
}
|
||||
std::sort(queue.begin(), queue.end(),
|
||||
[](const Node* a, const Node* b) { return a->x < b->x; });
|
||||
|
||||
// process holes from left to right
|
||||
for (size_t i = 0; i < queue.size(); i++) {
|
||||
outerNode = eliminateHole(queue[i], outerNode);
|
||||
outerNode = filterPoints(outerNode, outerNode->next);
|
||||
}
|
||||
|
||||
return outerNode;
|
||||
}
|
||||
|
||||
// find a bridge between vertices that connects hole with an outer ring and and
|
||||
// link it
|
||||
template <typename N>
|
||||
typename Earcut<N>::Node* Earcut<N>::eliminateHole(Node* hole,
|
||||
Node* outerNode) {
|
||||
Node* bridge = findHoleBridge(hole, outerNode);
|
||||
if (!bridge) {
|
||||
return outerNode;
|
||||
}
|
||||
|
||||
Node* bridgeReverse = splitPolygon(bridge, hole);
|
||||
|
||||
// filter collinear points around the cuts
|
||||
Node* filteredBridge = filterPoints(bridge, bridge->next);
|
||||
filterPoints(bridgeReverse, bridgeReverse->next);
|
||||
|
||||
// Check if input node was removed by the filtering
|
||||
return outerNode == bridge ? filteredBridge : outerNode;
|
||||
}
|
||||
|
||||
// David Eberly's algorithm for finding a bridge between hole and outer polygon
|
||||
template <typename N>
|
||||
typename Earcut<N>::Node* Earcut<N>::findHoleBridge(Node* hole,
|
||||
Node* outerNode) {
|
||||
Node* p = outerNode;
|
||||
double hx = hole->x;
|
||||
double hy = hole->y;
|
||||
double qx = -std::numeric_limits<double>::infinity();
|
||||
Node* m = nullptr;
|
||||
|
||||
// find a segment intersected by a ray from the hole's leftmost Vertex to the
|
||||
// left; segment's endpoint with lesser x will be potential connection Vertex
|
||||
do {
|
||||
if (hy <= p->y && hy >= p->next->y && p->next->y != p->y) {
|
||||
double x = p->x + (hy - p->y) * (p->next->x - p->x) / (p->next->y - p->y);
|
||||
if (x <= hx && x > qx) {
|
||||
qx = x;
|
||||
if (x == hx) {
|
||||
if (hy == p->y) return p;
|
||||
if (hy == p->next->y) return p->next;
|
||||
}
|
||||
m = p->x < p->next->x ? p : p->next;
|
||||
}
|
||||
}
|
||||
p = p->next;
|
||||
} while (p != outerNode);
|
||||
|
||||
if (!m) return 0;
|
||||
|
||||
if (hx == qx) return m; // hole touches outer segment; pick leftmost endpoint
|
||||
|
||||
// look for points inside the triangle of hole Vertex, segment intersection
|
||||
// and endpoint; if there are no points found, we have a valid connection;
|
||||
// otherwise choose the Vertex of the minimum angle with the ray as connection
|
||||
// Vertex
|
||||
|
||||
const Node* stop = m;
|
||||
double tanMin = std::numeric_limits<double>::infinity();
|
||||
double tanCur = 0;
|
||||
|
||||
p = m;
|
||||
double mx = m->x;
|
||||
double my = m->y;
|
||||
|
||||
do {
|
||||
if (hx >= p->x && p->x >= mx && hx != p->x &&
|
||||
pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy,
|
||||
p->x, p->y)) {
|
||||
tanCur = std::abs(hy - p->y) / (hx - p->x); // tangential
|
||||
|
||||
if (locallyInside(p, hole) &&
|
||||
(tanCur < tanMin ||
|
||||
(tanCur == tanMin && (p->x > m->x || sectorContainsSector(m, p))))) {
|
||||
m = p;
|
||||
tanMin = tanCur;
|
||||
}
|
||||
}
|
||||
|
||||
p = p->next;
|
||||
} while (p != stop);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
// whether sector in vertex m contains sector in vertex p in the same
|
||||
// coordinates
|
||||
template <typename N>
|
||||
bool Earcut<N>::sectorContainsSector(const Node* m, const Node* p) {
|
||||
return area(m->prev, m, p->prev) < 0 && area(p->next, m, m->next) < 0;
|
||||
}
|
||||
|
||||
// interlink polygon nodes in z-order
|
||||
template <typename N>
|
||||
void Earcut<N>::indexCurve(Node* start) {
|
||||
assert(start);
|
||||
Node* p = start;
|
||||
|
||||
do {
|
||||
p->z = p->z ? p->z : zOrder(p->x, p->y);
|
||||
p->prevZ = p->prev;
|
||||
p->nextZ = p->next;
|
||||
p = p->next;
|
||||
} while (p != start);
|
||||
|
||||
p->prevZ->nextZ = nullptr;
|
||||
p->prevZ = nullptr;
|
||||
|
||||
sortLinked(p);
|
||||
}
|
||||
|
||||
// Simon Tatham's linked list merge sort algorithm
|
||||
// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
|
||||
template <typename N>
|
||||
typename Earcut<N>::Node* Earcut<N>::sortLinked(Node* list) {
|
||||
assert(list);
|
||||
Node* p;
|
||||
Node* q;
|
||||
Node* e;
|
||||
Node* tail;
|
||||
int i, numMerges, pSize, qSize;
|
||||
int inSize = 1;
|
||||
|
||||
for (;;) {
|
||||
p = list;
|
||||
list = nullptr;
|
||||
tail = nullptr;
|
||||
numMerges = 0;
|
||||
|
||||
while (p) {
|
||||
numMerges++;
|
||||
q = p;
|
||||
pSize = 0;
|
||||
for (i = 0; i < inSize; i++) {
|
||||
pSize++;
|
||||
q = q->nextZ;
|
||||
if (!q) break;
|
||||
}
|
||||
|
||||
qSize = inSize;
|
||||
|
||||
while (pSize > 0 || (qSize > 0 && q)) {
|
||||
if (pSize == 0) {
|
||||
e = q;
|
||||
q = q->nextZ;
|
||||
qSize--;
|
||||
} else if (qSize == 0 || !q) {
|
||||
e = p;
|
||||
p = p->nextZ;
|
||||
pSize--;
|
||||
} else if (p->z <= q->z) {
|
||||
e = p;
|
||||
p = p->nextZ;
|
||||
pSize--;
|
||||
} else {
|
||||
e = q;
|
||||
q = q->nextZ;
|
||||
qSize--;
|
||||
}
|
||||
|
||||
if (tail)
|
||||
tail->nextZ = e;
|
||||
else
|
||||
list = e;
|
||||
|
||||
e->prevZ = tail;
|
||||
tail = e;
|
||||
}
|
||||
|
||||
p = q;
|
||||
}
|
||||
|
||||
tail->nextZ = nullptr;
|
||||
|
||||
if (numMerges <= 1) return list;
|
||||
|
||||
inSize *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
// z-order of a Vertex given coords and size of the data bounding box
|
||||
template <typename N>
|
||||
int32_t Earcut<N>::zOrder(const double x_, const double y_) {
|
||||
// coords are transformed into non-negative 15-bit integer range
|
||||
int32_t x = static_cast<int32_t>(32767.0 * (x_ - minX) * inv_size);
|
||||
int32_t y = static_cast<int32_t>(32767.0 * (y_ - minY) * inv_size);
|
||||
|
||||
x = (x | (x << 8)) & 0x00FF00FF;
|
||||
x = (x | (x << 4)) & 0x0F0F0F0F;
|
||||
x = (x | (x << 2)) & 0x33333333;
|
||||
x = (x | (x << 1)) & 0x55555555;
|
||||
|
||||
y = (y | (y << 8)) & 0x00FF00FF;
|
||||
y = (y | (y << 4)) & 0x0F0F0F0F;
|
||||
y = (y | (y << 2)) & 0x33333333;
|
||||
y = (y | (y << 1)) & 0x55555555;
|
||||
|
||||
return x | (y << 1);
|
||||
}
|
||||
|
||||
// find the leftmost node of a polygon ring
|
||||
template <typename N>
|
||||
typename Earcut<N>::Node* Earcut<N>::getLeftmost(Node* start) {
|
||||
Node* p = start;
|
||||
Node* leftmost = start;
|
||||
do {
|
||||
if (p->x < leftmost->x || (p->x == leftmost->x && p->y < leftmost->y))
|
||||
leftmost = p;
|
||||
p = p->next;
|
||||
} while (p != start);
|
||||
|
||||
return leftmost;
|
||||
}
|
||||
|
||||
// check if a point lies within a convex triangle
|
||||
template <typename N>
|
||||
bool Earcut<N>::pointInTriangle(double ax, double ay, double bx, double by,
|
||||
double cx, double cy, double px,
|
||||
double py) const {
|
||||
return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 &&
|
||||
(ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 &&
|
||||
(bx - px) * (cy - py) - (cx - px) * (by - py) >= 0;
|
||||
}
|
||||
|
||||
// check if a diagonal between two polygon nodes is valid (lies in polygon
|
||||
// interior)
|
||||
template <typename N>
|
||||
bool Earcut<N>::isValidDiagonal(Node* a, Node* b) {
|
||||
return a->next->i != b->i && a->prev->i != b->i &&
|
||||
!intersectsPolygon(a, b) && // dones't intersect other edges
|
||||
((locallyInside(a, b) && locallyInside(b, a) &&
|
||||
middleInside(a, b) && // locally visible
|
||||
(area(a->prev, a, b->prev) != 0.0 ||
|
||||
area(a, b->prev, b) !=
|
||||
0.0)) || // does not create opposite-facing sectors
|
||||
(equals(a, b) && area(a->prev, a, a->next) > 0 &&
|
||||
area(b->prev, b, b->next) > 0)); // special zero-length case
|
||||
}
|
||||
|
||||
// signed area of a triangle
|
||||
template <typename N>
|
||||
double Earcut<N>::area(const Node* p, const Node* q, const Node* r) const {
|
||||
return (q->y - p->y) * (r->x - q->x) - (q->x - p->x) * (r->y - q->y);
|
||||
}
|
||||
|
||||
// check if two points are equal
|
||||
template <typename N>
|
||||
bool Earcut<N>::equals(const Node* p1, const Node* p2) {
|
||||
return p1->x == p2->x && p1->y == p2->y;
|
||||
}
|
||||
|
||||
// check if two segments intersect
|
||||
template <typename N>
|
||||
bool Earcut<N>::intersects(const Node* p1, const Node* q1, const Node* p2,
|
||||
const Node* q2) {
|
||||
int o1 = sign(area(p1, q1, p2));
|
||||
int o2 = sign(area(p1, q1, q2));
|
||||
int o3 = sign(area(p2, q2, p1));
|
||||
int o4 = sign(area(p2, q2, q1));
|
||||
|
||||
if (o1 != o2 && o3 != o4) return true; // general case
|
||||
|
||||
if (o1 == 0 && onSegment(p1, p2, q1))
|
||||
return true; // p1, q1 and p2 are collinear and p2 lies on p1q1
|
||||
if (o2 == 0 && onSegment(p1, q2, q1))
|
||||
return true; // p1, q1 and q2 are collinear and q2 lies on p1q1
|
||||
if (o3 == 0 && onSegment(p2, p1, q2))
|
||||
return true; // p2, q2 and p1 are collinear and p1 lies on p2q2
|
||||
if (o4 == 0 && onSegment(p2, q1, q2))
|
||||
return true; // p2, q2 and q1 are collinear and q1 lies on p2q2
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// for collinear points p, q, r, check if point q lies on segment pr
|
||||
template <typename N>
|
||||
bool Earcut<N>::onSegment(const Node* p, const Node* q, const Node* r) {
|
||||
return q->x <= std::max<double>(p->x, r->x) &&
|
||||
q->x >= std::min<double>(p->x, r->x) &&
|
||||
q->y <= std::max<double>(p->y, r->y) &&
|
||||
q->y >= std::min<double>(p->y, r->y);
|
||||
}
|
||||
|
||||
template <typename N>
|
||||
int Earcut<N>::sign(double val) {
|
||||
return (0.0 < val) - (val < 0.0);
|
||||
}
|
||||
|
||||
// check if a polygon diagonal intersects any polygon segments
|
||||
template <typename N>
|
||||
bool Earcut<N>::intersectsPolygon(const Node* a, const Node* b) {
|
||||
const Node* p = a;
|
||||
do {
|
||||
if (p->i != a->i && p->next->i != a->i && p->i != b->i &&
|
||||
p->next->i != b->i && intersects(p, p->next, a, b))
|
||||
return true;
|
||||
p = p->next;
|
||||
} while (p != a);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if a polygon diagonal is locally inside the polygon
|
||||
template <typename N>
|
||||
bool Earcut<N>::locallyInside(const Node* a, const Node* b) {
|
||||
return area(a->prev, a, a->next) < 0
|
||||
? area(a, b, a->next) >= 0 && area(a, a->prev, b) >= 0
|
||||
: area(a, b, a->prev) < 0 || area(a, a->next, b) < 0;
|
||||
}
|
||||
|
||||
// check if the middle Vertex of a polygon diagonal is inside the polygon
|
||||
template <typename N>
|
||||
bool Earcut<N>::middleInside(const Node* a, const Node* b) {
|
||||
const Node* p = a;
|
||||
bool inside = false;
|
||||
double px = (a->x + b->x) / 2;
|
||||
double py = (a->y + b->y) / 2;
|
||||
do {
|
||||
if (((p->y > py) != (p->next->y > py)) && p->next->y != p->y &&
|
||||
(px < (p->next->x - p->x) * (py - p->y) / (p->next->y - p->y) + p->x))
|
||||
inside = !inside;
|
||||
p = p->next;
|
||||
} while (p != a);
|
||||
|
||||
return inside;
|
||||
}
|
||||
|
||||
// link two polygon vertices with a bridge; if the vertices belong to the same
|
||||
// ring, it splits polygon into two; if one belongs to the outer ring and
|
||||
// another to a hole, it merges it into a single ring
|
||||
template <typename N>
|
||||
typename Earcut<N>::Node* Earcut<N>::splitPolygon(Node* a, Node* b) {
|
||||
Node* a2 = nodes.construct(a->i, a->x, a->y);
|
||||
Node* b2 = nodes.construct(b->i, b->x, b->y);
|
||||
Node* an = a->next;
|
||||
Node* bp = b->prev;
|
||||
|
||||
a->next = b;
|
||||
b->prev = a;
|
||||
|
||||
a2->next = an;
|
||||
an->prev = a2;
|
||||
|
||||
b2->next = a2;
|
||||
a2->prev = b2;
|
||||
|
||||
bp->next = b2;
|
||||
b2->prev = bp;
|
||||
|
||||
return b2;
|
||||
}
|
||||
|
||||
// create a node and util::optionally link it with previous one (in a circular
|
||||
// doubly linked list)
|
||||
template <typename N>
|
||||
template <typename Point>
|
||||
typename Earcut<N>::Node* Earcut<N>::insertNode(std::size_t i, const Point& pt,
|
||||
Node* last) {
|
||||
Node* p = nodes.construct(static_cast<N>(i), util::nth<0, Point>::get(pt),
|
||||
util::nth<1, Point>::get(pt));
|
||||
|
||||
if (!last) {
|
||||
p->prev = p;
|
||||
p->next = p;
|
||||
|
||||
} else {
|
||||
assert(last);
|
||||
p->next = last->next;
|
||||
p->prev = last;
|
||||
last->next->prev = p;
|
||||
last->next = p;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
template <typename N>
|
||||
void Earcut<N>::removeNode(Node* p) {
|
||||
p->next->prev = p->prev;
|
||||
p->prev->next = p->next;
|
||||
|
||||
if (p->prevZ) p->prevZ->nextZ = p->nextZ;
|
||||
if (p->nextZ) p->nextZ->prevZ = p->prevZ;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
template <typename N = uint32_t, typename Polygon>
|
||||
std::vector<N> earcut(const Polygon& poly) {
|
||||
mapbox::detail::Earcut<N> earcut;
|
||||
earcut(poly);
|
||||
return std::move(earcut.indices);
|
||||
}
|
||||
} // namespace mapbox
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../builder/mesh_builder_data.hpp"
|
||||
#include <string>
|
||||
#include "renderer/models/color.hpp"
|
||||
#include "loaders/3d/obj_loader/tiny_obj_loader.hpp"
|
||||
#include <memory.h>
|
||||
#include <optional>
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
struct ObjLoaderAnimationOptions {
|
||||
u16 count = 1;
|
||||
u16 startingIndex = 1;
|
||||
};
|
||||
|
||||
struct ObjLoaderOptions {
|
||||
bool flipUVs = false;
|
||||
float scale = 1.0F;
|
||||
ObjLoaderAnimationOptions animation;
|
||||
};
|
||||
|
||||
struct MaterialVertexCount {
|
||||
size_t materialId;
|
||||
int count;
|
||||
};
|
||||
|
||||
/** Class responsible for loading & parsing obj files */
|
||||
class ObjLoader {
|
||||
public:
|
||||
static std::unique_ptr<MeshBuilderData> load(const char* fullpath);
|
||||
static std::unique_ptr<MeshBuilderData> load(const char* fullpath,
|
||||
const ObjLoaderOptions& options);
|
||||
static std::unique_ptr<MeshBuilderData> load(const std::string& fullpath);
|
||||
static std::unique_ptr<MeshBuilderData> load(const std::string& fullpath,
|
||||
const ObjLoaderOptions& options);
|
||||
|
||||
private:
|
||||
static void addOutputMaterialsAndFrames(
|
||||
MeshBuilderData* output, const tinyobj::attrib_t& attrib,
|
||||
const std::vector<tinyobj::shape_t>& shapes,
|
||||
const std::vector<tinyobj::material_t>& materials, const u16& framesCount,
|
||||
std::vector<MaterialVertexCount>& materialVertexCounts);
|
||||
|
||||
static std::vector<MaterialVertexCount> scan(
|
||||
const std::vector<tinyobj::shape_t>& shapes,
|
||||
const std::vector<tinyobj::material_t>& materials);
|
||||
|
||||
static void importFrame(MeshBuilderData* output,
|
||||
const tinyobj::attrib_t& attrib,
|
||||
const std::vector<tinyobj::shape_t>& shapes,
|
||||
const std::vector<tinyobj::material_t>& materials,
|
||||
const u16& frameIndex, const float& scale,
|
||||
const bool& invertY, const u16& count);
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "loaders/texture/builder/texture_builder_data.hpp"
|
||||
#include "renderer/core/texture/models/texture_bpp.hpp"
|
||||
#include <string>
|
||||
|
||||
namespace Tyra {
|
||||
class TextureLoader {
|
||||
public:
|
||||
/**
|
||||
* @brief Loads texture data from file.
|
||||
* Sets size, name and data.
|
||||
* @param fullpath Full path to texture file. Example: "host:texture.png"
|
||||
*/
|
||||
virtual TextureBuilderData* load(const char* fullpath) = 0;
|
||||
|
||||
inline TextureBuilderData* load(const std::string& fullpath) {
|
||||
return load(fullpath.c_str());
|
||||
}
|
||||
|
||||
u32 getTextureSize(const u32& width, const u32& height,
|
||||
const TextureBpp& bpp);
|
||||
};
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "loaders/texture/base/texture_loader.hpp"
|
||||
#include "loaders/texture/png_loader.hpp"
|
||||
#include <string>
|
||||
|
||||
namespace Tyra {
|
||||
class TextureLoaderSelector {
|
||||
public:
|
||||
TextureLoaderSelector();
|
||||
~TextureLoaderSelector();
|
||||
|
||||
TextureLoader& getLoaderByFileName(const char* fullpath);
|
||||
|
||||
inline TextureLoader& getLoaderByFileName(const std::string& fullpath) {
|
||||
return getLoaderByFileName(fullpath.c_str());
|
||||
}
|
||||
|
||||
TextureLoader& getLoaderByExtension(const std::string& extension);
|
||||
|
||||
private:
|
||||
PngLoader pngLoader;
|
||||
};
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tamtypes.h>
|
||||
#include <string>
|
||||
#include "renderer/core/texture/models/texture_bpp.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
class TextureBuilderData {
|
||||
public:
|
||||
TextureBuilderData();
|
||||
~TextureBuilderData();
|
||||
|
||||
std::string name;
|
||||
|
||||
int width, height;
|
||||
unsigned char* data;
|
||||
TextureBpp bpp;
|
||||
unsigned char gsComponents;
|
||||
|
||||
int clutWidth, clutHeight;
|
||||
unsigned char* clut;
|
||||
TextureBpp clutBpp;
|
||||
unsigned char clutGsComponents;
|
||||
};
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "loaders/texture/base/texture_loader.hpp"
|
||||
#include "renderer/core/texture/models/texture.hpp"
|
||||
|
||||
#ifdef INTELLISENSE
|
||||
typedef void* png_structp;
|
||||
typedef void* png_bytep;
|
||||
typedef void* png_infop;
|
||||
typedef void* png_colorp;
|
||||
#else
|
||||
#include <png.h>
|
||||
#endif
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
struct PngPixel3 {
|
||||
u8 r, g, b;
|
||||
};
|
||||
|
||||
struct PngPixel4 {
|
||||
u8 r, g, b, a;
|
||||
};
|
||||
|
||||
class PngLoader : public TextureLoader {
|
||||
public:
|
||||
PngLoader();
|
||||
~PngLoader();
|
||||
|
||||
inline TextureBuilderData* load(const std::string& fullpath) {
|
||||
return load(fullpath.c_str());
|
||||
}
|
||||
|
||||
TextureBuilderData* load(const char* fullpath);
|
||||
|
||||
private:
|
||||
void handle32bpp(TextureBuilderData* result, png_structp pngPtr,
|
||||
png_infop infoPtr, png_bytep* rowPointers);
|
||||
|
||||
void handle24bpp(TextureBuilderData* result, png_structp pngPtr,
|
||||
png_infop infoPtr, png_bytep* rowPointers);
|
||||
|
||||
void handlePalletized(TextureBuilderData* result, png_structp pngPtr,
|
||||
png_infop infoPtr, png_bytep* rowPointers,
|
||||
const int& bitDepth);
|
||||
|
||||
void handle8bppPalletized(TextureBuilderData* result, png_structp pngPtr,
|
||||
png_infop infoPtr, png_bytep* rowPointers,
|
||||
png_colorp palette, png_bytep trans,
|
||||
const int& numPallete, const int& numTrans);
|
||||
|
||||
void handle4bppPalletized(TextureBuilderData* result, png_structp pngPtr,
|
||||
png_infop infoPtr, png_bytep* rowPointers,
|
||||
png_colorp palette, png_bytep trans,
|
||||
const int& numPallete, const int& numTrans);
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "math/vec4.hpp"
|
||||
#include "math/math.hpp"
|
||||
#include <string>
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
class M4x4 {
|
||||
public:
|
||||
MATRIX data alignas(sizeof(float) * 16);
|
||||
|
||||
static const M4x4 Identity;
|
||||
|
||||
/** Create matrix with random values */
|
||||
M4x4() {}
|
||||
|
||||
M4x4(const M4x4& v) { copy(this, v); }
|
||||
|
||||
explicit M4x4(const float* v) { copy(this, v); }
|
||||
|
||||
M4x4(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);
|
||||
|
||||
static void copy(M4x4* out, const float* in);
|
||||
static void copy(M4x4* out, const M4x4& in);
|
||||
|
||||
void operator=(const M4x4& v);
|
||||
Vec4 operator*(const Vec4& v) const;
|
||||
M4x4 operator*(const M4x4& v) const;
|
||||
void operator*=(const M4x4& v);
|
||||
float& operator[](const u8& index);
|
||||
|
||||
/**
|
||||
* 1 0 0 0
|
||||
* 0 1 0 0
|
||||
* 0 0 1 0
|
||||
* 0 0 0 1
|
||||
*/
|
||||
void identity();
|
||||
|
||||
inline void unit() { identity(); }
|
||||
|
||||
void set(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);
|
||||
|
||||
void translate(const Vec4& v);
|
||||
void translateX(const float& v);
|
||||
void translateY(const float& v);
|
||||
void translateZ(const float& v);
|
||||
|
||||
void rotateByAngle(const float& angle, const Vec4& axis);
|
||||
void rotate(const Vec4& v);
|
||||
void rotateX(const float& radians);
|
||||
void rotateY(const float& radians);
|
||||
void rotateZ(const float& radians);
|
||||
|
||||
void scale(const float& v);
|
||||
void scale(const Vec4& v);
|
||||
void scaleX(const float& v);
|
||||
void scaleY(const float& v);
|
||||
void scaleZ(const float& v);
|
||||
|
||||
/** Create perspective projection M4x4 (gluPerspective) */
|
||||
static M4x4 perspective(const float& fov, const float& width,
|
||||
const float& height, const float& projectionScale,
|
||||
const float& aspectRatio, const float& near,
|
||||
const float& far);
|
||||
|
||||
/**
|
||||
* Create a view M4x4 that transforms coordinates in
|
||||
* such a way that the user looks at a target vector
|
||||
* direction from a position vector (glLookAt)
|
||||
*/
|
||||
static M4x4 lookAt(const Vec4& position, const Vec4& target);
|
||||
static void lookAt(M4x4* res, const Vec4& position, const Vec4& target);
|
||||
|
||||
void print() const;
|
||||
void print(const char* name) const;
|
||||
void print(const std::string& name) const { print(name.c_str()); }
|
||||
std::string getPrint(const char* name = nullptr) const;
|
||||
|
||||
private:
|
||||
static float upVec[4] alignas(sizeof(float) * 4);
|
||||
static float viewVec[4] alignas(sizeof(float) * 4);
|
||||
|
||||
static void cross(float res[16], const float a[16], const float b[16]);
|
||||
void rotationX(const float& v);
|
||||
void rotationY(const float& v);
|
||||
void rotationZ(const float& v);
|
||||
void rotationByAngle(const float& angle, const Vec4& axis);
|
||||
void translationX(const float& v);
|
||||
void translationY(const float& v);
|
||||
void translationZ(const float& v);
|
||||
void setScale(const Vec4& val);
|
||||
static M4x4 setCamera(const float pos[4], const float vz[4],
|
||||
const float vy[4]);
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
extern "C" {
|
||||
#include <tamtypes.h>
|
||||
}
|
||||
|
||||
#include <math.h>
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
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 atan2(float y, float x);
|
||||
static float mod(const float& x, const float& y);
|
||||
static float acos(const float& x);
|
||||
static float sin(const float& x);
|
||||
static float tan(const float& x);
|
||||
static float invSqrt(const float& x);
|
||||
static float randomf(const float& min, const float& max);
|
||||
static int randomi(const int& min, const int& max);
|
||||
static bool equalf(const float& a, const float& b,
|
||||
const float& epsilon = 0.00001F);
|
||||
|
||||
private:
|
||||
Math();
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "./vec4.hpp"
|
||||
#include <string>
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
class Plane {
|
||||
public:
|
||||
Vec4 normal;
|
||||
float distance;
|
||||
|
||||
Plane();
|
||||
Plane(const Vec4& a, const Vec4& b, const Vec4& c);
|
||||
~Plane();
|
||||
|
||||
void update(const Vec4& a, const Vec4& b, const Vec4& c);
|
||||
|
||||
float distanceTo(const Vec4& t_vec) const;
|
||||
|
||||
void print() const;
|
||||
void print(const char* name) const;
|
||||
void print(const std::string& name) const { print(name.c_str()); }
|
||||
std::string getPrint(const char* name = nullptr) const;
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
extern "C" {
|
||||
#include <stdio.h>
|
||||
#include <tamtypes.h>
|
||||
}
|
||||
|
||||
#include <string>
|
||||
#include "math/math.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
class Vec2 {
|
||||
public:
|
||||
union {
|
||||
struct {
|
||||
float x;
|
||||
float y;
|
||||
};
|
||||
float xy[2] alignas(sizeof(float) * 2);
|
||||
};
|
||||
|
||||
Vec2(const float& t_x, const float& t_y);
|
||||
Vec2(const Vec2& v);
|
||||
Vec2();
|
||||
~Vec2();
|
||||
|
||||
void operator=(const Vec2& v);
|
||||
|
||||
Vec2 operator+(const Vec2& v) const;
|
||||
Vec2 operator-(const Vec2& v) const;
|
||||
Vec2 operator*(const Vec2& v) const;
|
||||
Vec2 operator/(const Vec2& v) const;
|
||||
|
||||
Vec2 operator+(const float& v) const;
|
||||
Vec2 operator-(const float& v) const;
|
||||
Vec2 operator*(const float& v) const;
|
||||
Vec2 operator/(const float& v) const;
|
||||
|
||||
void operator+=(const Vec2& v);
|
||||
void operator-=(const Vec2& v);
|
||||
void operator*=(const Vec2& v);
|
||||
void operator/=(const Vec2& v);
|
||||
|
||||
void operator+=(const float& v);
|
||||
void operator-=(const float& v);
|
||||
void operator*=(const float& v);
|
||||
void operator/=(const float& v);
|
||||
|
||||
void set(const float& t_x, const float& t_y);
|
||||
void set(const Vec2& v);
|
||||
void rotate(const float& t_angle, const float& t_x, const float& t_y);
|
||||
|
||||
void print() const;
|
||||
void print(const char* name) const;
|
||||
void print(const std::string& name) const { print(name.c_str()); }
|
||||
std::string getPrint(const char* name = nullptr) const;
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
extern "C" {
|
||||
#include <stdio.h>
|
||||
#include <tamtypes.h>
|
||||
}
|
||||
|
||||
#include <math3d.h>
|
||||
#include <string>
|
||||
#include "math/math.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
class Vec4 {
|
||||
public:
|
||||
union {
|
||||
struct {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
};
|
||||
VECTOR xyzw alignas(sizeof(float) * 4);
|
||||
};
|
||||
|
||||
static void copy(Vec4* out, const float* in);
|
||||
static inline void copy(Vec4* out, const Vec4& in) { copy(out, in.xyzw); }
|
||||
|
||||
static const Vec4 Identity;
|
||||
|
||||
/** Initialize Vec4 without setting default values */
|
||||
Vec4() {}
|
||||
|
||||
/** Initialize Vec4 with provided values */
|
||||
Vec4(const float& x, const float& y = 0.0F, const float& z = 0.0F,
|
||||
const float& w = 1.0F)
|
||||
: x(x), y(y), z(z), w(w) {}
|
||||
|
||||
/** Initialize Vec4 with other Vec4 values */
|
||||
Vec4(const Vec4& v) { copy(this, v); }
|
||||
|
||||
/** Initialize Vec4 with float[4] values */
|
||||
explicit Vec4(const float* v) { copy(this, v); }
|
||||
|
||||
/** copy */
|
||||
void operator=(const Vec4& v);
|
||||
|
||||
/** negate xyz */
|
||||
Vec4 operator-(void) const;
|
||||
|
||||
/** xyz + xyz */
|
||||
Vec4 operator+(const Vec4& v) const;
|
||||
void operator+=(const Vec4& v);
|
||||
|
||||
/** xyz - xyz */
|
||||
Vec4 operator-(const Vec4& v) const;
|
||||
void operator-=(const Vec4& v);
|
||||
|
||||
/** xyzw * xyzw */
|
||||
Vec4 operator*(const Vec4& v) const;
|
||||
void operator*=(const Vec4& v);
|
||||
|
||||
/** xyzw / xyzw */
|
||||
Vec4 operator/(const Vec4& v) const;
|
||||
void operator/=(const Vec4& v);
|
||||
|
||||
/** xyz * v */
|
||||
Vec4 operator*(const float& v) const;
|
||||
void operator*=(const float& v);
|
||||
|
||||
/** xyz / v */
|
||||
Vec4 operator/(const float& v) const;
|
||||
void operator/=(const float& v);
|
||||
|
||||
/** (0,0,0,1) */
|
||||
void unit();
|
||||
|
||||
inline void set(const Vec4& v) { copy(this, v.xyzw); }
|
||||
inline void set(const float* v) { copy(this, v); }
|
||||
void set(const float& x, const float& y = 0.0F, const float& z = 0.0F,
|
||||
const float& w = 1.0F);
|
||||
|
||||
Vec4 cross(const Vec4& v) const;
|
||||
|
||||
void rotateZ(const int& angle);
|
||||
|
||||
int getRelativeCosBetween(const Vec4& v) const;
|
||||
int getRelativeAngleBetween(const Vec4& v) const;
|
||||
|
||||
float innerProduct(const Vec4& v) const;
|
||||
inline float dot3(const Vec4& v) const { return innerProduct(v); }
|
||||
|
||||
/** Get vector length */
|
||||
float length() const;
|
||||
|
||||
/** Normalize vector */
|
||||
void normalize();
|
||||
|
||||
Vec4 getNormalized() const;
|
||||
|
||||
/** Returns distance between two vectors */
|
||||
float distanceTo(const Vec4& v) const;
|
||||
|
||||
/**
|
||||
* Checks intersection with given box
|
||||
* @param min Opposite min vertex (ex. near, left, down vertex of bounding
|
||||
* box)
|
||||
* @param max Opposite max vertex (ex. far, right, up vertex of bounding
|
||||
* box)
|
||||
*/
|
||||
bool collidesBox(const Vec4& min, const Vec4& max) const;
|
||||
|
||||
/**
|
||||
* Checks if this vector is on given box (this->y >= box.y)
|
||||
* @param min Opposite min vertex (ex. near, left, down vertex of bounding
|
||||
* box)
|
||||
* @param max Opposite max vertex (ex. far, right, up vertex of bounding
|
||||
* box)
|
||||
*/
|
||||
bool isOnBox(const Vec4& min, const Vec4& max) const;
|
||||
|
||||
/** Check if given triangle should be backface culled */
|
||||
static u8 shouldBeBackfaceCulled(const Vec4* cameraPos, const Vec4* v0,
|
||||
const Vec4* v1, const Vec4* v2);
|
||||
|
||||
/**
|
||||
* Update this vector by linear interpolation between two vertices
|
||||
* @param v1 Before vertex
|
||||
* @param v2 After vertex
|
||||
* @param interp State of interpolation
|
||||
*/
|
||||
void lerp(const Vec4& v1, const Vec4& v2, const float& interp);
|
||||
|
||||
/**
|
||||
* Get vector by linear interpolation between two vertices
|
||||
* @param v1 Before vertex
|
||||
* @param v2 After vertex
|
||||
* @param interp State of interpolation
|
||||
*/
|
||||
static Vec4 getByLerp(const Vec4& v1, const Vec4& v2, const float& interp);
|
||||
|
||||
void print() const;
|
||||
void print(const char* name) const;
|
||||
void print(const std::string& name) const { print(name.c_str()); }
|
||||
std::string getPrint(const char* name = nullptr) const;
|
||||
|
||||
static void setLerp(Vec4* output, const Vec4& v1, const Vec4& v2,
|
||||
const float& interp);
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user