234 Commits

Author SHA1 Message Date
Sandro Sobczyński afa98e8bdf Update CHANGELOG.MD 2020-12-27 21:39:19 +01:00
Sandro Sobczyński 55bc876dfb Update README.MD 2020-12-27 21:32:18 +01:00
Sandro Sobczyński 6432fc183e Create README.MD 2020-12-27 21:21:38 +01:00
Sandro Sobczyński a971309e2d Update README.MD 2020-12-27 21:13:21 +01:00
Sandro Sobczyński b94fa40eac Update README.MD 2020-12-27 21:03:31 +01:00
Sandro Sobczyński c1ed10eb3b Create CHANGELOG.MD 2020-12-27 20:53:57 +01:00
Sandro Sobczyński 07ba692009 Merge pull request #82 from h4570/develop
Monthly release
2020-12-27 20:03:09 +01:00
Sandro Sobczyński 64a2ccd6f3 Merge pull request #80 from h4570/feature/dolphin
Dolphin: Cleanup & changed water logic.
2020-12-27 19:56:41 +01:00
h4570 ea0d47e09c cleanup & changed water logic 2020-12-27 19:49:36 +01:00
Michał Mostowik 913f52ec6f Merge pull request #77 from h4570/feature/draw-many
Renderer: Fixed sync between processors for draw() array mode.
2020-12-27 19:14:51 +01:00
h4570 55f476e9ed fixed sync between draw many 2020-12-27 19:10:14 +01:00
h4570 1d7730504b fixed sync between processors 2020-12-27 19:09:50 +01:00
h4570 c7fe915174 fixed volume 2020-12-27 13:41:32 +01:00
h4570 92d5ad7ad0 Merge branch 'develop' of https://github.com/ps2-tyra/tyra into develop 2020-12-27 13:40:04 +01:00
h4570 e987089df0 fixed floors bug 2020-12-27 13:39:44 +01:00
Sandro Sobczyński 89295ff27a Merge pull request #76 from h4570/feature/floors
Floors sample refactor, PNGLoader refactor
2020-12-26 17:30:35 +01:00
h4570 d0c2dfcaa3 disabled file service 2020-12-26 17:29:07 +01:00
h4570 7f9f86d7c3 added draw() in array mode 2020-12-26 13:31:43 +01:00
h4570 91772a905c cleanup 2020-12-26 13:31:30 +01:00
Sandro Sobczyński 8a8d453ee0 Merge pull request #75 from h4570/feature/renderer
Renderer: VU1 optimizations
2020-12-26 13:30:45 +01:00
h4570 8406dcee72 added optimized array mode to draw() 2020-12-26 13:29:37 +01:00
Michał Mostowik 4c8ead755b Merge pull request #74 from h4570/feature/renderer
New VU1 renderer, added VCL preprocessor
2020-12-24 14:38:39 +01:00
h4570 aeb25ad398 new vu1 renderer, added vcl preprocessor 2020-12-24 14:35:13 +01:00
h4570 d60d42cac6 removed unecessary include 2020-12-24 13:09:13 +01:00
h4570 c0ece7206c tweaked vu1 packets a bit 2020-12-24 13:08:03 +01:00
Michał Mostowik 096f2490ec Merge pull request #73 from h4570/feature/renderer
Renderer: optimized calcs of model-view-proj matrix
2020-12-24 12:53:48 +01:00
h4570 b4fe16dccc added manual calcs of model-view-proj matrix 2020-12-24 12:45:09 +01:00
Michał Mostowik 469ef48051 Merge pull request #71 from h4570/refactor/matrix
Refactor of Matrix and Vector3 class.
2020-12-24 10:54:04 +01:00
h4570 91934df5e8 fixed warning 2020-12-24 10:35:04 +01:00
h4570 e39c8c5de8 changes to match latest matrix/vector3 api 2020-12-24 10:34:56 +01:00
h4570 8589a298da added comments, increased performance 2020-12-24 10:33:30 +01:00
h4570 5a932b35ca fixed bug, added full rotation 2020-12-24 10:32:51 +01:00
h4570 7dd8947612 added vec3 multiply 2020-12-23 22:38:57 +01:00
h4570 4b2deb8b39 matrix refactor 2020-12-23 22:10:12 +01:00
h4570 e0ad58f72f fixed bug with matrix multiply 2020-12-23 20:28:41 +01:00
h4570 f95e805d33 added data alignment 2020-12-23 20:28:28 +01:00
h4570 b935d4da13 fixed newline warning 2020-12-23 20:24:08 +01:00
Sandro Sobczyński f6cbac7c20 Merge pull request #69 from Foxar/develop
BoundingBox refactor using new class.
2020-12-21 20:36:34 +01:00
Foxar 3af3576203 Added: Multiple doxygen @returns comments. 2020-12-21 20:35:09 +01:00
Foxar ae3dd737e5 Changed: Multiple const additions. 2020-12-21 20:28:26 +01:00
Foxar 23ea1a28f6 Changed: Comments, boundingbox getters in mesh.hpp 2020-12-21 20:22:40 +01:00
Foxar 115dac21bc Changed: Return types in mesh_frame and mesh_materials for getBoundingBoxVertex() to const. 2020-12-21 20:15:18 +01:00
Foxar f8f91c6b49 Changed: Return type of getVertex() to be const. 2020-12-21 20:09:00 +01:00
Foxar 8137bd56d8 Changed: Usage of getVertices()[y] to getVertex(y) 2020-12-21 20:07:34 +01:00
Foxar cf07cf78c8 Added: Comment for BoundingBox constructor parameters. 2020-12-21 20:06:55 +01:00
Foxar 13f6a2ecb7 Changed: Changed manual deep-copy of parameter vertex array to usage of memcpy() 2020-12-21 20:02:51 +01:00
Foxar 9e1a9e8b3c Changed: Renamed getBoundingBox() to getBoundingBoxVertices() as the function returns the array of vertices from the BoundingBox object. 2020-12-21 19:41:29 +01:00
Foxar 5c232aebce Removed: Newline below a doxygen comment. 2020-12-21 19:32:40 +01:00
Foxar 586fe136ea Changed: Removed old vertex array boundingbox declaration, forced usage of temporary vector array in initial boundingbox calculations. 2020-12-21 19:05:33 +01:00
Foxar 02d7916925 Fixed: Fixed incorrect naming of boundingbox constructor parameters. 2020-12-21 19:04:34 +01:00
Foxar 1cc1e62ed6 Fixed: Fixed incorrect vertex array for-loop iteration. 2020-12-21 19:03:40 +01:00
Foxar 1765885bec Removed: Commented-out ('disabled') method declarations. 2020-12-21 18:57:01 +01:00
Foxar d835f83e51 Added: New BoundingBox infrastructure into mesh_material, analogous to mesh_frame. 2020-12-21 18:48:11 +01:00
Foxar 974138d64e Changed: Replaced old getBoundingBox and getBoundingBoxVertex functions with new ones, using the new bounding_box class infrastructure. 2020-12-21 18:31:23 +01:00
Foxar ae15906c99 Added: Accessors in bounding_box class allowing access to vertices array. 2020-12-21 18:30:18 +01:00
Foxar 71ce30a8fc Added: Destructor for boundingbox class. 2020-12-20 14:13:47 +01:00
Foxar 55d8e445db Fixed: Typo in bounding box getters. 2020-12-20 14:12:52 +01:00
Foxar 11a4e2ee76 Changed: Updated makefile to include new boundingboxes. 2020-12-20 14:11:50 +01:00
Foxar 596bf2d89a Added: Mesh_frame getter for BoundingBox object pointer. 2020-12-20 13:44:48 +01:00
Foxar 53c134b0d5 Added: Integrated new BoundingBox class implentation with mesh_frame boundingbox calculations. 2020-12-20 13:38:26 +01:00
Foxar 9b2d39505b Added: BoundingBoxFaces assignments, calculations and doxygen comments. 2020-12-20 13:24:50 +01:00
Foxar 44776f7aba Added: Incomplete implenetation of BoundingBox class and BoundingBoxFace struct. 2020-12-20 13:13:03 +01:00
Sandro Sobczyński bb0ec257b2 Update README.MD 2020-12-19 09:21:58 +01:00
Michał Mostowik a8a649d723 Merge pull request #67 from h4570/feature/new-readme
Readme: Add new logo and modify some things
2020-12-18 22:58:29 +01:00
Sandro Sobczyński 73a3d1d7e5 Update README.MD 2020-12-18 22:36:17 +01:00
Sandro Sobczyński dfee1ab25f Update README.MD 2020-12-18 22:33:14 +01:00
Foxar d4f2a1e1a2 Restored: Undid the objloader changes, they should be in its own branch. 2020-12-17 14:19:23 +01:00
Foxar 12ef639516 Changed: Allowed obj_loader to load different .obj face element configurations.
New authorised .obj face elements configurations: v, v/t, v/vt/vn, v//vn
2020-12-17 13:33:22 +01:00
Michał Mostowik 552f2c6e4a Merge pull request #4 from h4570/develop
Develop
2020-12-16 15:24:03 +01:00
h4570 ea6d5215d1 fixed funcs declaration 2020-12-13 00:39:32 +01:00
h4570 4a1bca12aa small undo in rendering pipeline 2020-12-13 00:23:04 +01:00
h4570 0156d4444f Merge branch 'develop' of https://github.com/ps2-tyra/tyra into develop 2020-12-13 00:20:19 +01:00
Sandro Sobczyński 623576a387 Merge pull request #63 from h4570/revert-61-hotfix/matrix
Revert "Urgent hotfix in matrix multiply, added few funcs"
2020-12-13 00:19:42 +01:00
Sandro Sobczyński 3f4d2c5521 Revert "Urgent hotfix in matrix multiply, added few funcs" 2020-12-13 00:19:18 +01:00
h4570 206ccdf415 Merge branch 'develop' of https://github.com/ps2-tyra/tyra into develop 2020-12-12 23:57:21 +01:00
Sandro Sobczyński 7025f5371b Merge pull request #62 from h4570/feature/math
Math: Add max/min and tangens
2020-12-12 23:21:16 +01:00
Sandro Sobczyński 2455ce82dd Merge pull request #61 from h4570/hotfix/matrix
Urgent hotfix in matrix multiply, added few funcs
2020-12-12 23:20:30 +01:00
h4570 2ce2e76663 Merge branch 'hotfix/matrix' into develop 2020-12-12 23:19:33 +01:00
h4570 f4e699025a added useful funcs 2020-12-12 23:19:12 +01:00
h4570 b050e4643b multiply hotfix! added scale, angle rotation 2020-12-12 23:18:31 +01:00
Sandro Sobczyński e38f569bc4 Merge pull request #60 from h4570/feature/pipeline
Small refactoring of viewproj matrix calcs
2020-12-12 14:13:29 +01:00
h4570 3dd51607f0 refactored viewproj matrix calcs a bit 2020-12-12 14:12:30 +01:00
Sandro Sobczyński b7618c014a Merge pull request #59 from h4570/feature/math-matrix
Added some matrix/math funcs
2020-12-12 14:11:54 +01:00
h4570 8256efa7c8 switched zbuffer to 24bit mode 2020-12-12 14:10:50 +01:00
h4570 ac36012545 added some matrix/math funcs 2020-12-12 14:07:23 +01:00
Sandro Sobczyński 968718a549 Merge pull request #58 from Foxar/master
Missing commits and files from last PR
2020-12-10 18:01:19 +01:00
Michał Mostowik 24bab8464a Merge pull request #3 from Foxar/develop
Foxar develop->Foxar master-> PR #58 h4570/tyra
2020-12-10 17:59:09 +01:00
Foxar 4bee938106 PR Review: Memory de-allocation, misc. fixes. 2020-12-10 17:49:53 +01:00
Michał Mostowik 86c48eeca4 Merge pull request #2 from Foxar/master
PR Review, removing commented line
2020-12-10 17:43:36 +01:00
Michał Mostowik 97151ffc78 PR Review, removing commented line 2020-12-10 17:37:44 +01:00
Michał Mostowik bc44f598c1 Merge pull request #1 from Foxar/master
Master to develop
2020-12-10 16:35:09 +01:00
Foxar 5129d53b27 Added: Missing mine class files. 2020-12-10 16:32:01 +01:00
Foxar 1539aa4108 Merge branch 'master' of https://github.com/Foxar/tyra
I really freaked last pr up so here's a merge to fix it
2020-12-10 16:31:12 +01:00
Sandro Sobczyński 083c041973 Merge pull request #56 from Foxar/master
Added: Sea mines, healing by collectibles, game over screen
2020-12-10 14:46:35 +01:00
Foxar 0c0512b37f Added: Game over screen 2020-12-10 14:38:12 +01:00
Foxar e7aa4d13cc Added: Mines now explode and hurt the player, added new makefile and made more mines spawn on game start. 2020-12-10 13:52:45 +01:00
Foxar 1c9351e5e9 Added: Sea mines, when fully implemented, will explode and take lifes from player. 2020-12-10 12:52:54 +01:00
Foxar f86a1bf190 Added: Underwater/Above water soundscape, misc sound effects. Reworked player class a bit to contain pointer to the game engine for sound playing. 2020-12-09 14:27:40 +01:00
Michał Mostowik 36a637e5e6 Merge pull request #54 from h4570/hotfix/texture-size-vars
Texture: Fixed var type bug
2020-12-08 21:41:14 +01:00
Foxar c4fc52b043 Added: Sprites representing lifes player has left, and life variable. 2020-12-08 19:27:30 +01:00
Foxar 70efbcad46 Merge branch 'master' of https://github.com/Foxar/tyra 2020-12-08 19:24:22 +01:00
Michał Mostowik db635c09ea Merge pull request #4 from h4570/develop
Develop pull
2020-12-08 19:24:02 +01:00
Michał Mostowik edf5bd1e55 Merge pull request #50 from h4570/hotfix/draw-mesh-color
Add mesh color blending to draw()
2020-12-08 16:50:43 +01:00
Foxar f4421b659d Added: Seabed model/code. 2020-12-08 16:48:43 +01:00
h4570 a017c3a3b6 added color blending for draw() 2020-12-08 15:59:24 +01:00
Foxar 220caba84a Fixed: Added MODE_STRETCH to wateroverlay, fixing the tiling issue. 2020-12-08 15:30:48 +01:00
Michał Mostowik 921b482e61 Merge pull request #3 from h4570/develop
Develop pull
2020-12-08 14:54:12 +01:00
Foxar 45edf7aedb Added: Static fps member to dolphin.cpp, auto-updated with engine->fps, made player movement multiplied by deltatime of last frame. 2020-12-08 14:42:43 +01:00
Sandro Sobczyński d9b5f8a4aa Merge pull request #42 from Foxar/master
Dolphin sample: Controls adjusted, collectibles float up on pickup, camera adjusted.
2020-12-08 14:24:02 +01:00
Michał Mostowik 4557485cab Fixed datatype typos in dolphin.cpp 2020-12-08 14:20:00 +01:00
Foxar 582b42c29e Changed: Optimization from code review PR #42 2020-12-08 13:36:13 +01:00
Sandro Sobczyński 6e1c94a112 Merge pull request #47 from h4570/samples/floors
Floors sample rework
2020-12-08 08:15:52 +01:00
Michał Mostowik 62cff819ff Merge pull request #45 from h4570/doc/audio
Audio: Added small comment to loadADPCM().
2020-12-07 23:51:13 +01:00
Michał Mostowik 729bcff954 Merge pull request #43 from h4570/feature/ambient-color
Renderer: added setAmbientLight() and setWorldColor()
2020-12-07 23:50:41 +01:00
h4570 8a0f5f7b84 refactor #2 2020-12-07 22:14:36 +01:00
h4570 5787b6a920 refactor #1 2020-12-07 22:11:21 +01:00
h4570 6d9b93998a changed paths 2020-12-07 22:05:06 +01:00
h4570 96fe7c380e added reward 2020-12-07 21:51:48 +01:00
h4570 11a92c32ee audio changes 2020-12-07 21:51:44 +01:00
h4570 87ae4b0507 added info banner 2020-12-07 21:20:08 +01:00
h4570 ad855a13d2 Merge branch 'develop' into samples/floors 2020-12-07 21:09:39 +01:00
h4570 14b688c6cb Merge branch 'feature/ambient-color' into develop 2020-12-07 21:06:07 +01:00
h4570 0474fc07a5 doc: usefull tip for loadADPCM() 2020-12-07 21:05:46 +01:00
h4570 e00e677d1e fixed naming convention 2020-12-07 21:04:38 +01:00
h4570 3284c5a598 added setAmbientLight(), setWorldColor() 2020-12-07 21:02:06 +01:00
h4570 dd49fc165e lot of changes in floors 2020-12-07 20:47:41 +01:00
Foxar 83dce5cb92 Changed: Slowed player rotation speed. 2020-12-07 20:09:17 +01:00
Foxar 32422b87eb Added: Collectibles now rotate, float up before disapeparing after being picked up. 2020-12-07 20:08:11 +01:00
Foxar 6292c27c50 Added: Camera automatically shifts to an angle from behind the player. 2020-12-07 19:30:07 +01:00
h4570 4b158781af fixed var type bug 2020-12-07 17:31:37 +01:00
h4570 cad2623649 Merge branch 'feature/sprite-modes' into samples/floors 2020-12-07 17:27:18 +01:00
h4570 d94f51623c Merge branch 'feature/texture-inline' into samples/floors 2020-12-07 17:27:14 +01:00
Michał Mostowik 18f3398687 Merge pull request #40 from h4570/feature/texture-inline
Marked texture getters as inline
2020-12-07 17:23:28 +01:00
Michał Mostowik 1c3edb3887 Merge pull request #38 from h4570/feature/sprite-modes
Sprite modes (stretch/repeat)
2020-12-07 17:23:06 +01:00
h4570 5fb6858678 marked getters as inline 2020-12-07 17:19:34 +01:00
h4570 8a1bc254c5 added sprite modes (stretch/repeat) 2020-12-07 17:18:43 +01:00
Foxar 0423e484a5 Changed: Dolphin sample FOV is now 75.F, zoomed in the camera, increased the distance for collectibles pickup. 2020-12-07 14:28:56 +01:00
Michał Mostowik ed6c20e5df Merge pull request #2 from h4570/develop
Develop pull
2020-12-07 13:37:02 +01:00
Michał Mostowik f95794c181 Merge pull request #36 from h4570/hotfix/vector3
Fixed sqrt() VU0 calcs on real PS2
2020-12-07 00:41:34 +01:00
Michał Mostowik 9f4f6f4b18 Merge pull request #34 from h4570/bugfix/path3-lighting
Fixed path3 lighting on real PS2
2020-12-07 00:40:26 +01:00
h4570 fbbb41580c decreased vol 2020-12-06 21:20:24 +01:00
h4570 d15cdecd97 Merge branch 'bugfix/path3-lighting' into samples/floors 2020-12-06 20:36:24 +01:00
h4570 8b9ea4696e Merge branch 'hotfix/vector3' into samples/floors 2020-12-06 20:36:17 +01:00
h4570 9fb2cb385a Merge branch 'samples-floors-lighting-fix' into samples/floors 2020-12-06 20:36:11 +01:00
h4570 97c9a5cd90 fixed var initializing 2020-12-06 20:36:04 +01:00
h4570 f080a97dc5 fixes for real ps2 (vwaitq), and cosmetic changes 2020-12-06 20:25:52 +01:00
h4570 55cee63ace fixed path3 lighting on real ps2 2020-12-06 20:20:08 +01:00
Sandro Sobczyński 69d4cf81ec Merge pull request #33 from h4570/feature/vector3
Vector3::distanceTo() - marked as const
2020-12-06 17:05:53 +01:00
h4570 bcad6f7941 added ui, enemy, sounds, fixed anims 2020-12-06 16:41:40 +01:00
h4570 94e4f8ea3a fixed camera movement speed 2020-12-06 16:40:13 +01:00
h4570 d0017f26f1 marked distanceTo as const 2020-12-06 16:38:51 +01:00
Foxar 9a94d93747 Merge pull request #30 from h4570/bugfix/2d-sprite-size
Fixed rendering for non square 2D sprites
2020-12-06 08:24:37 +01:00
h4570 67a10cb724 Added tex max check 2020-12-06 00:13:37 +01:00
h4570 b8552330bd fixed rendering for non square sprites 2020-12-06 00:00:35 +01:00
Foxar 20b14a5168 Merge pull request #29 from h4570/h4570-patch-1
Add .gitignore to dolphin sample
2020-12-05 22:05:55 +01:00
Foxar c0ab97585c Added: collectibles class. Collectibles are strewn around the level and can be 'picked up' (deactivated, won't be rendered), when the player gets close and jumps. 2020-12-05 22:04:38 +01:00
Sandro Sobczyński d61396866d Add .gitignore for dolphin sample 2020-12-05 21:54:03 +01:00
Foxar b547de9cbb Stretched water overlay to fullscreen, made it appear when camera's sugmerged, disabled the invalid rotation during submerging ( issue number #10 ), enlargened and fixed position of the island mesh. 2020-12-04 16:50:25 +01:00
Foxar a05b4fbd0f Merge pull request #1 from h4570/develop
Updating fork to the current state of main repo's develop branch
2020-12-04 16:21:39 +01:00
Foxar 3e385f7c84 Merge pull request #6 from h4570/fix/readme
Urls changes in readme file (ps2-tyra to h4570)
2020-12-04 10:54:25 +01:00
Sandro Sobczyński fd29a11579 fixed all ps2-tyra to h4570 2020-12-04 08:56:45 +01:00
Foxar 82361e4619 Merge pull request #5 from Foxar/master
Included the missing dolphin.cpp and hpp files.
2020-12-04 00:21:57 +01:00
Foxar b48d342adf Included the missing dolphin.cpp and hpp files. 2020-12-04 00:20:43 +01:00
h4570 d22d125afa Merge branch 'samples/floors' into develop 2020-12-03 23:54:39 +01:00
h4570 513ae84577 added const to some vector3 funcs 2020-12-03 23:51:18 +01:00
Sandro Sobczyński db23acddd7 Merge pull request #4 from Foxar/master
Added: Dolphin sample [WIP]
2020-12-03 20:29:43 +01:00
Foxar 17ef6b9fbc Revert "Switched audio filenames to available binaries"
This reverts commit 51702d5ef7.
2020-12-03 20:25:13 +01:00
Sandro Sobczyński e5eb57e587 Merge pull request #3 from h4570/timer-rework
Timer rework
2020-12-03 20:08:37 +01:00
h4570 f45f5c39c7 small rework of timer class 2020-12-03 20:04:35 +01:00
Foxar bae834e599 Added water mesh, jumping animation, skybox and diving. 2020-12-03 18:33:20 +01:00
h4570 72266d0c25 fixed 2d alpha blending 2020-12-03 18:25:17 +01:00
h4570 a6f8bb9b36 removed ari sample 2020-12-02 21:40:40 +01:00
Foxar 940271fe8c Merge remote-tracking branch 'upstream/master'
zero
2020-12-02 20:59:09 +01:00
Foxar 7e676916a0 Added new sample dolphin. 2020-12-02 20:54:19 +01:00
h4570 d58163d75b fixed ps2sdk version 2020-12-01 21:32:08 +01:00
h4570 56e1d7d5d8 refactored gitignores 2020-12-01 19:43:44 +01:00
h4570 945aeb1bec added ignore bin/** 2020-12-01 19:40:16 +01:00
h4570 c662307942 Merge branch 'master' of https://github.com/ps2-tyra/tyra 2020-12-01 19:28:48 +01:00
h4570 389a5ee608 mesh_texture -> texture 2020-12-01 19:27:55 +01:00
h4570 ade89bbdd1 fixed addByMesh() 2020-12-01 19:18:57 +01:00
h4570 ca7846f60b refactored makefiles 2020-12-01 19:18:40 +01:00
h4570 510199164c added 2d png support 2020-12-01 17:26:10 +01:00
h4570 3841487388 added png loader 2020-12-01 17:25:18 +01:00
Foxar 51702d5ef7 Switched audio filenames to available binaries 2020-12-01 17:21:07 +01:00
h4570 6f1d0e2e33 fixed to match new packet2 api 2020-12-01 17:02:31 +01:00
Sandro Sobczyński eed34a17bc Update README.MD 2020-11-30 19:11:47 +01:00
h4570 2fad5f67f1 Merge branch 'feature/migration-libspacket' 2020-11-29 13:37:48 +01:00
h4570 7d2f354085 added test 2d rectangle to renderer 2020-11-29 13:37:30 +01:00
h4570 7233e6a4f4 fixed typo 2020-11-28 12:16:05 +01:00
Sandro Sobczyński 94db15da9b Update README.MD 2020-11-27 22:18:33 +01:00
Sandro Sobczyński d1f16cf9b3 Merge pull request #1 from h4570/feature/migration-libspacket
Feature/migration libspacket
2020-11-27 16:55:17 +01:00
h4570 25b5fb4295 fixed to last packet2 api 2020-11-23 22:01:28 +01:00
Sandro Sobczyński 3cbea1877a Update README.MD 2020-11-22 17:16:46 +01:00
h4570 e9febb5d8d changed order of wait/send 2020-11-22 13:15:15 +01:00
h4570 756f69d160 fixed packet size 2020-11-22 13:11:41 +01:00
Sandro Sobczyński 1e4022171d Update README.MD 2020-11-21 18:43:16 +01:00
Sandro Sobczyński 66f67b0d22 Update README.MD 2020-11-21 17:01:46 +01:00
h4570 82cab6f78b refactored to match latest libpacket2 api 2020-11-21 13:59:56 +01:00
h4570 5e811b78cd minor fixes 2020-11-20 22:34:24 +01:00
h4570 3d755e9983 fixed obj parsing bug 2020-11-20 22:34:13 +01:00
h4570 6b821afd86 fixes to match latest libpacket2 commit 2020-11-20 20:26:19 +01:00
h4570 8a3485e671 migrated VU1 into spacket 2020-11-17 17:33:30 +01:00
h4570 33d7f9648d testing spacket on vu1 2020-11-17 14:55:41 +01:00
h4570 2b42bc53cb function name change (spacket) 2020-11-17 14:45:14 +01:00
h4570 4112e6d327 migrated sendSingleRefList to spacket 2020-11-17 13:20:18 +01:00
h4570 d2ce2eb7b2 migrated vu1 upload_prog into spacket 2020-11-17 12:58:13 +01:00
h4570 00c171d6b9 migrated gif_sender to spacket 2020-11-16 23:15:07 +01:00
h4570 7e442bcf5c gif_sender migration #1 (libspacket) 2020-11-16 18:48:36 +01:00
h4570 c1ad6effbd migrated renderer to libspacket 2020-11-16 18:48:09 +01:00
Sandro Sobczyński 6c82beb383 fixed floors sample 2020-11-12 19:09:57 +01:00
Sandro Sobczyński fb0df1537e wip - file_service 2020-11-12 18:24:02 +01:00
Sandro Sobczyński c6af82943a small fixes 2020-11-10 20:31:15 +01:00
Sandro Sobczyński f3a1bcb47d added adpcm support 2020-11-10 19:31:30 +01:00
Sandro Sobczyński ac7a04b669 Merge branch 'feature/audio-adpcm' 2020-11-10 12:31:45 +01:00
Sandro Sobczyński a3a6150ecb adpcm support 2020-11-10 12:31:31 +01:00
Sandro Sobczyński 3b5fb1b670 fixing rendering issue on real PS2 2020-11-08 21:50:06 +01:00
Sandro Sobczyński 3dc304b829 wip audio #1 2020-11-08 10:06:41 +01:00
Sandro Sobczyński b11df0262e camera refactor 2020-11-05 14:53:42 +01:00
Sandro Sobczyński eba254f13b removed unitcircle pos from camera base 2020-11-05 14:41:08 +01:00
Sandro Sobczyński 3fdbda4a4a added comments to draw methods 2020-11-04 22:55:55 +01:00
Sandro Sobczyński 1868b714bc increased floors count, added gaps 2020-11-04 22:47:03 +01:00
Sandro Sobczyński bfd75003a4 fixed naming convention 2020-11-04 22:46:47 +01:00
Sandro Sobczyński 1757ef67dc moved floors audio logic from audio class 2020-11-04 22:33:16 +01:00
Sandro Sobczyński efe34c677d fixed backface culling (mesh rotation) 2020-11-04 22:02:09 +01:00
Sandro Sobczyński d2013d4467 reversed faces order in dff loader 2020-11-04 22:00:36 +01:00
Sandro Sobczyński b48fa16274 added vector rotate 2020-11-04 22:00:20 +01:00
Sandro Sobczyński 1f11c9f8e5 added description to shouldBeX in mesh 2020-11-04 16:18:40 +01:00
Sandro Sobczyński ef16f1dbe2 added enable/disable vsync 2020-11-04 16:03:53 +01:00
Sandro Sobczyński aa6b2d314b optimized draw data calculations using VU0 2020-11-04 16:03:30 +01:00
Sandro Sobczyński 4d53c6c5fe Merge branch 'static-game-try-1' 2020-11-04 13:21:08 +01:00
Sandro Sobczyński 02560f2d6f fixed frustum culling, static game class 2020-11-04 13:20:58 +01:00
Sandro Sobczyński 5399b1744f static game #1 2020-11-03 21:49:16 +01:00
Sandro Sobczyński 52518540f3 doc fixes, added irx load error 2020-11-03 21:48:59 +01:00
Sandro Sobczyński 9e3ed74b45 fixed md2 loading, fixed typo 2020-11-03 20:10:09 +01:00
110 changed files with 4995 additions and 2534 deletions
-7
View File
@@ -1,12 +1,5 @@
.vscode/ .vscode/
*.[Bb][Mm][Pp]
*.[Oo][Bb][Jj]
*.[Ww][Aa][Vv]
*.[Dd][Ff][Ff]
*.[Ii][Rr][Xx]
*.[Mm][Dd]2
# --- # ---
# Prerequisites # Prerequisites
+101
View File
@@ -0,0 +1,101 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.29.1] - 2020-12-27
### Added
- Created libpacket2 in PS2SDK
- Dolphin sample
- 2D support (Sprite class)
- Alpha blending (transparency)
- PNG support
- ADPCM support in audio class
- AudioFinish event in audio class
- BoundingBox class
- A lot of useful funcs in Matrix class
- Mock of file service
- Array mode to draw() (highly optimized for small meshes)
- VCLPP - Usage of VU1 Preprocessor
### Changed
- Project setup (makefile mostly)
- Readme
- Switched into libpacket2 in `vifsender` and `gifsender`
- Timer class refactor
- Engine base refactor
- MeshTexture into Texture
- Refactored floors sample
- Refactored Audio class
- Fixed Path 3 lighting
- Refactored, optimized math classes (vector, matrix..)
- Cleanup in camera base
- Refactored Path 3 and Path 1 rendering
- Synchronization functions (`renderer->waitForRender()`)
- BMP class refactor
- Dff Loader refactor
- Optimized rendering data preparation
### Removed
- Ari sample
- VU1 class
## [1.1.0] - 2020-11-03
### Added
- A lot of useful functions to Mesh class
- MeshFrame class
- MeshMaterial class
- MeshTexture class
- TextureLink struct
- Texture wrapping settings
- TextureRepository class
- PRINT_ERR()
- Ari sample
### Changed
- Project setup (gitignore etc.)
- Readme
- DFF loader refactor
- OBJ loader refactor
- MD2 loader refactor
- 3D data classes refactor (one interface for all)
- Rendering refactor
### Removed
- MeshSpec class
- Texture class
- Md2Model class
- ObjModel class
- DffModel class
## [1.0.0] - 2020-10-28
### Added
- Project setup (gitignore etc.)
- License
- Readme
- BMP support
- DFF support
- MD2 support
- OBJ support
- Animation support
- Engine base
- AudioListener class
- Rendering base
- Path 1 renderer (VU1)
- Path 3 renderer (GIF)
- Math classes (matrix, vector, plane..)
- Audio support (bg song only)
- Camera base
- Base lighting support (bugged) for Path 3
- Pad support
- EE Timer
- Math class
- String class
- Mesh class with AABB
- Makefile
- Primitive floors sample
[1.29.1]: https://github.com/h4570/tyra/compare/1.1.0...v1.29.1-alpha
[1.1.0]: https://github.com/h4570/tyra/compare/1.0.0...1.1.0
[1.0.0]: https://github.com/h4570/tyra/compare/1.0.0
+76 -73
View File
@@ -1,23 +1,27 @@
[![Contributors][contributors-shield]][contributors-url] [![Contributors][contributors-shield]][contributors-url]
[![MIT License][license-shield]][license-url] [![MIT License][license-shield]][license-url]
[![Discord](https://img.shields.io/badge/discord-Tyra-brightgreen?logo=discord)](https://discord.gg/NhhTmg3Gm5)
[![Discord](https://img.shields.io/badge/discord-PS2--Scene-brightgreen?logo=discord)](https://discord.gg/7dCr6ThSN5)
<br /> <br />
<p align="center"> <p align="center">
<a href="https://github.com/ps2-tyra/tyra"> <a href="https://github.com/h4570/tyra">
<img src="http://allvectorlogo.com/img/2016/05/ps2-logo.png" alt="Logo" width="230" height="125"> <img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/github-splash.png" alt="Logo" width="100%" height="auto">
</a> </a>
<h3 align="center">Tyra alpha 1.1.0</h3> <h3 align="center">Tyra - alpha 1.29.1</h3>
<p align="center"> <p align="center">
First open source renderer and game engine for PS2 (PlayStation 2™). Open source game engine for PlayStation 2™
<br /> <br />
<a href="https://www.youtube.com/"><strong>View Demo (soon) »</strong></a> <a href="https://github.com/h4570/tyra/tree/master/src/samples/dolphin"><strong>Dolphin sample »</strong></a>
&nbsp;
<a href="https://github.com/h4570/tyra/tree/master/src/samples/floors"><strong>Floors sample »</strong></a>
<br /> <br />
<br /> <br />
<a href="https://github.com/ps2-tyra/tyra/issues">Report Bug</a> <a href="https://github.com/h4570/tyra/issues">Report Bug</a>
· ·
<a href="https://github.com/ps2-tyra/tyra/issues">Request Feature</a> <a href="https://github.com/h4570/tyra/issues">Request Feature</a>
</p> </p>
</p> </p>
@@ -26,97 +30,84 @@
* [About the Project](#about-the-project) * [About the Project](#about-the-project)
* [Samples](#samples) * [Samples](#samples)
* [About project](#about-project) * [About project](#about-project)
* [Acronyms](#acronyms)
* [Tyra features](#tyra-features) * [Tyra features](#tyra-features)
* [Built With](#built-with) * [Branches](#branches)
* [Getting Started](#getting-started) * [Getting Started](#getting-started)
* [Prerequisites](#prerequisites)
* [Installation](#installation) * [Installation](#installation)
* [Prerequisites](#prerequisites)
* [Roadmap](#roadmap) * [Roadmap](#roadmap)
* [Tyra team](#tyra-team)
* [Contributing](#contributing) * [Contributing](#contributing)
* [License](#license) * [License](#license)
* [Contact](#contact) * [Built With](#built-with)
* [Acronyms](#acronyms)
* [Thanks](#thanks) * [Thanks](#thanks)
## About The Project ## About The Project
<img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/1.1.0/tyra.gif" alt="sample" width="600" height="auto"> <img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/1.29.1/tyra.gif" alt="sample" width="600" height="auto">
### Contributors wanted [![Discord](https://img.shields.io/badge/discord-Tyra-brightgreen?logo=discord)](https://discord.gg/NhhTmg3Gm5)
We will be grateful for any help. If you dont know PS2.. don't worry, we are open to explain how things work.
### Samples ### Samples
* [Floors](https://github.com/ps2-tyra/tyra/tree/master/src/samples/floors) * [Dolphin](https://github.com/h4570/tyra/tree/master/src/samples/dolphin)
* [Ari (WIP)](https://github.com/ps2-tyra/tyra/tree/master/src/samples/ari) * [Floors](https://github.com/h4570/tyra/tree/master/src/samples/floors)
### Contributors wanted
#### I will be grateful for any help, Discord: Sandro#3402
### About project ### About project
Goal of Tyra project is to provide simple API for PS2 (PlayStation 2™) game creation. So you can just run PS2 emulator, grab your .obj file, and put it into live in a seconds. Project is on early stage, so a lot of stuff is changing from release to release. Goal of Tyra project is to provide simple API for PS2 game creation, so you can just run PS2 emulator, grab .obj file, and put it into live in a seconds. Project is on alpha stage, so keep in mind that there are many things to be done and to fix.
YouTube tutorials soon! YouTube tutorials soon!
**Why PS2 game dev is so different?** Raw PS2 development can be a big challenge. PS2 it's pretty low-level and there are a lot of stuff that you must do from scratch. **Why Tyra is needed?** Raw PS2 development can be a big challenge. PS2 it's pretty low-level and there are a lot of stuff that you must do from scratch.
Tyra takes care for you, and rendering, coprocessors communication and many more low-level stuff is already done. Tyra takes care for you, and rendering, coprocessors communication, synchronization and many more low-level stuff is already done.
### Acronyms
* EE (Emotion Engine) - whole set of processors and subsystems that make up the PlayStation 2
* GS (Graphic synthesizer) - configurable rasterizer and texture mapper. Has only 2MB~ memory for textures, but for the opposite have very high transfer rate, so you can switch textures in the blink
* VU0 - programmable (ASM) vector processor that is accessed by inline assembly code injected into C program.
* VU1 - programmable (ASM) vector processor, which is similar to vertex shader. Accessed via DMA.
* IOP - I/O processor which enables access to peripheral devices, such the game controller
### Tyra features ### Tyra features
* VU1 rendering (PATH 1), double-buffered * 3D support - VU1 "Path 1 rendering"
* GIF rendering (PATH 3), double-buffered * 2D support - PNG & BMP
* Frustum culling, backface culling * Frustum culling, backface culling
* OpenGL adaptions: Perspective projection, lookAt camera * OpenGL adaptions: Perspective projection, lookAt camera
* Texture support (.bmp loader) * Texture support - .bmp and png
* Mesh loaders: ".obj", ".dff" (RenderWare, GTA:SA) and ".md2" (Quake II) * Mesh loaders: ".obj", ".dff" (RenderWare, GTA:SA) and ".md2" (Quake II)
* Threading support * Threading support
* Lighting support (now PATH3 only) * Animation support for obj and md2
* Animation support * Audio support - .wav and .adpcm
* Audio support
* Pad support * Pad support
* TODO: physics, ADPCM and many more!
### Built With ### Branches
* Master - monthly releases - tested on PS2 & PCSX2.
* [PS2SDK](https://github.com/ps2dev/ps2sdk) * Develop - daily builds - can be unstable.
## Getting Started ## Getting Started
To get a local copy up and running follow these simple steps. ### Installation [![Discord](https://img.shields.io/badge/discord-Tyra-brightgreen?logo=discord)](https://discord.gg/NhhTmg3Gm5)
YouTube tutorials soon! In our Discord channel, there is detailed tutorial which will help you with setting up the all environment - starting from installing dependencies and ending on emulator setup or intellisense.
### Prerequisites ### Prerequisites
This is an example of how to list things you need to use the software and how to install them. This is an example of how to list things you need to use the software.
* PS2 DEV environment - [PS2DEV](https://github.com/ps2dev/ps2dev) * PS2 DEV environment - [PS2DEV](https://github.com/ps2dev/ps2dev)
* At least #1a4587d PS2SDK - [PS2SDK](https://github.com/ps2dev/ps2sdk) * At least #674b6f4 PS2SDK (01.12.2020) - [PS2SDK](https://github.com/ps2dev/ps2sdk)
* PS2 Emulator. For example [PCSX2](https://pcsx2.net/) * PS2 Emulator. For example [PCSX2](https://pcsx2.net/)
### Installation
1. Clone the repo
```sh
git clone https://github.com/ps2-tyra/tyra.git
```
2. Get into src folder and compile it!
```sh
make
```
## Extra info ## Extra info
* Textures can be saved using GIMP. Just replace red with green color, and when exporting select .bmp, 24bit: RGB888, without saving information about colors * BMP loader needs some polishing so be sure that you exporting BMP with 24bit: RGB888 and without information about colors.
* If you want to run .elf in PCSX2, be sure that you have version >=1.6 and **Host access** enabled in PCSX2 configuration file. * If you want to run .elf in PCSX2, be sure that you have version >=1.6 and **Host access** enabled in PCSX2 configuration file.
* If you want to use your own .obj file, please check "triangulate faces" in blender. PS2 is supporting only trinagle primitive type. * If you want to use your own .obj file, please check "triangulate faces" in blender. PS2 is supporting only triangle primitive type.
## Roadmap ## Roadmap
### Roadmap moved to github kanban: ### Roadmap for next master release:
[https://github.com/ps2-tyra/tyra/projects/1](https://github.com/ps2-tyra/tyra/projects/1) [January 2021 Roadmap](https://github.com/h4570/tyra/projects/4)
## Tyra team
See the [open issues](https://github.com/ps2-tyra/tyra/issues) for a list of proposed features (and known issues). Sandro Sobczyński - sandro.sobczynski@gmail.com
[![LinkedIn][linkedin-shield]](https://linkedin.com/in/sandro-sobczyński-28820b15a)
Michał Mostowik - mostek3pl@gmail.com
[![LinkedIn][linkedin-shield]](https://www.linkedin.com/in/notfoxar)
See the [open issues](https://github.com/h4570/tyra/issues) for a list of proposed features (and known issues).
## Contributing ## Contributing
@@ -132,26 +123,38 @@ Contributions are what make the open source community such an amazing place to b
Distributed under the Apache License 2.0 License. See `LICENSE` for more information. Distributed under the Apache License 2.0 License. See `LICENSE` for more information.
## Contact ## Built With
Sandro Sobczyński - sandro.sobczynski@gmail.com * [PS2SDK](https://github.com/ps2dev/ps2sdk)
[![LinkedIn][linkedin-shield]][linkedin-url]
### Acronyms
* EE (Emotion Engine) - whole set of processors and subsystems that make up the PlayStation 2
* GS (Graphic synthesizer) - configurable rasterizer and texture mapper. Has only 2MB~ memory for textures, but for the opposite have very high transfer rate, so you can switch textures in the blink
* VU0 - programmable (ASM) vector processor that is accessed by inline assembly code injected into C program.
* VU1 - programmable (ASM) vector processor, which is similar to vertex shader. Accessed via DMA.
* IOP - I/O processor which enables access to peripheral devices, such the game controller
## Thanks ## Thanks
Without these guys, everything would be harder: Without these guys, everything would be harder:
* Dr Henry Fortuna - Abertay University (code sources) * Dr Henry Fortuna - for code sources
* Lukasz D.K. (huge archive of PS2 stuff) * Rick Gaiser - for help and new GCC!
* Guilherme Lampert - PlayStation London (code sources) * Lukasz D.K. - for huge archive of PS2 stuff-
* Jesper Svennevid, Daniel Collin - Microcode (openvcl, code samples) * Guilherme Lampert - for code sources
* Whole PS2SDK/PS2Scene team * Jesper Svennevid, Daniel Collin - for openvcl's code samples
* Whole PS2DEV team
* Manieq - for nice splash screens!
* And so many other guys. Thanks! * And so many other guys. Thanks!
Project Link: [https://github.com/ps2-tyra/tyra](https://github.com/ps2-tyra/tyra) Project Link: [https://github.com/h4570/tyra](https://github.com/h4570/tyra)
<br />
<a href="https://github.com/h4570/tyra">
<img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/github-splash2.png" alt="Logo" width="100%" height="auto">
</a>
[contributors-shield]: https://img.shields.io/github/contributors/ps2-tyra/tyra.svg?style=flat-square [contributors-shield]: https://img.shields.io/github/contributors/h4570/tyra.svg?style=flat-square
[contributors-url]: https://github.com/ps2-tyra/tyra/graphs/contributors [contributors-url]: https://github.com/h4570/tyra/graphs/contributors
[linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=flat-square&logo=linkedin&colorB=555 [linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=flat-square&logo=linkedin&colorB=555
[linkedin-url]: https://linkedin.com/in/sandro-sobczyński-28820b15a/ [license-shield]: https://img.shields.io/github/license/h4570/tyra.svg?style=flat-square
[license-shield]: https://img.shields.io/github/license/ps2-tyra/tyra.svg?style=flat-square [license-url]: https://github.com/h4570/tyra/blob/master/LICENSE
[license-url]: https://github.com/ps2-tyra/tyra/blob/master/LICENSE
+51
View File
@@ -0,0 +1,51 @@
TYRA_DIR = ./
EE_OBJS = \
models/math/matrix.o \
models/math/plane.o \
models/math/point.o \
models/math/vector3.o \
models/mesh_frame.o \
models/bounding_box.o \
models/mesh_material.o \
models/mesh.o \
models/sprite.o \
models/texture.o \
modules/audio.o \
modules/camera_base.o \
modules/file_service.o \
modules/gif_sender.o \
modules/light.o \
modules/pad.o \
modules/renderer.o \
modules/texture_repository.o \
modules/timer.o \
modules/vif_sender.o \
utils/math.o \
utils/string.o \
loaders/bmp_loader.o \
loaders/dff_loader.o \
loaders/md2_loader.o \
loaders/obj_loader.o \
loaders/png_loader.o \
vu1_progs/draw3D.o \
engine.o
all: $(EE_OBJS)
ar rcs $(LIB_NAME) $(EE_OBJS)
rm -f $(EE_OBJS)
#%.vcl: %.vclpp
# $(EE_VCLPP) $< $@
#%.vsm: %.vcl
# $(EE_VCL) $< >> $@
%.o: %.vsm
$(EE_DVP) $< -o $@
clean:
rm -f $(EE_OBJS)
rm -f $(LIB_NAME)
include Makefile.pref
+12
View File
@@ -0,0 +1,12 @@
EE_LIBS := $(EE_LIBS) -ldraw -lgraph -lmath3d -lpacket -ldma -lpacket2 -lpad -laudsrv -lc -lstdc++ -lpng -lz
EE_INCS := -I$(TYRA_DIR)/include -I$(PS2SDK)/ports/include $(EE_INCS)
EE_LDFLAGS := -L$(PS2SDK)/ports/lib -L$(TYRA_DIR) $(EE_LDFLAGS)
EE_CFLAGS := -DHAVE_LIBPNG -DHAVE_ZLIB $(EE_CFLAGS)
EE_CXXFLAGS := -DHAVE_LIBPNG -DHAVE_ZLIB $(EE_CXXFLAGS)
EE_DVP = dvp-as
EE_VCL = vcl
EE_VCLPP = vclpp
LIB_NAME = libtyra.a
include $(PS2SDK)/samples/Makefile.pref
include $(PS2SDK)/samples/Makefile.eeglobal
+24 -28
View File
@@ -15,28 +15,22 @@
#include <sifrpc.h> #include <sifrpc.h>
#include <time.h> #include <time.h>
#include <cstdlib> #include <cstdlib>
#include "include/modules/vu1.hpp"
#include "include/utils/debug.hpp" #include "include/utils/debug.hpp"
// VU1 micro program
extern u32 VU1Draw3D_CodeStart __attribute__((section(".vudata")));
extern u32 VU1Draw3D_CodeEnd __attribute__((section(".vudata")));
//
// ---- // ----
// Constructors/Destructors // Constructors/Destructors
// ---- // ----
Engine::Engine() Engine::Engine()
{ {
SifInitRpc(0); setDefaultScreen();
srand(time(NULL)); firePS2();
VU1::uploadProgram(0, &VU1Draw3D_CodeStart, &VU1Draw3D_CodeEnd); }
audio.startThread();
isInitialized = 0; Engine::Engine(const ScreenSettings &t_screen)
isScreenInitialized = 0; {
mainThreadId = GetThreadId(); screen = t_screen;
firePS2();
} }
Engine::~Engine() {} Engine::~Engine() {}
@@ -45,29 +39,20 @@ Engine::~Engine() {}
// Methods // Methods
// ---- // ----
void Engine::setScreen(ScreenSettings &t_settings)
{
screen = t_settings;
isScreenInitialized = true;
}
void Engine::setDefaultScreen() void Engine::setDefaultScreen()
{ {
screen.projectionScale = 4096.0F;
screen.nearPlaneDist = 2.0F; screen.nearPlaneDist = 2.0F;
screen.farPlaneDist = 2000.0F; screen.farPlaneDist = 2000.0F;
screen.fov = 60.0F; screen.fov = 60.0F;
screen.aspectRatio = 4.0F / 3.0F;
screen.width = 640.0F; screen.width = 640.0F;
screen.height = 480.0F; screen.height = 480.0F;
isScreenInitialized = true; screen.aspectRatio = screen.width / screen.height;
screen.projectionScale = 4096.0F; // PS2 have 4k drawing area
} }
void Engine::init(Game *t_game, u32 t_gifPacketSize) void Engine::init(Game *t_game, u32 t_gifPacketSize)
{ {
if (!isScreenInitialized) if (isInitialized)
PRINT_ERR("Cant init because screen was not set!");
else if (isInitialized)
PRINT_ERR("Already initialized!"); PRINT_ERR("Already initialized!");
else else
{ {
@@ -88,6 +73,17 @@ void Engine::wakeup(s32 t_alarmId, u16 t_time, void *t_common)
ExitHandler(); ExitHandler();
} }
void Engine::firePS2()
{
SifInitRpc(0);
srand(time(NULL));
// fileService.startThread();
// audio.startThread(&fileService);
audio.startThread(NULL);
isInitialized = 0;
mainThreadId = GetThreadId();
}
void Engine::gameLoop() void Engine::gameLoop()
{ {
for (;;) for (;;)
@@ -99,10 +95,10 @@ void Engine::gameLoop()
fps = timer.getFPS(); fps = timer.getFPS();
fpsDelayer = 0; fpsDelayer = 0;
} }
timer.primeTimer(); timer.prime();
renderer->endFrame(fps); renderer->endFrame(fps);
/** -6~ FPS */ /** -6~ FPS */
SetAlarm(fps > 49.0F ? 24 : 48, &Engine::wakeup, &mainThreadId); SetAlarm(150, &Engine::wakeup, &mainThreadId);
SleepThread(); SleepThread();
} }
} }
+5 -4
View File
@@ -19,33 +19,34 @@
#include "modules/timer.hpp" #include "modules/timer.hpp"
#include "modules/pad.hpp" #include "modules/pad.hpp"
#include "modules/audio.hpp" #include "modules/audio.hpp"
#include "modules/file_service.hpp"
class Engine class Engine
{ {
public: public:
Engine(const ScreenSettings &screen);
Engine(); Engine();
~Engine(); ~Engine();
void init(Game *t_game, u32 t_gifPacketSize); void init(Game *t_game, u32 t_gifPacketSize);
void setDefaultScreen(); void setDefaultScreen();
void setScreen(ScreenSettings &t_settings);
Renderer *renderer; Renderer *renderer;
// FileService fileService;
Audio audio; Audio audio;
ScreenSettings screen; ScreenSettings screen;
Pad pad; Pad pad;
float fps; float fps;
private: private:
void firePS2();
u8 fpsDelayer; u8 fpsDelayer;
Timer timer; Timer timer;
u8 isInitialized, isScreenInitialized; u8 isInitialized;
void gameLoop(); void gameLoop();
Game *game; Game *game;
s32 mainThreadId; s32 mainThreadId;
static void wakeup(s32 t_alarmId, u16 t_time, void *t_common); static void wakeup(s32 t_alarmId, u16 t_time, void *t_common);
// ThreadManager threadManager;
}; };
#endif #endif
+2 -2
View File
@@ -13,7 +13,7 @@
#include <stdio.h> #include <stdio.h>
#include <tamtypes.h> #include <tamtypes.h>
#include "../models/mesh_texture.hpp" #include "../models/texture.hpp"
/** Class responsible for loading images in bmp format */ /** Class responsible for loading images in bmp format */
class BmpLoader class BmpLoader
@@ -23,7 +23,7 @@ public:
BmpLoader(); BmpLoader();
~BmpLoader(); ~BmpLoader();
void load(MeshTexture &o_texture, char *t_subfolder, char *t_name, char *t_extension); void load(Texture &o_texture, char *t_subfolder, char *t_name, char *t_extension);
}; };
#endif #endif
@@ -22,6 +22,7 @@ public:
DffLoader(); DffLoader();
~DffLoader(); ~DffLoader();
// void im_not_used_anywhere(MeshFrame *o_result, char *t_fileName, float t_scale, u8 t_invertT);
void load(MeshFrame *o_result, char *t_fileName, float t_scale, u8 t_invertT); void load(MeshFrame *o_result, char *t_fileName, float t_scale, u8 t_invertT);
void serialize(MeshFrame *o_result, u8 t_invertT, u8 *t_data, float t_scale); void serialize(MeshFrame *o_result, u8 t_invertT, u8 *t_data, float t_scale);
+29
View File
@@ -0,0 +1,29 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#ifndef _TYRA_PNG_LOADER_
#define _TYRA_BMP_LOADER_
#include <stdio.h>
#include <tamtypes.h>
#include "../models/texture.hpp"
/** Class responsible for loading images in bmp format */
class PngLoader
{
public:
PngLoader();
~PngLoader();
void load(Texture &o_texture, char *t_subfolder, char *t_name, char *t_extension);
};
#endif
@@ -17,6 +17,7 @@ class AudioListener
public: public:
virtual ~AudioListener(){}; virtual ~AudioListener(){};
virtual void onAudioTick() = 0; virtual void onAudioTick() = 0;
virtual void onAudioFinish() = 0;
private: private:
}; };
@@ -0,0 +1,94 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Michał Mostowik <mostek3pl@gmail.com>
*/
#ifndef _TYRA_BOUNDING_BOX_
#define _TYRA_BOUNDING_BOX_
#include <stddef.h>
#include <tamtypes.h>
#include "math/point.hpp"
#include "math/vector3.hpp"
/**
* Struct containing face data used in
* bounding box class.
*/
struct BoundingBoxFace
{
BoundingBoxFace(){
};
BoundingBoxFace(const Vector3 &t_minCorner, const Vector3 &t_maxCorner, float t_axisPos)
{
minCorner = t_minCorner;
maxCorner = t_maxCorner;
axisPosition = t_axisPos;
}
/** Position of the face on it's respective axis. */
float axisPosition;
/** Corner of the face with lower coordinates */
Vector3 minCorner;
/** Corner of the face with higher coordinates */
Vector3 maxCorner;
};
/**
* Class containing bounding box data
* which can be used for collision detection.
*/
class BoundingBox
{
public:
BoundingBox(Vector3 *t_vertices);
~BoundingBox();
const float &getHeight() { return _height; };
const float &getDepth() { return _depth; };
const float &getWidth() { return _width; };
/** @returns the vector directly in middle of the bounding box. */
const Vector3 &getCenter() { return _centerVector; };
/** @returns the front face (further on z-axis) */
const BoundingBoxFace &getFrontFace() { return _frontFace; };
/** @returns the back face (nearer on z-axis) */
const BoundingBoxFace &getBackFace() { return _backFace; };
/** @returns the left face (further on x-axis) */
const BoundingBoxFace &getLeftFace() { return _leftFace; };
/** @returns the right face (nearer on x-axis) */
const BoundingBoxFace &getRightFace() { return _rightFace; };
/** @returns the top face (further on y-axis) */
const BoundingBoxFace &getTopFace() { return _topFace; };
/** @returns the bottom face (nearer on y-axis) */
const BoundingBoxFace &getBottomFace() { return _bottomFace; };
/**
* @returns bounding box raw vertices array.
* Total length: 8
*/
const Vector3 &getVertex(const u8 &i) { return _vertices[i]; };
/** @returns single vertex from raw vertices array.*/
Vector3 *getVertices() { return _vertices; };
private:
Vector3 _vertices[8];
float _height, _depth, _width;
Vector3 _centerVector;
/** Front face (further on z-axis) */
BoundingBoxFace _frontFace;
/** Back face (nearer on z-axis) */
BoundingBoxFace _backFace;
/** Left face (nearer on x-axis) */
BoundingBoxFace _leftFace;
/** Right face (further on x-axis) */
BoundingBoxFace _rightFace;
/** Top face (further on y-axis) */
BoundingBoxFace _topFace;
/** Bottom face (nearer on y-axis) */
BoundingBoxFace _bottomFace;
};
#endif
+1 -1
View File
@@ -17,7 +17,7 @@
struct LightBulb struct LightBulb
{ {
Vector3 position; Vector3 position;
u16 intensity; u8 intensity;
}; };
#endif #endif
+159 -14
View File
@@ -13,29 +13,174 @@
#include "vector3.hpp" #include "vector3.hpp"
#include "../screen_settings.hpp" #include "../screen_settings.hpp"
#include <string.h>
/** https://en.wikipedia.org/wiki/Matrix_(mathematics) */ /** 4x4 Matrix class. */
class Matrix class Matrix
{ {
public: public:
float data[16]; float data[16] __attribute__((aligned(64)));
Matrix(float m11, float m12, float m13, float m14, // ----
float m21, float m22, float m23, float m24, // Constructors/Destructors
float m31, float m32, float m33, float m34, // ----
float m41, float m42, float m43, float m44);
Matrix(const Matrix &v); /** Create empty matrix. */
Matrix operator*(Matrix &v);
Matrix(); Matrix();
~Matrix();
void lookAt(Vector3 &t_up, Vector3 &t_position, Vector3 &t_target); /**
* Create identity/empty matrix.
* @param t_do_identity Identity matrix if true, random matrix values otherwise
*/
Matrix(const u8 &t_do_identity)
{
if (t_do_identity)
identity();
}
/** Init matrix with given values. */
Matrix(const float &m11, const float &m12, const float &m13, const float &m14,
const float &m21, const float &m22, const float &m23, const float &m24,
const float &m31, const float &m32, const float &m33, const float &m34,
const float &m41, const float &m42, const float &m43, const float &m44);
/** Init matrix with other matrix values. */
Matrix(const Matrix &v) { memcpy(data, v.data, 16 * sizeof(float)); }
// ----
// Operators
// ----
Vector3 operator*(const Vector3 &v) const;
Matrix operator*(const Matrix &v) const
{
Matrix result;
cross(result.data, this->data, v.data);
return result;
}
inline void operator*=(const Matrix &v) { cross(this->data, this->data, v.data); }
float &operator[](const u8 &t_index) { return data[t_index]; }
// ----
// Functions
// ----
/**
* 1 0 0 0
* 0 1 0 0
* 0 0 1 0
* 0 0 0 1
*/
void identity(); void identity();
void makeZRotation(float t_radians);
void translate(float t_x, float t_y, float t_z); /**
void setPerspective(ScreenSettings &screen); * 1 0 0 0
void print(); * 0 1 0 0
* 0 0 1 0
* 0 0 0 1
*/
inline void unit() { identity(); };
/** Translate matrix. */
inline void translate(const Vector3 &t_val)
{
Matrix temp = Matrix(true);
temp.translation(t_val);
cross(this->data, temp.data, this->data);
}
/** Rotate matrix. */
inline void rotate(const Vector3 &t_val)
{
Matrix temp = Matrix(true);
temp.rotationZ(t_val.z);
cross(this->data, temp.data, this->data);
temp.identity();
temp.rotationY(t_val.y);
cross(this->data, temp.data, this->data);
temp.identity();
temp.rotationX(t_val.x);
cross(this->data, temp.data, this->data);
}
/** Rotate matrix by X. */
inline void rotateX(const float &t_radians)
{
Matrix temp = Matrix(true);
temp.rotationX(t_radians);
cross(this->data, temp.data, this->data);
}
/** Rotate matrix by Y. */
inline void rotateY(const float &t_radians)
{
Matrix temp = Matrix(true);
temp.rotationY(t_radians);
cross(this->data, temp.data, this->data);
}
/** Rotate matrix by Z. */
inline void rotateZ(const float &t_radians)
{
Matrix temp = Matrix(true);
temp.rotationZ(t_radians);
cross(this->data, temp.data, this->data);
}
/** Rotate matrix by angle. */
void rotateByAngle(const float &t_angle, const Vector3 &t_axis)
{
Matrix temp;
temp.rotationByAngle(t_angle, t_axis);
cross(this->data, temp.data, this->data);
}
/** Scale matrix. */
void scale(const Vector3 &t_val)
{
Matrix temp = Matrix(true);
temp.setScale(t_val);
cross(this->data, temp.data, this->data);
}
/**
* Create perspective projection matrix.
*
* Complies with OpenGL standard (gluPerspective).
* @see https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml
* @param screen Screen settings
*/
void setPerspective(const ScreenSettings &screen);
/**
* Create a view matrix that transforms coordinates in
* such a way that the user looks at a target vector
* direction from a position vector.
*
* Complies with OpenGL standard (glLookAt).
* @see https://learnopengl.com/Getting-started/Camera
*/
void lookAt(const Vector3 &t_position, const Vector3 &t_target);
/** Print matrix (printf). */
const void print() const;
private:
void rotationX(const float &t_radians);
void rotationY(const float &t_radians);
void rotationZ(const float &t_radians);
void rotationByAngle(const float &t_angle, const Vector3 &t_axis);
void translation(const Vector3 &t_val);
void setScale(const Vector3 &t_val);
void setCamera(const float t_pos[4], const float t_vz[4], const float t_vy[4]);
void cross(float res[16], const float a[16], const float b[16]) const;
}; };
#endif #endif
+1 -1
View File
@@ -27,7 +27,7 @@ public:
void update(Vector3 &a, Vector3 &b, Vector3 &c); void update(Vector3 &a, Vector3 &b, Vector3 &c);
inline float distanceTo(Vector3 &t_vec) { return this->distance + this->normal.innerProduct(t_vec); } inline float distanceTo(Vector3 &t_vec) { return this->distance + this->normal.innerProduct(t_vec); }
void print(); const void print() const;
}; };
#endif #endif
+2 -1
View File
@@ -32,8 +32,9 @@ public:
~Point(); ~Point();
void set(const float &t_x, const float &t_y); void set(const float &t_x, const float &t_y);
void rotate(const float &t_angle, const float &t_x, const float &t_y);
void set(const Point &v); void set(const Point &v);
void print(); const void print() const;
}; };
#endif #endif
+83 -20
View File
@@ -12,6 +12,7 @@
#define _TYRA_VECTOR3_ #define _TYRA_VECTOR3_
#include <tamtypes.h> #include <tamtypes.h>
#include <stdio.h>
class Math; // Forward definition class Math; // Forward definition
@@ -20,6 +21,7 @@ class Vector3
{ {
public: public:
/** This trick will allow use to use vec.x and vex[0] */
union union
{ {
struct struct
@@ -31,30 +33,91 @@ public:
float xyz[3] __attribute__((__aligned__(16))); float xyz[3] __attribute__((__aligned__(16)));
}; };
Vector3(float t_x, float t_y, float t_z); // ----
Vector3(const Vector3 &v); // Constructors/Destructors
// ----
/** Create empty vector. */
Vector3(); Vector3();
~Vector3();
Vector3 operator+(Vector3 v); /** Create vector with given vector values. */
Vector3 operator-(const Vector3 &v); Vector3(const Vector3 &t_v) { set(t_v); }
Vector3 operator*(Vector3 &v);
Vector3 operator*(float t);
Vector3 operator/(float t);
Vector3 operator-(void);
static u8 shouldBeBackfaceCulled(const Vector3 *t_cameraPos, const Vector3 *v0, const Vector3 *v1, const Vector3 *v2); /** Create vector with given values. */
u8 collidesSquare(Vector3 &t_min, Vector3 &t_max); Vector3(const float &t_x, const float &t_y, const float &t_z) { set(t_x, t_y, t_z); }
u8 isOnSquare(Vector3 &t_min, Vector3 &t_max);
float length(); // ----
void normalize(); // Operators
void setByLerp(const Vector3 &v1, const Vector3 &v2, const float &t_interp, const float &t_scale); // ----
float innerProduct(Vector3 &v);
Vector3 operator+(const Vector3 &v) const;
Vector3 operator-(const Vector3 &v) const;
/** Also called "cross product" */
Vector3 operator*(const Vector3 &v) const;
Vector3 operator*(const float &t) const;
Vector3 operator/(const float &t) const;
Vector3 operator-(void) const { return Vector3(-x, -y, -z); }
void operator+=(const Vector3 &t);
void operator*=(const float &t);
// ----
// Functions
// ----
/** Set vector values via VU0. */
void set(const Vector3 &v); void set(const Vector3 &v);
void set(const float &x, const float &y, const float &z);
void copy(Vector3 &v); /** Set vector values. */
float distanceTo(Vector3 &v); void set(const float &t_x, const float &t_y, const float &t_z);
void print();
/** Also called dot3. */
float innerProduct(const Vector3 &v) const;
/** Get vector length */
float length() const;
/** Normalize vector. */
void normalize();
/** Returns distance between two vectors */
float distanceTo(const Vector3 &v) const;
/**
* Checks intersection with given box
* @param t_min Opposite min vertex (ex. near, left, down vertex of bounding box)
* @param t_max Opposite max vertex (ex. far, right, up vertex of bounding box)
*/
u8 collidesBox(const Vector3 &t_min, const Vector3 &t_max) const
{
return ((this->x <= t_max.x && this->x >= t_min.x) && (this->y < t_max.y && this->y >= t_min.y) && (this->z <= t_max.z && this->z >= t_min.z)) ? 1 : 0;
}
/**
* Checks if this vector is on given box (this->y >= box.y)
* @param t_min Opposite min vertex (ex. near, left, down vertex of bounding box)
* @param t_max Opposite max vertex (ex. far, right, up vertex of bounding box)
*/
u8 isOnBox(const Vector3 &t_min, const Vector3 &t_max) const
{
return ((this->x <= t_max.x && this->x >= t_min.x) && (this->y >= t_max.y) && (this->z <= t_max.z && this->z >= t_min.z)) ? 1 : 0;
}
/** Check if given triangle should be backface culled. */
static u8 shouldBeBackfaceCulled(const Vector3 *t_cameraPos, const Vector3 *t_v0, const Vector3 *t_v1, const Vector3 *t_v2);
/**
* Set by linear interpolation between two vertices (animation).
* @param t_v1 Before vertex
* @param t_v2 After vertex
* @param t_interp State of interpolation
* @param t_scale Scale
*/
void setByLerp(const Vector3 &t_v1, const Vector3 &t_v2, const float &t_interp, const float &t_scale);
const void print() const
{
printf("Vector3(%f, %f, %f)\n", x, y, z);
}
}; };
#endif #endif
+23 -9
View File
@@ -13,7 +13,7 @@
#include "math/vector3.hpp" #include "math/vector3.hpp"
#include "math/plane.hpp" #include "math/plane.hpp"
#include "./mesh_texture.hpp" #include "./texture.hpp"
#include "./mesh_frame.hpp" #include "./mesh_frame.hpp"
#include <tamtypes.h> #include <tamtypes.h>
#include <draw_types.h> #include <draw_types.h>
@@ -21,7 +21,10 @@
#include <draw_sampling.h> #include <draw_sampling.h>
#include "./anim_state.hpp" #include "./anim_state.hpp"
/** Class which have common types for all 3D objects */ /**
* Class which have contain 3D object data.
* External data can be loaded via loadXXX() methods.
*/
class Mesh class Mesh
{ {
@@ -31,7 +34,15 @@ public:
Vector3 position, rotation; Vector3 position, rotation;
float scale; float scale;
u8 shouldBeLighted, shouldBeBackfaceCulled, shouldBeFrustumCulled; u8 shouldBeLighted;
/**
* When true, invisible triangles of mesh materials are not drawn.
*/
u8 shouldBeBackfaceCulled;
/**
* When true, mesh materials are not drawn when they are outside of view frustum.
*/
u8 shouldBeFrustumCulled;
color_t color; color_t color;
clutbuffer_t clut; clutbuffer_t clut;
lod_t lod; lod_t lod;
@@ -51,7 +62,7 @@ public:
/** Returns material, which is a mesh "subgroup". */ /** Returns material, which is a mesh "subgroup". */
MeshMaterial &getMaterial(const u32 &i) const { return frames[0].getMaterial(i); }; MeshMaterial &getMaterial(const u32 &i) const { return frames[0].getMaterial(i); };
/** Auto count of frames. Static object (not animated) will have only 1 frame. */ /** Count of frames. Static object (not animated) will have only 1 frame. */
const u32 &getFramesCount() const { return framesCount; }; const u32 &getFramesCount() const { return framesCount; };
/** Count of vertices. */ /** Count of vertices. */
@@ -83,10 +94,13 @@ public:
* Returns bounding vertex of current frame. * Returns bounding vertex of current frame.
* @param i 0-7. Because, bounding box have 8 corners * @param i 0-7. Because, bounding box have 8 corners
*/ */
Vector3 &getCurrentBoundingBoxVertex(const u8 &i) { return frames[animState.currentFrame].getBoundingBoxVertex(i); }; const Vector3 &getCurrentBoundingBoxVertex(const u8 &i) { return frames[animState.currentFrame].getBoundingBoxVertex(i); };
/** Returns bounding box of current frame. Size: 8 */ /** @returns bounding box vertex array of current frame. Size: 8 */
Vector3 *getCurrentBoundingBox() const { return frames[animState.currentFrame].getBoundingBox(); }; const Vector3 *getCurrentBoundingBoxVertices() const { return frames[animState.currentFrame].getBoundingBoxVertices(); };
/** @returns bounding box object of current frame. */
const BoundingBox *getCurrentBoundingBox() const { return frames[animState.currentFrame].getBoundingBox(); };
// ---- // ----
// Setters // Setters
@@ -97,7 +111,7 @@ public:
// ---- // ----
/** /**
* Load mesh data from .obj files. Animation not supported. * Load mesh data from .obj files. Animation supported.
* Be aware that texture names will be grabbed from material name. * Be aware that texture names will be grabbed from material name.
* So no .mtl file is needed. Please check if material names in .obj file * So no .mtl file is needed. Please check if material names in .obj file
* are equal to texture file names. * are equal to texture file names.
@@ -113,7 +127,7 @@ public:
void loadObj(char *t_subfolder, char *t_objFile, const float &t_scale, const u32 &t_framesCount, const u8 &t_invertT); void loadObj(char *t_subfolder, char *t_objFile, const float &t_scale, const u32 &t_framesCount, const u8 &t_invertT);
/** /**
* Load mesh data from .obj file. Animation supported. * Load mesh data from .obj file. Animation not supported.
* Be aware that texture names will be grabbed from material name. * Be aware that texture names will be grabbed from material name.
* So no .mtl file is needed. Please check if material names in .obj file * So no .mtl file is needed. Please check if material names in .obj file
* are equal to texture file names. * are equal to texture file names.
+13 -9
View File
@@ -13,6 +13,7 @@
#include <stddef.h> #include <stddef.h>
#include <tamtypes.h> #include <tamtypes.h>
#include "bounding_box.hpp"
#include "math/point.hpp" #include "math/point.hpp"
#include "math/vector3.hpp" #include "math/vector3.hpp"
#include "./mesh_material.hpp" #include "./mesh_material.hpp"
@@ -76,16 +77,21 @@ public:
MeshMaterial *getMaterials() const { return materials; }; MeshMaterial *getMaterials() const { return materials; };
/** /**
* Returns bounding box (AABB). * @returns bounding box (AABB).
* Total length: 8 * Total length: 8
*/ */
Vector3 *getBoundingBox() { return boundingBox; }; Vector3 *getBoundingBoxVertices() { return boundingBoxObj->getVertices(); };
/** /**
* Returns bounding box (AABB) vertex. * @returns bounding box (AABB) vertex.
* Total length: 8 * Total length: 8
*/ */
Vector3 &getBoundingBoxVertex(const u8 &i) { return boundingBox[i]; }; const Vector3 &getBoundingBoxVertex(const u8 &i) { return boundingBoxObj->getVertex(i); };
/**
* @returns bounding box (AABB) object pointer.
*/
BoundingBox *getBoundingBox() { return boundingBoxObj; };
// ---- // ----
// Setters // Setters
@@ -139,7 +145,7 @@ public:
void calculateBoundingBoxes(); void calculateBoundingBoxes();
private: private:
Vector3 boundingBox[8]; BoundingBox *boundingBoxObj;
u8 _areSTsAllocated, u8 _areSTsAllocated,
_areVerticesAllocated, _areVerticesAllocated,
_areNormalsAllocated, _areNormalsAllocated,
@@ -147,10 +153,8 @@ private:
_isBoundingBoxCalculated; _isBoundingBoxCalculated;
u32 vertexCount, stsCount, normalsCount, materialsCount; u32 vertexCount, stsCount, normalsCount, materialsCount;
MeshMaterial *materials; MeshMaterial *materials;
Point *sts __attribute__((aligned(16))); Point __attribute__((aligned(16))) * sts;
Vector3 Vector3 __attribute__((aligned(16))) * vertices, *normals;
*vertices __attribute__((aligned(16))),
*normals __attribute__((aligned(16)));
}; };
#endif #endif
+13 -6
View File
@@ -12,10 +12,12 @@
#define _TYRA_MESH_MATERIAL_ #define _TYRA_MESH_MATERIAL_
#include <tamtypes.h> #include <tamtypes.h>
#include "bounding_box.hpp"
#include "./math/vector3.hpp" #include "./math/vector3.hpp"
#include "./math/plane.hpp" #include "./math/plane.hpp"
/** Class which contains draw instructions for part mesh of mesh. /**
* Class which contains draw instructions for part of mesh.
* Mesh can have many materials. * Mesh can have many materials.
* For example, car mesh can have three materials: * For example, car mesh can have three materials:
* body, tires and windows. * body, tires and windows.
@@ -61,16 +63,21 @@ public:
u32 *getNormalFaces() const { return normalFaces; }; u32 *getNormalFaces() const { return normalFaces; };
/** /**
* Returns bounding box (AABB). * @returns bounding box (AABB).
* Total length: 8 * Total length: 8
*/ */
Vector3 *getBoundingBox() { return boundingBox; }; Vector3 *getBoundingBoxVertices() { return boundingBoxObj->getVertices(); };
/** /**
* Returns bounding box (AABB) vertex. * @returns bounding box (AABB) vertex.
* Total length: 8 * Total length: 8
*/ */
Vector3 &getBoundingBoxVertex(const u8 &i) { return boundingBox[i]; }; const Vector3 &getBoundingBoxVertex(const u8 &i) { return boundingBoxObj->getVertex(i); };
/**
* @returns bounding box (AABB) object pointer.
*/
BoundingBox *getBoundingBox() { return boundingBoxObj; };
// ---- // ----
// Setters // Setters
@@ -118,7 +125,7 @@ public:
u8 isInFrustum(Plane *t_frustumPlanes, const Vector3 &position); u8 isInFrustum(Plane *t_frustumPlanes, const Vector3 &position);
private: private:
Vector3 boundingBox[8]; BoundingBox *boundingBoxObj;
u32 facesCount, id; u32 facesCount, id;
u32 *vertexFaces, *stFaces, *normalFaces; u32 *vertexFaces, *stFaces, *normalFaces;
u8 _isNameSet, _areFacesAllocated, _isBoundingBoxCalculated; u8 _isNameSet, _areFacesAllocated, _isBoundingBoxCalculated;
+12 -4
View File
@@ -22,10 +22,18 @@ struct RenderData
{ {
LightBulb *bulbs; LightBulb *bulbs;
u16 bulbsCount; u16 bulbsCount;
/** Camera (lookAt) */ /**
Matrix *worldView; * Camera matrix (glLookAt)
/** Perspective projection */ * OpenGL name: View
Matrix *perspective; * Sony name: World view
*/
Matrix *view;
/**
* Projection matrix (glPerspective)
* OpenGL name: Projection
* Sony name: View screen
*/
Matrix *projection;
Vector3 *cameraPosition; Vector3 *cameraPosition;
Plane *frustumPlanes; Plane *frustumPlanes;
prim_t *prim; prim_t *prim;
@@ -21,7 +21,6 @@ struct ScreenSettings
float aspectRatio; float aspectRatio;
float nearPlaneDist; float nearPlaneDist;
float farPlaneDist; float farPlaneDist;
/** change it to 4096.0F to check out frustum culling! 😎 */
float projectionScale; float projectionScale;
}; };
+80
View File
@@ -0,0 +1,80 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#ifndef _TYRA_SPRITE_
#define _TYRA_SPRITE_
#include <models/math/point.hpp>
#include <draw_types.h>
#include <draw_buffers.h>
enum SpriteMode
{
MODE_STRETCH,
MODE_REPEAT
};
/**
* Class which have contain 2D image data.
*/
class Sprite
{
public:
Sprite();
~Sprite();
Point position, size;
float scale;
color_t color;
clutbuffer_t clut;
// ----
// Getters
// ----
/** Auto generated unique Id. */
inline const u32 &getId() const { return id; };
/** Get sprite drawing mode. */
inline const SpriteMode &getMode() const { return mode; };
// ----
// Setters
// ----
/** Set sprite drawing mode. */
void setMode(const SpriteMode &t_val) { mode = t_val; }
// ----
// Other
// ----
/** Flip texture horizontally. */
inline void flipHorizontally(const u8 &t_set) { _flipH = t_set; };
/** Flip texture vertically. */
inline void flipVertically(const u8 &t_set) { _flipV = t_set; };
/** Check if texture is vertically flipped. */
inline const u8 &isFlippedVertically() const { return _flipV; };
/** Check if texture is horizontally flipped. */
inline const u8 &isFlippedHorizontally() const { return _flipH; };
private:
u32 id;
SpriteMode mode;
u8 _isSizeSet, _flipH, _flipV;
void setDefaultColor();
void setDefaultLODAndClut();
};
#endif
@@ -8,8 +8,8 @@
# Sandro Sobczyński <sandro.sobczynski@gmail.com> # Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/ */
#ifndef _TYRA_MESH_TEXTURE_ #ifndef _TYRA_TEXTURE_
#define _TYRA_MESH_TEXTURE_ #define _TYRA_TEXTURE_
#include <tamtypes.h> #include <tamtypes.h>
#include <draw_sampling.h> #include <draw_sampling.h>
@@ -17,18 +17,25 @@
#include "./texture_link.hpp" #include "./texture_link.hpp"
#include "../include/utils/debug.hpp" #include "../include/utils/debug.hpp"
#include <vector> #include <vector>
#include <gs_psm.h>
enum TextureType
{
TEX_TYPE_RGB = GS_PSM_24, // BMP
TEX_TYPE_RGBA = GS_PSM_32 // PNG
};
/** /**
* Class which contains texture data. * Class which contains texture data.
* Textures are paired with meshes via addUsage(), * Textures are paired with meshes/sprites via addLink() and
* removeUsage() functions which use meshId and materialId. * removeLink() functions which use meshId/spriteId and materialId (for mesh).
*/ */
class MeshTexture class Texture
{ {
public: public:
MeshTexture(); Texture();
~MeshTexture(); ~Texture();
// ---- // ----
// Getters // Getters
@@ -40,36 +47,38 @@ public:
* again texture in renderer, when last sent texture id * again texture in renderer, when last sent texture id
* by renderer will be equal to this id. * by renderer will be equal to this id.
*/ */
const u32 &getId() const { return id; }; inline const u32 getId() const { return id; };
const u8 &getWidth() const { return width; }; inline const u16 getWidth() const { return width; };
const u8 &getHeight() const { return height; }; inline const u16 getHeight() const { return height; };
u32 getTextureLinksCount() const { return static_cast<u32>(texLinks.size()); }; inline const TextureType getType() const { return _type; };
texwrap_t *getWrapSettings() { return &wrapSettings; }; inline u32 getTextureLinksCount() const { return static_cast<u32>(texLinks.size()); };
inline texwrap_t *getWrapSettings() { return &wrapSettings; };
/** /**
* Returns always width * width * 3. * Returns always width * width * 3/4.
* 3 because of RGB * 3 for RGB, 4 for RGBA.
*/ */
u32 getDataSize() const { return width * height * 3; }; inline u32 getDataSize() const { return _type == TEX_TYPE_RGB ? width * height * 3 : width * height * 4; };
/** /**
* Texture data, used by renderer. * Texture data, used by renderer.
* Array of size getDataSize(). * Array of size getDataSize().
*/ */
unsigned char *getData() const { return data; }; inline unsigned char *getData() const { return data; };
/** /**
* Get texture name. * Get texture name.
* For "textures/abc.bmp" result will be: "abc" * For "textures/abc.bmp" result will be: "abc"
*/ */
char *getName() const { return name; }; inline char *getName() const { return name; };
/** Array of texture links. Size of getTextureLinksCount() */ /** Array of texture links. Size of getTextureLinksCount() */
const std::vector<TextureLink> &getTextureLinks() const { return texLinks; }; inline const std::vector<TextureLink> &getTextureLinks() const { return texLinks; };
/** /**
* Returns index of link. * Returns index of link.
@@ -78,11 +87,17 @@ public:
const s32 getIndexOfLink(const u32 &t_meshId, const u32 &t_materialId) const const s32 getIndexOfLink(const u32 &t_meshId, const u32 &t_materialId) const
{ {
for (u32 i = 0; i < texLinks.size(); i++) for (u32 i = 0; i < texLinks.size(); i++)
if (texLinks[i].materialId == t_materialId && texLinks[i].meshId == t_meshId) if (texLinks[i].materialId == t_materialId && texLinks[i].meshOrSpriteId == t_meshId)
return i; return i;
return -1; return -1;
}; };
/**
* Returns index of link.
* -1 if not found.
*/
inline const s32 getIndexOfLink(const u32 &t_spriteId) const { return getIndexOfLink(t_spriteId, 0); };
// ---- // ----
// Setters // Setters
// ---- // ----
@@ -92,7 +107,7 @@ public:
* Do not call this method unless you know what you do. * Do not call this method unless you know what you do.
* Should be called by data loader. * Should be called by data loader.
*/ */
void setSize(const u8 &t_width, const u8 &t_height); void setSize(const u8 &t_width, const u8 &t_height, const TextureType &t_type);
/** /**
* Do not call this method unless you know what you do. * Do not call this method unless you know what you do.
@@ -101,8 +116,8 @@ public:
void setHeight(const u8 &t_val) { height = t_val; } void setHeight(const u8 &t_val) { height = t_val; }
/** /**
* Set texture name. * Do not call this method unless you know what you do.
* Should be the file name without extension * Should be called by data loader.
*/ */
void setData(const u32 &t_index, const unsigned char &t_val) { data[t_index] = t_val; } void setData(const u32 &t_index, const unsigned char &t_val) { data[t_index] = t_val; }
@@ -119,9 +134,12 @@ public:
// Other // Other
// ---- // ----
/** Assign texture to mesh and mesh material */ /** Assign texture to mesh and mesh material. */
void addLink(const u32 &t_meshId, const u32 &t_materialId); void addLink(const u32 &t_meshId, const u32 &t_materialId);
/** Assign texture to sprite. */
void addLink(const u32 &t_spriteId);
const u8 &isNameSet() const { return _isNameSet; }; const u8 &isNameSet() const { return _isNameSet; };
const u8 &isSizeSet() const { return _isSizeSet; }; const u8 &isSizeSet() const { return _isSizeSet; };
@@ -135,13 +153,31 @@ public:
return false; return false;
}; };
void removeLink(const u32 &t_index) { texLinks.erase(texLinks.begin() + t_index); } const u8 isLinkedWith(const u32 &t_spriteId) const
{
s32 index = getIndexOfLink(t_spriteId);
if (index != -1)
return true;
else
return false;
};
void removeLink(const u32 &t_meshId, const u32 &t_materialId) void removeLinkByIndex(const u32 &t_index) { texLinks.erase(texLinks.begin() + t_index); }
void removeLinkBySprite(const u32 &t_spriteId)
{
s32 index = getIndexOfLink(t_spriteId);
if (index != -1)
removeLinkByIndex(index);
else
PRINT_ERR("Cant remove link, because it was not found!");
}
void removeLinkByMesh(const u32 &t_meshId, const u32 &t_materialId)
{ {
s32 index = getIndexOfLink(t_meshId, t_materialId); s32 index = getIndexOfLink(t_meshId, t_materialId);
if (index != -1) if (index != -1)
removeLink(index); removeLinkByIndex(index);
else else
PRINT_ERR("Cant remove link, because it was not found!"); PRINT_ERR("Cant remove link, because it was not found!");
} }
@@ -150,9 +186,11 @@ private:
void setDefaultWrapSettings(); void setDefaultWrapSettings();
texwrap_t wrapSettings; texwrap_t wrapSettings;
char *name; char *name;
TextureType _type;
std::vector<TextureLink> texLinks; std::vector<TextureLink> texLinks;
u32 id; u32 id;
u8 width, height, _isNameSet, _isSizeSet; u16 width, height;
u8 _isNameSet, _isSizeSet;
unsigned char *data; unsigned char *data;
}; };
+4 -1
View File
@@ -15,7 +15,10 @@
struct TextureLink struct TextureLink
{ {
u32 meshId, materialId; /** Mesh id or sprite id */
u32 meshOrSpriteId;
/** Mesh material id or 0 if is sprite */
u32 materialId;
}; };
#endif #endif
+119 -29
View File
@@ -11,56 +11,146 @@
#ifndef _TYRA_AUDIO_ #ifndef _TYRA_AUDIO_
#define _TYRA_AUDIO_ #define _TYRA_AUDIO_
#include "../models/audio_listener.hpp"
#include "./file_service.hpp"
#include <tamtypes.h> #include <tamtypes.h>
#include <stdio.h> #include <stdio.h>
#include <audsrv.h> #include <audsrv.h>
#include <kernel.h> #include <kernel.h>
#include "../models/audio_listener.hpp" #include <vector>
#define STACK_SIZE 8 * 1024 struct AudioListenerRef
{
AudioListener *listener;
u32 id;
};
/** Class responsible for audio playing */ /**
* Class responsible for audio playing.
* There are two main features:
* - WAV song (background music)
* - ADPCM samples
*/
class Audio class Audio
{ {
public: public:
/** Constructor is called by the engine. */
Audio(); Audio();
~Audio(); ~Audio();
u8 isTrackDone; // Song
ee_sema_t sema;
int fillbufferSema;
void init(u32 t_listenersAmount); /**
void play(); * Load 24bit 22050Hz Stereo WAV.
void stop(); * Can be used multiple times for song switching.
void loadSong(char *t_filename); * @param t_path Example: "song.wav" or "folder/song.wav"
void unloadSong(); */
void setVolume(u8 t_volume); void loadSong(char *t_path);
void addListener(AudioListener *t_listener);
void startThread(); void playSong();
void stopSong();
/**
* Set song volume.
* @param t_vol Value 0-100
*/
void setSongVolume(const u8 &t_vol);
/**
* If you want to synchronize some actions with
* background song, add audio listener.
* @returns Listener id.
*/
u32 addSongListener(AudioListener *t_listener);
/** Remove song listener. */
void removeSongListener(const u32 &t_id);
const u8 &isSongPlaying() const { return songPlaying; }
const u8 &isSongLoaded() const { return songLoaded; }
const u8 &isSongInLoop() const { return songInLoop; }
u32 getSongListenersCount() const { return songListeners.size(); }
const u8 &getVolume() const { return volume; }
/**
* Set song loop/noloop.
* @param t_set false - noloop, true - loop
*/
void setSongLoop(const u8 &t_set) { songInLoop = t_set; }
// ADPCM
/**
* Load ADPCM sample. ADPCM sample is an output from
* "adpenc" tool, shipped with PS2SDK.
* @param t_path Example: "hit.adpcm" or "folder/jump.adpcm"
*/
audsrv_adpcm_t *loadADPCM(char *t_path);
/**
* Play ADPCM sample.
* ADPCM sample can't be stopped.
* @param t_adpcm ADPCM data, created by loadADPCM();
*/
void playADPCM(audsrv_adpcm_t *t_adpcm);
/**
* Play ADPCM sample.
* ADPCM sample can't be stopped.
* @param t_adpcm ADPCM data, created by loadADPCM();
* @param t_ch Channel (0-23). Type -1 for use any free channel.
*/
void playADPCM(audsrv_adpcm_t *t_adpcm, const s8 &t_ch);
/**
* Set ADPCM volume.
* @param t_vol Value 0-100
* @param t_ch Channel (0-23)
*/
void setADPCMVolume(u8 t_vol, const s8 &t_ch) { audsrv_adpcm_set_volume(t_ch, t_vol); }
// Other
/**
* Start audio thread.
* Do not call this method unless you know what you do.
* Should be called by engine.
*/
void startThread(FileService *t_fileService);
private: private:
void work(); u8 songLoaded, volume, realVolume, songPlaying, songInLoop, songFinished;
static void audioThread(); std::vector<AudioListenerRef *> songListeners;
u8 isInitialized, shouldPlay, songLoaded, isVolumeSet; FILE *wav;
audsrv_fmt_t format;
FileService *fileService;
ee_thread_t audioThreadAttr; char wavChunk[2 * 1024] __attribute__((aligned(16)));
u8 audioThreadStack[STACK_SIZE] ALIGNED(16); s32 chunkReadStatus;
int audioThreadId;
u8 threadStack[8 * 1024] __attribute__((aligned(16)));
u32 getThreadStackSize() { return 8 * 1024; }
u32 getSongBufferSize() { return 4 * 1024; }
ee_thread_t thread;
int threadId;
ee_sema_t sema;
s32 fillbufferSema;
void setSongFormat();
void unloadSong();
void rewindSongToStart();
AudioListener **listeners;
u32 listenersAmount;
u32 addedListeners;
void initSema(); void initSema();
void loadModules(); void loadModules();
void initAUDSRV(); void initAUDSRV();
void threadLoop();
int ret, played; static void mainThread();
char chunk[2048];
FILE *wav;
audsrv_fmt_t format;
static int fillbuffer(void *arg);
}; };
#endif #endif
+29 -5
View File
@@ -21,21 +21,45 @@ class CameraBase
{ {
public: public:
CameraBase(ScreenSettings *t_screen, Vector3 *t_position, Vector3 *t_up, Vector3 *t_unitCirclePosition); CameraBase(ScreenSettings *t_screen, Vector3 *t_position);
virtual ~CameraBase(){}; virtual ~CameraBase(){};
void setScreen(); /**
void updatePlanes(Vector3 t_target); * Frustum planes.
* Set by lookAt() method.
*/
Plane planes[6]; Plane planes[6];
Matrix worldView;
/**
* View matrix
* Set by lookAt() method.
*/
Matrix view;
protected: protected:
/** Pointer to screen settings */
ScreenSettings *screen; ScreenSettings *screen;
/**
* Adaption of OpenGL lookAt camera.
* Calculates view matrix and update frustum planes
* Should be called every frame.
*/
void lookAt(Vector3 &t_target);
/**
* Do not call this method unless you know what you do.
* Called via lookAt().
* Calculate and update frustum planes.
* http://www.lighthouse3d.com/tutorials/view-frustum-culling/geometric-approach-extracting-the-planes/
*/
void updatePlanes(Vector3 t_target);
private: private:
Vector3 *position2, *up2, *unitCirclePosition2; Vector3 *p_position;
float farPlaneDist, nearPlaneDist, nearHeight, nearWidth, farHeight, farWidth; float farPlaneDist, nearPlaneDist, nearHeight, nearWidth, farHeight, farWidth;
Vector3 ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr; Vector3 ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr;
Vector3 up; // always 0.0F, 1.0F, 0.0F
}; };
#endif #endif
+115
View File
@@ -0,0 +1,115 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#ifndef _TYRA_FILE_SERVICE_
#define _TYRA_FILE_SERVICE_
#include <tamtypes.h>
#include <stdio.h>
#include <kernel.h>
#include <vector>
enum FileServiceTaskType
{
ReadChunk = 0
};
struct FileServiceTask
{
FileServiceTaskType type;
u32 id;
/**
* Used by types:
* - ReadChunk
*/
FILE *file;
/**
* Used by types:
* - ReadChunk
*/
s32 readStatus;
/**
* Used by types:
* - ReadChunk
*/
void *destination;
/**
* Used by types:
* - ReadChunk
*/
u32 size;
/**
* Used by types:
* - ReadChunk
*/
u32 n;
};
/** Class responsible for background, non-blocking file loading playing. */
class FileService
{
public:
/** Constructor is called by the engine. */
FileService();
~FileService();
/**
* Add task to read next chunk. ( fread() )
* @returns Task id
*/
u32 addReadChunk(FILE *t_file, void *t_destination, const u32 &t_size, const u32 &t_n);
/**
* Check if given task was done.
* When task is done, this method will return read status.
* After this, task is removed from file service, so this method
* will return something once per task.
* @returns Read status (ex. result of fread()). -2137 if task is not done.
*/
s32 isTaskDone(const u32 &t_taskId);
/**
* Start file service thread.
* Do not call this method unless you know what you do.
* Should be called by engine.
*/
void startThread();
std::vector<FileServiceTask> tasks;
private:
/** Remove task by index */
void removeByIndex(const u32 &t_index) { tasks.erase(tasks.begin() + t_index); }
/** Remove task by id */
const void removeById(const u32 &t_taskId);
/**
* Get index of task.
* @returns Index of task. -1 if not found.
*/
const s32 getIndexOf(const u32 &t_taskId);
u8 threadStack[8 * 1024] __attribute__((aligned(16)));
u32 getThreadStackSize() { return 8 * 1024; }
ee_thread_t thread;
int threadId;
void threadLoop();
static void mainThread();
};
#endif
+11 -11
View File
@@ -16,39 +16,39 @@
#include <draw_types.h> #include <draw_types.h>
#include <draw_primitives.h> #include <draw_primitives.h>
#include <math3d.h> #include <math3d.h>
#include <packet.h> #include <packet2.h>
#include "./light.hpp"
#include "../models/mesh.hpp" #include "../models/mesh.hpp"
#include "../models/math/matrix.hpp" #include "../models/math/matrix.hpp"
#include "../models/screen_settings.hpp" #include "../models/screen_settings.hpp"
#include "../models/light_bulb.hpp" #include "../models/light_bulb.hpp"
#include "../models/render_data.hpp" #include "../models/render_data.hpp"
#include "../models/mesh_texture.hpp" #include "../models/texture.hpp"
/** Class responsible for sending data packets via GIF (PATH3) */ /** Class responsible for sending data packets via GIF (PATH3) */
class GifSender class GifSender
{ {
public: public:
GifSender(u32 t_packetSize, ScreenSettings *t_screen); GifSender(u32 t_packetSize, ScreenSettings *t_screen, Light *t_light);
~GifSender(); ~GifSender();
void initPacket(u8 context); void initPacket(u8 context);
void addObject(RenderData *t_renderData, Mesh *t_objects3D, u32 vertexCount, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer); void addObject(RenderData *t_renderData, Mesh &t_mesh, u32 vertexCount, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer);
void addClear(zbuffer_t *t_zBuffer); void addClear(zbuffer_t *t_zBuffer, color_t *t_rgb);
void sendPacket(); void sendPacket();
void sendClear(zbuffer_t *t_zBuffer); void sendClear(zbuffer_t *t_zBuffer, color_t *t_rgb);
static void sendTexture(MeshTexture &texture, texbuffer_t *t_texBuffer); static void sendTexture(Texture &texture, texbuffer_t *t_texBuffer);
private: private:
Light *light;
xyz_t *xyz; xyz_t *xyz;
color_t *rgbaq; color_t *rgbaq;
texel_t *st; texel_t *st;
u8 isAnyObjectAdded; u8 isAnyObjectAdded;
ScreenSettings *screen; ScreenSettings *screen;
u64 *dw; packet2_t *packets[2];
qword_t *q, *dmatag; packet2_t *currentPacket;
packet_t *packets[2];
packet_t *currentPacket;
u8 packetsCount; u8 packetsCount;
int packetSize; int packetSize;
float halfScreenW, halfScreenH; float halfScreenW, halfScreenH;
+6 -2
View File
@@ -23,10 +23,14 @@ public:
Light(); Light();
~Light(); ~Light();
static u16 getLightsCount(u32 t_bulbsCount); u16 getLightsCount(u32 t_bulbsCount);
static void calculateLight(VECTOR *t_lightDirections, VECTOR *t_lightColors, int *t_lightTypes, LightBulb *t_bulbs, u32 t_bulbsCount, Vector3 t_objPosition);
/** Values from 0.0000F to 1.0000F */
void setAmbientLight(const Vector3 &t_rgb);
void calculateLight(VECTOR *t_lightDirections, VECTOR *t_lightColors, int *t_lightTypes, LightBulb *t_bulbs, u32 t_lightsCount, Vector3 t_objPosition);
private: private:
Vector3 ambientLight;
}; };
#endif #endif
+113 -24
View File
@@ -13,10 +13,14 @@
#include <draw_buffers.h> #include <draw_buffers.h>
#include <draw_primitives.h> #include <draw_primitives.h>
#include <packet.h> #include <gs_privileged.h>
#include <draw.h>
#include <packet2.h>
#include "gif_sender.hpp" #include "gif_sender.hpp"
#include "vif_sender.hpp" #include "vif_sender.hpp"
#include "light.hpp"
#include "../models/math/plane.hpp" #include "../models/math/plane.hpp"
#include "../models/sprite.hpp"
#include "../models/screen_settings.hpp" #include "../models/screen_settings.hpp"
#include "../models/render_data.hpp" #include "../models/render_data.hpp"
#include "./texture_repository.hpp" #include "./texture_repository.hpp"
@@ -30,52 +34,137 @@ public:
~Renderer(); ~Renderer();
framebuffer_t frameBuffers[2]; framebuffer_t frameBuffers[2];
u8 context; u8 context; // TODO
zbuffer_t zBuffer; zbuffer_t zBuffer;
prim_t prim; prim_t prim;
/** PATH3 Many + lighting */ void enableVSync() { isVSyncEnabled = true; }
void drawByPath3(Mesh **t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount); void disableVSync() { isVSyncEnabled = false; }
/** PATH3 Single + lighting */
void drawByPath3(Mesh *t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount);
/** PATH3 Many */
void drawByPath3(Mesh **t_meshes, u16 t_amount);
/** PATH3 Single */
void drawByPath3(Mesh *t_mesh);
/** PATH1 Many + lighting */ /** Reset draw wait flag. */
inline void resetWaitFlag()
{
*GS_REG_CSR |= 2;
}
/** Checks if draw wait flag is set */
inline u8 isWaitFlagSet() const
{
return *GS_REG_CSR & 2;
}
/** Waits for draw wait flag and reset it. */
inline void waitForRender()
{
while (!isWaitFlagSet())
;
resetWaitFlag();
}
/** 2D draw. */
void draw(Sprite &t_sprite);
/// --- Draw: PATH3
/**
* WARNING: THIS FUNC CAUSE VISUAL ARTIFACTS!
* Draw many meshes with lighting information.
* Slowest way of rendering (PATH 3, using EE and GIF).
* NOTICE: Animation supported, lighting supported
*/
void drawByPath3(Mesh *t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount);
/**
* WARNING: THIS FUNC CAUSE VISUAL ARTIFACTS!
* Draw mesh with lighting information.
* Slowest way of rendering (PATH 3, using EE and GIF).
* NOTICE: Animation supported, lighting supported
*/
void drawByPath3(Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount);
/**
* WARNING: THIS FUNC CAUSE VISUAL ARTIFACTS!
* Draw many meshes without lighting information.
* Slowest way of rendering (PATH 3, using EE and GIF).
* NOTICE: Animation supported, lighting supported
*/
void drawByPath3(Mesh *t_meshes, u16 t_amount);
/**
* WARNING: THIS FUNC CAUSE VISUAL ARTIFACTS!
* Draw mesh without lighting information.
* Slowest way of rendering (PATH 3, using EE and GIF).
* NOTICE: Animation supported, lighting supported
*/
void drawByPath3(Mesh &t_mesh);
/// --- Draw: PATH1
/**
* Draw many meshes with lighting information.
* Draw in array mode, can be A LOT faster than for looping!
* Fastest way of rendering (PATH 1, using VU1).
* NOTICE: Animation supported, lighting NOT supported (at this moment)
*/
void draw(Mesh **t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount); void draw(Mesh **t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount);
/** PATH1 Single + lighting */
void draw(Mesh *t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount); /**
/** PATH1 Many */ * Draw mesh with lighting information.
* Fastest way of rendering (PATH 1, using VU1).
* NOTICE: Animation supported, lighting NOT supported (at this moment)
*/
void draw(Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount);
/**
* Draw many meshes without lighting information.
* Draw in array mode, can be A LOT faster than for looping!
* Fastest way of rendering (PATH 1, using VU1).
* NOTICE: Animation supported, lighting NOT supported (at this moment)
*/
void draw(Mesh **t_meshes, u16 t_amount); void draw(Mesh **t_meshes, u16 t_amount);
/** PATH1 Single */
void draw(Mesh *t_mesh); /**
* Draw mesh without lighting information.
* Fastest way of rendering (PATH 1, using VU1).
* NOTICE: Animation supported, lighting NOT supported (at this moment)
*/
void draw(Mesh &t_mesh);
void setCameraDefinitions(Matrix *t_worldView, Vector3 *t_cameraPos, Plane *t_planes); void setCameraDefinitions(Matrix *t_worldView, Vector3 *t_cameraPos, Plane *t_planes);
void setWorldColor(const color_t &t_rgb);
void endFrame(float fps); void endFrame(float fps);
TextureRepository *getTextureRepository() { return &textureRepo; }; void setAmbientLight(const Vector3 &t_rgb) { light.setAmbientLight(t_rgb); }
TextureRepository *getTextureRepository()
{
return &textureRepo;
};
private: private:
void changeTexture(Mesh *t_mesh, u32 t_materialId); // We have some GCC bug here. Just try to reorder declarations. For example move worldColor up - game will crash.
void changeTexture(Texture *t_tex);
u32 lastTextureId; u32 lastTextureId;
texbuffer_t textureBuffer; texbuffer_t textureBuffer;
u8 isTextureVRAMAllocated; u8 isTextureVRAMAllocated, isVSyncEnabled;
void allocateTextureBuffer(u16 t_width, u16 t_height); void allocateTextureBuffer(Texture *t_texture);
void deallocateTextureBuffer(); void deallocateTextureBuffer();
void flipBuffers(); void flipBuffers();
void beginFrameIfNeeded(); void beginFrameIfNeeded();
u8 isFrameEmpty; u8 isFrameEmpty;
Matrix perspective; Matrix perspective, camRotation;
Light light;
RenderData renderData; RenderData renderData;
TextureRepository textureRepo; TextureRepository textureRepo;
ScreenSettings *screen;
GifSender *gifSender; GifSender *gifSender;
VifSender *vifSender; VifSender *vifSender;
packet_t *flipPacket; packet2_t *flipPacket;
void allocateBuffers(float t_screenW, float t_screenH); color_t worldColor;
void initDrawingEnv(float t_screenW, float t_screenH); void allocateBuffers(int t_screenW, int t_screenH);
void initDrawingEnv();
void setPrim(); void setPrim();
}; };
@@ -17,6 +17,13 @@
#include "../models/mesh.hpp" #include "../models/mesh.hpp"
#include "../models/mesh_frame.hpp" #include "../models/mesh_frame.hpp"
#include "../loaders/bmp_loader.hpp" #include "../loaders/bmp_loader.hpp"
#include "../loaders/png_loader.hpp"
enum TextureFormat
{
BMP,
PNG
};
/** Class responsible for intializing draw env, textures and buffers */ /** Class responsible for intializing draw env, textures and buffers */
class TextureRepository class TextureRepository
@@ -31,7 +38,7 @@ public:
// ---- // ----
/** Returns all repository textures. */ /** Returns all repository textures. */
std::vector<MeshTexture *> *getAll() { return &textures; } std::vector<Texture *> *getAll() { return &textures; }
u32 getTexturesCount() const { return static_cast<u32>(textures.size()); }; u32 getTexturesCount() const { return static_cast<u32>(textures.size()); };
@@ -39,7 +46,19 @@ public:
* Returns single texture. * Returns single texture.
* NULL if not found. * NULL if not found.
*/ */
MeshTexture *getByMesh(const u32 &t_meshId, const u32 &t_materialId) Texture *getBySprite(const u32 &t_spriteId)
{
for (u32 i = 0; i < textures.size(); i++)
if (textures[i]->isLinkedWith(t_spriteId))
return textures[i];
return NULL;
}
/**
* Returns single texture.
* NULL if not found.
*/
Texture *getByMesh(const u32 &t_meshId, const u32 &t_materialId)
{ {
for (u32 i = 0; i < textures.size(); i++) for (u32 i = 0; i < textures.size(); i++)
if (textures[i]->isLinkedWith(t_meshId, t_materialId)) if (textures[i]->isLinkedWith(t_meshId, t_materialId))
@@ -51,7 +70,7 @@ public:
* Returns single texture. * Returns single texture.
* NULL if not found. * NULL if not found.
*/ */
MeshTexture *getByTextureId(const u32 &t_id) const Texture *getByTextureId(const u32 &t_id) const
{ {
for (u32 i = 0; i < textures.size(); i++) for (u32 i = 0; i < textures.size(); i++)
if (t_id == textures[i]->getId()) if (t_id == textures[i]->getId())
@@ -79,20 +98,22 @@ public:
// Other // Other
// ---- // ----
/** Add unlinked texture. /**
* NOTICE: BMP (RGB 888 24bit, without color information) is suppored only! * Add unlinked texture.
* @param t_subfolder Relative path. Ex.: "textures/" * @param t_subfolder Relative path. Ex.: "textures/"
* @param t_name Filename without extension. Ex.: "water" * @param t_name Filename without extension. Ex.: "water"
* * @param t_format if you want to use BMP, be sure that you have
* BMP with RGB 888 24bit, without color information.
*/ */
MeshTexture *add(char *t_subfolder, char *t_name); Texture *add(char *t_subfolder, char *t_name, TextureFormat t_format);
/** /**
* Add linked textures in given subpath for mesh material names. * Add linked textures in given subpath for mesh material names.
* NOTICE: BMP (RGB 888 24bit, without color information) is suppored only! * @param t_path Relative path where textures should be searched.
* @param t_path Relative path where textures should be searched * @param t_format if you want to use BMP, be sure that you have
* BMP with RGB 888 24bit, without color information.
*/ */
void addByMesh(char *t_path, Mesh &mesh); void addByMesh(char *t_path, Mesh &mesh, TextureFormat t_format);
/** /**
* Remove texture from repository. * Remove texture from repository.
@@ -114,8 +135,9 @@ public:
} }
private: private:
std::vector<MeshTexture *> textures; std::vector<Texture *> textures;
BmpLoader loader; BmpLoader bmpLoader;
PngLoader pngLoader;
}; };
#endif #endif
+2 -1
View File
@@ -12,6 +12,7 @@
#define _TYRA_TIMER_ #define _TYRA_TIMER_
#include <tamtypes.h> #include <tamtypes.h>
#include <timer.h>
/** Class responsible for fps counting */ /** Class responsible for fps counting */
class Timer class Timer
@@ -22,7 +23,7 @@ public:
~Timer(); ~Timer();
u32 getTimeDelta(); u32 getTimeDelta();
void primeTimer(); inline void prime() { lastTime = *T3_COUNT; }
float getFPS(); float getFPS();
private: private:
+27 -7
View File
@@ -12,29 +12,49 @@
#define _TYRA_VIF_SENDER_ #define _TYRA_VIF_SENDER_
#include <tamtypes.h> #include <tamtypes.h>
#include <packet2_utils.h>
#include "../models/render_data.hpp" #include "../models/render_data.hpp"
#include "./light.hpp"
#include "../models/light_bulb.hpp" #include "../models/light_bulb.hpp"
#include "../models/mesh.hpp" #include "../models/mesh.hpp"
#include "../models/math/matrix.hpp" #include "../models/math/matrix.hpp"
#include "../models/math/vector3.hpp" #include "../models/math/vector3.hpp"
#include "vu1.hpp"
/** Class responsible for sending 3D objects via VIF (PATH 1) */ /** Class responsible for sending 3D objects via VIF (PATH 1) */
class VifSender class VifSender
{ {
public: public:
VifSender(); VifSender(Light *t_light);
~VifSender(); ~VifSender();
// TODO refactor // TODO refactor
void drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 vertCount2, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, Mesh *t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer); void drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 vertCount2, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer);
void sendMatrices(const RenderData &t_renderData, const Vector3 &t_position, const Vector3 &t_rotation); void calcMatrix(const RenderData &t_renderData, const Vector3 &t_position, const Vector3 &t_rotation);
void drawTheSameWithOtherMatrices(const RenderData &t_renderData, Mesh **t_meshes, const u32 &t_skip, const u32 &t_count);
void enableWait() { isDrawWaitEnabled = true; }
void disableWait() { isDrawWaitEnabled = false; }
private: private:
void drawVertices(Mesh *t_mesh, u32 t_start, u32 t_end, VECTOR *t_vertices, VECTOR *t_coordinates, prim_t *t_prim, texbuffer_t *textureBuffer); u32 lastVertCount; // needed for drawTheSameWithOtherMatrices()
VU1 vu1; // TODO u8 isDrawWaitEnabled;
MATRIX localWorld, localScreen; Light *light;
void uploadMicroProgram();
void setDoubleBufferAddStaticData();
void drawVertices(Mesh &t_mesh, u32 t_start, u32 t_end, VECTOR *t_vertices, VECTOR *t_coordinates, prim_t *t_prim, texbuffer_t *t_textureBuffer, u8 t_addDrawWait);
packet2_t *packets[2] __attribute__((aligned(64)));
packet2_t *currPacket;
/**
* OpenGL name: Model
* Sony name: local world
*/
Matrix model;
/**
* OpenGL name: ModelViewProjection
* Sony name: local screen
*/
Matrix modelViewProj;
u8 context;
VECTOR position, rotation; VECTOR position, rotation;
u32 vertCount; u32 vertCount;
}; };
-98
View File
@@ -1,98 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#ifndef _TYRA_VU1_
#define _TYRA_VU1_
#include "../models/math/matrix.hpp"
#include <draw_buffers.h>
#include <tamtypes.h>
#include <draw_primitives.h>
#include <packet.h>
#include <math3d.h>
const u32 VIF_BUFFER_SIZE = 48 * 1024;
typedef struct VU1BuildList
{
u8 isBuilding;
void *offset;
void *kickBuffer;
u32 dmaSize;
u32 dmaSizeAll;
u32 dmaDestination;
} VU1BuildList;
/** Class responsible for managing VU1 micro programs */
class VU1
{
public:
VU1();
~VU1();
static void uploadProgram(int t_dest, u32 *t_start, u32 *t_end);
void createList();
void sendSingleRefList(int t_destAddress, void *t_data, int t_quadSize);
void addListBeginning();
void continueList();
void addReferenceList(u32 t_offset, void *t_data, u32 t_size, u8 t_useTops);
void addFloat(float v);
void add32(u32 v);
void add64(u64 v);
void add128(u64 v1, u64 v2);
void addListEnding();
void addStartProgram();
void addContinueProgram();
void sendList();
void addDoubleBufferSetting();
void addFlush();
private:
u8 isDoubleBufferSet;
void checkDataAlignment(void *data);
VU1BuildList buildList;
char dmaBuffer1[VIF_BUFFER_SIZE] __attribute__((aligned(16)));
char dmaBuffer2[VIF_BUFFER_SIZE] __attribute__((aligned(16)));
void *currentBuffer;
u32 switchBuffer;
static u32 countProgramSize(u32 *t_start, u32 *t_end);
void checkList();
inline s32 AddUnpack(int format, int addr, int num, int usetops = 0, int nosign = 1, int masking = 0)
{
return (s32)((0x60 << 24) + (format << 24) + (masking << 28) + (usetops << 15) +
(nosign << 14) + (num << 16) + addr);
}
};
#define DMA_REF_TAG(ADDR, COUNT) ((((unsigned long)ADDR) << 32) | (0x3 << 28) | COUNT)
#define DMA_CNT_TAG(COUNT) (((unsigned long)(0x1) << 28) | COUNT)
#define DMA_END_TAG(COUNT) (((unsigned long)(0x7) << 28) | COUNT)
#define VIF_NOP 0x00
#define VIF_STCYL 0x01
#define VIF_OFFSET 0x02
#define VIF_BASE 0x03
#define VIF_FLUSH 0x11
#define VIF_MSCAL 0x14
#define VIF_MSCNT 0x17
#define VIF_MPG 0x4A
#define V4_32 0xC
#define VIF_UNPACK 0x60
#define U128(n) ((u128)(n))
#define VIF_UNPACK_V4_32 (VIF_UNPACK | V4_32)
#define VIF_CODE(CMD, NUM, IMMEDIATE) ((((unsigned int)(CMD)) << 24) | \
(((unsigned int)(NUM)) << 16) | \
((unsigned int)(IMMEDIATE)))
#define GS_PRIM(PRIM, IIP, TME, FGE, ABE, AA1, FST, CTXT, FIX) U128((FIX << 10) | (CTXT << 9) | (FST << 8) | (AA1 << 7) | (ABE << 6) | (FGE << 5) | (TME << 4) | (IIP << 3) | (PRIM))
#define GS_GIFTAG(NLOOP, EOP, PRE, PRIM, FLG, NREG) (((u64)(NREG) << 60) | ((u64)(FLG) << 58) | ((u64)(PRIM) << 47) | ((u64)(PRE) << 46) | (EOP << 15) | (NLOOP << 0))
#define VU1_DMA_CHAN_TIMEOUT -1
#define GS_GIFTAG_PACKED 0
#endif
+11 -1
View File
@@ -24,13 +24,23 @@ class Math
{ {
public: public:
const static float HALF_ANG2RAD = 3.14159265358979323846 / 360.0; const static float HALF_ANG2RAD = 3.14159265358979323846F / 360.0F;
const static float ANG2RAD = 3.14159265358979323846F / 180.0F;
const static float PI = 3.1415926535897932384626433832795F; const static float PI = 3.1415926535897932384626433832795F;
const static float HALF_PI = 1.5707963267948966192313216916398F; const static float HALF_PI = 1.5707963267948966192313216916398F;
static float cos(float x); static float cos(float x);
static float asin(float x);
static float mod(float x, float y);
static inline float sin(float x) { return cos(x - HALF_PI); }; static inline float sin(float x) { return cos(x - HALF_PI); };
static inline float tan(float x) { return sin(x) / cos(x); }
static float sqrt(float x); static float sqrt(float x);
static float invSqrt(float x); static float invSqrt(float x);
static inline u32 max(u32 a, u32 b) { return (a > b) ? a : b; }
static inline s32 max(s32 a, s32 b) { return (a > b) ? a : b; }
static inline float max(float a, float b) { return (a > b) ? a : b; }
static inline u32 min(u32 a, u32 b) { return (a < b) ? a : b; }
static inline s32 min(s32 a, s32 b) { return (a < b) ? a : b; }
static inline float min(float a, float b) { return (a < b) ? a : b; }
private: private:
Math(); Math();
+16 -22
View File
@@ -30,12 +30,14 @@ BmpLoader::~BmpLoader() {}
* @param t_name Without extension. Example "skyfall2" * @param t_name Without extension. Example "skyfall2"
* @param t_extension With dot and extension. Example ".BMP" * @param t_extension With dot and extension. Example ".BMP"
*/ */
void BmpLoader::load(MeshTexture &o_texture, char *t_subfolder, char *t_name, char *t_extension) void BmpLoader::load(Texture &o_texture, char *t_subfolder, char *t_name, char *t_extension)
{ {
char *t_path_part = String::createConcatenated(t_subfolder, t_name); char *path_part1 = String::createConcatenated(t_subfolder, t_name);
char *t_path = String::createConcatenated(t_path_part, t_extension); char *path_part2 = String::createConcatenated("host:", path_part1);
delete[] t_path_part; char *path = String::createConcatenated(path_part2, t_extension);
FILE *file = fopen(t_path, "rb"); delete[] path_part1;
delete[] path_part2;
FILE *file = fopen(path, "rb");
if (file == NULL) if (file == NULL)
{ {
@@ -46,36 +48,28 @@ void BmpLoader::load(MeshTexture &o_texture, char *t_subfolder, char *t_name, ch
unsigned char header[54]; unsigned char header[54];
fread(header, sizeof(unsigned char), 54, file); fread(header, sizeof(unsigned char), 54, file);
u32 width = *(u32 *)&header[18]; u32 width = (u32)header[18];
u32 height = *(u32 *)&header[22]; u32 height = (u32)header[22];
o_texture.setSize(width, height); o_texture.setSize(width, height, TEX_TYPE_RGB);
printf("BMPLoader - width: %d | height: %d\n", width, height); printf("BMPLoader - width: %d | height: %d\n", width, height);
if (width > 128 || height > 128)
PRINT_ERR("Given texture is big for PS2. Please strict to 128x128 max");
u64 rowPadded = (width * 3 + 3) & (~3); u64 rowPadded = (width * 3 + 3) & (~3);
unsigned char *data = new unsigned char[rowPadded]; unsigned char row[rowPadded];
unsigned char tmp;
u32 x = 0; u32 x = 0;
for (u32 i = 0; i < height; i++) for (u32 i = 0; i < height; i++)
{ {
fread(data, sizeof(unsigned char), rowPadded, file); fread(&row, sizeof(unsigned char), rowPadded, file);
for (u32 j = 0; j < width * 3; j += 3) for (u32 j = 0; j < width * 3; j += 3)
{ {
// Convert (B, G, R) to (R, G, B) // Convert (B, G, R) to (R, G, B)
tmp = data[j]; o_texture.setData(x, row[j + 2]);
data[j] = data[j + 2]; o_texture.setData(x + 1, row[j + 1]);
data[j + 2] = tmp; o_texture.setData(x + 2, row[j]);
o_texture.setData(x, data[j]);
o_texture.setData(x + 1, data[j + 1]);
o_texture.setData(x + 2, data[j + 2]);
x += 3; x += 3;
} }
} }
delete[] t_path; delete[] path;
delete[] data;
fclose(file); fclose(file);
} }
+27 -5
View File
@@ -37,9 +37,10 @@ DffLoader::~DffLoader() {}
void DffLoader::load(MeshFrame *o_result, char *t_filename, float t_scale, u8 t_invertT) void DffLoader::load(MeshFrame *o_result, char *t_filename, float t_scale, u8 t_invertT)
{ {
PRINT_LOG("Loading dff file"); PRINT_LOG("Loading dff file");
FILE *file = fopen(t_filename, "rb"); char *path = String::createConcatenated("host:", t_filename);
FILE *file = fopen(path, "rb");
if (file == NULL) if (file == NULL)
PRINT_ERR("Failed to load .obj file!"); PRINT_ERR("Failed to load .dff file!");
fseek(file, 0L, SEEK_END); fseek(file, 0L, SEEK_END);
long fileSize = ftell(file); long fileSize = ftell(file);
u8 data[fileSize]; u8 data[fileSize];
@@ -48,9 +49,29 @@ void DffLoader::load(MeshFrame *o_result, char *t_filename, float t_scale, u8 t_
fclose(file); fclose(file);
serialize(o_result, t_invertT, data, t_scale); serialize(o_result, t_invertT, data, t_scale);
o_result->calculateBoundingBoxes(); o_result->calculateBoundingBoxes();
delete[] path;
PRINT_LOG("Dff file loaded!"); PRINT_LOG("Dff file loaded!");
} }
// void DffLoader::im_not_used_anywhere(MeshFrame *o_result, char *t_filename, float t_scale, u8 t_invertT)
// {
// PRINT_LOG("Loading dff file");
// char *path = String::createConcatenated("host:", t_filename);
// FILE *file = fopen(path, "rb");
// if (file == NULL)
// PRINT_ERR("Failed to load .dff file!");
// fseek(file, 0L, SEEK_END);
// long fileSize = ftell(file);
// u8 data[fileSize];
// rewind(file);
// fread(&data, sizeof(u8), fileSize, file);
// fclose(file);
// serialize(o_result, t_invertT, data, t_scale);
// o_result->calculateBoundingBoxes();
// delete[] path;
// PRINT_LOG("Dff file loaded!");
// }
void DffLoader::serialize(MeshFrame *o_result, u8 t_invertT, u8 *t_data, float t_scale) void DffLoader::serialize(MeshFrame *o_result, u8 t_invertT, u8 *t_data, float t_scale)
{ {
u32 ptrPos = 0; u32 ptrPos = 0;
@@ -228,9 +249,10 @@ void DffLoader::readGeometryExtension(MeshFrame *o_frame, char **materialNames,
for (u32 j = 0; j < facesCount; j++) for (u32 j = 0; j < facesCount; j++)
{ {
u32 vertex1 = readDwordFromArrayLE(t_buffer, t_ptrPos); u32 vertex1 = readDwordFromArrayLE(t_buffer, t_ptrPos);
o_frame->getMaterial(i).setVertexFace(j, vertex1); // Inverted insertind due to backface culling
o_frame->getMaterial(i).setNormalFace(j, vertex1); o_frame->getMaterial(i).setVertexFace(facesCount - 1 - j, vertex1);
o_frame->getMaterial(i).setSTFace(j, vertex1); o_frame->getMaterial(i).setNormalFace(facesCount - 1 - j, vertex1);
o_frame->getMaterial(i).setSTFace(facesCount - 1 - j, vertex1);
} }
} }
} }
+4 -2
View File
@@ -46,8 +46,10 @@ MeshFrame *MD2Loader::load(u32 &o_framesCount, char *t_subpath, char *t_nameWith
{ {
PRINT_LOG("Loading new MD2 file"); PRINT_LOG("Loading new MD2 file");
char *part1 = String::createConcatenated(t_subpath, t_nameWithoutExtension); char *part1 = String::createConcatenated(t_subpath, t_nameWithoutExtension);
char *finalPath = String::createConcatenated(part1, ".md2"); // "folder/object.md2" char *part2 = String::createConcatenated("host:", part1);
char *finalPath = String::createConcatenated(part2, ".md2"); // "folder/object.md2"
delete[] part1; delete[] part1;
delete[] part2;
md2_t header; md2_t header;
FILE *file = fopen(finalPath, "rb"); FILE *file = fopen(finalPath, "rb");
@@ -85,7 +87,7 @@ MeshFrame *MD2Loader::load(u32 &o_framesCount, char *t_subpath, char *t_nameWith
fclose(file); fclose(file);
MeshFrame *resultFrames = new MeshFrame[26]; MeshFrame *resultFrames = new MeshFrame[framesCount];
frame_t *frame; frame_t *frame;
Vector3 tempVec = Vector3(); Vector3 tempVec = Vector3();
+6 -1
View File
@@ -28,7 +28,8 @@ ObjLoader::~ObjLoader() {}
void ObjLoader::load(MeshFrame *o_result, char *t_filename, float t_scale, u8 t_invertT) void ObjLoader::load(MeshFrame *o_result, char *t_filename, float t_scale, u8 t_invertT)
{ {
FILE *file = fopen(t_filename, "rb"); char *path = String::createConcatenated("host:", t_filename);
FILE *file = fopen(path, "rb");
if (file == NULL) if (file == NULL)
PRINT_ERR("Failed to load .obj file!"); PRINT_ERR("Failed to load .obj file!");
allocateObjMemory(file, o_result); allocateObjMemory(file, o_result);
@@ -98,6 +99,7 @@ void ObjLoader::load(MeshFrame *o_result, char *t_filename, float t_scale, u8 t_
} }
o_result->calculateBoundingBoxes(); o_result->calculateBoundingBoxes();
fclose(file); fclose(file);
delete[] path;
} }
/** Calculate how many vertices(v), coordinates(vt), normals(vn) and faces(f) have .obj file */ /** Calculate how many vertices(v), coordinates(vt), normals(vn) and faces(f) have .obj file */
@@ -145,7 +147,10 @@ void ObjLoader::allocateObjMemory(FILE *t_file, MeshFrame *o_result)
if (strcmp(lineHeader, "usemtl") == 0) if (strcmp(lineHeader, "usemtl") == 0)
{ {
if (currentMatI >= 0) // Skip -1 if (currentMatI >= 0) // Skip -1
{
o_result->getMaterial(currentMatI).allocateFaces(facesCounter); o_result->getMaterial(currentMatI).allocateFaces(facesCounter);
facesCounter = 0;
}
currentMatI++; currentMatI++;
} }
else if (strcmp(lineHeader, "f") == 0) else if (strcmp(lineHeader, "f") == 0)
+139
View File
@@ -0,0 +1,139 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "../include/loaders/png_loader.hpp"
#include "../include/utils/debug.hpp"
#include "../include/utils/string.hpp"
#include <cstdlib>
#include <png.h>
// ----
// Constructors/Destructors
// ----
PngLoader::PngLoader() {}
PngLoader::~PngLoader() {}
// ----
// Methods
// ----
/**
* @param t_name Without extension. Example "skyfall2"
* @param t_extension With dot and extension. Example ".png"
*/
void PngLoader::load(Texture &o_texture, char *t_subfolder, char *t_name, char *t_extension)
{
char *path_part1 = String::createConcatenated(t_subfolder, t_name);
char *path_part2 = String::createConcatenated("host:", path_part1);
char *path = String::createConcatenated(path_part2, t_extension);
delete[] path_part1;
delete[] path_part2;
FILE *file = fopen(path, "rb");
if (file == NULL)
PRINT_ERR("Failed to open .png file!");
png_structp png_ptr;
png_infop info_ptr;
png_uint_32 width, height;
u32 sig_read = 0, row = 0, i = 0, j = 0;
int bit_depth, color_type, interlace_type;
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL);
if (!png_ptr)
PRINT_ERR("PNG struct info init failed(1)!");
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr)
PRINT_ERR("PNG struct info init failed(2)!");
if (setjmp(png_jmpbuf(png_ptr)))
PRINT_ERR("PNG reader fatal error!");
png_init_io(png_ptr, file);
png_set_sig_bytes(png_ptr, sig_read);
png_read_info(png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL);
png_set_strip_16(png_ptr);
if (color_type == PNG_COLOR_TYPE_PALETTE)
png_set_expand(png_ptr);
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
png_set_expand(png_ptr);
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
png_set_tRNS_to_alpha(png_ptr);
png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
png_read_update_info(png_ptr, info_ptr);
png_byte pngType = png_get_color_type(png_ptr, info_ptr);
TextureType type;
switch (pngType)
{
case PNG_COLOR_TYPE_RGB_ALPHA:
type = TEX_TYPE_RGBA;
break;
case PNG_COLOR_TYPE_RGB:
type = TEX_TYPE_RGB;
break;
default:
PRINT_ERR("This png format is not supported! RGB/RGBA only.");
}
o_texture.setSize(width, height, type);
printf("PNGLoader - width: %d | height: %d\n", width, height);
size_t row_bytes = png_get_rowbytes(png_ptr, info_ptr);
png_byte *row_pointers[height];
for (row = 0; row < height; row++)
row_pointers[row] = new png_byte[row_bytes];
png_read_image(png_ptr, row_pointers);
u32 x = 0;
for (i = 0; i < height; i++)
for (j = 0; j < width; j++)
{
o_texture.setData(x, row_pointers[i][4 * j]);
o_texture.setData(x + 1, row_pointers[i][4 * j + 1]);
o_texture.setData(x + 2, row_pointers[i][4 * j + 2]);
if (type == TEX_TYPE_RGBA)
{
o_texture.setData(x + 3, ((int)row_pointers[i][4 * j + 3] * 128 / 255));
x += 4;
}
else if (type == TEX_TYPE_RGB)
x += 3;
}
for (row = 0; row < height; row++)
delete[] row_pointers[row];
png_read_end(png_ptr, NULL);
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
delete[] path;
fclose(file);
}
+49
View File
@@ -0,0 +1,49 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Michał Mostowik <mostek3pl@gmail.com>
*/
#include "../include/models/bounding_box.hpp"
#include "../include/utils/debug.hpp"
#include <cstring>
/**
* Construct a BoundingBox class
* Allows for user friendly access to bounding box data.
* @param t_vertices Array of 8 Vector3 elements.
*/
BoundingBox::BoundingBox(Vector3 *t_vertices)
{
//Perform a deep copy of vertex array parameter
memcpy(_vertices, t_vertices, 8 * sizeof(Vector3));
//This might be shortened with Vector3 operator overloading, but current
//implementation is more human readable.
_height = _vertices[0].y - _vertices[2].y;
_width = _vertices[0].x - _vertices[4].x;
_depth = _vertices[0].z - _vertices[1].z;
_centerVector = _vertices[0];
_centerVector.x += (_width / 2);
_centerVector.y += (_height / 2);
_centerVector.z += (_depth / 2);
//Z-Axis faces
_frontFace = BoundingBoxFace(_vertices[1], _vertices[7], _vertices[1].z);
_backFace = BoundingBoxFace(_vertices[0], _vertices[6], _vertices[0].z);
//X-Axis faces
_leftFace = BoundingBoxFace(_vertices[0], _vertices[3], _vertices[0].x);
_rightFace = BoundingBoxFace(_vertices[4], _vertices[7], _vertices[4].x);
//Y-Axis faces
_topFace = BoundingBoxFace(_vertices[2], _vertices[7], _vertices[2].y);
_bottomFace = BoundingBoxFace(_vertices[0], _vertices[5], _vertices[0].y);
}
BoundingBox::~BoundingBox()
{
}
+266 -158
View File
@@ -17,11 +17,16 @@
// Constructors/Destructors // Constructors/Destructors
// ---- // ----
/** Create by specifying all points */ Matrix::Matrix()
Matrix::Matrix(float m11, float m12, float m13, float m14, {
float m21, float m22, float m23, float m24, for (u8 i = 0; i < 16; i++)
float m31, float m32, float m33, float m34, data[i] = 0.0F;
float m41, float m42, float m43, float m44) }
Matrix::Matrix(const float &m11, const float &m12, const float &m13, const float &m14,
const float &m21, const float &m22, const float &m23, const float &m24,
const float &m31, const float &m32, const float &m33, const float &m34,
const float &m41, const float &m42, const float &m43, const float &m44)
{ {
data[0] = m11; data[0] = m11;
data[1] = m12; data[1] = m12;
@@ -44,30 +49,34 @@ Matrix::Matrix(float m11, float m12, float m13, float m14,
data[15] = m44; data[15] = m44;
} }
/** Create with another matrix values */ // ----
Matrix::Matrix(const Matrix &v) // Operators
// ----
Vector3 Matrix::operator*(const Vector3 &v) const
{ {
data[0] = v.data[0]; float a[4] = {v.x, v.y, v.z, 1.0F};
data[1] = v.data[1]; float res[4];
data[2] = v.data[2]; asm volatile(
data[3] = v.data[3]; "lqc2 vf4, 0x00(%1) \n\t"
"lqc2 vf5, 0x10(%1) \n\t"
data[4] = v.data[4]; "lqc2 vf6, 0x20(%1) \n\t"
data[5] = v.data[5]; "lqc2 vf7, 0x30(%1) \n\t"
data[6] = v.data[6]; "lqc2 vf8, 0x00(%2) \n\t"
data[7] = v.data[7]; "vmulax.xyzw ACC, vf4, vf8 \n\t"
"vmadday.xyzw ACC, vf5, vf8 \n\t"
data[8] = v.data[8]; "vmaddaz.xyzw ACC, vf6, vf8 \n\t"
data[9] = v.data[9]; "vmaddw.xyzw vf9, vf7, vf8 \n\t"
data[10] = v.data[10]; "sqc2 vf9, 0x00(%0) \n\t"
data[11] = v.data[11]; :
: "r"(res), "r"(this->data), "r"(a));
data[12] = v.data[12]; return Vector3(res[0], res[1], res[2]);
data[13] = v.data[13];
data[14] = v.data[14];
data[15] = v.data[15];
} }
// ----
// Functions
// ----
void Matrix::identity() void Matrix::identity()
{ {
asm volatile( asm volatile(
@@ -84,17 +93,126 @@ void Matrix::identity()
: "r"(this->data)); : "r"(this->data));
} }
void Matrix::translate(float x, float y, float z) void Matrix::setPerspective(const ScreenSettings &t_screen)
{ {
this->identity(); float fovYdiv2 = Math::HALF_ANG2RAD * t_screen.fov;
this->data[(3 << 2) + 0] = x; // 3,0 float cotFOV = 1.0F / (Math::sin(fovYdiv2) / Math::cos(fovYdiv2));
this->data[(3 << 2) + 1] = y; // 3,1 float w = cotFOV * (t_screen.width / t_screen.projectionScale) / t_screen.aspectRatio;
this->data[(3 << 2) + 2] = z; // 3,2 float h = cotFOV * (t_screen.height / t_screen.projectionScale);
this->data[0] = w;
this->data[1] = 0.0F;
this->data[2] = 0.0F;
this->data[3] = 0.0F;
this->data[4] = 0.0F;
this->data[5] = -h;
this->data[6] = 0.0F;
this->data[7] = 0.0F;
this->data[8] = 0.0F;
this->data[9] = 0.0F;
this->data[10] =
(t_screen.farPlaneDist + t_screen.nearPlaneDist) /
(t_screen.farPlaneDist - t_screen.nearPlaneDist);
this->data[11] = -1.0F;
this->data[12] = 0.0F;
this->data[13] = 0.0F;
this->data[14] =
(2.0F * t_screen.farPlaneDist * t_screen.nearPlaneDist) /
(t_screen.farPlaneDist - t_screen.nearPlaneDist);
this->data[15] = 0.0F;
} }
void Matrix::makeZRotation(float t_radians) void Matrix::lookAt(const Vector3 &t_position, const Vector3 &t_target)
{
VECTOR up_vec, view_vec;
VECTOR eye = {t_position.x, t_position.y, t_position.z, 1.0F};
VECTOR obj = {t_target.x, t_target.y, t_target.z, 1.0F};
asm volatile(
"lqc2 vf4, 0x00(%2) # eye \n\t"
"lqc2 vf5, 0x00(%3) # obj \n\t"
"vsub.xyz vf7, vf4, vf5 # view_vec = vf7 \n\t"
"vmove.xyzw vf6, vf0 \n\t"
"vaddw.y vf6, vf0, vf0 # vf6 = { 0.0f, 1.0f, 0.0f, 1.0f } \n\t"
"vopmula.xyz ACC, vf6, vf7 \n\t"
"vopmsub.xyz vf9, vf7, vf6 # vec = vf9 \n\t"
"vopmula.xyz ACC, vf7, vf9 \n\t"
"vopmsub.xyz vf8, vf9, vf7 # up_vec = vf8 \n\t"
"sqc2 vf7, 0x00(%0) # view_vec \n\t"
"sqc2 vf6, 0x00(%1) # up_vec \n\t"
:
: "r"(view_vec), "r"(up_vec), "r"(eye), "r"(obj));
Matrix temp;
temp.setCamera(eye, view_vec, up_vec);
identity();
cross(this->data, this->data, temp.data);
// Vector3 camForward, camUp, camRight;
// Vector3 t_up = Vector3(0.0F, 1.0F, 0.0F);
// camForward = t_position - t_target;
// camForward.normalize();
// camRight = t_up * camForward;
// camRight.normalize();
// camUp = camForward * camRight;
// data[0] = camRight.x;
// data[4] = camRight.y;
// data[8] = camRight.z;
// data[12] = -camRight.innerProduct(t_position);
// data[1] = camUp.x;
// data[5] = camUp.y;
// data[9] = camUp.z;
// data[13] = -camUp.innerProduct(t_position);
// data[2] = camForward.x;
// data[6] = camForward.y;
// data[10] = camForward.z;
// data[14] = -camForward.innerProduct(t_position);
// data[3] = 0;
// data[7] = 0;
// data[11] = 0;
// data[15] = 1;
}
const void Matrix::print() const
{
printf("MATRIX(\n%f, %f, %f, %f\n%f, %f, %f, %f\n%f, %f, %f, %f\n%f, %f, %f, %f\n)\n",
data[0], data[1], data[2], data[3],
data[4], data[5], data[6], data[7],
data[8], data[9], data[10], data[11],
data[12], data[13], data[14], data[15]);
}
// ----
// Private
// ----
void Matrix::rotationX(const float &t_radians)
{
float c = Math::cos(t_radians);
float s = Math::sin(t_radians);
this->data[5] = c; // 1,1
this->data[6] = s; // 1,2
this->data[9] = -s; // 2,1
this->data[10] = c; // 2,2
}
void Matrix::rotationY(const float &t_radians)
{
float c = Math::cos(t_radians);
float s = Math::sin(t_radians);
this->data[0] = c; // 0,0
this->data[2] = -s; // 0,3
this->data[8] = s; // 2,0
this->data[10] = c; // 2,2
}
void Matrix::rotationZ(const float &t_radians)
{ {
this->identity();
float c = Math::cos(t_radians); float c = Math::cos(t_radians);
float s = Math::sin(t_radians); float s = Math::sin(t_radians);
this->data[0] = c; // 0,0 this->data[0] = c; // 0,0
@@ -103,9 +221,121 @@ void Matrix::makeZRotation(float t_radians)
this->data[5] = c; // 1,1 this->data[5] = c; // 1,1
} }
Matrix Matrix::operator*(Matrix &t) void Matrix::rotationByAngle(const float &t_angle, const Vector3 &t_axis)
{
Vector3 localAxis = Vector3(t_axis);
localAxis.normalize();
float x = localAxis.x;
float y = localAxis.y;
float z = localAxis.z;
float c = Math::cos(t_angle);
float s = Math::sin(t_angle);
this->data[0] = x * x * (1 - c) + c;
this->data[1] = y * x * (1 - c) + z * s;
this->data[2] = x * z * (1 - c) - y * s;
this->data[3] = 0.0F;
this->data[4] = x * y * (1 - c) - z * s;
this->data[5] = y * y * (1 - c) + c;
this->data[6] = y * z * (1 - c) + x * s;
this->data[7] = 0.0F;
this->data[8] = x * z * (1 - c) + y * s;
this->data[9] = y * z * (1 - c) - x * s;
this->data[10] = z * z * (1 - c) + c;
this->data[11] = 0.0F;
this->data[12] = 0.0F;
this->data[13] = 0.0F;
this->data[14] = 0.0F;
this->data[15] = 1.0F;
}
void Matrix::translation(const Vector3 &t_val)
{
this->data[12] = t_val.x; // 3,0
this->data[13] = t_val.y; // 3,1
this->data[14] = t_val.z; // 3,2
}
void Matrix::setScale(const Vector3 &t_val)
{
this->data[0] = t_val.x;
this->data[5] = t_val.y;
this->data[10] = t_val.z;
this->data[15] = 1.0F;
}
void Matrix::setCamera(const float t_pos[4], const float t_vz[4], const float t_vy[4])
{
// Matrix vf4, vf5, vf6, vf7
// t_pos vf8
// t_vz vf9
// t_vy vf10
// vtmp vf11
asm volatile(
"lqc2 vf9, 0x00(%2) \n\t"
"lqc2 vf10, 0x00(%3) \n\t"
// mtmp.unit()
"vsub.w vf5, vf0, vf0 # mtmp[1][PW] = 0.0F \n\t"
// vtmp.outerProduct(vy, vz);
"vopmula.xyz ACC, vf10, vf9 \n\t"
"vopmsub.xyz vf11, vf9, vf10 \n\t"
// mtmp[0] = vtmp.normalize();
"vmul.xyz vf12, vf11, vf11 \n\t"
"vaddy.x vf12, vf12, vf12 \n\t"
"vaddz.x vf12, vf12, vf12 \n\t"
"vrsqrt Q, vf0w, vf12x \n\t"
"vsub.xyzw vf4, vf0, vf0 \n\t"
"vwaitq \n\t"
"vmulq.xyz vf4, vf11, Q \n\t"
// mtmp[2] = vz.normalize();
"vmul.xyz vf12, vf9, vf9 \n\t"
"vaddy.x vf12, vf12, vf12 \n\t"
"vaddz.x vf12, vf12, vf12 \n\t"
"vrsqrt Q, vf0w, vf12x \n\t"
"vsub.xyzw vf6, vf0, vf0 \n\t"
"vwaitq \n\t"
"vmulq.xyz vf6, vf9, Q \n\t"
// mtmp[1].outerProduct(mtmp[2], mtmp[0]);
"vopmula.xyz ACC, vf6, vf4 \n\t"
"vopmsub.xyz vf5, vf4, vf6 \n\t"
// mtmp.transpose(pos);
"lqc2 vf7, 0x00(%1) \n\t"
// m = mtmp.inverse();
"qmfc2.ni $11, vf0 \n\t"
"qmfc2.ni $8, vf4 \n\t"
"qmfc2.ni $9, vf5 \n\t"
"qmfc2.ni $10, vf6 \n\t"
"pextlw $12, $9, $8 \n\t"
"pextuw $13, $9, $8 \n\t"
"pextlw $14, $11, $10 \n\t"
"pextuw $15, $11, $10 \n\t"
"pcpyld $8, $14, $12 \n\t"
"pcpyud $9, $12, $14 \n\t"
"pcpyld $10, $15, $13 \n\t"
"qmtc2.ni $8, vf16 \n\t"
"qmtc2.ni $9, vf17 \n\t"
"qmtc2.ni $10, vf18 \n\t"
"vmulax.xyz ACC, vf16, vf7 \n\t"
"vmadday.xyz ACC, vf17, vf7 \n\t"
"vmaddz.xyz vf5, vf18, vf7 \n\t"
"vsub.xyzw vf5, vf0, vf5 \n\t"
"sq $8, 0x00(%0) \n\t"
"sq $9, 0x10(%0) \n\t"
"sq $10, 0x20(%0) \n\t"
"sqc2 vf5, 0x30(%0) \n\t"
:
: "r"(this->data), "r"(t_pos), "r"(t_vz), "r"(t_vy));
}
void Matrix::cross(float res[16], const float a[16], const float b[16]) const
{ {
Matrix result;
asm volatile( asm volatile(
"lqc2 vf1, 0x00(%1) \n\t" "lqc2 vf1, 0x00(%1) \n\t"
"lqc2 vf2, 0x10(%1) \n\t" "lqc2 vf2, 0x10(%1) \n\t"
@@ -136,128 +366,6 @@ Matrix Matrix::operator*(Matrix &t)
"sqc2 vf3, 0x20(%0) \n\t" "sqc2 vf3, 0x20(%0) \n\t"
"sqc2 vf4, 0x30(%0) \n\t" "sqc2 vf4, 0x30(%0) \n\t"
: :
: "r"(result.data), "r"(this->data), "r"(t.data) : "r"(res), "r"(b), "r"(a)
: "memory"); : "memory");
return result;
}
/** Create empty matrix */
Matrix::Matrix()
{
data[0] = 0.0F;
data[1] = 0.0F;
data[2] = 0.0F;
data[3] = 0.0F;
data[4] = 0.0F;
data[5] = 0.0F;
data[6] = 0.0F;
data[7] = 0.0F;
data[8] = 0.0F;
data[9] = 0.0F;
data[10] = 0.0F;
data[11] = 0.0F;
data[12] = 0.0F;
data[13] = 0.0F;
data[14] = 0.0F;
data[15] = 0.0F;
}
Matrix::~Matrix() {}
// ----
// Methods
// ----
/** Set up a perspective projection matrix
*
* Clone of gluPerspective()
* https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml
* @param fov (FOV in radians)/2
* @param aspect Aspect ratio
* @param scrW Half of screen width
* @param scrH Half of screen height
* @param zNear Distance to near plane
* @param zFar Distance to far plane
* @param projScale Projection scale
*/
void Matrix::setPerspective(ScreenSettings &t_screen)
{
float fovYdiv2 = Math::HALF_ANG2RAD * t_screen.fov;
float cotFOV = 1.0F / (Math::sin(fovYdiv2) / Math::cos(fovYdiv2));
float w = cotFOV * (t_screen.width / 4096.0F) / t_screen.aspectRatio;
float h = cotFOV * (t_screen.height / 4096.0F);
this->data[0] = w;
this->data[1] = 0.0F;
this->data[2] = 0.0F;
this->data[3] = 0.0F;
this->data[4] = 0.0F;
this->data[5] = -h;
this->data[6] = 0.0F;
this->data[7] = 0.0F;
this->data[8] = 0.0F;
this->data[9] = 0.0F;
this->data[10] =
(t_screen.farPlaneDist + t_screen.nearPlaneDist) /
(t_screen.farPlaneDist - t_screen.nearPlaneDist);
this->data[11] = -1.0F;
this->data[12] = 0.0F;
this->data[13] = 0.0F;
this->data[14] =
(2.0F * t_screen.farPlaneDist * t_screen.nearPlaneDist) /
(t_screen.farPlaneDist - t_screen.nearPlaneDist);
this->data[15] = 0.0F;
}
/** Create a view matrix that transforms coordinates in
* such a way that the user looks at a target vector
* direction from a position vector.
*
* Clone of OpenGL lookAt function
* https://learnopengl.com/Getting-started/Camera
*/
void Matrix::lookAt(Vector3 &t_up, Vector3 &t_position, Vector3 &t_target)
{
Vector3 camForward, camUp, camRight;
camForward = t_position - t_target;
camForward.normalize();
camRight = t_up * camForward;
camRight.normalize();
camUp = camForward * camRight;
data[0] = camRight.x;
data[4] = camRight.y;
data[8] = camRight.z;
data[12] = -camRight.innerProduct(t_position);
data[1] = camUp.x;
data[5] = camUp.y;
data[9] = camUp.z;
data[13] = -camUp.innerProduct(t_position);
data[2] = camForward.x;
data[6] = camForward.y;
data[10] = camForward.z;
data[14] = -camForward.innerProduct(t_position);
data[3] = 0;
data[7] = 0;
data[11] = 0;
data[15] = 1;
}
void Matrix::print()
{
printf("MATRIX(\n%f, %f, %f, %f\n%f, %f, %f, %f\n%f, %f, %f, %f\n%f, %f, %f, %f\n)\n",
data[0], data[1], data[2], data[3],
data[4], data[5], data[6], data[7],
data[8], data[9], data[10], data[11],
data[12], data[13], data[14], data[15]);
} }
+1 -1
View File
@@ -44,7 +44,7 @@ void Plane::update(Vector3 &a, Vector3 &b, Vector3 &c)
this->distance = -this->normal.innerProduct(b); this->distance = -this->normal.innerProduct(b);
} }
void Plane::print() const void Plane::print() const
{ {
printf("Plane(Vector3(%f, %f, %f), %f)\n", this->normal.x, this->normal.y, this->normal.z, this->distance); printf("Plane(Vector3(%f, %f, %f), %f)\n", this->normal.x, this->normal.y, this->normal.z, this->distance);
} }
+17 -1
View File
@@ -9,6 +9,7 @@
*/ */
#include "../../include/models/math/point.hpp" #include "../../include/models/math/point.hpp"
#include "../../include/utils/math.hpp"
#include <stdio.h> #include <stdio.h>
@@ -55,7 +56,22 @@ void Point::set(const Point &v)
y = v.y; y = v.y;
} }
void Point::print() void Point::rotate(const float &t_angle, const float &t_x, const float &t_y)
{
float s = Math::sin(t_angle);
float c = Math::cos(t_angle);
x -= t_x;
y -= t_y;
float xnew = x * c - y * s;
float ynew = x * s + y * c;
x = xnew + t_x;
y = ynew + t_y;
}
const void Point::print() const
{ {
printf("Point(%f, %f)\n", x, y); printf("Point(%f, %f)\n", x, y);
} }
+151 -198
View File
@@ -9,64 +9,24 @@
*/ */
#include "../../include/models/math/vector3.hpp" #include "../../include/models/math/vector3.hpp"
#include "../../include/utils/math.hpp" #include "../../include/utils/math.hpp"
#include <stdio.h>
// ---- // ----
// Constructors/Destructors // Constructors/Destructors
// ---- // ----
/** Create by specifying 3 points */
Vector3::Vector3(float t_x, float t_y, float t_z)
{
x = t_x;
y = t_y;
z = t_z;
}
/** Create with another vector values */
Vector3::Vector3(const Vector3 &another)
{
x = another.x;
y = another.y;
z = another.z;
}
void Vector3::setByLerp(const Vector3 &v1, const Vector3 &v2, const float &t_interp, const float &t_scale)
{
asm volatile(
"lqc2 vf4, 0x0(%1) \n\t" // vf4 = v1
"lqc2 vf5, 0x0(%2) \n\t" // vf5 = v2
"mfc1 $8, %3 \n\t" // vf6 = t
"qmtc2 $8, vf6 \n\t" // lerp:
"vsub.xyz vf7, vf5, vf4 \n\t" // vf7 = v2 - v1
"vmulx.xyz vf8, vf7, vf6 \n\t" // vf8 = vf7 * t
"vadd.xyz vf9, vf8, vf4 \n\t" // vf9 = vf8 + vf4
"sqc2 vf9, 0x0(%0) \n\t" // v0 = vf9
:
: "r"(&this->xyz), "r"(&v1.xyz), "r"(&v2.xyz), "f"(t_interp)
: "$8");
x *= t_scale;
y *= t_scale;
z *= t_scale;
}
/** Create empty vector */
Vector3::Vector3() Vector3::Vector3()
{ {
x = 0; x = 0.0F;
y = 0; y = 0.0F;
z = 0; z = 0.0F;
} }
Vector3::~Vector3() {}
// ---- // ----
// Methods // Operators
// ---- // ----
Vector3 Vector3::operator+(Vector3 v) Vector3 Vector3::operator+(const Vector3 &v) const
{ {
Vector3 result; Vector3 result;
asm volatile( // VU0 Macro program asm volatile( // VU0 Macro program
@@ -79,7 +39,7 @@ Vector3 Vector3::operator+(Vector3 v)
return result; return result;
} }
Vector3 Vector3::operator-(const Vector3 &v) Vector3 Vector3::operator-(const Vector3 &v) const
{ {
Vector3 result; Vector3 result;
asm volatile( // VU0 Macro program asm volatile( // VU0 Macro program
@@ -92,38 +52,16 @@ Vector3 Vector3::operator-(const Vector3 &v)
return result; return result;
} }
Vector3 Vector3::operator-(void) Vector3 Vector3::operator*(const Vector3 &v) const
{
Vector3 result;
result.x = -x;
result.y = -y;
result.z = -z;
return result;
}
/** Also called "cross product" */
Vector3 Vector3::operator*(Vector3 &v)
{ {
Vector3 res; Vector3 res;
asm volatile( // VU0 Macro program asm volatile( // VU0 Macro program
"lqc2 vf4, 0x0(%1) \n\t" // vf4 = this "lqc2 vf4, 0x0(%1) \n\t" // vf4 = this
"lqc2 vf5, 0x0(%2) \n\t" // vf5 = v "lqc2 vf5, 0x0(%2) \n\t" // vf5 = v
"vopmula.xyz ACC, vf4, vf5 \n\t"
"vmulz.y vf6, vf4, vf5 \n\t" // vf6.y = vf4.y * vf5.z "vopmsub.xyz vf8, vf5, vf4 \n\t"
"vmuly.z vf6, vf4, vf5 \n\t" "vsub.w vf8, vf00, vf00 \n\t"
"vsubz.y vf6, vf6, vf6 \n\t" // vf6.y = vf4.y - vf4.z "sqc2 vf8, 0x0(%0) \n\t" // vf8 = res
"vaddy.x vf8, vf0, vf6 \n\t" // res.x = vf4.y * vf5.z - vf4.z * vf5.y
"vmulx.z vf6, vf4, vf5 \n\t"
"vmulz.x vf6, vf4, vf5 \n\t"
"vsubx.z vf6, vf6, vf6 \n\t"
"vaddz.y vf8, vf0, vf6 \n\t" // res.y = vf4.z * vf5.x - vf4.x * vf5.z
"vmuly.x vf6, vf4, vf5 \n\t"
"vmulx.y vf6, vf4, vf5 \n\t"
"vsuby.x vf6, vf6, vf6 \n\t"
"vaddx.z vf8, vf0, vf6 \n\t" // res.z = vf4.x * vf5.y - vf4.y * vf5.x
"sqc2 vf8, 0x0(%0) \n\t"
: :
: "r"(res.xyz), "r"(this->xyz), "r"(v.xyz)); : "r"(res.xyz), "r"(this->xyz), "r"(v.xyz));
// result.x = y * v.z - z * v.y; // result.x = y * v.z - z * v.y;
@@ -132,7 +70,7 @@ Vector3 Vector3::operator*(Vector3 &v)
return res; return res;
} }
Vector3 Vector3::operator*(float t) Vector3 Vector3::operator*(const float &t) const
{ {
Vector3 result; Vector3 result;
asm volatile( asm volatile(
@@ -142,12 +80,11 @@ Vector3 Vector3::operator*(float t)
"vmulx.xyz vf6, vf4, vf5 \n\t" "vmulx.xyz vf6, vf4, vf5 \n\t"
"sqc2 vf6, 0x0(%0) \n\t" "sqc2 vf6, 0x0(%0) \n\t"
: :
: "r"(result.xyz), "r"(this->xyz), "f"(t) : "r"(result.xyz), "r"(this->xyz), "f"(t));
: "$8");
return result; return result;
} }
Vector3 Vector3::operator/(float t) Vector3 Vector3::operator/(const float &t) const
{ {
Vector3 result; Vector3 result;
result.x = x / t; result.x = x / t;
@@ -156,7 +93,127 @@ Vector3 Vector3::operator/(float t)
return result; return result;
} }
u8 Vector3::shouldBeBackfaceCulled(const Vector3 *t_cameraPos, const Vector3 *v0, const Vector3 *v1, const Vector3 *v2) void Vector3::operator+=(const Vector3 &t)
{
asm volatile( // VU0 Macro program
"lqc2 vf4, 0x0(%0) \n\t"
"lqc2 vf5, 0x0(%1) \n\t"
"vadd.xyz vf4, vf4, vf5 \n\t"
"sqc2 vf4, 0x0(%0) \n\t"
:
: "r"(this->xyz), "r"(t.xyz));
}
void Vector3::operator*=(const float &t)
{
asm volatile(
"lqc2 vf4, 0x0(%0) \n\t"
"mfc1 $8, %1 \n\t"
"qmtc2 $8, vf5 \n\t"
"vmulx.xyz vf4, vf4, vf5 \n\t"
"sqc2 vf4, 0x0(%0) \n\t"
:
: "r"(this->xyz), "f"(t));
}
// ----
// Functions
// ----
void Vector3::set(const Vector3 &v)
{
asm volatile( // VU0 Macro program
"lq $6, 0x0(%1) \n\t"
"sq $6, 0x0(%0) \n\t"
:
: "r"(this->xyz), "r"(v.xyz));
}
void Vector3::set(const float &t_x, const float &t_y, const float &t_z)
{
x = t_x;
y = t_y;
z = t_z;
}
float Vector3::innerProduct(const Vector3 &v) const
{
float result;
asm volatile( // VU0 Macro program
"lqc2 vf4, 0x0(%1) \n\t"
"lqc2 vf5, 0x0(%2) \n\t"
"vmul.xyz vf6, vf4, vf5 \n\t"
"vaddy.x vf6, vf6, vf6 \n\t"
"vaddz.x vf6, vf6, vf6 \n\t"
"qmfc2 $2, vf6 \n\t"
"mtc1 $2, %0 \n\t"
: "=f"(result)
: "r"(this->xyz), "r"(v.xyz));
return result;
// return (x * v.x + y * v.y + z * v.z);
}
float Vector3::length() const
{
float result;
asm volatile( // VU0 Macro program
"lqc2 vf4, 0x0(%1) \n\t"
"vmul.xyz vf5, vf4, vf4 \n\t"
"vaddy.x vf5, vf5, vf5 \n\t"
"vaddz.x vf5, vf5, vf5 \n\t"
"vsqrt Q , vf5x \n\t"
"vwaitq \n\t"
"vaddq.x vf8, vf0, Q \n\t"
"qmfc2 $2, vf8 \n\t"
"mtc1 $2, %0 \n\t"
: "=f"(result)
: "r"(this->xyz));
return result;
// return Math::sqrt(x * x + y * y + z * z);
}
void Vector3::normalize()
{
asm volatile( // VU0 Macro program
"lqc2 vf4, 0x0(%0) \n\t"
"vmul.xyz vf5, vf4, vf4 \n\t"
"vaddy.x vf5, vf5, vf5 \n\t"
"vaddz.x vf5, vf5, vf5 \n\t"
"vrsqrt Q, vf0w, vf5x \n\t"
"vwaitq \n\t"
"vsub.xyz vf6, vf0, vf0 \n\t"
"vaddw.xyz vf6, vf6, vf4 \n\t"
"vwaitq \n\t"
"vmulq.xyz vf6, vf4, Q \n\t"
"sqc2 vf6, 0x0(%0) \n\t"
:
: "r"(this->xyz));
}
float Vector3::distanceTo(const Vector3 &v) const
{
register float result;
asm volatile( // VU0 Macro program
"lqc2 vf4, 0x0(%1) \n\t"
"lqc2 vf5, 0x0(%2) \n\t"
"vsub.xyz vf6, vf4, vf5 \n\t"
"vmul.xyz vf7, vf6, vf6 \n\t"
"vaddy.x vf7, vf7, vf7 \n\t"
"vaddz.x vf7, vf7, vf7 \n\t"
"vsqrt Q , vf7x \n\t"
"vwaitq \n\t"
"vaddq.x vf8, vf0, Q \n\t"
"qmfc2 $2, vf8 \n\t"
"mtc1 $2, %0 \n\t"
: "=f"(result)
: "r"(this->xyz), "r"(v.xyz));
return result;
// return Math::sqrt((this->x - v.x) * (this->x - v.x) +
// (this->y - v.y) * (this->y - v.y) +
// (this->z - v.z) * (this->z - v.z));
}
u8 Vector3::shouldBeBackfaceCulled(const Vector3 *t_cameraPos, const Vector3 *t_v0, const Vector3 *t_v1, const Vector3 *t_v2)
{ {
register float dot; register float dot;
asm volatile( asm volatile(
@@ -176,126 +233,22 @@ u8 Vector3::shouldBeBackfaceCulled(const Vector3 *t_cameraPos, const Vector3 *v0
"qmfc2 $2, vf5 \n\t" // store result on `dot` variable "qmfc2 $2, vf5 \n\t" // store result on `dot` variable
"mtc1 $2, %0 \n\t" "mtc1 $2, %0 \n\t"
: "=f"(dot) : "=f"(dot)
: "r"(t_cameraPos->xyz), "r"(v0->xyz), "r"(v1->xyz), "r"(v2->xyz) : "r"(t_cameraPos->xyz), "r"(t_v0->xyz), "r"(t_v1->xyz), "r"(t_v2->xyz));
: "$2");
return dot <= 0.0F; return dot <= 0.0F;
} }
/** Checks intersection with given square */ void Vector3::setByLerp(const Vector3 &t_v1, const Vector3 &t_v2, const float &t_interp, const float &t_scale)
u8 Vector3::collidesSquare(Vector3 &t_min, Vector3 &t_max)
{ {
return ((this->x <= t_max.x && this->x >= t_min.x) && (this->y < t_max.y && this->y >= t_min.y) && (this->z <= t_max.z && this->z >= t_min.z)) ? 1 : 0; asm volatile(
} "lqc2 vf4, 0x0(%1) \n\t" // vf4 = v1
"lqc2 vf5, 0x0(%2) \n\t" // vf5 = v2
/** Checks is this vector is on given square */ "mfc1 $8, %3 \n\t" // vf6 = t
u8 Vector3::isOnSquare(Vector3 &t_min, Vector3 &t_max) "qmtc2 $8, vf6 \n\t" // lerp:
{ "vsub.xyz vf7, vf5, vf4 \n\t" // vf7 = v2 - v1
return ((this->x <= t_max.x && this->x >= t_min.x) && (this->y >= t_max.y) && (this->z <= t_max.z && this->z >= t_min.z)) ? 1 : 0; "vmulx.xyz vf8, vf7, vf6 \n\t" // vf8 = vf7 * t
} "vadd.xyz vf9, vf8, vf4 \n\t" // vf9 = vf8 + vf4
"sqc2 vf9, 0x0(%0) \n\t" // v0 = vf9
float Vector3::length()
{
register float result;
asm volatile( // VU0 Macro program
"lqc2 vf4, 0x0(%1) \n\t"
"vmul.xyz vf5, vf4, vf4 \n\t"
"vaddy.x vf5, vf5, vf5 \n\t"
"vaddz.x vf5, vf5, vf5 \n\t"
"vsqrt Q , vf5x \n\t"
"vaddq.x vf8, vf0, Q \n\t"
"qmfc2 $2, vf8 \n\t"
"mtc1 $2, %0 \n\t"
: "=f"(result)
: "r"(this->xyz)
: "$2");
return result;
// return Math::sqrt(x * x + y * y + z * z);
}
void Vector3::normalize()
{
asm volatile( // VU0 Macro program
"lqc2 vf4, 0x0(%0) \n\t"
"vmul.xyz vf5, vf4, vf4 \n\t"
"vaddy.x vf5, vf5, vf5 \n\t"
"vaddz.x vf5, vf5, vf5 \n\t"
"vrsqrt Q, vf0w, vf5x \n\t"
"vsub.xyz vf6, vf0, vf0 \n\t"
"vaddw.xyz vf6, vf6, vf4 \n\t"
"vwaitq \n\t"
"vmulq.xyz vf6, vf4, Q \n\t"
"sqc2 vf6, 0x0(%0) \n\t"
: :
: "r"(this->xyz)); : "r"(&this->xyz), "r"(&t_v1.xyz), "r"(&t_v2.xyz), "f"(t_interp));
} operator*=(t_scale);
/** Also called dot3 */
float Vector3::innerProduct(Vector3 &v)
{
register float result;
asm volatile( // VU0 Macro program
"lqc2 vf4, 0x0(%1) \n\t"
"lqc2 vf5, 0x0(%2) \n\t"
"vmul.xyz vf6, vf4, vf5 \n\t"
"vaddy.x vf6, vf6, vf6 \n\t"
"vaddz.x vf6, vf6, vf6 \n\t"
"qmfc2 $2, vf6 \n\t"
"mtc1 $2, %0 \n\t"
: "=f"(result)
: "r"(this->xyz), "r"(v.xyz)
: "$2");
return result;
// return (x * v.x + y * v.y + z * v.z);
}
void Vector3::set(const float &x, const float &y, const float &z)
{
this->x = x;
this->y = y;
this->z = z;
}
void Vector3::set(const Vector3 &v)
{
this->x = v.x;
this->y = v.y;
this->z = v.z;
}
void Vector3::copy(Vector3 &v)
{
asm volatile( // VU0 Macro program
"lq $6, 0x0(%1) \n\t"
"sq $6, 0x0(%0) \n\t"
:
: "r"(v.xyz), "r"(this->xyz)
: "$6");
}
float Vector3::distanceTo(Vector3 &v)
{
register float result;
asm volatile( // VU0 Macro program
"lqc2 vf4, 0x0(%1) \n\t"
"lqc2 vf5, 0x0(%2) \n\t"
"vsub.xyz vf6, vf4, vf5 \n\t"
"vmul.xyz vf7, vf6, vf6 \n\t"
"vaddy.x vf7, vf7, vf7 \n\t"
"vaddz.x vf7, vf7, vf7 \n\t"
"vsqrt Q , vf7x \n\t"
"vaddq.x vf8, vf0, Q \n\t"
"qmfc2 $2, vf8 \n\t"
"mtc1 $2, %0 \n\t"
: "=f"(result)
: "r"(this->xyz), "r"(v.xyz)
: "$2");
return result;
// return Math::sqrt((this->x - another.x) * (this->x - another.x) +
// (this->y - another.y) * (this->y - another.y) +
// (this->z - another.z) * (this->z - another.z));
}
void Vector3::print()
{
printf("Vector3(%f, %f, %f)\n", x, y, z);
} }
+140 -35
View File
@@ -13,7 +13,7 @@
#include "../include/loaders/md2_loader.hpp" #include "../include/loaders/md2_loader.hpp"
#include "../include/loaders/dff_loader.hpp" #include "../include/loaders/dff_loader.hpp"
#include "../include/loaders/bmp_loader.hpp" #include "../include/loaders/bmp_loader.hpp"
#include "../include/models/mesh_texture.hpp" #include "../include/models/texture.hpp"
#include "../include/utils/debug.hpp" #include "../include/utils/debug.hpp"
#include "../include/utils/string.hpp" #include "../include/utils/string.hpp"
#include <cstdlib> #include <cstdlib>
@@ -185,55 +185,160 @@ void Mesh::animate()
u32 Mesh::getDrawData(u32 t_materialIndex, VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, Vector3 &t_cameraPos) u32 Mesh::getDrawData(u32 t_materialIndex, VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, Vector3 &t_cameraPos)
{ {
VECTOR ONE_VEC = {1.0F, 1.0F, 1.0F, 1.0F};
asm volatile(
// VU0 macro program:
// Load vector with 1.0F values to VF21
"lqc2 vf21, 0x0(%0) \n\t" // load "one vec"
:
: "r"(ONE_VEC));
u32 addedFaces = 0; u32 addedFaces = 0;
#define CURR_FRAME frames[animState.currentFrame] #define CURR_FRAME frames[animState.currentFrame]
#define NEXT_FRAME frames[animState.nextFrame] #define NEXT_FRAME frames[animState.nextFrame]
MeshMaterial *material = &CURR_FRAME.getMaterial(t_materialIndex); // cache MeshMaterial *material = &CURR_FRAME.getMaterial(t_materialIndex); // cache
u32 *vertFaces = material->getVertexFaces(); // cache
u32 *normalFaces = material->getNormalFaces(); // cache
u32 *stFaces = material->getSTFaces(); // cache
Vector3 *verts = CURR_FRAME.getVertices(); // cache Vector3 *verts = CURR_FRAME.getVertices(); // cache
Vector3 *nextVerts = NEXT_FRAME.getVertices(); // cache Vector3 *nextVerts = NEXT_FRAME.getVertices(); // cache
Point *sts = CURR_FRAME.getSTs(); // cache Point *sts = CURR_FRAME.getSTs(); // cache
Vector3 *normals = CURR_FRAME.getNormals(); // cache Vector3 *normals = CURR_FRAME.getNormals(); // cache
#define CURR_VERT verts[material->getVertexFace(matI + vertI)]
#define CURR_ST sts[material->getSTFace(matI + vertI)]
#define CURR_NORMAL normals[material->getNormalFace(matI + vertI)]
#define NEXT_VERT nextVerts[material->getVertexFace(matI + vertI)]
for (u32 matI = 0; matI < material->getFacesCount(); matI += 3) for (u32 faceI = 0; faceI < material->getFacesCount(); faceI += 3)
{ {
for (u32 vertI = 0; vertI < 3; vertI++) if (animState.currentFrame != animState.nextFrame)
if (animState.currentFrame != animState.nextFrame) {
calc3Vectors[vertI].setByLerp(CURR_VERT, NEXT_VERT, animState.interpolation, scale); asm volatile(
// VU0 macro program:
// Calculate lerp() and store data into calc3Vectors
// Vertex 0
"lqc2 vf4, 0x0(%3) \n\t" // vf4 = v1
"lqc2 vf5, 0x0(%6) \n\t" // vf5 = v2
"mfc1 $10, %9 \n\t" // vf6 = t
"qmtc2 $10, vf6 \n\t" // lerp:
"vsub.xyz vf7, vf5, vf4 \n\t" // vf7 = v2 - v1
"vmulx.xyz vf8, vf7, vf6 \n\t" // vf8 = vf7 * t
"vadd.xyz vf9, vf8, vf4 \n\t" // vf9 = vf8 + vf4
"sqc2 vf9, 0x0(%0) \n\t" // v0 = vf9
// Vertex 1
"lqc2 vf4, 0x0(%4) \n\t" // vf4 = v1
"lqc2 vf5, 0x0(%7) \n\t" // vf5 = v2
"mfc1 $10, %9 \n\t" // vf6 = t
"qmtc2 $10, vf6 \n\t" // lerp:
"vsub.xyz vf7, vf5, vf4 \n\t" // vf7 = v2 - v1
"vmulx.xyz vf8, vf7, vf6 \n\t" // vf8 = vf7 * t
"vadd.xyz vf9, vf8, vf4 \n\t" // vf9 = vf8 + vf4
"sqc2 vf9, 0x0(%1) \n\t" // v0 = vf9
// Vertex 2
"lqc2 vf4, 0x0(%5) \n\t" // vf4 = v1
"lqc2 vf5, 0x0(%8) \n\t" // vf5 = v2
"mfc1 $10, %9 \n\t" // vf6 = t
"qmtc2 $10, vf6 \n\t" // lerp:
"vsub.xyz vf7, vf5, vf4 \n\t" // vf7 = v2 - v1
"vmulx.xyz vf8, vf7, vf6 \n\t" // vf8 = vf7 * t
"vadd.xyz vf9, vf8, vf4 \n\t" // vf9 = vf8 + vf4
"sqc2 vf9, 0x0(%2) \n\t" // v0 = vf9
:
: "r"(calc3Vectors[0].xyz),
"r"(calc3Vectors[1].xyz),
"r"(calc3Vectors[2].xyz),
"r"(verts[vertFaces[faceI]].xyz),
"r"(verts[vertFaces[faceI + 1]].xyz),
"r"(verts[vertFaces[faceI + 2]].xyz),
"r"(nextVerts[vertFaces[faceI]].xyz),
"r"(nextVerts[vertFaces[faceI + 1]].xyz),
"r"(nextVerts[vertFaces[faceI + 2]].xyz),
"f"(animState.interpolation)
: "$10");
}
else
{
asm volatile(
// VU0 macro program
// Copy 0,1,2 vertices
"lqc2 vf1, 0x0(%3) \n\t" // load vert
"lqc2 vf2, 0x0(%4) \n\t" // load normal
"lqc2 vf3, 0x0(%5) \n\t" // load st
"sqc2 vf1, 0x0(%0) \n\t" // store vert
"sqc2 vf2, 0x0(%1) \n\t" // store normal
"sqc2 vf3, 0x0(%2) \n\t" // store st
:
: "r"(calc3Vectors[0].xyz),
"r"(calc3Vectors[1].xyz),
"r"(calc3Vectors[2].xyz),
"r"(verts[vertFaces[faceI]].xyz),
"r"(verts[vertFaces[faceI + 1]].xyz),
"r"(verts[vertFaces[faceI + 2]].xyz));
}
if (!shouldBeBackfaceCulled || if (!shouldBeBackfaceCulled ||
Vector3::shouldBeBackfaceCulled(&t_cameraPos, &calc3Vectors[0], &calc3Vectors[1], &calc3Vectors[2])) !Vector3::shouldBeBackfaceCulled(&t_cameraPos, &calc3Vectors[2], &calc3Vectors[1], &calc3Vectors[0]))
{
for (u32 vertI = 0; vertI < 3; vertI++) asm volatile(
{ // VU0 macro program:
// Copy data and set vert/normal "w" and st "z"+"w" to 1.0F
if (animState.currentFrame == animState.nextFrame) // Vertex 0
{ "lqc2 vf1, 0x0(%3) \n\t" // load vert
o_vertices[addedFaces][0] = CURR_VERT.x; "lqc2 vf2, 0x0(%4) \n\t" // load normal
o_vertices[addedFaces][1] = CURR_VERT.y; "lqc2 vf3, 0x0(%5) \n\t" // load st
o_vertices[addedFaces][2] = CURR_VERT.z; "vadd.w vf1, vf20, vf21 \n\t" // set vert.w to 1.0F
} "vadd.w vf2, vf20, vf21 \n\t" // set normal.W to 1.0F
else "vadd.zw vf3, vf20, vf21 \n\t" // set st.zw to 1.0F
{ "sqc2 vf1, 0x0(%0) \n\t" // store vert
o_vertices[addedFaces][0] = calc3Vectors[vertI].x; "sqc2 vf2, 0x0(%1) \n\t" // store normal
o_vertices[addedFaces][1] = calc3Vectors[vertI].y; "sqc2 vf3, 0x0(%2) \n\t" // store st
o_vertices[addedFaces][2] = calc3Vectors[vertI].z;
}
o_vertices[addedFaces][3] = 1.0F;
o_normals[addedFaces][0] = CURR_NORMAL.x; // Vertex 1
o_normals[addedFaces][1] = CURR_NORMAL.y; "lqc2 vf1, 0x0(%9) \n\t" // load vert
o_normals[addedFaces][2] = CURR_NORMAL.z; "lqc2 vf2, 0x0(%10) \n\t" // load normal
o_normals[addedFaces][3] = 1.0F; "lqc2 vf3, 0x0(%11) \n\t" // load st
"vadd.w vf1, vf20, vf21 \n\t" // set vert.w to 1.0F
"vadd.w vf2, vf20, vf21 \n\t" // set normal.W to 1.0F
"vadd.zw vf3, vf20, vf21 \n\t" // set st.zw to 1.0F
"sqc2 vf1, 0x0(%6) \n\t" // store vert
"sqc2 vf2, 0x0(%7) \n\t" // store normal
"sqc2 vf3, 0x0(%8) \n\t" // store st
o_coordinates[addedFaces][0] = CURR_ST.x; // Vertex 2
o_coordinates[addedFaces][1] = CURR_ST.y; "lqc2 vf1, 0x0(%15) \n\t" // load vert
o_coordinates[addedFaces][2] = 1.0F; "lqc2 vf2, 0x0(%16) \n\t" // load normal
o_coordinates[addedFaces++][3] = 1.0F; "lqc2 vf3, 0x0(%17) \n\t" // load st
} "vadd.w vf1, vf20, vf21 \n\t" // set vert.w to 1.0F
"vadd.w vf2, vf20, vf21 \n\t" // set normal.W to 1.0F
"vadd.zw vf3, vf20, vf21 \n\t" // set st.zw to 1.0F
"sqc2 vf1, 0x0(%12) \n\t" // store vert
"sqc2 vf2, 0x0(%13) \n\t" // store normal
"sqc2 vf3, 0x0(%14) \n\t" // store st
:
: "r"(o_vertices[addedFaces]),
"r"(o_normals[addedFaces]),
"r"(o_coordinates[addedFaces]),
"r"(calc3Vectors[0].xyz),
"r"(normals[normalFaces[faceI]].xyz),
"r"(sts[stFaces[faceI]].xy),
"r"(o_vertices[addedFaces + 1]),
"r"(o_normals[addedFaces + 1]),
"r"(o_coordinates[addedFaces + 1]),
"r"(calc3Vectors[1].xyz),
"r"(normals[normalFaces[faceI + 1]].xyz),
"r"(sts[stFaces[faceI + 1]].xy),
"r"(o_vertices[addedFaces + 2]),
"r"(o_normals[addedFaces + 2]),
"r"(o_coordinates[addedFaces + 2]),
"r"(calc3Vectors[2].xyz),
"r"(normals[normalFaces[faceI + 2]].xyz),
"r"(sts[stFaces[faceI + 2]].xy));
addedFaces += 3;
}
} }
return addedFaces; return addedFaces;
} }
@@ -242,7 +347,7 @@ u8 Mesh::isInFrustum(Plane *t_frustumPlanes)
{ {
Vector3 boxCalcTemp; Vector3 boxCalcTemp;
u8 boxResult = 1, boxIn = 0, boxOut = 0; u8 boxResult = 1, boxIn = 0, boxOut = 0;
Vector3 *currentBoundingBox = getCurrentBoundingBox(); const Vector3 *currentBoundingBox = getCurrentBoundingBoxVertices();
for (int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
{ {
boxOut = 0; boxOut = 0;
+7
View File
@@ -37,6 +37,7 @@ MeshFrame::~MeshFrame()
delete[] normals; delete[] normals;
if (_areMaterialsAllocated) if (_areMaterialsAllocated)
delete[] materials; delete[] materials;
delete boundingBoxObj;
} }
// ---- // ----
@@ -93,6 +94,7 @@ void MeshFrame::allocateMaterials(const u32 &t_val)
void MeshFrame::calculateBoundingBoxes() void MeshFrame::calculateBoundingBoxes()
{ {
Vector3 boundingBox[8];
if (!_areVerticesAllocated) if (!_areVerticesAllocated)
{ {
PRINT_ERR("Can't calculate bounding box, because vertices were not allocated!"); PRINT_ERR("Can't calculate bounding box, because vertices were not allocated!");
@@ -121,6 +123,7 @@ void MeshFrame::calculateBoundingBoxes()
if (hiZ < vertices[i].z) if (hiZ < vertices[i].z)
hiZ = vertices[i].z; hiZ = vertices[i].z;
} }
boundingBox[0].set(lowX, lowY, lowZ); boundingBox[0].set(lowX, lowY, lowZ);
boundingBox[1].set(lowX, lowY, hiZ); boundingBox[1].set(lowX, lowY, hiZ);
boundingBox[2].set(lowX, hiY, lowZ); boundingBox[2].set(lowX, hiY, lowZ);
@@ -131,4 +134,8 @@ void MeshFrame::calculateBoundingBoxes()
boundingBox[6].set(hiX, hiY, lowZ); boundingBox[6].set(hiX, hiY, lowZ);
boundingBox[7].set(hiX, hiY, hiZ); boundingBox[7].set(hiX, hiY, hiZ);
_isBoundingBoxCalculated = true; _isBoundingBoxCalculated = true;
//BoundingBox is declared on the heap to prevent any ill-formed default
//constructor instantiated BoundingBox objects.
boundingBoxObj = new BoundingBox(boundingBox);
} }
+12 -5
View File
@@ -9,6 +9,7 @@
*/ */
#include "../include/models/mesh_material.hpp" #include "../include/models/mesh_material.hpp"
#include "../include/models/bounding_box.hpp"
#include "../include/utils/debug.hpp" #include "../include/utils/debug.hpp"
#include "../include/utils/string.hpp" #include "../include/utils/string.hpp"
#include <cstdlib> #include <cstdlib>
@@ -71,19 +72,20 @@ u8 MeshMaterial::isInFrustum(Plane *t_frustumPlanes, const Vector3 &position)
{ {
Vector3 boxCalcTemp; Vector3 boxCalcTemp;
u8 boxResult = 1, boxIn = 0, boxOut = 0; u8 boxResult = 1, boxIn = 0, boxOut = 0;
for (int i = 0; i < 6; i++)
for (u8 i = 0; i < 6; i++)
{ {
boxOut = 0; boxOut = 0;
boxIn = 0; boxIn = 0;
// for each corner of the box do ... // for each corner of the box do ...
// get out of the cycle as soon as a box as corners // get out of the cycle as soon as a box as corners
// both inside and out of the frustum // both inside and out of the frustum
for (int y = 0; y < 8 && (boxIn == 0 || boxOut == 0); y++) for (u8 y = 0; y < 8 && (boxIn == 0 || boxOut == 0); y++)
{ {
boxCalcTemp.set( boxCalcTemp.set(
boundingBox[y].x + position.x, boundingBoxObj->getVertex(y).x + position.x,
boundingBox[y].y + position.y, boundingBoxObj->getVertex(y).y + position.y,
boundingBox[y].z + position.z); boundingBoxObj->getVertex(y).z + position.z);
if (t_frustumPlanes[i].distanceTo(boxCalcTemp) < 0) if (t_frustumPlanes[i].distanceTo(boxCalcTemp) < 0)
boxOut++; boxOut++;
else else
@@ -100,6 +102,7 @@ u8 MeshMaterial::isInFrustum(Plane *t_frustumPlanes, const Vector3 &position)
void MeshMaterial::calculateBoundingBox(Vector3 *t_vertices, u32 t_vertCount) void MeshMaterial::calculateBoundingBox(Vector3 *t_vertices, u32 t_vertCount)
{ {
Vector3 boundingBox[8];
float lowX, lowY, lowZ, hiX, hiY, hiZ; float lowX, lowY, lowZ, hiX, hiY, hiZ;
lowX = hiX = t_vertices[vertexFaces[0]].x; lowX = hiX = t_vertices[vertexFaces[0]].x;
lowY = hiY = t_vertices[vertexFaces[0]].y; lowY = hiY = t_vertices[vertexFaces[0]].y;
@@ -131,4 +134,8 @@ void MeshMaterial::calculateBoundingBox(Vector3 *t_vertices, u32 t_vertCount)
boundingBox[6].set(hiX, hiY, lowZ); boundingBox[6].set(hiX, hiY, lowZ);
boundingBox[7].set(hiX, hiY, hiZ); boundingBox[7].set(hiX, hiY, hiZ);
_isBoundingBoxCalculated = true; _isBoundingBoxCalculated = true;
//BoundingBox is declared on the heap to prevent any ill-formed default
//constructor instantiated BoundingBox objects.
boundingBoxObj = new BoundingBox(boundingBox);
} }
+56
View File
@@ -0,0 +1,56 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "../include/models/sprite.hpp"
#include "../include/utils/debug.hpp"
#include "../include/utils/string.hpp"
#include <cstdlib>
// ----
// Constructors/Destructors
// ----
Sprite::Sprite()
{
id = rand() % 1000000;
_isSizeSet = false;
_flipH = false;
_flipV = false;
scale = 1.0F;
mode = MODE_REPEAT;
setDefaultColor();
setDefaultLODAndClut();
}
Sprite::~Sprite() {}
// ----
// Methods
// ----
/** Set's default object color + no transparency */
void Sprite::setDefaultColor()
{
color.r = 0x80;
color.g = 0x80;
color.b = 0x80;
color.a = 0x80;
color.q = 0.0F;
}
/** Sets texture level of details settings and CLUT settings */
void Sprite::setDefaultLODAndClut()
{
clut.storage_mode = CLUT_STORAGE_MODE1;
clut.start = 0;
clut.psm = 0;
clut.load_method = CLUT_NO_LOAD;
clut.address = 0;
}
@@ -8,7 +8,7 @@
# Sandro Sobczyński <sandro.sobczynski@gmail.com> # Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/ */
#include "../include/models/mesh_texture.hpp" #include "../include/models/texture.hpp"
#include "../include/utils/string.hpp" #include "../include/utils/string.hpp"
#include <cstdlib> #include <cstdlib>
#include <draw_sampling.h> #include <draw_sampling.h>
@@ -17,7 +17,7 @@
// Constructors/Destructors // Constructors/Destructors
// ---- // ----
MeshTexture::MeshTexture() Texture::Texture()
{ {
id = rand() % 1000000; id = rand() % 1000000;
_isSizeSet = false; _isSizeSet = false;
@@ -25,7 +25,7 @@ MeshTexture::MeshTexture()
setDefaultWrapSettings(); setDefaultWrapSettings();
} }
MeshTexture::~MeshTexture() Texture::~Texture()
{ {
if (getTextureLinksCount() > 0) if (getTextureLinksCount() > 0)
texLinks.clear(); texLinks.clear();
@@ -39,20 +39,23 @@ MeshTexture::~MeshTexture()
// Methods // Methods
// ---- // ----
void MeshTexture::setSize(const u8 &t_width, const u8 &t_height) void Texture::setSize(const u8 &t_width, const u8 &t_height, const TextureType &t_type)
{ {
if (_isSizeSet) if (_isSizeSet)
{ {
PRINT_ERR("Can't set size, because was already set!"); PRINT_ERR("Can't set size, because was already set!");
return; return;
} }
if (t_width > 256 || t_height > 256)
PRINT_ERR("Given texture can be too big for PS2. Please strict to 256x256 max. Prefer 128x128.");
width = t_width; width = t_width;
height = t_height; height = t_height;
_type = t_type;
data = new unsigned char[getDataSize()]; data = new unsigned char[getDataSize()];
_isSizeSet = true; _isSizeSet = true;
} }
void MeshTexture::setName(char *t_val) void Texture::setName(char *t_val)
{ {
if (_isNameSet) if (_isNameSet)
{ {
@@ -63,7 +66,7 @@ void MeshTexture::setName(char *t_val)
_isNameSet = true; _isNameSet = true;
} }
void MeshTexture::setDefaultWrapSettings() void Texture::setDefaultWrapSettings()
{ {
wrapSettings.horizontal = WRAP_REPEAT; wrapSettings.horizontal = WRAP_REPEAT;
wrapSettings.vertical = WRAP_REPEAT; wrapSettings.vertical = WRAP_REPEAT;
@@ -73,16 +76,24 @@ void MeshTexture::setDefaultWrapSettings()
wrapSettings.minv = 0; wrapSettings.minv = 0;
} }
void MeshTexture::setWrapSettings(const WrapSettings t_horizontal, const WrapSettings t_vertical) void Texture::setWrapSettings(const WrapSettings t_horizontal, const WrapSettings t_vertical)
{ {
wrapSettings.horizontal = t_horizontal; wrapSettings.horizontal = t_horizontal;
wrapSettings.vertical = t_vertical; wrapSettings.vertical = t_vertical;
} }
void MeshTexture::addLink(const u32 &t_meshId, const u32 &t_materialId) void Texture::addLink(const u32 &t_meshId, const u32 &t_materialId)
{ {
TextureLink link; TextureLink link;
link.materialId = t_materialId; link.materialId = t_materialId;
link.meshId = t_meshId; link.meshOrSpriteId = t_meshId;
texLinks.push_back(link);
}
void Texture::addLink(const u32 &t_spriteId)
{
TextureLink link;
link.materialId = 0;
link.meshOrSpriteId = t_spriteId;
texLinks.push_back(link); texLinks.push_back(link);
} }
+233 -179
View File
@@ -9,30 +9,34 @@
*/ */
#include "../include/modules/audio.hpp" #include "../include/modules/audio.hpp"
#include <loadfile.h>
#include "../include/utils/string.hpp" #include "../include/utils/string.hpp"
#include "../include/utils/debug.hpp" #include "../include/utils/debug.hpp"
#include <loadfile.h>
#define SONG_NAME "MOV-CIRC.WAV" #include <cstdlib>
const int AUDSRV_BUFFER_SIZE = 1024 * 4;
// ---- // ----
// Constructors/Destructors // Constructors/Destructors
// ---- // ----
Audio *audioRef; Audio *audioRef;
Audio::Audio() Audio::Audio()
{ {
addedListeners = 0; // We must set it to 0 on songStop();
isInitialized = 0; realVolume = 100;
songLoaded = 0; volume = 100;
isVolumeSet = 0; chunkReadStatus = 0;
shouldPlay = 0;
songLoaded = false;
songPlaying = false;
songInLoop = false;
songFinished = false;
audioRef = this; audioRef = this;
initSema(); initSema();
loadModules(); loadModules();
initAUDSRV(); initAUDSRV();
setSongFormat();
} }
Audio::~Audio() {} Audio::~Audio() {}
@@ -41,208 +45,258 @@ Audio::~Audio() {}
// Methods // Methods
// ---- // ----
/** Initialize audio module void Audio::loadSong(char *t_path)
* {
* - Initialize threading semaphore if (songLoaded)
* - Load modules unloadSong();
* - Initialize AUDSRV char *fullFilename = String::createConcatenated("host:", t_path);
* - Load background song wav = fopen(fullFilename, "rb");
delete[] fullFilename;
if (wav == NULL)
PRINT_ERR("Failed to open wav file!");
else
{
rewindSongToStart();
songLoaded = true;
PRINT_LOG("Song loaded!");
}
}
void Audio::playSong()
{
if (!songLoaded)
PRINT_ERR("Cant play song because was not loaded!");
if (songFinished)
rewindSongToStart();
volume = realVolume;
songPlaying = true;
}
void Audio::stopSong()
{
volume = 0;
audsrv_set_volume(volume);
songPlaying = false;
}
void Audio::setSongVolume(const u8 &t_vol)
{
realVolume = t_vol;
if (songPlaying)
volume = t_vol;
audsrv_set_volume(volume);
}
u32 Audio::addSongListener(AudioListener *t_listener)
{
AudioListenerRef *ref = new AudioListenerRef;
ref->id = rand() % 1000000;
ref->listener = t_listener;
songListeners.push_back(ref);
return ref->id;
}
void Audio::removeSongListener(const u32 &t_id)
{
s32 index = -1;
for (u32 i = 0; i < songListeners.size(); i++)
if (songListeners[i]->id == t_id)
{
index = i;
break;
}
if (index == -1)
PRINT_ERR("Cant remove listener because given id was not found!");
delete songListeners[index];
songListeners.erase(songListeners.begin() + index);
}
// ADPCM
audsrv_adpcm_t *Audio::loadADPCM(char *t_path)
{
char *fullFilename = String::createConcatenated("host:", t_path);
FILE *file = fopen(fullFilename, "rb");
delete[] fullFilename;
fseek(file, 0, SEEK_END);
u32 adpcmFileSize = ftell(file);
u8 data[adpcmFileSize];
rewind(file);
fread(data, sizeof(u8), adpcmFileSize, file);
audsrv_adpcm_t *result = new audsrv_adpcm_t();
result->size = 0;
result->buffer = 0;
result->loop = 0;
result->pitch = 0;
result->channels = 0;
if (audsrv_load_adpcm(result, data, adpcmFileSize))
{
printf("AUDSRV returned error string: %s", audsrv_get_error_string());
PRINT_ERR("audsrv_load_adpcm() failed!");
}
fclose(file);
return result;
}
void Audio::playADPCM(audsrv_adpcm_t *t_adpcm)
{
if (audsrv_play_adpcm(t_adpcm))
{
printf("AUDSRV returned error string: %s", audsrv_get_error_string());
PRINT_ERR("audsrv_play_adpcm() failed!");
}
}
void Audio::playADPCM(audsrv_adpcm_t *t_adpcm, const s8 &t_ch)
{
if (audsrv_ch_play_adpcm(t_ch, t_adpcm))
{
printf("AUDSRV returned error string: %s", audsrv_get_error_string());
PRINT_ERR("audsrv_play_adpcm() failed!");
}
}
// Other
void Audio::startThread(FileService *t_fileService)
{
PRINT_LOG("Creating audio thread");
// fileService = t_fileService;
extern void *_gp;
thread.func = (void *)Audio::mainThread;
thread.stack = threadStack;
thread.stack_size = getThreadStackSize();
thread.gp_reg = (void *)&_gp;
thread.initial_priority = 0x17;
if ((threadId = CreateThread(&thread)) < 0)
PRINT_ERR("Create audio thread failed!");
PRINT_LOG("Audio thread created");
StartThread(threadId, NULL);
PRINT_LOG("Audio thread started");
}
/** Main thread loop */
void Audio::threadLoop()
{
if (!songPlaying || !songLoaded)
return;
if (songFinished)
{
printf("Audio: Song finished. ");
if (songInLoop)
{
printf("Running again.\n");
for (u32 i = 0; i < getSongListenersCount(); i++)
songListeners[i]->listener->onAudioFinish();
rewindSongToStart();
}
else
{
printf("Stopping song.\n");
stopSong();
return;
}
}
if (chunkReadStatus > 0)
{
WaitSema(fillbufferSema); // wait until previous chunk wasn't finished
audsrv_play_audio(wavChunk, chunkReadStatus);
for (u32 i = 0; i < getSongListenersCount(); i++)
songListeners[i]->listener->onAudioTick();
}
chunkReadStatus = fread(wavChunk, 1, sizeof(wavChunk), wav);
if (chunkReadStatus < (s32)sizeof(wavChunk))
songFinished = true;
}
/**
* Close file.
* Delete song path from memory.
*/ */
void Audio::init(u32 t_listenersAmount) void Audio::unloadSong()
{ {
PRINT_LOG("Initialize audio module started"); songLoaded = false;
listenersAmount = t_listenersAmount; fclose(wav);
listeners = new AudioListener *[t_listenersAmount];
isInitialized = true;
PRINT_LOG("Audio module initialized!");
} }
void Audio::addListener(AudioListener *t_listener) /** Set WAV format to 16bit, 22050Hz, stereo. */
void Audio::setSongFormat()
{ {
listeners[addedListeners++] = t_listener; format.bits = 16;
format.freq = 22050;
format.channels = 2;
audsrv_set_format(&format);
} }
/** Initialize threading semaphore */ /** Fseek on wav. */
void Audio::rewindSongToStart()
{
if (wav != NULL)
fseek(wav, 0x30, SEEK_SET);
songFinished = false;
}
/** Initialize semaphore which will wait until chunk of the song is not finished. */
void Audio::initSema() void Audio::initSema()
{ {
PRINT_LOG("Creating semaphore started"); PRINT_LOG("Creating audio semaphore");
sema.init_count = 0; sema.init_count = 0;
sema.max_count = 1; sema.max_count = 1;
sema.option = 0; sema.option = 0;
fillbufferSema = CreateSema(&sema); fillbufferSema = CreateSema(&sema);
PRINT_LOG("Semaphore created"); PRINT_LOG("Audio semaphore created");
} }
/** Load LIBSD and AUDSRV */ /** Load LIBSD and AUDSRV modules */
void Audio::loadModules() void Audio::loadModules()
{ {
PRINT_LOG("Modules loading started (LIBSD, AUDSRV)"); PRINT_LOG("Modules loading started (LIBSD, AUDSRV)");
ret = SifLoadModule("rom0:LIBSD", 0, NULL); int ret = SifLoadModule("rom0:LIBSD", 0, NULL);
if (ret == -203)
PRINT_ERR("LIBSD loading failed!");
ret = SifLoadModule("host:AUDSRV.IRX", 0, NULL); ret = SifLoadModule("host:AUDSRV.IRX", 0, NULL);
PRINT_LOG("Modules loaded"); if (ret == -203)
PRINT_ERR("AUDSRV.IRX loading failed!");
PRINT_LOG("Audio modules loaded");
} }
/** Initialize AUDSRV and install fillbuffer callback */ /**
* Initialize AUDSRV main and ADPCM module.
* Install AUDSRV callback.
*/
void Audio::initAUDSRV() void Audio::initAUDSRV()
{ {
PRINT_LOG("Initialize AUDSRV started"); PRINT_LOG("Initializing AUDSRV");
ret = audsrv_init(); int ret = audsrv_init();
if (ret != 0) if (ret != 0)
{ {
printf("AUDSRV returned error string: %s", audsrv_get_error_string());
PRINT_ERR("Failed to initialize AUDSRV!"); PRINT_ERR("Failed to initialize AUDSRV!");
}
ret = audsrv_adpcm_init();
if (ret != 0)
{
printf("AUDSRV returned error string: %s", audsrv_get_error_string()); printf("AUDSRV returned error string: %s", audsrv_get_error_string());
PRINT_ERR("Failed to initialize AUDSRV ADPCM!");
} }
else ret = audsrv_on_fillbuf(getSongBufferSize(), (audsrv_callback_t)iSignalSema, (void *)fillbufferSema);
if (ret != 0)
{ {
ret = audsrv_on_fillbuf(AUDSRV_BUFFER_SIZE, Audio::fillbuffer, (void *)fillbufferSema);
PRINT_LOG("AUDSRV initialized!");
}
}
/** Set audio format, volume and load song */
void Audio::loadSong(char *t_filename)
{
if (!isInitialized)
{
PRINT_ERR("Please initialize audio class first!");
return;
}
PRINT_LOG("Song loading started");
format.bits = 16;
format.freq = 22050;
format.channels = 2;
char *fullFilename = String::createConcatenated("host:", t_filename);
int err = audsrv_set_format(&format);
if (err == 0)
{
PRINT_LOG("Audio format set");
if (!isVolumeSet)
setVolume(MAX_VOLUME);
PRINT_LOG("Opening song file: " SONG_NAME);
wav = fopen(fullFilename, "rb");
delete[] fullFilename;
if (wav == NULL)
{
PRINT_ERR("Failed to open wav file!");
audsrv_quit();
}
else
{
fseek(wav, 0x30, SEEK_SET);
played = 0;
songLoaded = 1;
PRINT_LOG("Song loaded!");
}
}
else
{
PRINT_ERR("Failed to set audio format!");
printf("AUDSRV returned error string: %s", audsrv_get_error_string()); printf("AUDSRV returned error string: %s", audsrv_get_error_string());
PRINT_ERR("Failed to initialize AUDSRV fillbuffer!");
} }
PRINT_LOG("AUDSRV initialized!");
} }
void Audio::setVolume(u8 t_volume) /**
{ * Do not call this function.
audsrv_set_volume(t_volume); * This is a audio thread, runned by engine
isVolumeSet = true; */
} void Audio::mainThread()
/** Create and start audio thread. */
void Audio::startThread()
{
PRINT_LOG("Creating audio thread");
extern void *_gp;
audioThreadAttr.func = (void *)Audio::audioThread;
audioThreadAttr.stack = audioThreadStack;
audioThreadAttr.stack_size = STACK_SIZE;
audioThreadAttr.gp_reg = (void *)&_gp;
audioThreadAttr.initial_priority = 0x17;
if ((audioThreadId = CreateThread(&audioThreadAttr)) < 0)
PRINT_ERR("Create audio thread failed!");
PRINT_LOG("Audio thread created");
StartThread(audioThreadId, NULL);
PRINT_LOG("Audio thread started");
}
/** Do not call this function.
* This is a audio thread, runned by AudioThread::start()
*/
void Audio::audioThread()
{ {
while (true) while (true)
{ audioRef->threadLoop();
if (audioRef->shouldPlay)
audioRef->work();
}
}
void Audio::play()
{
if (!isInitialized)
{
PRINT_ERR("Please initialize audio class first!");
return;
}
shouldPlay = 1;
}
void Audio::stop()
{
if (!isInitialized)
{
PRINT_ERR("Please initialize audio class first!");
return;
}
shouldPlay = 0;
}
/** Play song and run it again on finish */
void Audio::work()
{
if (!isTrackDone)
{
ret = fread(chunk, 1, sizeof(chunk), wav);
if (ret > 0)
{
WaitSema(fillbufferSema);
audsrv_play_audio(chunk, ret);
}
if (ret < (int)sizeof(chunk))
{
isTrackDone = true;
return;
}
played++;
if ((played + 20) % 41 == 0 && addedListeners)
for (u32 i = 0; i < addedListeners; i++)
listeners[i]->onAudioTick();
}
else
{
PRINT_LOG("Song " SONG_NAME " finished. Running again...");
played = 0;
fseek(wav, 0x30, SEEK_SET);
isTrackDone = false;
}
}
/** Unload audio module by closing file stream and stopping AUDSRV */
void Audio::unloadSong()
{
PRINT_LOG("Unloading audio module started");
fclose(wav);
PRINT_LOG("Song file stream closed");
audsrv_quit();
PRINT_LOG("AUDSRV stopped");
PRINT_LOG("Audio module unloaded");
}
/** Do not call this function.
* This is a static callback function
* for AUDSRV fillbuffer (semaphore)
*/
int Audio::fillbuffer(void *arg)
{
iSignalSema((int)arg);
return 0;
} }
+13 -15
View File
@@ -18,11 +18,7 @@
// Constructors/Destructors // Constructors/Destructors
// ---- // ----
/** Initializes vars and calculate width/height of near and far plane CameraBase::CameraBase(ScreenSettings *t_screen, Vector3 *t_position)
* @param fov (FOV in radians)/2
* @param ratio Aspect ratio
*/
CameraBase::CameraBase(ScreenSettings *t_screen, Vector3 *t_position, Vector3 *t_up, Vector3 *t_unitCirclePosition)
: screen(t_screen) : screen(t_screen)
{ {
PRINT_LOG("Initializing frustum"); PRINT_LOG("Initializing frustum");
@@ -33,9 +29,8 @@ CameraBase::CameraBase(ScreenSettings *t_screen, Vector3 *t_position, Vector3 *t
nearWidth = nearHeight * screen->aspectRatio; nearWidth = nearHeight * screen->aspectRatio;
farHeight = tang * farPlaneDist; farHeight = tang * farPlaneDist;
farWidth = farHeight * screen->aspectRatio; farWidth = farHeight * screen->aspectRatio;
position2 = t_position; p_position = t_position;
up2 = t_up; up.set(0.0F, 1.0F, 0.0F);
unitCirclePosition2 = t_unitCirclePosition;
PRINT_LOG("CameraBase initialized!"); PRINT_LOG("CameraBase initialized!");
} }
@@ -43,23 +38,26 @@ CameraBase::CameraBase(ScreenSettings *t_screen, Vector3 *t_position, Vector3 *t
// Methods // Methods
// ---- // ----
/** Calculates and updates frustum planes void CameraBase::lookAt(Vector3 &t_target)
* http://www.lighthouse3d.com/tutorials/view-frustum-culling/geometric-approach-extracting-the-planes/ {
*/ updatePlanes(t_target);
view.lookAt(*p_position, t_target);
}
void CameraBase::updatePlanes(Vector3 t_target) void CameraBase::updatePlanes(Vector3 t_target)
{ {
Vector3 nearCenter, farCenter, X, Y, Z; Vector3 nearCenter, farCenter, X, Y, Z;
// compute the Z axis of camera // compute the Z axis of camera
Z = *position2 - t_target; Z = *p_position - t_target;
Z.normalize(); Z.normalize();
// X axis of camera of given "up" vector and Z axis // X axis of camera of given "up" vector and Z axis
X = *up2 * Z; X = up * Z;
X.normalize(); X.normalize();
// the real "up" vector is the cross product of Z and X // the real "up" vector is the cross product of Z and X
Y = Z * X; Y = Z * X;
// compute the center of the near and far planes // compute the center of the near and far planes
nearCenter = *position2 - Z * nearPlaneDist; nearCenter = *p_position - Z * nearPlaneDist;
farCenter = *position2 - Z * farPlaneDist; farCenter = *p_position - Z * farPlaneDist;
// compute the 8 corners of the frustum // compute the 8 corners of the frustum
ntl = nearCenter + Y * nearHeight - X * nearWidth; ntl = nearCenter + Y * nearHeight - X * nearWidth;
ntr = nearCenter + Y * nearHeight + X * nearWidth; ntr = nearCenter + Y * nearHeight + X * nearWidth;
+117
View File
@@ -0,0 +1,117 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "../include/modules/file_service.hpp"
#include "../include/utils/string.hpp"
#include "../include/utils/debug.hpp"
#include <cstdlib>
// ----
// Constructors/Destructors
// ----
FileService *fsRef;
FileService::FileService() {}
FileService::~FileService() {}
// ----
// Methods
// ----
u32 FileService::addReadChunk(FILE *t_file, void *t_destination, const u32 &t_size, const u32 &t_n)
{
FileServiceTask task;
task.id = rand() % 1000000;
task.file = t_file;
task.destination = t_destination;
task.size = t_size;
task.n = t_n;
task.readStatus = -2137;
tasks.push_back(task);
return task.id;
}
s32 FileService::isTaskDone(const u32 &t_taskId)
{
s32 taskIndex = getIndexOf(t_taskId);
if (taskIndex == -1)
PRINT_ERR("Task was not found!");
s32 result = tasks[taskIndex].readStatus;
if (result != -2137)
removeByIndex(taskIndex);
return result;
}
const void FileService::removeById(const u32 &t_taskId)
{
s32 index = getIndexOf(t_taskId);
if (index != -1)
removeByIndex(index);
else
PRINT_ERR("Cant remove task, because it was not found!");
}
const s32 FileService::getIndexOf(const u32 &t_taskId)
{
for (u32 i = 0; i < tasks.size(); i++)
if (tasks[i].id == t_taskId)
return i;
return -1;
};
// Other
void FileService::startThread()
{
PRINT_LOG("Creating file service thread");
extern void *_gp;
thread.func = (void *)FileService::mainThread;
thread.stack = threadStack;
thread.stack_size = getThreadStackSize();
thread.gp_reg = (void *)&_gp;
thread.initial_priority = 0x12;
if ((threadId = CreateThread(&thread)) < 0)
PRINT_ERR("Create audio thread failed!");
PRINT_LOG("File service created");
StartThread(threadId, NULL);
PRINT_LOG("File service started");
}
/** Main thread loop */
void FileService::threadLoop()
{
// This will cause an error
// printf("\n\n\n\n\nsize:%d\n", tasks.size());
// for (size_t i = 0; i < tasks.size(); i++)
// {
// switch (tasks[i].type)
// {
// case ReadChunk:
// tasks[i].readStatus = fread(tasks[i].destination, tasks[i].n, tasks[i].size, tasks[i].file);
// break;
// default:
// break;
// }
// }
SleepThread();
}
/**
* Do not call this function.
* This is an file service thread, runned by engine
*/
void FileService::mainThread()
{
while (true)
fsRef->threadLoop();
}
+80 -94
View File
@@ -12,7 +12,8 @@
#include "../include/utils/math.hpp" #include "../include/utils/math.hpp"
#include "../include/utils/debug.hpp" #include "../include/utils/debug.hpp"
#include "../include/modules/light.hpp" #include <packet2_chain.h>
#include <kernel.h>
#include <dma.h> #include <dma.h>
#include <draw.h> #include <draw.h>
#include <stdio.h> #include <stdio.h>
@@ -27,20 +28,21 @@
/** Initializes vars and creates data transfer packets /** Initializes vars and creates data transfer packets
* @param packetSize Size of data packet, should be increased when more data will be rendered * @param packetSize Size of data packet, should be increased when more data will be rendered
*/ */
GifSender::GifSender(u32 t_packetSize, ScreenSettings *t_screen) : screen(t_screen) GifSender::GifSender(u32 t_packetSize, ScreenSettings *t_screen, Light *t_light) : screen(t_screen)
{ {
PRINT_LOG("Initializing GifSender"); PRINT_LOG("Initializing GifSender");
light = t_light;
packetSize = t_packetSize; packetSize = t_packetSize;
packets[0] = packet_init(t_packetSize, PACKET_NORMAL); packets[0] = packet2_create(t_packetSize, P2_TYPE_NORMAL, P2_MODE_CHAIN, false);
packets[1] = packet_init(t_packetSize, PACKET_NORMAL); packets[1] = packet2_create(t_packetSize, P2_TYPE_NORMAL, P2_MODE_CHAIN, false);
PRINT_LOG("GifSender initialized!"); PRINT_LOG("GifSender initialized!");
} }
/** Releases packets memory */ /** Releases packets memory */
GifSender::~GifSender() GifSender::~GifSender()
{ {
packet_free(packets[0]); packet2_free(packets[0]);
packet_free(packets[1]); packet2_free(packets[1]);
} }
// ---- // ----
@@ -51,37 +53,45 @@ GifSender::~GifSender()
#include <gs_gp.h> #include <gs_gp.h>
/** Send texture via GIF */ /** Send texture via GIF */
void GifSender::sendTexture(MeshTexture &texture, texbuffer_t *t_texBuffer) void GifSender::sendTexture(Texture &texture, texbuffer_t *t_texBuffer)
{ {
const u16 packetSize = 40; packet2_t *packet2 = packet2_create(15, P2_TYPE_NORMAL, P2_MODE_CHAIN, false);
packet_t *packet = packet_init(packetSize, PACKET_NORMAL); packet2_update(
qword_t *q = packet->data; packet2,
q = draw_texture_transfer(q, texture.getData(), texture.getWidth(), texture.getHeight(), GS_PSM_24, t_texBuffer->address, t_texBuffer->width); draw_texture_transfer(
DMATAG_CNT(q, 2, 0, 0, 0); packet2->base,
q++; texture.getData(),
q = draw_texture_wrapping(q, 0, texture.getWrapSettings()); texture.getWidth(),
q = draw_texture_flush(q); texture.getHeight(),
dma_channel_send_chain(DMA_CHANNEL_GIF, packet->data, q - packet->data, 0, 0); texture.getType(),
dma_wait_fast(); t_texBuffer->address,
packet_free(packet); t_texBuffer->width));
packet2_chain_open_cnt(packet2, 0, 0, 0);
packet2_update(packet2, draw_texture_wrapping(packet2->next, 0, texture.getWrapSettings()));
packet2_chain_close_tag(packet2);
packet2_update(packet2, draw_texture_flush(packet2->next));
dma_channel_wait(DMA_CHANNEL_GIF, 0);
dma_channel_send_packet2(packet2, DMA_CHANNEL_GIF, true);
dma_channel_wait(DMA_CHANNEL_GIF, 0);
packet2_free(packet2);
} }
void GifSender::sendClear(zbuffer_t *t_zBuffer) void GifSender::sendClear(zbuffer_t *t_zBuffer, color_t *t_rgb)
{ {
packet_t *packet = packet_init(100, PACKET_NORMAL); packet2_t *packet2 = packet2_create(36, P2_TYPE_NORMAL, P2_MODE_CHAIN, false);
qword_t *q = packet->data; packet2_chain_open_end(packet2, 0, 0);
q++; packet2_update(packet2, draw_disable_tests(packet2->next, 0, t_zBuffer));
q = draw_disable_tests(q, 0, t_zBuffer); packet2_update(packet2, draw_clear(packet2->next, 0,
q = draw_clear(q, 0, 2048.0F - (screen->width / 2), 2048.0F - (screen->height / 2),
2048.0F - (screen->width / 2), 2048.0F - (screen->height / 2), screen->width, screen->height,
screen->width, screen->height, t_rgb->r, t_rgb->g, t_rgb->b));
0x10, 0x10, 0x10); packet2_update(packet2, draw_enable_tests(packet2->next, 0, t_zBuffer));
q = draw_enable_tests(q, 0, t_zBuffer); packet2_update(packet2, draw_finish(packet2->next));
q = draw_finish(q); packet2_chain_close_tag(packet2);
DMATAG_END(packet->data, q - packet->data - 1, 0, 0, 0); dma_channel_wait(DMA_CHANNEL_GIF, 0);
dma_channel_send_chain(DMA_CHANNEL_GIF, packet->data, q - packet->data, 0, 0); dma_channel_send_packet2(packet2, DMA_CHANNEL_GIF, true);
dma_wait_fast(); dma_channel_wait(DMA_CHANNEL_GIF, 0);
packet_free(packet); packet2_free(packet2);
} }
/** Used in game loop. /** Used in game loop.
@@ -90,12 +100,8 @@ void GifSender::sendClear(zbuffer_t *t_zBuffer)
void GifSender::initPacket(u8 t_context) void GifSender::initPacket(u8 t_context)
{ {
currentPacket = packets[t_context]; currentPacket = packets[t_context];
if (currentPacket->qwords > (u32)packetSize || currentPacket->qwords < 0) packet2_reset(currentPacket, false);
PRINT_ERR("GifSender packet size error. Please consider to change packet size!\n"); isAnyObjectAdded = false;
q = currentPacket->data;
dmatag = q;
q++;
isAnyObjectAdded = 0;
} }
/** Sends packet to GIF. */ /** Sends packet to GIF. */
@@ -103,69 +109,48 @@ void GifSender::sendPacket()
{ {
if (isAnyObjectAdded) if (isAnyObjectAdded)
{ {
dmatag = q; packet2_chain_open_end(currentPacket, 0, 0);
q++; packet2_update(currentPacket, draw_finish(currentPacket->next));
packet2_chain_close_tag(currentPacket);
} }
q = draw_finish(q); dma_channel_wait(DMA_CHANNEL_GIF, 0);
DMATAG_END(dmatag, q - dmatag - 1, 0, 0, 0); dma_channel_send_packet2(currentPacket, DMA_CHANNEL_GIF, true);
dma_wait_fast();
dma_channel_send_chain(DMA_CHANNEL_GIF, currentPacket->data, q - currentPacket->data, 0, 0);
} }
/** Adds clear screen to current packet */ /** Adds clear screen to current packet */
void GifSender::addClear(zbuffer_t *t_zBuffer) void GifSender::addClear(zbuffer_t *t_zBuffer, color_t *t_rgb)
{ {
q = draw_disable_tests(q, 0, t_zBuffer); packet2_chain_open_cnt(currentPacket, 0, 0, 0);
q = draw_clear(q, 0, packet2_update(currentPacket, draw_disable_tests(currentPacket->next, 0, t_zBuffer));
2048.0F - (screen->width / 2), 2048.0F - (screen->height / 2), packet2_update(currentPacket, draw_clear(currentPacket->next, 0,
screen->width, screen->height, 2048.0F - (screen->width / 2), 2048.0F - (screen->height / 2),
0x10, 0x10, 0x10); screen->width, screen->height,
q = draw_enable_tests(q, 0, t_zBuffer); t_rgb->r, t_rgb->g, t_rgb->b));
packet2_update(currentPacket, draw_enable_tests(currentPacket->next, 0, t_zBuffer));
packet2_chain_close_tag(currentPacket);
} }
/** Adds 3D objects to current packet /** Adds meshes to current packet */
* @param worldView Matrix void GifSender::addObject(RenderData *t_renderData, Mesh &t_mesh, u32 vertexCount, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer)
* @param perspective Matrix with .setPerpsective() used [clone of gluPerspective]
* @param objects3D Array of 3D objects pointers
* @param amount Amount of 3D objects
*/
void GifSender::addObject(RenderData *t_renderData, Mesh *t_mesh, u32 vertexCount, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer)
{ {
if (!isAnyObjectAdded) packet2_chain_open_cnt(currentPacket, 0, 0, 0);
{ packet2_update(currentPacket, draw_texture_sampling(currentPacket->next, 0, &t_mesh.lod));
isAnyObjectAdded = true; packet2_update(currentPacket, draw_texturebuffer(currentPacket->next, 0, textureBuffer, &t_mesh.clut));
DMATAG_CNT(dmatag, q - dmatag - 1, 0, 0, 0); // init tag (before first 3d obj) packet2_update(currentPacket, draw_prim_start(currentPacket->next, 0, t_renderData->prim, &t_mesh.color));
}
qword_t *tempDMATag;
tempDMATag = q;
q++;
q = draw_texture_sampling(q, 0, &t_mesh->lod);
q = draw_texturebuffer(q, 0, textureBuffer, &t_mesh->clut);
dw = (u64 *)draw_prim_start(q, 0, t_renderData->prim, &t_mesh->color);
xyz = new xyz_t[vertexCount]; xyz = new xyz_t[vertexCount];
rgbaq = new color_t[vertexCount]; rgbaq = new color_t[vertexCount];
st = new texel_t[vertexCount]; st = new texel_t[vertexCount];
calc3DObject(*t_renderData->perspective, *t_mesh, vertexCount, vertices, normals, coordinates, t_renderData, t_bulbs, t_bulbsCount); calc3DObject(*t_renderData->projection, t_mesh, vertexCount, vertices, normals, coordinates, t_renderData, t_bulbs, t_bulbsCount);
addCurrentCalcs(vertexCount); addCurrentCalcs(vertexCount);
delete[] xyz; delete[] xyz;
delete[] rgbaq; delete[] rgbaq;
delete[] st; delete[] st;
packet2_update(currentPacket, draw_prim_end(currentPacket->next, 3, DRAW_STQ_REGLIST));
if ((u32)dw % 16) // if we are in the middle of qw, switch packet packet2_chain_close_tag(currentPacket);
*dw++ = 0;
q = draw_prim_end((qword_t *)dw, 3, DRAW_STQ_REGLIST);
DMATAG_CNT(tempDMATag, q - tempDMATag - 1, 0, 0, 0);
} }
/** Calculates 3D object data into xyz, rgbq, st /** Calculates 3D object data into xyz, rgbq, st
* After it addCurrentSTQ() can be done * After it addCurrentCalcs() can be done
* @param worldView Matrix
* @param perspective Matrix with .setPerpsective() used [clone of gluPerspective]
* @param mesh 3D object
*/ */
void GifSender::calc3DObject(Matrix t_perspective, Mesh &t_mesh, u32 vertexCount, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, RenderData *t_renderData, LightBulb *t_bulbs, u16 t_bulbsCount) void GifSender::calc3DObject(Matrix t_perspective, Mesh &t_mesh, u32 vertexCount, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, RenderData *t_renderData, LightBulb *t_bulbs, u16 t_bulbsCount)
{ {
@@ -183,11 +168,11 @@ void GifSender::calc3DObject(Matrix t_perspective, Mesh &t_mesh, u32 vertexCount
create_local_light(localLight, rotation); create_local_light(localLight, rotation);
// I cant put perspective from renderData here. ee-gcc bug? // I cant put perspective from renderData here. ee-gcc bug?
create_local_screen(localScreen, localWorld, t_renderData->worldView->data, t_perspective.data); create_local_screen(localScreen, localWorld, t_renderData->view->data, t_perspective.data);
if (SHOULD_BE_LIGHTED) if (SHOULD_BE_LIGHTED)
{ {
const u16 lightsCount = Light::getLightsCount(t_bulbsCount); const u16 lightsCount = light->getLightsCount(t_bulbsCount);
VECTOR *lightDirections = new VECTOR[lightsCount]; VECTOR *lightDirections = new VECTOR[lightsCount];
VECTOR *lightColors = new VECTOR[lightsCount]; VECTOR *lightColors = new VECTOR[lightsCount];
int *lightTypes = new int[lightsCount]; int *lightTypes = new int[lightsCount];
@@ -195,17 +180,17 @@ void GifSender::calc3DObject(Matrix t_perspective, Mesh &t_mesh, u32 vertexCount
VECTOR *lights = new VECTOR[vertexCount]; VECTOR *lights = new VECTOR[vertexCount];
calculate_normals(normals, vertexCount, normals, localLight); calculate_normals(normals, vertexCount, normals, localLight);
Light::calculateLight(lightDirections, lightColors, lightTypes, t_bulbs, t_bulbsCount, t_mesh.position); light->calculateLight(lightDirections, lightColors, lightTypes, t_bulbs, lightsCount, t_mesh.position);
calculate_lights(lights, vertexCount, normals, lightDirections, lightColors, lightTypes, lightsCount); calculate_lights(lights, vertexCount, normals, lightDirections, lightColors, lightTypes, lightsCount);
for (u32 i = 0; i < vertexCount; i++) for (u32 i = 0; i < vertexCount; i++)
{ {
// Apply the light value to the colour. // Apply the light value to the colour.
colors[i][0] = (t_mesh.color.r * lights[i][0] / 128.0F); colors[i][0] = (t_mesh.color.r * lights[i][0]);
colors[i][1] = (t_mesh.color.g * lights[i][1] / 128.0F); colors[i][1] = (t_mesh.color.g * lights[i][1]);
colors[i][2] = (t_mesh.color.b * lights[i][2] / 128.0F); colors[i][2] = (t_mesh.color.b * lights[i][2]);
vector_clamp(colors[i], colors[i], 0.00f, 1.99f); vector_clamp(colors[i], colors[i], 0.00F, 1.99F);
} }
delete[] lightDirections; delete[] lightDirections;
@@ -262,8 +247,9 @@ void GifSender::addCurrentCalcs(u32 &t_vertexCount)
{ {
for (u32 i = 0; i < t_vertexCount; i++) for (u32 i = 0; i < t_vertexCount; i++)
{ {
*dw++ = rgbaq[i].rgbaq; packet2_add_u64(currentPacket, rgbaq[i].rgbaq);
*dw++ = st[i].uv; packet2_add_u64(currentPacket, st[i].uv);
*dw++ = xyz[i].xyz; packet2_add_u64(currentPacket, xyz[i].xyz);
} }
packet2_pad128(currentPacket, 0);
} }
+29 -22
View File
@@ -23,11 +23,15 @@ Light::~Light() {}
// ---- // ----
const u8 ADDITIONAL_LIGHTS = 1; // Ambient const u8 ADDITIONAL_LIGHTS = 1; // Ambient
const float LIGHT_MAX = 255.0F;
const float LIGHT_DIS_MOD = 4.0F;
void Light::setAmbientLight(const Vector3 &t_rgb) { ambientLight.set(t_rgb); }
u16 Light::getLightsCount(u32 t_bulbsCount) { return t_bulbsCount + ADDITIONAL_LIGHTS; } u16 Light::getLightsCount(u32 t_bulbsCount) { return t_bulbsCount + ADDITIONAL_LIGHTS; }
/** Calculates lighting. Used in gifSender in object 3D calculations */ /** Calculates lighting. Used in gifSender in object 3D calculations */
void Light::calculateLight(VECTOR *t_lightDirections, VECTOR *t_lightColors, int *t_lightTypes, LightBulb *t_bulbs, u32 t_bulbsCount, Vector3 t_objPosition) void Light::calculateLight(VECTOR *t_lightDirections, VECTOR *t_lightColors, int *t_lightTypes, LightBulb *t_bulbs, u32 t_lightsCount, Vector3 t_objPosition)
{ {
// --- Ambient light // --- Ambient light
@@ -38,34 +42,37 @@ void Light::calculateLight(VECTOR *t_lightDirections, VECTOR *t_lightColors, int
t_lightDirections[0][2] = 0.0F; t_lightDirections[0][2] = 0.0F;
t_lightDirections[0][3] = 1.0F; t_lightDirections[0][3] = 1.0F;
t_lightColors[0][0] = 0.0F; t_lightColors[0][0] = ambientLight.x;
t_lightColors[0][1] = 0.0F; t_lightColors[0][1] = ambientLight.y;
t_lightColors[0][2] = 0.0F; t_lightColors[0][2] = ambientLight.z;
t_lightColors[0][3] = 1.0F; t_lightColors[0][3] = 1.0F;
// --- // ---
for (u8 i = 0; i < t_bulbsCount; i++) for (u8 i = 1; i < t_lightsCount; i++)
{ {
t_lightTypes[i + 1] = LIGHT_DIRECTIONAL; t_lightTypes[i] = LIGHT_DIRECTIONAL;
Vector3 newLight = Vector3(t_objPosition.x - t_bulbs[i].position.x,
t_objPosition.y - t_bulbs[i].position.y,
t_objPosition.z - t_bulbs[i].position.z);
Vector3 newLight = Vector3(t_objPosition.x - t_bulbs[i - 1].position.x,
t_objPosition.y - t_bulbs[i - 1].position.y,
t_objPosition.z - t_bulbs[i - 1].position.z);
newLight.normalize(); newLight.normalize();
newLight = newLight * t_lightDirections[i][0] = newLight.x;
(.1F + t_lightDirections[i][1] = newLight.y;
(t_bulbs[i].intensity / t_bulbs[i].position.distanceTo(t_objPosition))); t_lightDirections[i][2] = newLight.z;
t_lightDirections[i][3] = 1.0F;
t_lightDirections[i + 1][0] = newLight.x; // Intensity range 0.0F - 1.0F
t_lightDirections[i + 1][1] = newLight.y; float intensity = t_bulbs[i - 1].intensity / LIGHT_MAX;
t_lightDirections[i + 1][2] = newLight.z; // Distance range 0.0F - LIGHT_MAX * LIGHT_DIS_MOD (1020.0F at this time)
t_lightDirections[i + 1][3] = 1.0F; float distance = t_bulbs[i - 1].position.distanceTo(t_objPosition);
// printf("Distance:%f\n", distance);
t_lightColors[i + 1][0] = 0.8F; distance = distance > (LIGHT_MAX - LIGHT_DIS_MOD) * LIGHT_DIS_MOD ? LIGHT_MAX - LIGHT_DIS_MOD : distance;
t_lightColors[i + 1][1] = 0.8F; intensity /= 1.0F + (distance / LIGHT_DIS_MOD); // intensity /= 1.0F - 251.0F
t_lightColors[i + 1][2] = 0.8F; intensity /= 3.0F; // it looks better
t_lightColors[i + 1][3] = 1.0F; t_lightColors[i][0] = intensity;
t_lightColors[i][1] = intensity;
t_lightColors[i][2] = intensity;
t_lightColors[i][3] = 1.0F;
} }
} }
+182 -94
View File
@@ -13,8 +13,6 @@
#include <dma.h> #include <dma.h>
#include <graph.h> #include <graph.h>
#include <packet.h> #include <packet.h>
#include <draw.h>
#include <gs_psm.h>
#include "../include/utils/debug.hpp" #include "../include/utils/debug.hpp"
#include "../include/utils/math.hpp" #include "../include/utils/math.hpp"
@@ -22,6 +20,9 @@
// Constructors/Destructors // Constructors/Destructors
// ---- // ----
static const float GS_CENTER = 4096.0F;
static const float SCREEN_CENTER = GS_CENTER / 2.0F;
/** Initialize DMA<->GIF channel /** Initialize DMA<->GIF channel
* Allocate buffers * Allocate buffers
* Initialize screen * Initialize screen
@@ -35,18 +36,23 @@ Renderer::Renderer(u32 t_packetSize, ScreenSettings *t_screen)
PRINT_LOG("Initializing renderer"); PRINT_LOG("Initializing renderer");
dma_channel_initialize(DMA_CHANNEL_GIF, NULL, 0); // Initialize DMA to enable data transfer dma_channel_initialize(DMA_CHANNEL_GIF, NULL, 0); // Initialize DMA to enable data transfer
dma_channel_fast_waits(DMA_CHANNEL_GIF); dma_channel_fast_waits(DMA_CHANNEL_GIF);
screen = t_screen;
context = 0; context = 0;
isTextureVRAMAllocated = false; isTextureVRAMAllocated = false;
isVSyncEnabled = true;
isFrameEmpty = false; isFrameEmpty = false;
lastTextureId = 0; lastTextureId = 0;
flipPacket = packet_init(3, PACKET_UCAB); // Uncached accelerated flipPacket = packet2_create(4, P2_TYPE_UNCACHED_ACCL, P2_MODE_NORMAL, 0);
allocateBuffers(t_screen->width, t_screen->height); allocateBuffers((int)t_screen->width, (int)t_screen->height);
initDrawingEnv(t_screen->width, t_screen->height); initDrawingEnv();
setPrim(); setPrim();
gifSender = new GifSender(t_packetSize, t_screen); worldColor.r = 0x10;
vifSender = new VifSender(); worldColor.g = 0x10;
worldColor.b = 0x10;
gifSender = new GifSender(t_packetSize, t_screen, &light);
vifSender = new VifSender(&light);
perspective.setPerspective(*t_screen); perspective.setPerspective(*t_screen);
renderData.perspective = &perspective; renderData.projection = &perspective;
PRINT_LOG("Renderer initialized!"); PRINT_LOG("Renderer initialized!");
} }
@@ -57,16 +63,16 @@ Renderer::~Renderer() {}
// ---- // ----
/** Configure and allocate vRAM for texture buffer */ /** Configure and allocate vRAM for texture buffer */
void Renderer::allocateTextureBuffer(u16 t_width, u16 t_height) void Renderer::allocateTextureBuffer(Texture *t_texture)
{ {
textureBuffer.width = t_width; textureBuffer.width = t_texture->getWidth();
textureBuffer.psm = GS_PSM_24; textureBuffer.psm = t_texture->getType();
textureBuffer.address = graph_vram_allocate(t_width, t_height, GS_PSM_24, GRAPH_ALIGN_BLOCK); textureBuffer.info.components = textureBuffer.psm == TEX_TYPE_RGBA ? TEXTURE_COMPONENTS_RGBA : TEXTURE_COMPONENTS_RGB;
textureBuffer.address = graph_vram_allocate(t_texture->getWidth(), t_texture->getHeight(), textureBuffer.psm, GRAPH_ALIGN_BLOCK);
if (textureBuffer.address <= 1) if (textureBuffer.address <= 1)
PRINT_ERR("Texture buffer allocation error. No memory!"); PRINT_ERR("Texture buffer allocation error. No memory!");
textureBuffer.info.width = draw_log2(t_width); textureBuffer.info.width = draw_log2(t_texture->getWidth());
textureBuffer.info.height = draw_log2(t_height); textureBuffer.info.height = draw_log2(t_texture->getHeight());
textureBuffer.info.components = TEXTURE_COMPONENTS_RGB;
textureBuffer.info.function = TEXTURE_FUNCTION_MODULATE; textureBuffer.info.function = TEXTURE_FUNCTION_MODULATE;
isTextureVRAMAllocated = true; isTextureVRAMAllocated = true;
} }
@@ -81,39 +87,93 @@ void Renderer::deallocateTextureBuffer()
} }
} }
void Renderer::changeTexture(Mesh *t_mesh, u32 t_materialId) void Renderer::changeTexture(Texture *t_tex)
{ {
if (t_tex != NULL)
MeshTexture *tex = textureRepo.getByMesh(t_mesh->getId(), t_materialId);
if (tex != NULL)
{ {
if (tex->getId() != lastTextureId) if (t_tex->getId() != lastTextureId)
{ {
lastTextureId = tex->getId(); lastTextureId = t_tex->getId();
deallocateTextureBuffer(); deallocateTextureBuffer();
allocateTextureBuffer(tex->getWidth(), tex->getHeight()); allocateTextureBuffer(t_tex);
GifSender::sendTexture(*tex, &textureBuffer); GifSender::sendTexture(*t_tex, &textureBuffer);
} }
} }
else else
PRINT_ERR("Texture was not found in texture repository!"); PRINT_ERR("Texture was not found in texture repository!");
} }
void Renderer::draw(Sprite &t_sprite)
{
Texture *texture = textureRepo.getBySprite(t_sprite.getId());
texrect_t rect;
float sizeX, sizeY;
if (t_sprite.getMode() == MODE_REPEAT)
{
sizeX = t_sprite.size.x;
sizeY = t_sprite.size.y;
}
else
{
sizeX = (float)texture->getWidth();
sizeY = (float)texture->getHeight();
}
float texS, texT;
float texMax = texT = texS = sizeX > sizeY ? sizeX : sizeY;
if (sizeX > sizeY)
texT = texMax / (sizeX / sizeY);
else if (sizeY > sizeX)
texS = texMax / (sizeY / sizeX);
rect.t0.s = t_sprite.isFlippedHorizontally() ? texS : 0.0F;
rect.t0.t = t_sprite.isFlippedVertically() ? texT : 0.0F;
rect.t1.s = t_sprite.isFlippedHorizontally() ? 0.0F : texS;
rect.t1.t = t_sprite.isFlippedVertically() ? 0.0F : texT;
rect.color.r = t_sprite.color.r;
rect.color.g = t_sprite.color.g;
rect.color.b = t_sprite.color.b;
rect.color.a = t_sprite.color.a;
rect.color.q = 0;
rect.v0.x = t_sprite.position.x;
rect.v0.y = t_sprite.position.y;
rect.v0.z = (u32)-1;
rect.v1.x = (t_sprite.size.x * t_sprite.scale) + t_sprite.position.x;
rect.v1.y = (t_sprite.size.y * t_sprite.scale) + t_sprite.position.y;
rect.v1.z = (u32)-1;
beginFrameIfNeeded();
changeTexture(texture);
packet2_t *packet2 = packet2_create(12, P2_TYPE_NORMAL, P2_MODE_NORMAL, 0);
packet2_update(packet2, draw_primitive_xyoffset(packet2->next, 0, SCREEN_CENTER, SCREEN_CENTER));
packet2_utils_gif_add_set(packet2, 1);
packet2_utils_gs_add_texbuff_clut(packet2, &textureBuffer, &t_sprite.clut);
draw_enable_blending();
packet2_update(packet2, draw_rect_textured(packet2->next, 0, &rect));
packet2_update(packet2,
draw_primitive_xyoffset(
packet2->next,
0,
SCREEN_CENTER - (screen->width / 2.0F),
SCREEN_CENTER - (screen->height / 2.0F)));
draw_disable_blending();
packet2_update(packet2, draw_finish(packet2->next));
dma_channel_wait(DMA_CHANNEL_GIF, 0);
dma_channel_send_packet2(packet2, DMA_CHANNEL_GIF, true);
packet2_free(packet2);
}
/** Initializes drawing environment (1st app packet) */ /** Initializes drawing environment (1st app packet) */
void Renderer::initDrawingEnv(float t_screenW, float t_screenH) void Renderer::initDrawingEnv()
{ {
PRINT_LOG("Initializing drawing environment"); PRINT_LOG("Initializing drawing environment");
packet_t *packet = packet_init(20, PACKET_NORMAL); packet2_t *packet2 = packet2_create(20, P2_TYPE_NORMAL, P2_MODE_NORMAL, 0);
u16 halfW = (u16)t_screenW / 2; packet2_update(packet2, draw_setup_environment(packet2->base, 0, frameBuffers, &(zBuffer)));
u16 halfH = (u16)t_screenH / 2; packet2_update(packet2, draw_primitive_xyoffset(packet2->next, 0,
qword_t *q = packet->data; // Generic qword pointer. SCREEN_CENTER - (screen->width / 2.0F),
q = draw_setup_environment(q, 0, frameBuffers, &(zBuffer)); SCREEN_CENTER - (screen->height / 2.0F)));
q = draw_primitive_xyoffset(q, 0, (2048 - halfW), (2048 - halfH)); packet2_update(packet2, draw_finish(packet2->next));
q = draw_finish(q); dma_channel_send_packet2(packet2, DMA_CHANNEL_GIF, true);
// Now send the packet, no need to wait since it's the first. dma_channel_wait(DMA_CHANNEL_GIF, 0);
dma_channel_send_normal(DMA_CHANNEL_GIF, packet->data, q - packet->data, 0, 0); packet2_free(packet2);
dma_wait_fast();
packet_free(packet);
PRINT_LOG("Drawing environment initialized!"); PRINT_LOG("Drawing environment initialized!");
} }
@@ -132,60 +192,66 @@ void Renderer::setPrim()
PRINT_LOG("Prim set!"); PRINT_LOG("Prim set!");
} }
/** Defines and allocates framebuffers and zbuffer */ void Renderer::setWorldColor(const color_t &t_rgb)
void Renderer::allocateBuffers(float t_screenW, float t_screenH)
{ {
frameBuffers[0].width = (u16)t_screenW; worldColor.r = t_rgb.r;
frameBuffers[0].height = (u16)t_screenH; worldColor.g = t_rgb.g;
worldColor.b = t_rgb.b;
}
/** Defines and allocates framebuffers and zbuffer */
void Renderer::allocateBuffers(int t_screenW, int t_screenH)
{
frameBuffers[0].width = (unsigned int)t_screenW;
frameBuffers[0].height = (unsigned int)t_screenH;
frameBuffers[0].mask = 0; frameBuffers[0].mask = 0;
frameBuffers[0].psm = GS_PSM_32; frameBuffers[0].psm = GS_PSM_32;
frameBuffers[0].address = graph_vram_allocate((u16)t_screenW, (u16)t_screenH, frameBuffers[0].psm, GRAPH_ALIGN_PAGE); frameBuffers[0].address = graph_vram_allocate(t_screenW, t_screenH, frameBuffers[0].psm, GRAPH_ALIGN_PAGE);
frameBuffers[1].width = (u16)t_screenW; frameBuffers[1].width = (unsigned int)t_screenW;
frameBuffers[1].height = (u16)t_screenH; frameBuffers[1].height = (unsigned int)t_screenH;
frameBuffers[1].mask = 0; frameBuffers[1].mask = 0;
frameBuffers[1].psm = GS_PSM_32; frameBuffers[1].psm = GS_PSM_32;
frameBuffers[1].address = graph_vram_allocate((u16)t_screenW, (u16)t_screenH, frameBuffers[1].psm, GRAPH_ALIGN_PAGE); frameBuffers[1].address = graph_vram_allocate(t_screenW, t_screenH, frameBuffers[1].psm, GRAPH_ALIGN_PAGE);
zBuffer.enable = DRAW_ENABLE; zBuffer.enable = DRAW_ENABLE;
zBuffer.mask = 0; zBuffer.mask = 0;
zBuffer.method = ZTEST_METHOD_GREATER_EQUAL; zBuffer.method = ZTEST_METHOD_GREATER_EQUAL;
zBuffer.zsm = GS_ZBUF_32; zBuffer.zsm = GS_ZBUF_24;
zBuffer.address = graph_vram_allocate((u16)t_screenW, (u16)t_screenH, zBuffer.zsm, GRAPH_ALIGN_PAGE); zBuffer.address = graph_vram_allocate(t_screenW, t_screenH, zBuffer.zsm, GRAPH_ALIGN_PAGE);
PRINT_LOG("Framebuffers, zBuffer set and allocated!"); PRINT_LOG("Framebuffers, zBuffer set and allocated!");
// Initialize the screen and tie the first framebuffer to the read circuits. // Initialize the screen and tie the first framebuffer to the read circuits.
graph_initialize(frameBuffers[1].address, frameBuffers[1].width, frameBuffers[1].height, frameBuffers[1].psm, 0, 0); graph_initialize(frameBuffers[0].address, frameBuffers[0].width, frameBuffers[0].height, frameBuffers[0].psm, 0, 0);
} }
/// --- Draw: PATH3 /// --- Draw: PATH3
/** PATH3 Many + lighting */ void Renderer::drawByPath3(Mesh *t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount)
void Renderer::drawByPath3(Mesh **t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount)
{ {
for (u16 i = 0; i < t_amount; i++) for (u16 i = 0; i < t_amount; i++)
drawByPath3(t_meshes[i], t_bulbs, t_bulbsCount); drawByPath3(t_meshes[i], t_bulbs, t_bulbsCount);
} }
/** PATH3 Single + lighting */ void Renderer::drawByPath3(Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount)
void Renderer::drawByPath3(Mesh *t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount)
{ {
beginFrameIfNeeded(); beginFrameIfNeeded();
if (!t_mesh->isDataLoaded()) if (!t_mesh.isDataLoaded())
PRINT_ERR("Can't draw, because no mesh data was loaded!"); PRINT_ERR("Can't draw, because no mesh data was loaded!");
if (t_mesh->getCurrentAnimationFrame() != t_mesh->getNextAnimationFrame()) if (t_mesh.getCurrentAnimationFrame() != t_mesh.getNextAnimationFrame())
t_mesh->animate(); t_mesh.animate();
for (u32 i = 0; i < t_mesh->getMaterialsCount(); i++) for (u32 i = 0; i < t_mesh.getMaterialsCount(); i++)
{ {
if (t_mesh->shouldBeFrustumCulled && !t_mesh->getMaterial(i).isInFrustum(renderData.frustumPlanes, t_mesh->position)) if (t_mesh.shouldBeFrustumCulled && !t_mesh.getMaterial(i).isInFrustum(renderData.frustumPlanes, t_mesh.position))
return; return;
changeTexture(t_mesh, t_mesh->getMaterial(i).getId()); Texture *tex = textureRepo.getByMesh(t_mesh.getId(), t_mesh.getMaterial(i).getId());
changeTexture(tex);
gifSender->initPacket(context); gifSender->initPacket(context);
u32 vertCount = t_mesh->getMaterial(i).getFacesCount(); u32 vertCount = t_mesh.getMaterial(i).getFacesCount();
VECTOR *vertices = new VECTOR[vertCount]; VECTOR *vertices = new VECTOR[vertCount];
VECTOR *normals = new VECTOR[vertCount]; VECTOR *normals = new VECTOR[vertCount];
VECTOR *coordinates = new VECTOR[vertCount]; VECTOR *coordinates = new VECTOR[vertCount];
vertCount = t_mesh->getDrawData(i, vertices, normals, coordinates, *renderData.cameraPosition); vertCount = t_mesh.getDrawData(i, vertices, normals, coordinates, *renderData.cameraPosition);
gifSender->addObject(&renderData, t_mesh, vertCount, vertices, normals, coordinates, t_bulbs, t_bulbsCount, &textureBuffer); gifSender->addObject(&renderData, t_mesh, vertCount, vertices, normals, coordinates, t_bulbs, t_bulbsCount, &textureBuffer);
gifSender->sendPacket(); gifSender->sendPacket();
delete[] vertices; delete[] vertices;
@@ -194,59 +260,83 @@ void Renderer::drawByPath3(Mesh *t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount)
} }
} }
/** PATH3 Many */ void Renderer::drawByPath3(Mesh *t_meshes, u16 t_amount) { drawByPath3(t_meshes, t_amount, NULL, 0); }
void Renderer::drawByPath3(Mesh **t_meshes, u16 t_amount) { drawByPath3(t_meshes, t_amount, NULL, 0); }
/** PATH3 Single */ void Renderer::drawByPath3(Mesh &t_mesh) { drawByPath3(t_mesh, NULL, 0); }
void Renderer::drawByPath3(Mesh *t_mesh) { drawByPath3(t_mesh, NULL, 0); }
/// --- Draw: PATH1 /// --- Draw: PATH1
/** PATH1 Many + lighting */
void Renderer::draw(Mesh **t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount) void Renderer::draw(Mesh **t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount)
{ {
for (u16 i = 0; i < t_amount; i++) beginFrameIfNeeded();
draw(t_meshes[i], t_bulbs, t_bulbsCount); if (!t_meshes[0]->isDataLoaded())
PRINT_ERR("Can't draw, because no mesh data was loaded!");
else if (
t_amount >= 3 &&
!t_meshes[0]->shouldBeBackfaceCulled &&
t_meshes[0]->getFramesCount() == 1 &&
t_meshes[0]->getMaterialsCount() == 1 &&
t_meshes[0]->getFrame(0).getVertexCount() <= 96)
{
vifSender->disableWait();
Mesh **meshesInFrustum = new Mesh *[t_amount];
u16 addedMeshes = 0;
for (u16 i = 0; i < t_amount; i++)
if (t_meshes[i]->getMaterial(0).isInFrustum(renderData.frustumPlanes, t_meshes[i]->position))
meshesInFrustum[addedMeshes++] = t_meshes[i];
draw(*meshesInFrustum[0], t_bulbs, t_bulbsCount);
draw(*meshesInFrustum[1], t_bulbs, t_bulbsCount);
vifSender->enableWait();
resetWaitFlag();
vifSender->drawTheSameWithOtherMatrices(renderData, meshesInFrustum, 2, addedMeshes);
if (isWaitFlagSet())
resetWaitFlag();
else
waitForRender();
delete[] meshesInFrustum;
}
else
for (u16 i = 0; i < t_amount; i++)
draw(*t_meshes[i], t_bulbs, t_bulbsCount);
} }
/** PATH1 Single + lighting */ void Renderer::draw(Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount)
void Renderer::draw(Mesh *t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount)
{ {
beginFrameIfNeeded(); beginFrameIfNeeded();
vifSender->sendMatrices(renderData, t_mesh->position, t_mesh->rotation); vifSender->calcMatrix(renderData, t_mesh.position, t_mesh.rotation);
if (!t_mesh->isDataLoaded()) if (!t_mesh.isDataLoaded())
PRINT_ERR("Can't draw, because no mesh data was loaded!"); PRINT_ERR("Can't draw, because no mesh data was loaded!");
if (t_mesh->getCurrentAnimationFrame() != t_mesh->getNextAnimationFrame()) camRotation.identity();
t_mesh->animate(); camRotation.rotate(-t_mesh.rotation);
for (u32 i = 0; i < t_mesh->getMaterialsCount(); i++) Vector3 rotatedCamera = Vector3(camRotation * *renderData.cameraPosition);
if (t_mesh.getCurrentAnimationFrame() != t_mesh.getNextAnimationFrame())
t_mesh.animate();
for (u32 i = 0; i < t_mesh.getMaterialsCount(); i++)
{ {
if (t_mesh->shouldBeFrustumCulled && !t_mesh->getMaterial(i).isInFrustum(renderData.frustumPlanes, t_mesh->position)) if (t_mesh.shouldBeFrustumCulled && !t_mesh.getMaterial(i).isInFrustum(renderData.frustumPlanes, t_mesh.position))
return; return;
u32 vertCount = t_mesh->getMaterial(i).getFacesCount(); u32 vertCount = t_mesh.getMaterial(i).getFacesCount();
VECTOR *vertices = new VECTOR[vertCount]; VECTOR vertices[vertCount] __attribute__((aligned(16)));
VECTOR *normals = new VECTOR[vertCount]; VECTOR normals[vertCount] __attribute__((aligned(16)));
VECTOR *coordinates = new VECTOR[vertCount]; VECTOR coordinates[vertCount] __attribute__((aligned(16)));
changeTexture(t_mesh, t_mesh->getMaterial(i).getId()); Texture *tex = textureRepo.getByMesh(t_mesh.getId(), t_mesh.getMaterial(i).getId());
vertCount = t_mesh->getDrawData(i, vertices, normals, coordinates, *renderData.cameraPosition); changeTexture(tex);
vertCount = t_mesh.getDrawData(i, vertices, normals, coordinates, rotatedCamera);
vifSender->drawMesh(&renderData, perspective, vertCount, vertices, normals, coordinates, t_mesh, t_bulbs, t_bulbsCount, &textureBuffer); vifSender->drawMesh(&renderData, perspective, vertCount, vertices, normals, coordinates, t_mesh, t_bulbs, t_bulbsCount, &textureBuffer);
delete[] vertices;
delete[] normals;
delete[] coordinates;
} }
} }
/** PATH1 Many */ void Renderer::draw(Mesh **t_meshes, u16 t_amount) { draw(t_meshes, t_amount, NULL, 0); }
void Renderer::draw(Mesh **t_objects3D, u16 t_amount) { draw(t_objects3D, t_amount, NULL, 0); }
/** PATH1 Single */ void Renderer::draw(Mesh &t_mesh) { draw(t_mesh, NULL, 0); }
void Renderer::draw(Mesh *t_mesh) { draw(t_mesh, NULL, 0); }
/// --- /// ---
void Renderer::setCameraDefinitions(Matrix *t_worldView, Vector3 *t_cameraPos, Plane *t_planes) void Renderer::setCameraDefinitions(Matrix *t_worldView, Vector3 *t_cameraPos, Plane *t_planes)
{ {
renderData.worldView = t_worldView; renderData.view = t_worldView;
renderData.cameraPosition = t_cameraPos; renderData.cameraPosition = t_cameraPos;
renderData.frustumPlanes = t_planes; renderData.frustumPlanes = t_planes;
} }
@@ -256,7 +346,7 @@ void Renderer::beginFrameIfNeeded()
if (isFrameEmpty) if (isFrameEmpty)
{ {
isFrameEmpty = false; isFrameEmpty = false;
gifSender->sendClear(&zBuffer); gifSender->sendClear(&zBuffer, &worldColor);
} }
} }
@@ -264,7 +354,7 @@ void Renderer::endFrame(float fps)
{ {
if (!isFrameEmpty) if (!isFrameEmpty)
{ {
if (fps > 49.0F) if (fps > 49.0F && isVSyncEnabled)
graph_wait_vsync(); graph_wait_vsync();
flipBuffers(); flipBuffers();
} }
@@ -284,10 +374,8 @@ void Renderer::flipBuffers()
0); 0);
context ^= 1; context ^= 1;
isFrameEmpty = 1; isFrameEmpty = 1;
qword_t *q = flipPacket->data; packet2_update(flipPacket, draw_framebuffer(flipPacket->base, 0, &frameBuffers[context]));
q = draw_framebuffer(q, 0, &frameBuffers[context]); packet2_update(flipPacket, draw_finish(flipPacket->next));
q = draw_finish(q); dma_channel_send_packet2(flipPacket, DMA_CHANNEL_GIF, true);
dma_wait_fast();
dma_channel_send_normal_ucab(DMA_CHANNEL_GIF, flipPacket->data, q - flipPacket->data, 0);
draw_wait_finish(); draw_wait_finish();
} }
+12 -6
View File
@@ -35,21 +35,27 @@ TextureRepository::~TextureRepository()
// Methods // Methods
// ---- // ----
MeshTexture *TextureRepository::add(char *t_subfolder, char *t_name) Texture *TextureRepository::add(char *t_subfolder, char *t_name, TextureFormat t_format)
{ {
MeshTexture *texture = new MeshTexture(); Texture *texture = new Texture();
loader.load(*texture, t_subfolder, t_name, ".bmp"); if (t_format == BMP)
bmpLoader.load(*texture, t_subfolder, t_name, ".bmp");
else
pngLoader.load(*texture, t_subfolder, t_name, ".png");
texture->setName(t_name); texture->setName(t_name);
textures.push_back(texture); textures.push_back(texture);
return texture; return texture;
} }
void TextureRepository::addByMesh(char *t_path, Mesh &mesh) void TextureRepository::addByMesh(char *t_path, Mesh &mesh, TextureFormat t_format)
{ {
for (u32 i = 0; i < mesh.getMaterialsCount(); i++) for (u32 i = 0; i < mesh.getMaterialsCount(); i++)
{ {
MeshTexture *texture = new MeshTexture(); Texture *texture = new Texture();
loader.load(*texture, t_path, mesh.getMaterial(i).getName(), ".bmp"); if (t_format == BMP)
bmpLoader.load(*texture, t_path, mesh.getMaterial(i).getName(), ".bmp");
else
pngLoader.load(*texture, t_path, mesh.getMaterial(i).getName(), ".png");
texture->setName(mesh.getMaterial(i).getName()); texture->setName(mesh.getMaterial(i).getName());
texture->addLink(mesh.getId(), mesh.getMaterial(i).getId()); texture->addLink(mesh.getId(), mesh.getMaterial(i).getId());
textures.push_back(texture); textures.push_back(texture);
+6 -18
View File
@@ -10,16 +10,11 @@
#include "../include/modules/timer.hpp" #include "../include/modules/timer.hpp"
#include <timer.h>
// ---- // ----
// Constructors/Destructors // Constructors/Destructors
// ---- // ----
Timer::Timer() Timer::Timer() { prime(); }
{
this->lastTime = *T3_COUNT;
}
Timer::~Timer() {} Timer::~Timer() {}
@@ -29,20 +24,13 @@ Timer::~Timer() {}
u32 Timer::getTimeDelta() u32 Timer::getTimeDelta()
{ {
this->time = *T3_COUNT; time = *T3_COUNT;
if (this->time < this->lastTime) // The counter has wrapped if (time < lastTime) // The counter has wrapped
this->change = this->time + (65536 - this->lastTime); change = time + (65536 - lastTime);
else else
this->change = this->time - this->lastTime; change = time - lastTime;
return change;
this->lastTime = this->time;
return this->change;
}
void Timer::primeTimer()
{
lastTime = *T3_COUNT;
} }
float Timer::getFPS() float Timer::getFPS()
+182 -121
View File
@@ -16,49 +16,88 @@
#include "../include/utils/math.hpp" #include "../include/utils/math.hpp"
#include "../include/utils/debug.hpp" #include "../include/utils/debug.hpp"
// Similiar set is in PS2SDK, but for VU1 we have to switch ST with RGBAQ, because VU1 must know Q before sending RGBAQ
#define DRAW_R_STQ_REGLIST ((u64)GIF_REG_ST) << 0 | ((u64)GIF_REG_RGBAQ) << 4 | ((u64)GIF_REG_XYZ2) << 8
const u32 VU1_PACKAGE_VERTS_PER_BUFF = 96; // Remember to modify buffer size in vu1 also const u32 VU1_PACKAGE_VERTS_PER_BUFF = 96; // Remember to modify buffer size in vu1 also
const u32 VU1_PACKAGES_PER_PACKET = 6; const u32 VU1_PACKAGES_PER_PACKET = 9;
const u32 VU1_PACKET_SIZE = 256; // should be 128, but 256 is more safe for future
const u8 VU1_PARAMS_ADDRESS = 4;
const u8 VU1_RGBA_ADDRESS = 8;
// ---- // ----
// Constructors/Destructors // Constructors/Destructors
// ---- // ----
VifSender::VifSender() // VU1 micro program
extern u32 VU1Draw3D_CodeStart __attribute__((section(".vudata")));
extern u32 VU1Draw3D_CodeEnd __attribute__((section(".vudata")));
//
VifSender::VifSender(Light *t_light)
{ {
PRINT_LOG("Initializing VifSender"); PRINT_LOG("Initializing VifSender");
light = t_light;
lastVertCount = 0;
isDrawWaitEnabled = true;
dma_channel_initialize(DMA_CHANNEL_VIF1, NULL, 0);
dma_channel_fast_waits(DMA_CHANNEL_VIF1);
uploadMicroProgram();
packets[0] = packet2_create(VU1_PACKET_SIZE, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
packets[1] = packet2_create(VU1_PACKET_SIZE, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
context = 0;
setDoubleBufferAddStaticData();
PRINT_LOG("VifSender initialized!"); PRINT_LOG("VifSender initialized!");
} }
VifSender::~VifSender() {} VifSender::~VifSender()
{
packet2_free(packets[0]);
packet2_free(packets[1]);
}
// ---- // ----
// Methods // Methods
// ---- // ----
void VifSender::sendMatrices(const RenderData &t_renderData, const Vector3 &t_position, const Vector3 &t_rotation) void VifSender::uploadMicroProgram()
{ {
vec3ToNative(position, t_position, 1.0F); packet2_t *packet2 = packet2_create(
vec3ToNative(rotation, t_rotation, 1.0F); packet2_utils_get_packet_size_for_program(&VU1Draw3D_CodeStart, &VU1Draw3D_CodeEnd) + 1, // + end tag
create_local_world(localWorld, position, rotation); P2_TYPE_NORMAL,
create_local_screen(localScreen, localWorld, t_renderData.worldView->data, t_renderData.perspective->data); P2_MODE_CHAIN,
vu1.sendSingleRefList(0, &localScreen, 4); 1);
packet2_vif_add_micro_program(packet2, 0, &VU1Draw3D_CodeStart, &VU1Draw3D_CodeEnd);
packet2_utils_vu_add_end_tag(packet2);
dma_channel_wait(DMA_CHANNEL_VIF1, 0);
dma_channel_send_packet2(packet2, DMA_CHANNEL_VIF1, 1);
packet2_free(packet2);
} }
void VifSender::drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 vertCount2, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, Mesh *t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer) void VifSender::calcMatrix(const RenderData &t_renderData, const Vector3 &t_position, const Vector3 &t_rotation)
{
model.identity();
model.rotate(t_rotation);
model.translate(t_position);
modelViewProj.identity();
modelViewProj = model * modelViewProj;
modelViewProj = *t_renderData.view * modelViewProj;
modelViewProj = *t_renderData.projection * modelViewProj;
}
void VifSender::drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 vertCount2, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, Mesh &t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer)
{ {
// we have to split 3D object into small parts, because of small memory of VU1 // we have to split 3D object into small parts, because of small memory of VU1
for (u32 i = 0; i < vertCount2;) for (u32 i = 0; i < vertCount2;)
{ {
vu1.createList(); currPacket = packets[context];
packet2_reset(currPacket, false);
for (u8 j = 0; j < VU1_PACKAGES_PER_PACKET; j++) // how many "packages" per one packet for (u8 j = 0; j < VU1_PACKAGES_PER_PACKET; j++) // how many "packages" per one packet
{ {
if (i != 0) // we have to go back to avoid the visual artifacts if (i != 0) // we have to go back to avoid the visual artifacts
i -= 3; i -= 3;
const u32 endI = i + (VU1_PACKAGE_VERTS_PER_BUFF - 1) > vertCount2 ? vertCount2 : i + (VU1_PACKAGE_VERTS_PER_BUFF - 1); const u32 endI = i + (VU1_PACKAGE_VERTS_PER_BUFF - 1) > vertCount2 ? vertCount2 : i + (VU1_PACKAGE_VERTS_PER_BUFF - 1);
drawVertices(t_mesh, i, endI, vertices, coordinates, t_renderData->prim, textureBuffer); drawVertices(t_mesh, i, endI, vertices, coordinates, t_renderData->prim, textureBuffer, isDrawWaitEnabled ? endI == vertCount2 : false);
if (endI == vertCount2) // if there are no more vertices to draw, break if (endI == vertCount2) // if there are no more vertices to draw, break
{ {
i = vertCount2; i = vertCount2;
@@ -67,117 +106,139 @@ void VifSender::drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 ver
i += (VU1_PACKAGE_VERTS_PER_BUFF - 1); i += (VU1_PACKAGE_VERTS_PER_BUFF - 1);
i++; i++;
} }
vu1.sendList(); packet2_utils_vu_add_end_tag(currPacket);
dma_channel_send_packet2(currPacket, DMA_CHANNEL_VIF1, 1);
dma_channel_wait(DMA_CHANNEL_VIF1, 0);
context = !context;
} }
} }
void VifSender::setDoubleBufferAddStaticData()
{
packet2_t *settings = packet2_create(10, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
packet2_utils_vu_open_unpack(settings, 0, false);
{
packet2_utils_gs_add_draw_finish_giftag(settings);
packet2_utils_gif_add_set(settings, 1);
}
packet2_utils_vu_close_unpack(settings);
packet2_utils_vu_add_double_buffer(settings, 10, 498);
packet2_utils_vu_add_end_tag(settings);
dma_channel_send_packet2(settings, DMA_CHANNEL_VIF1, true);
dma_channel_wait(DMA_CHANNEL_VIF1, 0);
packet2_free(settings);
}
/** Draw using PATH1 */ /** Draw using PATH1 */
void VifSender::drawVertices(Mesh *t_mesh, u32 t_start, u32 t_end, VECTOR *t_vertices, VECTOR *t_coordinates, prim_t *t_prim, texbuffer_t *textureBuffer) void VifSender::drawVertices(Mesh &t_mesh, u32 t_start, u32 t_end, VECTOR *t_vertices, VECTOR *t_coordinates, prim_t *t_prim, texbuffer_t *t_texBuff, u8 t_addDrawWait)
{ {
const u32 vertCount = t_end - t_start; const u32 vertCount = t_end - t_start;
vu1.addListBeginning(); lastVertCount = vertCount;
packet2_utils_vu_open_unpack(currPacket, 0, true);
// TODO get this via screensettings packet2_add_data(currPacket, modelViewProj.data, 4);
vu1.addFloat(2048.0F); // scale packet2_add_u32(currPacket, t_addDrawWait); // Draw finish?
vu1.addFloat(2048.0F); // scale packet2_add_u32(currPacket, vertCount); // Vertex count
vu1.addFloat(((float)0xFFFFFF) / 32.0F); // scale packet2_add_u32(currPacket, vertCount / 3); // Triangles count
vu1.add32(vertCount); // vertex count packet2_add_u32(currPacket, 0); // Free
packet2_utils_gs_add_lod(currPacket, &t_mesh.lod);
vu1.add128(GIF_SET_TAG(1, 0, 0, 0, GIF_FLG_PACKED, 1), GIF_REG_AD); // 1x set tag packet2_utils_gs_add_texbuff_clut(currPacket, t_texBuff, &t_mesh.clut);
packet2_utils_gs_add_prim_giftag(currPacket, t_prim, vertCount, DRAW_STQ2_REGLIST, 3, 0);
vu1.add128( // tex -> lod packet2_add_u32(currPacket, t_mesh.color.r);
GS_SET_TEX1( packet2_add_u32(currPacket, t_mesh.color.g);
t_mesh->lod.calculation, packet2_add_u32(currPacket, t_mesh.color.b);
t_mesh->lod.max_level, packet2_add_u32(currPacket, t_mesh.color.a);
t_mesh->lod.mag_filter, u32 vif_added_bytes = packet2_utils_vu_close_unpack(currPacket);
t_mesh->lod.min_filter, packet2_utils_vu_add_unpack_data(currPacket, vif_added_bytes, t_vertices + t_start, vertCount, true);
t_mesh->lod.mipmap_select, vif_added_bytes += vertCount;
t_mesh->lod.l, packet2_utils_vu_add_unpack_data(currPacket, vif_added_bytes, t_coordinates + t_start, vertCount, true);
(int)(t_mesh->lod.k * 16.0F)), vif_added_bytes += vertCount;
GS_REG_TEX1); packet2_utils_vu_add_start_program(currPacket, 0);
}
vu1.add128( // tex -> buff + clut
GS_SET_TEX0( void VifSender::drawTheSameWithOtherMatrices(const RenderData &t_renderData, Mesh **t_meshes, const u32 &t_skip, const u32 &t_count)
textureBuffer->address >> 6, {
textureBuffer->width >> 6, // Standard double buffering (packets)
textureBuffer->psm, packet2_t *packet1 = packet2_create(300, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
textureBuffer->info.width, packet2_t *packet2 = packet2_create(300, P2_TYPE_NORMAL, P2_MODE_CHAIN, true);
textureBuffer->info.height, packet2_t *currMPacket = packet1;
textureBuffer->info.components, u8 currPacketIndex = 1;
textureBuffer->info.function,
t_mesh->clut.address >> 6, // We are sending 32 matrices max per one VU1 send
t_mesh->clut.psm, u8 switchCounter = 0;
t_mesh->clut.storage_mode, for (u32 i = t_skip; i < t_count; i++)
t_mesh->clut.start, {
t_mesh->clut.load_method), model.identity();
GS_REG_TEX0); model.rotate(t_meshes[i]->rotation);
model.translate(t_meshes[i]->position);
vu1.add128(
GS_GIFTAG( modelViewProj.identity();
vertCount, // amount of loops modelViewProj = model * modelViewProj;
1, modelViewProj = *t_renderData.view * modelViewProj;
1, modelViewProj = *t_renderData.projection * modelViewProj;
GS_PRIM(
t_prim->type, packet2_utils_vu_open_unpack(currMPacket, 0, true);
t_prim->shading, {
t_prim->mapping, packet2_add_data(currMPacket, modelViewProj.data, 4);
t_prim->fogging, }
t_prim->blending, packet2_utils_vu_close_unpack(currMPacket);
t_prim->antialiasing, packet2_utils_vu_open_unpack(currMPacket, VU1_RGBA_ADDRESS, true);
t_prim->mapping_type, {
0, // context packet2_add_u32(currMPacket, t_meshes[i]->color.r);
t_prim->colorfix), packet2_add_u32(currMPacket, t_meshes[i]->color.g);
GS_GIFTAG_PACKED, packet2_add_u32(currMPacket, t_meshes[i]->color.b);
3), // STQ + RGBA + XYZ packet2_add_u32(currMPacket, t_meshes[i]->color.a);
DRAW_R_STQ_REGLIST); }
packet2_utils_vu_close_unpack(currMPacket);
for (u8 j = 0; j < 4; j++)
vu1.add32(128); if (i != t_count - 1) // if it is last, we must also add draw wait finish interrupt.
packet2_utils_vu_add_start_program(currMPacket, 0);
//// Clipping tests start
if (switchCounter++ >= 32)
// // const float minZ = 1; {
// // const float maxZ = 65535; switchCounter = 0;
// // const int iGuardDimXY = 2048; if (i == t_count - 1) // is last
{
// // vu1.addFloat(1.0F); // f_TODO clipping maybe there is problem? packet2_utils_vu_open_unpack(currMPacket, VU1_PARAMS_ADDRESS, true);
// // vu1.addFloat(1.0F); {
// // vu1.addFloat(1.0F); packet2_add_u32(currMPacket, true); // Draw wait finish?
// // vu1.addFloat(1.0F); packet2_add_u32(currMPacket, lastVertCount); // Vertex count
// // float xClip = (float)2048.0f/(drawContext.GetFBWidth() * 0.5f * 2.0f); packet2_add_u32(currMPacket, lastVertCount / 3); // Triangles count
// // packet += Math::Max( xClip, 1.0f ); packet2_add_u32(currMPacket, 0); // Free
// // float yClip = (float)2048.0f/(drawContext.GetFBHeight() * 0.5f * 2.0f); }
// // packet += Math::Max( yClip, 1.0f ); packet2_utils_vu_close_unpack(currMPacket);
// // float depthClip = 2048.0f / depthClipToGs; packet2_utils_vu_add_start_program(currMPacket, 0); // and start program
// // // F_FIXME: maybe these 2048's should be 2047.5s... }
// // depthClip *= 1.003f; // round up a bit for fp error (????) packet2_utils_vu_add_end_tag(currMPacket);
// // packet += depthClip; dma_channel_wait(DMA_CHANNEL_VIF1, 0);
// // // enable/disable clipping dma_channel_send_packet2(currMPacket, DMA_CHANNEL_VIF1, 1);
// // packet += (drawContext.GetDoClipping()) ? 1 : 0; if (currPacketIndex == 1) // Switch double buffer (packets)
{
// u32 depthBits = 24; // or 28(fog) or 16 currPacketIndex = 2;
// float depthClipToGs = (float)((1 << depthBits) - 1) / 2.0f; currMPacket = packet2;
// vu1.addFloat(2048.0f / (640.0F * 0.5f * 2.0f)); }
// vu1.addFloat(2048.0f / (480.0F * 0.5f * 2.0f)); else
// vu1.addFloat((2048.0f / depthClipToGs) * 1.003F); {
// // vu1.addFloat(2048.0F); // scale currPacketIndex = 1;
// // vu1.addFloat(2048.0F); // scale currMPacket = packet1;
// // vu1.addFloat(((float)0xFFFFFF) / 32.0F); // scale }
// vu1.addFloat(0.0F); packet2_reset(currMPacket, false);
// // vu1.addFloat(0.5f * iGuardDimXY); }
// // vu1.addFloat(-0.5f * iGuardDimXY); }
// // vu1.addFloat(1.0F); if (switchCounter != 0) // if there are any not sended matrices
// // vu1.addFloat(500.0F); // far {
packet2_utils_vu_open_unpack(currMPacket, VU1_PARAMS_ADDRESS, true);
vu1.addFloat(0.0F); {
vu1.addFloat(0.0F); packet2_add_u32(currMPacket, true); // Draw wait finish?
vu1.addFloat(0.0F); packet2_add_u32(currMPacket, lastVertCount); // Vertex count
vu1.addFloat(0.0F); packet2_add_u32(currMPacket, lastVertCount / 3); // Triangles count
packet2_add_u32(currMPacket, 0); // Free
//// Clipping tests end }
packet2_utils_vu_close_unpack(currMPacket);
vu1.addListEnding(); packet2_utils_vu_add_start_program(currMPacket, 0);
vu1.addReferenceList(0, t_vertices + t_start, 2 * vertCount, 1); packet2_utils_vu_add_end_tag(currMPacket);
vu1.addReferenceList(0, t_coordinates + t_start, 2 * vertCount, 1); dma_channel_wait(DMA_CHANNEL_VIF1, 0);
vu1.addStartProgram(); dma_channel_send_packet2(currMPacket, DMA_CHANNEL_VIF1, 1);
}
packet2_free(packet1);
packet2_free(packet2);
} }
-275
View File
@@ -1,275 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "../include/modules/vu1.hpp"
#include "../include/utils/debug.hpp"
#include <dma.h>
#include <string.h>
#include <kernel.h>
// ----
// Constructors/Destructors
// ----
VU1::VU1()
{
PRINT_LOG("Initializing VU1");
currentBuffer = 0;
switchBuffer = 0;
PRINT_LOG("VU1 initialized!");
}
VU1::~VU1() {}
// ----
// Methods
// -
/** Create dynamic list */
void VU1::createList()
{
switchBuffer = !switchBuffer;
memset((char *)&buildList, 0, sizeof(buildList));
if (switchBuffer)
currentBuffer = (char *)&dmaBuffer1;
else
currentBuffer = (char *)&dmaBuffer2;
buildList.kickBuffer = currentBuffer;
}
/** Add reference list and send via VIF1
* Not using TOPS register
* Similar to addReferenceList()
*/
void VU1::sendSingleRefList(int t_destAddress, void *t_data, int t_quadSize)
{
checkDataAlignment(t_data);
u8 tempBuffer[32] __attribute__((aligned(16)));
void *chain = (u64 *)&tempBuffer; // uncached
*((u64 *)chain)++ = DMA_REF_TAG((u32)t_data, t_quadSize);
*((u32 *)chain)++ = VIF_CODE(VIF_STCYL, 0, 0x0101);
*((u32 *)chain)++ = VIF_CODE(VIF_UNPACK_V4_32, t_quadSize, t_destAddress);
*((u64 *)chain)++ = DMA_END_TAG(0);
*((u32 *)chain)++ = VIF_CODE(VIF_NOP, 0, 0);
*((u32 *)chain)++ = VIF_CODE(VIF_NOP, 0, 0);
FlushCache(0);
dma_channel_send_chain(DMA_CHANNEL_VIF1, tempBuffer, 0, DMA_FLAG_TRANSFERTAG, 0);
dma_channel_wait(DMA_CHANNEL_VIF1, VU1_DMA_CHAN_TIMEOUT);
}
/** Add list beginning, set's double buffer if not set */
void VU1::addListBeginning()
{
if (buildList.isBuilding == 1)
PRINT_ERR("Please end current list list before adding new one!");
if (isDoubleBufferSet == 0)
addDoubleBufferSetting();
else
addFlush();
buildList.dmaSizeAll += buildList.dmaSize;
buildList.dmaSize = 0;
buildList.offset = currentBuffer;
*((u64 *)currentBuffer)++ = DMA_CNT_TAG(0); // placeholder
*((u32 *)currentBuffer)++ = VIF_CODE(VIF_STCYL, 0, 0x0101); // placeholder
*((u32 *)currentBuffer)++ = VIF_CODE(VIF_UNPACK_V4_32, 0, 0); // placeholder
buildList.isBuilding = 1;
}
/** Add list ending and fix unpack size */
void VU1::addListEnding()
{
if (buildList.isBuilding == 0)
{
PRINT_ERR("Please add list beginning first. Nothing to end!");
return;
}
while ((buildList.dmaSize & 0xF))
{
*((u32 *)currentBuffer)++ = 0;
buildList.dmaSize += 4;
}
*((u64 *)buildList.offset)++ = DMA_CNT_TAG(buildList.dmaSize >> 4);
*((u32 *)buildList.offset)++ = VIF_CODE(VIF_STCYL, 0, 0x0101);
*((u32 *)buildList.offset)++ = AddUnpack(V4_32, 0, buildList.dmaSize >> 4, 1);
buildList.isBuilding = 0;
}
/** Add list which will load data from given pointer
* A lot faster than standard list.
* @param offset offset before data in quadwords
* @param data data pointer
* @param size in quadwords
* @param useTops when true, data will be loaded at the beginning of buffer (BASE+OFFSET)
*/
void VU1::addReferenceList(u32 t_offset, void *t_data, u32 t_size, u8 t_useTops)
{
checkDataAlignment(t_data);
if (buildList.isBuilding == 1)
PRINT_ERR("Please end current list list before adding new one!");
*((u64 *)currentBuffer)++ = DMA_REF_TAG((u32)t_data, t_size);
*((u32 *)currentBuffer)++ = VIF_CODE(VIF_STCYL, 0, 0x0101);
*((u32 *)currentBuffer)++ =
AddUnpack(V4_32, t_useTops == 1 ? buildList.dmaSize / 16 : t_offset / 16, t_size, t_useTops);
buildList.dmaSize += t_size * 8;
buildList.dmaSizeAll += buildList.dmaSize;
}
/** Start VU1 program */
void VU1::addStartProgram()
{
*((u64 *)currentBuffer)++ = DMA_CNT_TAG(8 >> 4);
*((u32 *)currentBuffer)++ = VIF_CODE(VIF_MSCAL, 0, 0);
*((u32 *)currentBuffer)++ = VIF_CODE(VIF_FLUSH, 0, 0);
;
}
/** Continue VU1 program from "--cont" line */
void VU1::addContinueProgram()
{
*((u64 *)currentBuffer)++ = DMA_CNT_TAG(8 >> 4);
*((u32 *)currentBuffer)++ = VIF_CODE(VIF_MSCAL, 0, 0);
*((u32 *)currentBuffer)++ = VIF_CODE(VIF_FLUSH, 0, 0);
;
}
/** Add end tag and send packet via VIF1 */
void VU1::sendList()
{
*((u64 *)currentBuffer)++ = DMA_END_TAG(0);
*((u32 *)currentBuffer)++ = VIF_CODE(VIF_NOP, 0, 0);
*((u32 *)currentBuffer)++ = VIF_CODE(VIF_NOP, 0, 0);
dma_channel_wait(DMA_CHANNEL_VIF1, VU1_DMA_CHAN_TIMEOUT);
dma_channel_send_chain(DMA_CHANNEL_VIF1, buildList.kickBuffer, (u32 *)currentBuffer - (u32 *)buildList.kickBuffer, DMA_FLAG_TRANSFERTAG, 0);
}
void VU1::addDoubleBufferSetting()
{
*((u64 *)currentBuffer)++ = DMA_CNT_TAG(8 >> 4);
*((u32 *)currentBuffer)++ = VIF_CODE(VIF_BASE, 0, 8);
*((u32 *)currentBuffer)++ = VIF_CODE(VIF_OFFSET, 0, 496);
isDoubleBufferSet = 1;
}
void VU1::addFlush()
{
*((u64 *)currentBuffer)++ = DMA_CNT_TAG(8 >> 4);
*((u32 *)currentBuffer)++ = VIF_CODE(VIF_NOP, 0, 0);
*((u32 *)currentBuffer)++ = VIF_CODE(VIF_FLUSH, 0, 0);
}
void VU1::checkDataAlignment(void *t_data)
{
if (((u32)t_data & 0xF))
PRINT_ERR("data is not 16 byte aligned!");
}
// ----
// List adding
// ----
void VU1::add128(u64 v1, u64 v2)
{
checkList();
*((u64 *)currentBuffer)++ = v1;
*((u64 *)currentBuffer)++ = v2;
buildList.dmaSize += 16;
}
void VU1::add64(u64 v)
{
checkList();
*((u64 *)currentBuffer)++ = v;
buildList.dmaSize += 8;
}
void VU1::add32(u32 v)
{
checkList();
*((u32 *)currentBuffer)++ = v;
buildList.dmaSize += 4;
}
void VU1::addFloat(float v)
{
checkList();
*((float *)currentBuffer)++ = v;
buildList.dmaSize += 4;
}
void VU1::checkList()
{
if (buildList.isBuilding == 0)
PRINT_ERR("Please add list beginning before adding data!");
if (buildList.dmaSizeAll > VIF_BUFFER_SIZE)
PRINT_ERR("Buffer size exceed!");
}
// ----
// Static
// ----
u8 IS_DMA_VIF1_INITIALIZED = 0;
/** TODO */
void VU1::uploadProgram(int t_dest, u32 *t_start, u32 *t_end)
{
if (!IS_DMA_VIF1_INITIALIZED)
{
IS_DMA_VIF1_INITIALIZED = 1;
dma_channel_initialize(DMA_CHANNEL_VIF1, NULL, 0);
dma_channel_fast_waits(DMA_CHANNEL_VIF1);
}
int count = 0;
u8 tempBuffer[512] __attribute__((aligned(16)));
void *chain = (u64 *)&tempBuffer; // uncached
// get the size of the code as we can only send 256 instructions in each MPGtag
count = VU1::countProgramSize(t_start, t_end);
while (count > 0)
{
u32 currentCount = count > 256 ? 256 : count;
*((u64 *)chain)++ = DMA_REF_TAG((u32)t_start, currentCount / 2);
*((u32 *)chain)++ = VIF_CODE(VIF_NOP, 0, 0);
*((u32 *)chain)++ = VIF_CODE(VIF_MPG, currentCount & 0xFF, t_dest);
t_start += currentCount * 2;
count -= currentCount;
t_dest += currentCount;
}
*((u64 *)chain)++ = DMA_END_TAG(0);
*((u32 *)chain)++ = VIF_CODE(VIF_NOP, 0, 0);
*((u32 *)chain)++ = VIF_CODE(VIF_NOP, 0, 0);
// Send it to vif1
FlushCache(0);
dma_channel_send_chain(DMA_CHANNEL_VIF1, tempBuffer, 0, DMA_FLAG_TRANSFERTAG, 0);
dma_channel_wait(DMA_CHANNEL_VIF1, VU1_DMA_CHAN_TIMEOUT); // synchronize immediately.
}
u32 VU1::countProgramSize(u32 *t_start, u32 *t_end)
{
u32 size = (t_end - t_start) / 2;
if (size & 1)
size++;
return size;
}
+84
View File
@@ -99,3 +99,87 @@ void manyVec3ToNative(VECTOR *o_result, Vector3 *t_vec, int t_amount, float t_fo
for (int i = 0; i < t_amount; i++) for (int i = 0; i < t_amount; i++)
vec3ToNative(o_result[i], t_vec[i], t_fourthVal); vec3ToNative(o_result[i], t_vec[i], t_fourthVal);
} }
float Math::asin(float x)
{
float r;
asm volatile(
"lui $9, 0x3f00 \n\t"
".set noreorder \n\t"
".align 3 \n\t"
"abs.s %0, %1 \n\t"
"lui $8, 0xbe22 \n\t"
"mtc1 $9, $f1 \n\t"
"ori $8, $8, 0xf983 \n\t"
"mtc1 $8, $f8 \n\t"
"lui $9, 0x4b00 \n\t"
"mtc1 $9, $f3 \n\t"
"lui $8, 0x3f80 \n\t"
"mtc1 $8, $f2 \n\t"
"mula.s %0, $f8 \n\t"
"msuba.s $f3, $f2 \n\t"
"madda.s $f3, $f2 \n\t"
"lui $8, 0x40c9 \n\t"
"msuba.s %0, $f8 \n\t"
"ori $8, 0x0fdb \n\t"
"msub.s %0, $f1, $f2 \n\t"
"lui $9, 0xc225 \n\t"
"abs.s %0, %0 \n\t"
"lui $10, 0x3e80 \n\t"
"mtc1 $10, $f7 \n\t"
"ori $9, 0x5de1 \n\t"
"sub.s %0, %0, $f7 \n\t"
"lui $10, 0x42a3 \n\t"
"mtc1 $8, $f3 \n\t"
"ori $10, 0x3458 \n\t"
"mtc1 $9, $f4 \n\t"
"lui $8, 0xc299 \n\t"
"mtc1 $10, $f5 \n\t"
"ori $8, 0x2663 \n\t"
"mul.s $f8, %0, %0 \n\t"
"lui $9, 0x421e \n\t"
"mtc1 $8, $f6 \n\t"
"ori $9, 0xd7bb \n\t"
"mtc1 $9, $f7 \n\t"
"nop \n\t"
"mul.s $f1, %0, $f8 \n\t"
"mul.s $f9, $f8, $f8 \n\t"
"mula.s $f3, %0 \n\t"
"mul.s $f2, $f1, $f8 \n\t"
"madda.s $f4, $f1 \n\t"
"mul.s $f1, $f1, $f9 \n\t"
"mul.s %0, $f2, $f9 \n\t"
"madda.s $f5, $f2 \n\t"
"madda.s $f6, $f1 \n\t"
"madd.s %0, $f7, %0 \n\t"
".set reorder \n\t"
: "=&f"(r)
: "f"(x)
: "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", "$f9", "$8", "$9", "$10");
return r;
}
float Math::mod(float x, float y)
{
/*
* Portable fmod(x,y) implementation for systems
* that don't have it. Adapted from code found here:
* http://www.opensource.apple.com/source/python/python-3/python/Python/fmod.c
*/
float i, f;
if (y == 0.0f)
{
return 0.0f;
}
i = floorf(x / y);
f = x - i * y;
if ((x < 0.0f) != (y < 0.0f))
{
f = f - y;
}
return f;
}
-154
View File
@@ -1,154 +0,0 @@
; ______ ____ ___
; | \/ ____| |___|
; | | | \ | |
;---------------------------
; Copyright 2020, tyra - https://github.com/h4570/tyra
; Sandro Sobczyński <sandro.sobczynski@gmail.com>
;
;---------------------------------------------------------------
; draw3D.vcl |
;---------------------------------------------------------------
; A VU1 microprogram to draw 3D object using XYZ2, RGBAQ and ST|
; This program uses double buffering (xtop) |
; |
; Many thanks to: |
; - Dr Henry Fortuna |
; - Jesper Svennevid, Daniel Collin |
; - Guilherme Lampert |
;---------------------------------------------------------------
; TODO
; - Fix vertex clipping (is clipping visible triangles :/)
; - Move lerp() from EE to VU1 (performance)
; - Add dynamic lighting (feature)
; - Add --cont + MSCNT instead of alltime MSCAL (performance)
.syntax new
.name VU1Draw3D
.vu
.init_vf_all
.init_vi_all
--enter
--endenter
;//////////// --- Load data 1 --- /////////////
; Updated once per frame
lq matrixRow0, 0(vi00) ; load view-projection matrix
lq matrixRow1, 1(vi00)
lq matrixRow2, 2(vi00)
lq matrixRow3, 3(vi00)
;/////////////////////////////////////////////
fcset 0x000000 ; VCL won't let us use CLIP without first zeroing
; the clip flags
;//////////// --- Load data 2 --- /////////////
; Updated dynamically
xtop iBase
lq.xyz scale, 0(iBase) ; load program params
; float : X, Y, Z - scale vector that we will use to scale the verts after projecting them.
; float : W - vert count.
lq gifSetTag, 1(iBase) ; GIF tag - set
lq texGifTag1, 2(iBase) ; GIF tag - texture LOD
lq texGifTag2, 3(iBase) ; GIF tag - texture buffer & CLUT
lq primTag, 4(iBase) ; GIF tag - tell GS how many data we will send
lq rgba, 5(iBase) ; RGBA
;lq clipScale, 6(iBase) ; TODO clipping tests
; u32 : R, G, B, A (0-128)
iaddiu vertexData, iBase, 7 ; pointer to vertex data
ilw.w vertCount, 0(iBase) ; load vert count from scale vector
iadd stqData, vertexData, vertCount ; pointer to stq
iadd kickAddress, stqData, vertCount ; pointer for XGKICK
iadd destAddress, stqData, vertCount ; helper pointer for data inserting
;////////////////////////////////////////////
;/////////// --- Store tags --- /////////////
sqi gifSetTag, (destAddress++) ;
sqi texGifTag1, (destAddress++) ; texture LOD tag
sqi gifSetTag, (destAddress++) ;
sqi texGifTag2, (destAddress++) ; texture buffer & CLUT tag
sqi primTag, (destAddress++) ; prim + tell gs how many data will be
;////////////////////////////////////////////
;/////////////// --- Loop --- ///////////////
iadd vertexCounter, iBase, vertCount ; loop vertCount times
vertexLoop:
;////////// --- Load loop data --- //////////
lq vertex, 0(vertexData) ; load xyz
; float : X, Y, Z
; any32 : _ = 0
lq stq, 0(stqData) ; load stq
; float : S, T
; any32 : Q = 1 ; 1, because we will mul this by 1/vert[w] and this
; will be our q for texture perspective correction
; any32 : _ = 0
;////////////////////////////////////////////
;////////////// --- Vertex --- //////////////
mul acc, matrixRow0, vertex[x] ; transform each vertex by the matrix
madd acc, matrixRow1, vertex[y]
madd acc, matrixRow2, vertex[z]
madd vertex, matrixRow3, vertex[w]
;add.z acc, vf0, clipScale[w] ; TODO clipping maybe this?
;madd.z clipVec, clipScale, vertex
;mul.xy clipVec, clipScale, vertex
;mul.w clipVec, vf0, vertex[z]
;mul.xyz clipVec, vertex, clipScale ; TODO clipping maybe this?
clipw.xyz vertex, vertex ; Dr. Fortuna: This instruction checks if the vertex is outside
; the viewing frustum. If it is, then the appropriate
; clipping flags are set
fcand VI01, 0x3FFFF ; Bitwise AND the clipping flags with 0x3FFFF, this makes
; sure that we get the clipping judgement for the last three
; verts (i.e. that make up the triangle we are about to draw)
iaddiu iADC, VI01, 0x7FFF ; Add 0x7FFF. If any of the clipping flags were set this will
; cause the triangle not to be drawn (any values above 0x8000
; that are stored in the w component of XYZ2 will set the ADC
; bit, which tells the GS not to perform a drawing kick on this
; triangle.
;ilw.w iNoDraw, UVStart(Counter) ; Load the iNoDraw flag. If true we should set the ADC bit so the vert isn't drawn
;iadd iADC, iADC, iNoDraw ; TODO clipping maybe this?
isw.w iADC, 2(destAddress)
div q, vf00[w], vertex[w] ; perspective divide (1/vert[w]):
mul.xyz vertex, vertex, q
mula.xyz acc, scale, vf00[w] ; scale to GS screen space
madd.xyz vertex, vertex, scale ; multiply and add the scales -> vert = vert * scale + scale
ftoi4.xyz vertex, vertex ; convert vertex to 12:4 fixed point format
;////////////////////////////////////////////
;//////////////// --- ST --- ////////////////
mulq modStq, stq, q
;////////////////////////////////////////////
;//////////// --- Store data --- ////////////
sq modStq, 0(destAddress) ; STQ
sq rgba, 1(destAddress) ; RGBA ; q is grabbed from stq
sq.xyz vertex, 2(destAddress) ; XYZ2
;////////////////////////////////////////////
iaddiu vertexData, vertexData, 1
iaddiu stqData, stqData, 1
iaddiu destAddress, destAddress, 3
iaddi vertexCounter, vertexCounter, -1 ; decrement the loop counter
ibne vertexCounter, iBase, vertexLoop ; and repeat if needed
;////////////////////////////////////////////
--barrier
xgkick kickAddress ; dispatch to the GS rasterizer.
--exit
--endexit
+153
View File
@@ -0,0 +1,153 @@
; ______ ____ ___
; | \/ ____| |___|
; | | | \ | |
;---------------------------
; Copyright 2020, tyra - https://github.com/h4570/tyra
; Sandro Sobczyński <sandro.sobczynski@gmail.com>
;
;---------------------------------------------------------------
; draw3D.vcl |
;---------------------------------------------------------------
; First tyra VU1 microprogram. |
; Features: |
; - Draw triangles (no strip) with STQ (textures) and 1 RGBA. |
; This program uses double buffering (xtop) |
; |
; I want to say thank you to: |
; - Dr Henry Fortuna - for teaching how things work |
; - Jesper Svennevid, Daniel Collin - for openvcl samples |
; - Guilherme Lampert - for VU1 idea for PS2 Quake and vclpp |
; - Tyler Daniel - for PS2GL source code for PS2 Linux |
;---------------------------------------------------------------
; TODO
; - Add dynamic lighting (feature)
; - Add --cont + MSCNT instead of alltime MSCAL
#include "/repos/tyra/src/engine/vu1_progs/geometry.inc"
#include "/repos/tyra/src/engine/vu1_progs/matrix.inc"
#include "/repos/tyra/src/engine/vu1_progs/vector.inc"
#vuprog draw3D
.syntax new
.name VU1Draw3D
.vu
.init_vf_all
.init_vi_all
--enter
--endenter
;///////////// LOAD STATIC DATA /////////////
lq gif_draw_finish_tag, 0(vi00) ; GIF tag - wait
lq gif_set_tag, 1(vi00) ; GIF tag - set
;////////////////////////////////////////////
xtop double_buffer
;//////// LOAD CURRENT BUFFER DATA //////////
MatrixLoad{ matrix, 0, double_buffer }
ilw.x do_draw_finish, 4(double_buffer) ; Add draw finish tag? (sync)
ilw.y vertex_count, 4(double_buffer) ; Vertex count
ilw.z triangles_count, 4(double_buffer) ; Triangles count
lq tex_gif_tag_1, 5(double_buffer) ; GIF tag - texture LOD
lq tex_gif_tag_2, 6(double_buffer) ; GIF tag - texture buffer & CLUT
lq prim_tag, 7(double_buffer) ; GIF tag - tell GS how many data we will send
lq rgba, 8(double_buffer) ; Mesh RGBA
iaddiu vertex_data, double_buffer, 9 ; pointer to vertex data
iadd stq_data, vertex_data, vertex_count ; pointer to stq
iadd kick_address, stq_data, vertex_count ; pointer for XGKICK
iadd dest_address, stq_data, vertex_count ; helper pointer for data inserting
;////////////////////////////////////////////
LoadScaleConstant{ gs_scale }
fcset 0x000000 ; VCL won't let us use CLIP without first zeroing the clip flags
;/////////////// STORE TAGS /////////////////
sqi gif_set_tag, (dest_address++) ;
sqi tex_gif_tag_1, (dest_address++) ; texture LOD tag
sqi gif_set_tag, (dest_address++) ;
sqi tex_gif_tag_2, (dest_address++) ; texture buffer & CLUT tag
iblez do_draw_finish, kick
sqi gif_set_tag, (dest_address++) ;
sqi gif_draw_finish_tag, (dest_address++) ; do draw_finish is needed
kick:
sqi prim_tag, (dest_address++) ; prim + tell gs how many data will be
;////////////////////////////////////////////
;//////// FIX ADC BIT FOR CLIPPING //////////
iaddiu adc_bit, vi00, 0x7FFF
iaddiu adc_bit, adc_bit, 1
;////////////////////////////////////////////
;/////////// START TRIANGLE LOOP ////////////
iaddiu triangle_counter, vi00, 0 ; Reset counter
triangle_loop: --LoopCS 1,3
;//////////////// VERTEX 1 //////////////////
VectorLoad{ vertex, vertex_data, 0 }
VectorLoad{ stq1, stq_data, 0 }
MatrixXForm{ xformed_vertex, matrix, vertex }
VectorClip{ gs_vertex, xformed_vertex }
VectorPerspectiveDivide{ xformed_vertex }
VectorAddGSScales{ gs_vertex, xformed_vertex, gs_scale }
VectorTexturePerspectiveCorrection{ pers_stq, stq1 }
VectorStore{ pers_stq, dest_address, 0 }
VectorStore{ rgba, dest_address, 1 }
VectorStore{ gs_vertex, dest_address, 2 }
;////////////////////////////////////////////
;//////////////// VERTEX 2 //////////////////
VectorLoad{ vertex, vertex_data, 1 }
VectorLoad{ stq2, stq_data, 1 }
MatrixXForm{ xformed_vertex, matrix, vertex }
VectorClip{ gs_vertex, xformed_vertex }
VectorPerspectiveDivide{ xformed_vertex }
VectorAddGSScales{ gs_vertex, xformed_vertex, gs_scale }
VectorTexturePerspectiveCorrection{ pers_stq, stq2 }
VectorStore{ pers_stq, dest_address, 3 }
VectorStore{ rgba, dest_address, 4 }
VectorStore{ gs_vertex, dest_address, 5 }
;////////////////////////////////////////////
;//////////////// VERTEX 3 //////////////////
VectorLoad{ vertex, vertex_data, 2 }
VectorLoad{ stq3, stq_data, 2 }
MatrixXForm{ xformed_vertex, matrix, vertex }
VectorClip{ gs_vertex, xformed_vertex }
VectorPerspectiveDivide{ xformed_vertex }
VectorAddGSScales{ gs_vertex, xformed_vertex, gs_scale }
VectorTexturePerspectiveCorrection{ pers_stq, stq3 }
VectorStore{ pers_stq, dest_address, 6 }
VectorStore{ rgba, dest_address, 7 }
fcand vi01, 0x03FFFF
iaddiu new_adc_bit, vi01, 0x7FFF
mfir.w gs_vertex, new_adc_bit
VectorStore{ gs_vertex, dest_address, 8 }
;////////////////////////////////////////////
;////////////// LOOP CONTROL ////////////////
iaddiu vertex_data, vertex_data, 3
iaddiu stq_data, stq_data, 3
iaddiu dest_address, dest_address, 9
iaddiu triangle_counter, triangle_counter, 1 // Incrementing this
// by other value than 1 is causing HUGE problems, but.. why?
// My first idea was do vertex_counter and incrementing by 3
ibne triangle_counter, triangles_count, triangle_loop
;////////////////////////////////////////////
;////////////////////////////////////////////
--barrier
xgkick kick_address ; dispatch to the GS rasterizer.
--exit
--endexit
#endvuprog
+152 -40
View File
@@ -3,6 +3,10 @@
;-----VCL CODE------------ ;-----VCL CODE------------
;------------------------- ;-------------------------
;------------------------- ;-------------------------
; === __LP__ EXPL_draw3D_vcl_triangle_loop__MAIN_LOOP:
; === hDown : optimal=30 clid=0 mlid=2 size=(31)
; === dUp : optimal=30 clid=0 mlid=2 size=(31)
; === another : optimal=30 clid=0 mlid=2 size=(31)
; ================================================= ; =================================================
; flowMon::Emit() vcl 1.4beta7 produced this code: ; flowMon::Emit() vcl 1.4beta7 produced this code:
.vu .vu
@@ -11,63 +15,171 @@
.global VU1Draw3D_CodeEnd .global VU1Draw3D_CodeEnd
VU1Draw3D_CodeStart: VU1Draw3D_CodeStart:
__v_draw3D_vcl_4: __v_draw3D_vcl_4:
; _LNOPT_w=[ normal2 ] 23 [23 0] 23 [__v_draw3D_vcl_4] ; _LNOPT_w=[ normal2 ] 26 [26 0] 26 [__v_draw3D_vcl_4]
NOP lq VF01,0(VI00) NOP xtop VI05
NOP xtop VI02
NOP lq VF02,1(VI00) NOP lq VF02,1(VI00)
NOP lq VF06,1(VI02) NOP lq VF01,0(VI00)
NOP lq VF09,2(VI02) NOP ilw.x VI01,4(VI05)
NOP lq VF08,3(VI02) NOP ilw.y VI07,4(VI05)
NOP lq VF07,4(VI02) NOP lq VF03,0(VI05)
NOP lq VF03,2(VI00) NOP lq VF08,5(VI05)
NOP iaddiu VI03,VI02,0x00000007 NOP lq VF10,6(VI05)
NOP ilw.w VI07,0(VI02) NOP lq VF04,1(VI05)
NOP lq VF04,3(VI00) NOP lq VF05,2(VI05)
NOP fcset 0 NOP iaddiu VI03,VI05,0x00000009
NOP lq.xyz VF05,0(VI02)
NOP iadd VI04,VI03,VI07 NOP iadd VI04,VI03,VI07
NOP lq VF06,3(VI05)
NOP iadd VI06,VI04,VI07 NOP iadd VI06,VI04,VI07
NOP sqi VF06,(VI06++) NOP loi 0x44fff000
NOP sqi VF09,(VI06++) NOP ilw.z VI02,4(VI05)
NOP sqi VF06,(VI06++) NOP lq VF07,7(VI05)
NOP sqi VF02,(VI06++)
NOP sqi VF08,(VI06++) NOP sqi VF08,(VI06++)
NOP lq VF06,5(VI02) NOP sqi VF02,(VI06++)
NOP lq VF08,8(VI05)
NOP iadd VI05,VI04,VI07 NOP iadd VI05,VI04,VI07
addi.xy VF09,VF00,I loi 0x492aaaaa
NOP fcset 0
NOP iblez VI01,kick
addi.z VF09,VF00,I sqi VF10,(VI06++)
; _LNOPT_w=[ normal2 ] 2 [2 0] 2 [__v_draw3D_vcl_5]
NOP sqi VF02,(VI06++)
NOP sqi VF01,(VI06++)
kick:
; _LNOPT_w=[ normal2 ] 27 [27 0] 32 [kick]
NOP sqi VF07,(VI06++) NOP sqi VF07,(VI06++)
NOP iadd VI07,VI02,VI07
vertexLoop:
; _LNOPT_w=[ normal2 ] 21 [31 14] 31 [vertexLoop]
NOP lq VF07,0(VI03) NOP lq VF07,0(VI03)
mulax ACC,VF01,VF07x sq VF06,1(VI06) ; STALL_LATENCY ?3 mulax ACC,VF03,VF07x lq VF14,1(VI03) ; STALL_LATENCY ?3
madday ACC,VF02,VF07y lq VF08,0(VI04) madday ACC,VF04,VF07y sq VF08,1(VI06)
maddaz ACC,VF03,VF07z iaddiu VI06,VI06,0x00000003 maddaz ACC,VF05,VF07z sq VF08,7(VI06)
maddw VF07,VF04,VF07w NOP maddw VF11,VF06,VF07w NOP
clipw.xyz VF07xyz,VF07w div Q,VF00w,VF07w ; STALL_LATENCY ?3 mulax ACC,VF03,VF14x lq VF07,2(VI03)
madday ACC,VF04,VF14y NOP
maddaz ACC,VF05,VF14z NOP
maddw VF14,VF06,VF14w div Q,VF00w,VF11w
mulax ACC,VF03,VF07x NOP
madday ACC,VF04,VF07y iaddiu VI07,VI00,0x00007fff
maddaz ACC,VF05,VF07z iaddiu VI07,VI07,0x00000001
maddw VF07,VF06,VF07w iaddiu VI08,VI00,0
clipw.xyz VF11xyz,VF11w iaddiu VI04,VI04,0
clipw.xyz VF14xyz,VF14w div Q,VF00w,VF14w ; STALL_THRUPUT ?1
clipw.xyz VF07xyz,VF07w lq VF15,0(VI04)
mulq.xyz VF02,VF11,Q sq VF08,4(VI06)
mulaw.xyz ACC,VF09,VF00w iaddiu VI03,VI03,0
mulq VF11,VF15,Q iaddiu VI06,VI06,0 ; STALL_LATENCY ?1
madd.xyz VF01,VF02,VF09 lq VF02,1(VI04)
NOP div Q,VF00w,VF07w
mulq.xyz VF15,VF14,Q iaddiu VI08,VI08,0x00000001
mulaw.xyz ACC,VF09,VF00w sq VF11,0(VI06)
mulq VF14,VF02,Q mfir.w VF11,VI07
ftoi4.xyz VF11,VF01 ibeq VI08,VI02,EXPL_draw3D_vcl_triangle_loop__EPI1
madd.xyz VF02,VF15,VF09 lq VF15,2(VI04)
; _LNOPT_w=[ ] 31 [29 0] 31 [EXPL_draw3D_vcl_triangle_loop__PRO1]
NOP lq VF12,3(VI03)
NOP NOP NOP NOP
mulq.xyz VF01,VF07,Q NOP
mulq VF11,VF15,Q sq VF11,2(VI06)
mulax ACC,VF03,VF12x lq VF10,4(VI03)
madday ACC,VF04,VF12y NOP
maddaz ACC,VF05,VF12z NOP
maddw VF11,VF06,VF12w sq VF11,6(VI06)
mulax ACC,VF03,VF10x lq VF07,5(VI03)
madday ACC,VF04,VF10y sq VF14,3(VI06)
maddaz ACC,VF05,VF10z sq VF08,10(VI06)
maddw VF10,VF06,VF10w div Q,VF00w,VF11w
mulax ACC,VF03,VF07x sq VF08,13(VI06)
madday ACC,VF04,VF07y sq VF08,16(VI06)
maddaz ACC,VF05,VF07z iaddiu VI03,VI03,0x00000006
maddw VF07,VF06,VF07w iaddiu VI04,VI04,0x00000006
clipw.xyz VF11xyz,VF11w lq VF12,-3(VI04)
clipw.xyz VF10xyz,VF10w iaddiu VI06,VI06,0x00000012
mulq.xyz VF14,VF11,Q div Q,VF00w,VF10w
clipw.xyz VF07xyz,VF07w fcand VI01,262143
mulq VF12,VF12,Q iaddiu VI08,VI08,0x00000001
ftoi4.xyz VF11,VF02 iaddiu VI01,VI01,0x00007fff
mulaw.xyz ACC,VF09,VF00w mfir.w VF11,VI07
madd.xyz VF14,VF14,VF09 mfir.w VF10,VI01
mulaw.xyz ACC,VF09,VF00w lq VF02,-2(VI04)
madd.xyz VF01,VF01,VF09 div Q,VF00w,VF07w
mulq.xyz VF10,VF10,Q lq VF15,-1(VI04)
ftoi4.xyz VF11,VF14 sq VF11,-13(VI06)
mulq VF14,VF02,Q sq VF12,-9(VI06)
mulaw.xyz ACC,VF09,VF00w ibeq VI08,VI02,EXPL_draw3D_vcl_triangle_loop__EPI0
madd.xyz VF02,VF10,VF09 mfir.w VF11,VI07
EXPL_draw3D_vcl_triangle_loop__MAIN_LOOP:
; _LPOPT_w=[ hDown ] 31 [30 30] 31 [EXPL_draw3D_vcl_triangle_loop__MAIN_LOOP]
ftoi4.xyz VF10,VF01 lq VF13,0(VI03)
NOP lq VF12,1(VI03)
mulq.xyz VF01,VF07,Q sq VF14,-6(VI06)
mulq VF11,VF15,Q sq VF11,-7(VI06)
mulax ACC,VF03,VF13x sq VF10,-10(VI06)
madday ACC,VF04,VF13y sq VF08,1(VI06)
maddaz ACC,VF05,VF13z NOP
maddw VF11,VF06,VF13w sq VF11,-3(VI06)
mulax ACC,VF03,VF12x lq VF07,2(VI03)
madday ACC,VF04,VF12y sq VF08,4(VI06)
maddaz ACC,VF05,VF12z sq VF08,7(VI06)
maddw VF10,VF06,VF12w div Q,VF00w,VF11w
mulax ACC,VF03,VF07x NOP
madday ACC,VF04,VF07y iaddiu VI03,VI03,0x00000003
maddaz ACC,VF05,VF07z NOP
maddw VF07,VF06,VF07w iaddiu VI04,VI04,0x00000003
clipw.xyz VF11xyz,VF11w lq VF12,-3(VI04)
clipw.xyz VF10xyz,VF10w iaddiu VI06,VI06,0x00000009
mulq.xyz VF13,VF11,Q fcand VI01,262143
clipw.xyz VF07xyz,VF07w div Q,VF00w,VF10w
mulq VF12,VF12,Q iaddiu VI08,VI08,0x00000001
ftoi4.xyz VF11,VF02 iaddiu VI01,VI01,0x00007fff
mulaw.xyz ACC,VF09,VF00w mfir.w VF10,VI01
madd.xyz VF13,VF13,VF09 mfir.w VF11,VI07
mulaw.xyz ACC,VF09,VF00w lq VF02,-2(VI04)
madd.xyz VF01,VF01,VF09 sq VF12,-9(VI06)
mulq.xyz VF10,VF10,Q div Q,VF00w,VF07w
ftoi4.xyz VF11,VF13 sq VF11,-13(VI06)
mulq VF14,VF02,Q mfir.w VF11,VI07
mulaw.xyz ACC,VF09,VF00w ibne VI08,VI02,EXPL_draw3D_vcl_triangle_loop__MAIN_LOOP
madd.xyz VF02,VF10,VF09 lq VF15,-1(VI04)
EXPL_draw3D_vcl_triangle_loop__EPI0:
; _LNOPT_w=[ ] 13 [13 0] 15 [EXPL_draw3D_vcl_triangle_loop__EPI0]
NOP NOP NOP NOP
ftoi4.xyz VF10,VF01 fcand VI01,262143
mulq.xyz VF01,VF07,Q sq VF14,-6(VI06)
mulq VF11,VF15,Q sq VF11,-7(VI06)
mulaw.xyz ACC,VF09,VF00w iaddiu VI01,VI01,0x00007fff
madd.xyz VF01,VF01,VF09 sq VF10,-10(VI06) ; STALL_LATENCY ?1
ftoi4.xyz VF11,VF02 sq VF11,-3(VI06)
NOP mfir.w VF11,VI07
NOP mfir.w VF10,VI01
ftoi4.xyz VF10,VF01 NOP
NOP sq VF11,-4(VI06) ; STALL_LATENCY ?1
NOP b EXPL_draw3D_vcl_triangle_loop__EXIT_POINT
NOP sq VF10,-1(VI06)
EXPL_draw3D_vcl_triangle_loop__EPI1:
; _LNOPT_w=[ ] 12 [13 0] 14 [EXPL_draw3D_vcl_triangle_loop__EPI1]
NOP NOP NOP NOP
mulq.xyz VF14,VF07,Q sq VF14,3(VI06)
NOP NOP NOP NOP
NOP NOP mulq VF11,VF15,Q sq VF11,2(VI06)
NOP NOP mulaw.xyz ACC,VF09,VF00w fcand VI01,262143
mulq.xyz VF07,VF07,Q fcand VI01,262143 madd.xyz VF14,VF14,VF09 iaddiu VI01,VI01,0x00007fff
mulaw.xyz ACC,VF05,VF00w iaddiu VI03,VI03,0x00000001 NOP mfir.w VF14,VI01
madd.xyz VF07,VF07,VF05 iaddiu VI04,VI04,0x00000001 ; STALL_LATENCY ?2 ftoi4.xyz VF11,VF02 sq VF11,6(VI06)
mulq VF08,VF08,Q isubiu VI07,VI07,1 NOP mfir.w VF11,VI07
ftoi4.xyz VF07,VF07 iaddiu VI01,VI01,0x00007fff ; STALL_LATENCY ?2 ftoi4.xyz VF14,VF14 NOP
NOP isw.w VI01,-1(VI06) NOP sq VF11,5(VI06) ; STALL_LATENCY ?2
NOP sq VF08,-3(VI06) NOP sq VF14,8(VI06)
NOP ibne VI07,VI02,vertexLoop EXPL_draw3D_vcl_triangle_loop__EXIT_POINT:
NOP sq.xyz VF07,-1(VI06) ; _LNOPT_w=[ ] 0 [0 0] 0 [EXPL_draw3D_vcl_triangle_loop__EXIT_POINT]
; _LNOPT_w=[ normal2 ] 3 [1 0] 3 [__v_draw3D_vcl_7] ; _LNOPT_w=[ normal2 ] 3 [1 0] 3 [__v_draw3D_vcl_9]
NOP xgkick VI05 NOP xgkick VI05
NOP[E] NOP NOP[E] NOP
NOP NOP NOP NOP
.align 4 .align 4
VU1Draw3D_CodeEnd: VU1Draw3D_CodeEnd:
; iCount=47 ; iCount=145
; register stats: ; register stats:
; 8 VU User integer ; 9 VU User integer
; 10 VU User floating point ; 16 VU User floating point
;------------------------- ;-------------------------
;------------------------- ;-------------------------
;------------------------- ;-------------------------
+7
View File
@@ -0,0 +1,7 @@
; Load GS offsets to center xformed vertex in gs coord space and color clamping constant
#macro LoadScaleConstant: gs_scale
loi 2047.5
addi.xy gs_scale, vf00, i
loi 699050.625000 // ((float)0xFFFFFF) / 24.0F
addi.z gs_scale, vf00, i
#endmacro
+13
View File
@@ -0,0 +1,13 @@
#macro MatrixLoad: matrix, offset, vumem
lq matrix[0], offset+0(vumem)
lq matrix[1], offset+1(vumem)
lq matrix[2], offset+2(vumem)
lq matrix[3], offset+3(vumem)
#endmacro
#macro MatrixXForm: output_vertex, matrix, input_vertex
mul acc, matrix[0], input_vertex[x]
madd acc, matrix[1], input_vertex[y]
madd acc, matrix[2], input_vertex[z]
madd output_vertex, matrix[3], input_vertex[w]
#endmacro
+27
View File
@@ -0,0 +1,27 @@
#macro VectorPerspectiveDivide: vertex
div q, vf00[w], vertex[w]
mulq.xyz vertex, vertex, q
#endmacro
#macro VectorAddGSScales: output_vertex, input_vertex, gs_scale
mula.xyz acc, gs_scale, vf00[w]
madd.xyz output_vertex, input_vertex, gs_scale
ftoi4.xyz output_vertex, output_vertex
#endmacro
#macro VectorTexturePerspectiveCorrection: output_vertex, input_vertex
mulq output_vertex, input_vertex, q
#endmacro
#macro VectorStore: vertex, vumem, num
sq vertex, num(vumem)
#endmacro
#macro VectorClip: output_vertex, input_vertex
clipw.xyz input_vertex, input_vertex
mfir.w output_vertex, adc_bit
#endmacro
#macro VectorLoad: output_vertex, vumem, offset
lq output_vertex, offset(vumem)
#endmacro
-56
View File
@@ -1,56 +0,0 @@
EE_BIN = ari.elf
EE_OBJS = \
../../engine/models/math/matrix.o \
../../engine/models/math/plane.o \
../../engine/models/math/point.o \
../../engine/models/math/vector3.o \
../../engine/models/mesh_frame.o \
../../engine/models/mesh_material.o \
../../engine/models/mesh.o \
../../engine/models/mesh_texture.o \
../../engine/modules/audio.o \
../../engine/modules/camera_base.o \
../../engine/modules/gif_sender.o \
../../engine/modules/light.o \
../../engine/modules/pad.o \
../../engine/modules/renderer.o \
../../engine/modules/texture_repository.o \
../../engine/modules/timer.o \
../../engine/modules/vif_sender.o \
../../engine/modules/vu1.o \
../../engine/utils/math.o \
../../engine/utils/string.o \
../../engine/loaders/bmp_loader.o \
../../engine/loaders/dff_loader.o \
../../engine/loaders/md2_loader.o \
../../engine/loaders/obj_loader.o \
../../engine/vu1_progs/draw3D.o \
../../engine/engine.o \
camera.o \
objects/player.o \
ari.o \
main.o
EE_LIBS = -ldraw -lgraph -lmath3d -lpacket -ldma -lpad -laudsrv -lc -lstdc++
EE_INCS := -I./../../engine/include $(EE_INCS)
EE_DVP = dvp-as
EE_VCL = vcl
all: $(EE_BIN)
$(EE_STRIP) --strip-all $(EE_BIN)
mv $(EE_BIN) bin/$(EE_BIN)
rm $(EE_OBJS)
# https://github.com/microsoft/wsl/issues/2468#issuecomment-374904520
#%.vsm: %.vcl # sudo service binfmt-support start
# $(EE_VCL) $< >> $@
%.o: %.vsm
$(EE_DVP) $< -o $@
clean:
rm -f $(EE_OBJS)
include $(PS2SDK)/samples/Makefile.pref
include $(PS2SDK)/samples/Makefile.eeglobal
-19
View File
@@ -1,19 +0,0 @@
## Ari sample
### Description
* .obj (skybox, water)
* .dff (island)
* .md2 (ari)
* mesh cloning (water)
Testing demo. In future there will be Ariana Grande demo.
### Assets
[Download](http://apgcglz.cluster028.hosting.ovh.net/tyra/1.1.0/samples/ari/assets.zip)
### Screenshot
[![Ari screenshot][ari-screenshot]](#)
[ari-screenshot]: http://apgcglz.cluster028.hosting.ovh.net/tyra/1.1.0/samples/ari/ari.gif
-135
View File
@@ -1,135 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "ari.hpp"
#include "utils/math.hpp"
// ----
// Constructors/Destructors
// ----
Ari::Ari() {}
Ari::~Ari() {}
// ----
// Methods
// ----
// TEST START
const u8 WATER_TILES_COUNT = 64;
Mesh *island, *islandAddons, *skybox, *test;
Mesh **waterFloors;
Point *spirals;
void calcSpiral(int X, int Y)
{
int x, y, dx;
x = y = dx = 0;
int dy = -1;
int t = X > Y ? X : Y;
int maxI = t * t;
for (int i = 0; i < maxI; i++)
{
if ((-X / 2 <= x) && (x <= X / 2) && (-Y / 2 <= y) && (y <= Y / 2))
{
spirals[i].x = x;
spirals[i].y = y;
}
if ((x == y) || ((x < 0) && (x == -y)) || ((x > 0) && (x == 1 - y)))
{
t = dx;
dx = -dy;
dy = t;
}
x += dx;
y += dy;
}
}
// TEST END
// TODO 1 - const & in parameters
// TODO 2 - Destructor mesh
void Ari::onInit()
{
player = new Player();
camera = new Camera(&engine.screen);
engine.renderer->setCameraDefinitions(&camera->worldView, &camera->unitCirclePosition, camera->planes);
engine.audio.init(0);
engine.audio.setVolume(40);
engine.audio.loadSong("MOV-CIRC.WAV");
engine.audio.play();
texRepo = engine.renderer->getTextureRepository();
island = new Mesh();
island->loadDff("sunnyisl/", "sunnyisl", 0.1F, false);
island->rotation.x = -1.6F;
island->position.set(0.0F, 10.0F, 20.0F);
island->shouldBeBackfaceCulled = true;
island->shouldBeFrustumCulled = false;
islandAddons = new Mesh();
islandAddons->loadDff("sunnyisl/", "sunnyisl3", 0.1F, false);
islandAddons->rotation.x = -1.6F;
islandAddons->position.set(0.0F, 10.0F, 20.0F);
skybox = new Mesh();
skybox->loadObj("skybox/", "skybox", 100.0F, false);
skybox->shouldBeFrustumCulled = false;
waterFloors = new Mesh *[WATER_TILES_COUNT];
spirals = new Point[WATER_TILES_COUNT];
waterFloors[0] = new Mesh();
waterFloors[0]->loadObj("water/", "water", 5.0F, false);
waterFloors[0]->position.set(0.0F, 8.0F, 0.0F);
texRepo->addByMesh("water/", *waterFloors[0]);
for (u8 i = 0; i < WATER_TILES_COUNT; i++)
{
spirals[i].x = 1.0F;
spirals[i].y = 2.0F;
}
u32 spiralOffset = (u32)Math::sqrt(WATER_TILES_COUNT);
calcSpiral(spiralOffset, spiralOffset);
for (u8 i = 1; i < WATER_TILES_COUNT; i++)
{
waterFloors[i] = new Mesh();
waterFloors[i]->loadFrom(*waterFloors[0]);
waterFloors[i]->position.set(10.0F * spirals[i].x, 8.0F, 10.0F * spirals[i].y);
texRepo->getByMesh(waterFloors[0]->getId(), waterFloors[0]->getMaterial(0).getId())
->addLink(waterFloors[i]->getId(), waterFloors[i]->getMaterial(0).getId());
}
texRepo->addByMesh("sunnyisl/", *island);
texRepo->addByMesh("sunnyisl/", *islandAddons);
texRepo->addByMesh("skybox/", *skybox);
texRepo->addByMesh("ari/", player->mesh);
}
void Ari::initBulb()
{
bulb.intensity = 15;
bulb.position.set(5.0F, 10.0F, 10.0F);
}
void Ari::onUpdate()
{
if (engine.pad.isCrossClicked)
printf("FPS:%f\n", engine.fps);
camera->update(engine.pad, player->mesh);
engine.renderer->draw(skybox);
engine.renderer->draw(island);
engine.renderer->draw(islandAddons);
engine.renderer->draw(&player->mesh);
for (u8 i = 0; i < WATER_TILES_COUNT; i++)
engine.renderer->draw(waterFloors[i]);
}
-83
View File
@@ -1,83 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "camera.hpp"
#include <utils/math.hpp>
#include <utils/debug.hpp>
const float CAMERA_Y = 15.0F;
// ----
// Constructors/Destructors
// ----
Camera::Camera(ScreenSettings *t_screen) : CameraBase(t_screen, &position, &up, &unitCirclePosition)
{
PRINT_LOG("Initializing camera");
verticalLevel = 80.0F;
up.x = 0.0F;
up.y = 1.0F;
up.z = 0.0F;
PRINT_LOG("Camera initialized!");
}
Camera::~Camera() {}
// ----
// Methods
// ----
void Camera::update(Pad &t_pad, Mesh &t_mesh)
{
rotate(t_pad);
followBy(t_mesh);
updatePlanes(t_mesh.position); // TODO move it out
Vector3 newPos = Vector3(t_mesh.position.x, t_mesh.position.y + 10.0F, t_mesh.position.z);
worldView.lookAt(up, position, newPos);
}
/** Set camera rotation by pad right joy and update unit circle
* https://en.wikipedia.org/wiki/Unit_circle
* https://www.desmos.com/calculator/3e7iypw4ow
*/
void Camera::rotate(Pad &t_pad)
{
if (t_pad.rJoyH <= 50)
horizontalLevel -= 0.08;
else if (t_pad.rJoyH >= 200)
horizontalLevel += 0.04;
if (t_pad.rJoyV <= 50 && verticalLevel > 25.0F)
verticalLevel -= 0.9F;
else if (t_pad.rJoyV >= 200 && verticalLevel < 80.0F)
verticalLevel += 0.9F;
unitCirclePosition.x = (Math::sin(horizontalLevel) * verticalLevel);
unitCirclePosition.y = CAMERA_Y;
unitCirclePosition.z = (Math::cos(horizontalLevel) * verticalLevel);
}
/** Rotate camera around 3D object */
void Camera::followBy(Mesh &t_mesh)
{
position.x = unitCirclePosition.x + t_mesh.position.x;
position.y = unitCirclePosition.y + t_mesh.position.y;
position.z = unitCirclePosition.z + t_mesh.position.z;
if (position.x > (-0.04F * verticalLevel) &&
position.x < 0.0F &&
position.z > (0.998F * verticalLevel))
{
// TODO
// position.x = 0.0F;
// position.y = 0.0F;
// position.z = 0.0F;
// horizontalLevel = 0.0F;
}
}
-44
View File
@@ -1,44 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "player.hpp"
#include <loaders/obj_loader.hpp>
#include <loaders/bmp_loader.hpp>
#include <modules/gif_sender.hpp>
#include <utils/debug.hpp>
#include <utils/math.hpp>
// ----
// Constructors/Destructors
// ----
Player::Player()
{
PRINT_LOG("Creating player object");
this->gravity = 0.1F;
this->lift = -1.0F;
this->mesh.loadMD2("ari/", "ari", 0.0001F, true);
this->mesh.position.set(0.0F, 10.0F, 0.0F);
this->mesh.shouldBeBackfaceCulled = true;
this->mesh.shouldBeFrustumCulled = false;
this->mesh.shouldBeLighted = true;
this->mesh.setAnimSpeed(0.05F);
this->mesh.playAnimation(0, 1);
PRINT_LOG("Player object created!");
}
Player::~Player()
{
}
// ----
// Methods
// ----
-65
View File
@@ -1,65 +0,0 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#ifndef _PLAYER_
#define _PLAYER_
#include "../camera.hpp"
#include <modules/pad.hpp>
#include <tamtypes.h>
/** Player 3D object class */
class Player
{
public:
float gravity, velocity, lift;
u8 isOnFloor, isCollideFloor, indexOfCurrentFloor;
Mesh mesh;
Player();
~Player();
private:
Vector3 playerNextPosition;
};
// TODO Rysowanie idzie wg tekstur
// 2 Graczy, 1 mesh 2 tekstury
// sharedFrames = objLoader.load("meshes/", "block", 1.0F);
// var addedTextures = texturesRepo.addByMaterialNames("textures/dirt/", sharedFrames);
// var addedTexture = texturesRepo.add("textures/blocks/sand.bmp");
// dirt = new Mesh(sharedFrames);
// sand = new Mesh(sharedFrames);
// addedTextures[0].addUsage(dirt.Id, sharedFrames.getMaterialId(0));
// addedTexture.addUsage(sand.Id, sand.getMaterialId(0));
// 1 gracz, 2 dynamic tekstury
// sharedFrames = objLoader.load("meshes/", "block", 1.0F);
// var addedTexture1 = texturesRepo.add("textures/blocks/sand.bmp");
// var addedTexture2 = texturesRepo.add("textures/blocks/sand_damaged.bmp");
// sand = new Mesh(sharedFrames);
// addedTexture1.removeUsage(sand.Id, sand.getMaterialId(0));
// draw()
// addedTexture2.addUsage(sand.Id, sand.getMaterialId(0));
// 2 różne obj, te same tekstury
// frames1 = objLoader.load("meshes/", "island", 1.0F);
// frames2 = objLoader.load("meshes/", "islandAddons", 1.0F);
// island = new Mesh(frames1);
// islandAddons = new Mesh(frames2);
// var addedTextures1 = texturesRepo.addByMaterialNames("textures/island/",frames1);
// var addedTextures2 = texturesRepo.addByMaterialNames("textures/island/",frames2);
// texturesRepo.remove(addedTextures2[0]); // duplicate
// addedTextures1[0].addUsage(islandAddons.Id, islandAddons.getMaterialId(0));
// Mesh -> position, rotation, color, scale, shouldBeLighted, clut, lod
#endif
+3
View File
@@ -0,0 +1,3 @@
.vscode/
bin/**
fonts/**
+35
View File
@@ -0,0 +1,35 @@
EE_BIN = dolphin.elf
TYRA_DIR = ./../../engine
EE_OBJS = \
camera.o \
objects/player.o \
objects/collectible.o \
objects/mine.o \
dolphin.o \
main.o
EE_LIBS = -ltyra
all: $(EE_BIN)
$(EE_STRIP) --strip-all $(EE_BIN)
mv $(EE_BIN) bin/$(EE_BIN)
rm $(EE_OBJS)
rebuild-engine:
cd $(TYRA_DIR) && make clean && make
clean:
rm -f $(EE_OBJS)
run: $(EE_BIN)
killall -v ps2client || true
ps2client reset
ps2client reset
$(EE_STRIP) --strip-all $(EE_BIN)
mv $(EE_BIN) bin/$(EE_BIN)
rm $(EE_OBJS)
cd bin/ && ps2client execee host:$(EE_BIN)
include $(TYRA_DIR)/Makefile.pref
+20
View File
@@ -0,0 +1,20 @@
## Dolphin sample
### Features
- Animated character
- Collectibles and mines
- Big DFF mesh
- Background songs
- Overlay
- Audio effects (ADPCM)
- Transparent 2D UI
- Usage of draw() in array mode (for water tiles, very fast)
### Assets
[Download](http://apgcglz.cluster028.hosting.ovh.net/tyra/1.29.1/samples/dolphin/assets.zip)
### Screenshot
[![Dolphin screenshot][dolphin-screenshot]](#)
[dolphin-screenshot]: http://apgcglz.cluster028.hosting.ovh.net/tyra/1.29.1/samples/dolphin/dolphin.gif
+54
View File
@@ -0,0 +1,54 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Michał Mostowik <mostek3pl@gmail.com>
*/
#include "camera.hpp"
#include <utils/math.hpp>
const float CAMERA_Y = 25.0F;
Camera::Camera(ScreenSettings *t_screen) : CameraBase(t_screen, &position)
{
verticalLevel = 30.0F;
}
Camera::~Camera() {}
void Camera::update(Pad &t_pad, Mesh &t_mesh)
{
float cameraRot = (t_mesh.rotation.z * 180 / Math::PI) - (horizontalLevel * 180 / Math::PI);
cameraRot += 180;
cameraRot /= 15;
horizontalLevel += cameraRot / (180 / Math::PI);
rotate(t_pad);
followBy(t_mesh);
Vector3 lookPos = Vector3(t_mesh.position.x, t_mesh.position.y + 10.0F, t_mesh.position.z);
lookAt(lookPos);
}
void Camera::rotate(Pad &t_pad)
{
if (t_pad.rJoyH <= 100)
horizontalLevel -= 0.08;
else if (t_pad.rJoyH >= 200)
horizontalLevel += 0.08;
unitCirclePosition.x = (Math::sin(horizontalLevel) * verticalLevel);
unitCirclePosition.y = CAMERA_Y;
unitCirclePosition.z = (Math::cos(horizontalLevel) * verticalLevel);
}
void Camera::followBy(Mesh &t_mesh)
{
position.x = unitCirclePosition.x + t_mesh.position.x;
position.y = unitCirclePosition.y + t_mesh.position.y;
position.z = unitCirclePosition.z + t_mesh.position.z;
}
+2 -4
View File
@@ -5,7 +5,7 @@
#----------------------------------------------------------------------- #-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra # Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0 # Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com> # Michał Mostowik <mostek3pl@gmail.com>
*/ */
#ifndef _CAMERA_ #ifndef _CAMERA_
@@ -18,12 +18,11 @@
#include <modules/camera_base.hpp> #include <modules/camera_base.hpp>
#include <tamtypes.h> #include <tamtypes.h>
/** 3D camera which follow by 3D object. Can be rotated via pad */
class Camera : public CameraBase class Camera : public CameraBase
{ {
public: public:
Vector3 up, position, unitCirclePosition; Vector3 position, up, unitCirclePosition;
float horizontalLevel, verticalLevel; float horizontalLevel, verticalLevel;
Camera(ScreenSettings *t_screen); Camera(ScreenSettings *t_screen);
@@ -35,7 +34,6 @@ public:
protected: protected:
Vector3 *getPosition() { return &position; }; Vector3 *getPosition() { return &position; };
Vector3 *getUp() { return &up; };
ScreenSettings screen; ScreenSettings screen;
}; };
+299
View File
@@ -0,0 +1,299 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Michał Mostowik <mostek3pl@gmail.com>
*/
#include "dolphin.hpp"
#include "utils/math.hpp"
float Dolphin::engineFPS = 60.0F;
const float WATER_TILE_SCALE = 6.0F;
const u8 WATER_SIZE = 4;
const u8 MINES_COUNT = 15;
const u8 OYSTERS_COUNT = 5;
Dolphin::Dolphin(Engine *t_engine) : engine(t_engine), camera(&engine->screen)
{
oysters = new Collectible[OYSTERS_COUNT];
mines = new Mine[MINES_COUNT];
}
Dolphin::~Dolphin()
{
delete[] oysters;
delete[] mines;
delete[] waterDrawList;
}
void Dolphin::onInit()
{
player.init(engine);
engine->renderer->setCameraDefinitions(&camera.view, &camera.position, camera.planes);
engine->audio.loadSong("sound/dirediredocks.wav");
engine->audio.playSong();
engine->audio.setSongVolume(60);
surfaceAmbient = engine->audio.loadADPCM("sound/surface.sad");
underwaterAmbient = engine->audio.loadADPCM("sound/underwater.sad");
pickupSound = engine->audio.loadADPCM("sound/pickup.sad");
boomSound = engine->audio.loadADPCM("sound/boom.sad");
engine->audio.playADPCM(surfaceAmbient, 0);
engine->audio.playADPCM(underwaterAmbient, 1);
texRepo = engine->renderer->getTextureRepository();
engine->renderer->disableVSync();
printf("loading island..\n");
island.loadDff("sunnyisl/", "sunnyisl", 5.0F, false);
printf("Loaded..\n");
island.rotation.x = -1.6F;
island.position.set(0.0F, 60.0F, 20.0F);
island.shouldBeBackfaceCulled = true;
island.shouldBeFrustumCulled = false;
gameOver.size.set(640.0F, 480.0F);
Texture *gameOverTex = texRepo->add("2d/", "gameover", PNG);
gameOver.setMode(MODE_STRETCH);
gameOverTex->addLink(gameOver.getId());
printf("Loading water overlay...\n");
waterOverlay.size.set(640.0F, 480.0F);
Texture *watOverlayTex = texRepo->add("2d/", "underwater_overlay", PNG);
waterOverlay.setMode(MODE_STRETCH);
watOverlayTex->addLink(waterOverlay.getId());
printf("Loaded.\n");
printf("Loading water...\n");
u32 spiralOffset = (u32)Math::sqrt(WATER_TILES_COUNT);
waterDrawList = new Mesh *[WATER_TILES_COUNT];
calcSpiral(spiralOffset, spiralOffset);
water[0].loadObj("water/", "water", WATER_TILE_SCALE, false);
water[0].position.set(0.0F, WATER_LEVEL, 0.0F);
texRepo->addByMesh("water/", water[0], BMP);
water[0].shouldBeFrustumCulled = true;
water[0].shouldBeBackfaceCulled = false;
waterDrawList[0] = &water[0];
for (size_t i = 1; i < WATER_TILES_COUNT; i++)
{
water[i].loadFrom(water[0]);
water[i].shouldBeFrustumCulled = true;
water[i].shouldBeBackfaceCulled = false;
water[i].position.set(WATER_TILE_SCALE * 2.0F * spirals[i].x, WATER_LEVEL, WATER_TILE_SCALE * 2.0F * spirals[i].y);
texRepo->getByMesh(water[0].getId(), water[0].getMaterial(0).getId())
->addLink(water[i].getId(), water[i].getMaterial(0).getId());
waterDrawList[i] = &water[i];
}
printf("Loading seabed...\n");
seabed.loadObj("seabed/", "seabed", 10.0F, false);
seabed.position.set(0, -250.0F, 0);
texRepo->addByMesh("seabed/", seabed, BMP);
seabed.shouldBeBackfaceCulled = false;
seabed.shouldBeFrustumCulled = false;
skybox.loadObj("skybox/", "skybox", 400.0F, false);
skybox.shouldBeFrustumCulled = false;
waterbox.loadObj("waterbox/", "waterbox", 250.0F, false);
waterbox.shouldBeFrustumCulled = false;
waterbox.shouldBeBackfaceCulled = false;
waterbox.rotation.x = Math::PI;
waterbox.position.y = -100.F;
printf("Loading oyster dff\n");
oysters[0].mesh.loadObj("oyster/", "oyster", 10.F, false);
printf("Loaded.");
oysters[0].mesh.shouldBeBackfaceCulled = false;
oysters[0].mesh.shouldBeFrustumCulled = false;
oysters[0].mesh.position.set(15, 0, 15);
texRepo->addByMesh("oyster/", oysters[0].mesh, BMP);
printf("Adding oyster texture.\n");
for (int i = 1; i < OYSTERS_COUNT; i++)
{
printf("Processing oyster %d\n", i);
oysters[i].mesh.loadFrom(oysters[0].mesh);
oysters[i].mesh.shouldBeBackfaceCulled = false;
oysters[i].mesh.shouldBeFrustumCulled = false;
texRepo->getByMesh(oysters[0].mesh.getId(), oysters[0].mesh.getMaterial(0).getId())
->addLink(oysters[i].mesh.getId(), oysters[i].mesh.getMaterial(0).getId());
oysters[i].mesh.position.set(i * -100, 5.0F, i * -100);
}
printf("Loading mine .obj\n");
mines[0].mesh.loadObj("mine/", "mine", 10.F, false);
mines[0].mesh.shouldBeBackfaceCulled = false;
mines[0].mesh.shouldBeFrustumCulled = false;
mines[0].mesh.position.set(5, -15, 32);
texRepo->addByMesh("mine/", mines[0].mesh, BMP);
printf("Adding mine texture.\n");
for (int i = 1; i < MINES_COUNT; i++)
{
printf("Processing mine %d\n", i);
mines[i].mesh.loadFrom(mines[0].mesh);
mines[i].mesh.shouldBeBackfaceCulled = false;
mines[i].mesh.shouldBeFrustumCulled = false;
texRepo->getByMesh(mines[0].mesh.getId(), mines[0].mesh.getMaterial(0).getId())
->addLink(mines[i].mesh.getId(), mines[i].mesh.getMaterial(0).getId());
mines[i].mesh.position.set(i * -10, 0.0F, i * -68);
}
Texture *pLifeTex = texRepo->add("2d/", "life", PNG);
// pLifeTex->addLink(lifeSprites[0].getId());
for (int i = 0; i < 3; i++)
{
lifeSprites[i].size.set(64.0F, 64.0F);
lifeSprites[i].setMode(MODE_STRETCH);
lifeSprites[i].position.set(395 + (64 * i), 0);
pLifeTex->addLink(lifeSprites[i].getId());
}
texRepo->addByMesh("dolphin/", player.mesh, BMP);
texRepo->addByMesh("sunnyisl/", island, BMP);
texRepo->addByMesh("skybox/", skybox, BMP);
texRepo->addByMesh("waterbox/", waterbox, BMP);
bulb.intensity = 55;
bulb.position.set(5.0F, 10.0F, 10.0f);
printf("Finished initialization\n");
}
void Dolphin::onUpdate()
{
if (player.getLifes() <= 0)
{
engine->audio.stopSong();
engine->audio.setADPCMVolume(0, 0);
engine->audio.setADPCMVolume(75, 1);
engine->renderer->draw(gameOver);
return;
}
Dolphin::engineFPS = engine->fps;
// if (engine->pad.isCrossClicked)
// printf("Delta multiplier: %f\n", 60.0F / engine->fps);
float xDist = player.mesh.position.x - water[0].position.x;
float zDist = player.mesh.position.z - water[0].position.z;
if (xDist < 0)
xDist *= -1;
if (zDist < 0)
zDist *= -1;
if (xDist > WATER_SIZE * WATER_TILE_SCALE / 4 ||
zDist > WATER_SIZE * WATER_TILE_SCALE / 4)
{
for (size_t i = 0; i < WATER_TILES_COUNT; i++)
{
water[i].position.x = player.mesh.position.x + (WATER_TILE_SCALE * 2.0F * spirals[i].x);
water[i].position.z = player.mesh.position.z + (WATER_TILE_SCALE * 2.0F * spirals[i].y);
}
}
for (int i = 0; i < OYSTERS_COUNT; i++)
{
oysters[i].update();
Vector3 vecDist = oysters[i].mesh.position - player.mesh.position;
float dist = vecDist.length();
if (dist < 20.F && player.isJumping() && oysters[i].isActive())
{
printf("Pickup:%d Dist:%f\n", i, dist);
oysters[i].disappear();
player.setLife(player.getLifes() + 1);
engine->audio.setADPCMVolume(30, 3);
engine->audio.playADPCM(pickupSound, 3);
}
}
for (int i = 0; i < MINES_COUNT; i++)
{
mines[i].update();
Vector3 vecDist = mines[i].mesh.position - player.mesh.position;
float dist = vecDist.length();
if (dist < 20.F && !mines[i].getExplosionTicks())
{
printf("Vecdist: %f,%f,%f\n", vecDist.x, vecDist.y, vecDist.z);
printf("Explode:%d Dist:%f\n", i, dist);
mines[i].explode();
player.setLife(player.getLifes() - 1);
// Buffer switching to prevent playing two sounds on one buffer
engine->audio.setADPCMVolume(65, Mine::lastSoundBuffer);
engine->audio.playADPCM(boomSound, Mine::lastSoundBuffer);
Mine::lastSoundBuffer = Mine::lastSoundBuffer == 4 ? 5 : 4;
}
}
if (player.mesh.position.y > WATER_LEVEL - 5)
player.mesh.position.y = WATER_LEVEL - 5;
player.update(engine->pad);
camera.update(engine->pad, player.mesh);
skybox.position.set(player.mesh.position.x, +200.0F, player.mesh.position.z);
waterbox.position.set(player.mesh.position.x, -260.0F, player.mesh.position.z);
engine->renderer->draw(island);
engine->renderer->draw(waterDrawList, WATER_TILES_COUNT);
engine->renderer->draw(skybox);
engine->renderer->draw(waterbox);
engine->renderer->draw(seabed);
for (u8 i = 0; i < OYSTERS_COUNT; i++)
if (oysters[i].isActive())
engine->renderer->draw(oysters[i].mesh);
for (u8 i = 0; i < MINES_COUNT; i++)
if (mines[i].getExplosionTicks() < MINE_EXPLOSION_TICKS)
engine->renderer->draw(mines[i].mesh);
for (u8 i = 0; i < player.getLifes(); i++)
engine->renderer->draw(lifeSprites[i]);
engine->renderer->draw(player.mesh);
if (camera.position.y < WATER_LEVEL)
{
engine->renderer->draw(waterOverlay);
engine->audio.setADPCMVolume(0, 0); // Surface ambient
engine->audio.setADPCMVolume(65, 1); // Underwater ambient
}
else
{
engine->audio.setADPCMVolume(50, 0); //Surface ambient
engine->audio.setADPCMVolume(0, 1); //Underwater ambient
}
}
void Dolphin::calcSpiral(int X, int Y)
{
int x, y, dx;
x = y = dx = 0;
int dy = -1;
int t = X > Y ? X : Y;
int maxI = t * t;
for (int i = 0; i < maxI; i++)
{
if ((-X / 2 <= x) && (x <= X / 2) && (-Y / 2 <= y) && (y <= Y / 2))
{
spirals[i].x = x;
spirals[i].y = y;
}
if ((x == y) || ((x < 0) && (x == -y)) || ((x > 0) && (x == 1 - y)))
{
t = dx;
dx = -dy;
dy = t;
}
x += dx;
y += dy;
}
}
+69
View File
@@ -0,0 +1,69 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Michał Mostowik <mostek3pl@gmail.com>
*/
#ifndef _DRIVER_
#define _DRIVER_
#include <tamtypes.h>
#include <audsrv.h>
#include <game.hpp>
#include <engine.hpp>
#include <models/light_bulb.hpp>
#include <models/sprite.hpp>
#include <modules/texture_repository.hpp>
#include "./camera.hpp"
#include "./objects/player.hpp"
#include "./objects/collectible.hpp"
#include "./objects/mine.hpp"
class Dolphin : public Game
{
public:
Dolphin(Engine *t_engine);
~Dolphin();
void onInit();
void onUpdate();
Engine *engine;
static float engineFPS;
private:
void calcSpiral(int X, int Y);
static const u16 WATER_TILES_COUNT = 1024;
Point spirals[WATER_TILES_COUNT];
Mesh **waterDrawList;
/**
* DO NOT TOUCH ORDER OF DECLARATION!
* GCC BUG CAUSES RENDERING TO FAIL IN ANY OTHER ORDER OF DECLARATION!
*/
Mesh seabed;
Mesh island;
Mesh skybox;
Mesh mine;
LightBulb bulb;
Player player;
Camera camera;
Collectible *oysters;
TextureRepository *texRepo;
Sprite waterOverlay;
Mesh water[WATER_TILES_COUNT];
Mesh waterbox;
Sprite lifeSprites[3];
Sprite gameOver;
audsrv_adpcm_t *underwaterAmbient, *surfaceAmbient;
audsrv_adpcm_t *pickupSound;
audsrv_adpcm_t *boomSound;
Mine *mines;
};
#endif
+6 -5
View File
@@ -5,16 +5,17 @@
#----------------------------------------------------------------------- #-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra # Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0 # Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com> # Michał Mostowik <mostek3pl@gmail.com>
*/ */
#include "ari.hpp" #include "dolphin.hpp"
int main() int main()
{ {
Ari game = Ari(); Engine engine = Engine();
game.engine.setDefaultScreen(); engine.screen.fov = 75.F;
game.engine.init(&game, 40000); Dolphin game = Dolphin(&engine);
game.engine->init(&game, 128);
SleepThread(); SleepThread();
return 0; return 0;
} }
@@ -0,0 +1,47 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Michał Mostowik <mostek3pl@gmail.com>
*/
#include "collectible.hpp"
#include <loaders/obj_loader.hpp>
#include <loaders/bmp_loader.hpp>
#include <modules/gif_sender.hpp>
#include <utils/debug.hpp>
#include <utils/math.hpp>
Collectible::Collectible()
{
mesh.loadObj("oyster/", "oyster", 10.F, false);
mesh.shouldBeFrustumCulled = false;
mesh.position.set(0.0F, 0.0F, 0.0f);
bActive = true;
bDisappearing = false;
}
void Collectible::disappear()
{
bDisappearing = true;
lift = 10;
}
void Collectible::update()
{
mesh.rotation.y += 0.08F;
if (bDisappearing)
{
mesh.position.y += lift;
lift = lift > 0 ? lift / 2 : 0;
if (lift < 1)
{
setActive(false);
bDisappearing = false;
}
}
}
@@ -0,0 +1,34 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Michał Mostowik <mostek3pl@gmail.com>
*/
#ifndef _COLLECTIBLE_
#define _COLLECTIBLE_
#include "../camera.hpp"
#include <tamtypes.h>
class Collectible
{
public:
float rotation;
Mesh mesh;
Collectible();
void update();
void disappear();
void setActive(const u8 &b) { bActive = b; }
u8 isActive() { return bActive; }
private:
u8 bActive, bDisappearing;
u8 lift;
};
#endif
+30
View File
@@ -0,0 +1,30 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Michał Mostowik <mostek3pl@gmail.com>
*/
#include "mine.hpp"
u8 Mine::lastSoundBuffer = 4;
Mine::Mine()
{
mesh.position.set(0.0F, 0.0F, 0.0F);
bExploding = false;
explosionTicks = 0;
}
void Mine::update()
{
if (bExploding && explosionTicks < MINE_EXPLOSION_TICKS)
{
explosionTicks++;
mesh.scale++;
}
}
+34
View File
@@ -0,0 +1,34 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Michał Mostowik <mostek3pl@gmail.com>
*/
#ifndef _MINE_
#define _MINE_
#include <tamtypes.h>
#include <models/mesh.hpp>
#define MINE_EXPLOSION_TICKS 10
class Mine
{
public:
static u8 lastSoundBuffer;
Mesh mesh;
void explode() { bExploding = true; }
void update();
Mine();
const u8 &getExplosionTicks() { return explosionTicks; }
private:
u8 bExploding;
u8 explosionTicks;
};
#endif
+98
View File
@@ -0,0 +1,98 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Michał Mostowik <mostek3pl@gmail.com>
*/
#include "player.hpp"
#include "dolphin.hpp"
#include <loaders/obj_loader.hpp>
#include <loaders/bmp_loader.hpp>
#include <modules/gif_sender.hpp>
#include <utils/debug.hpp>
#include <utils/math.hpp>
Player::Player()
{
mesh.loadMD2("dolphin/", "dolphin", 0.025F, true);
mesh.shouldBeFrustumCulled = false;
mesh.position.set(0.0F, 0.0F, 10.0f);
mesh.rotation.x = -1.6F;
mesh.setAnimSpeed(0.04F);
bIsJumping = false;
lifes = 3;
}
void Player::init(Engine *t_engine)
{
pEngine = t_engine;
waterImpact = t_engine->audio.loadADPCM("sound/water_impact.sad");
}
void Player::update(Pad &t_pad)
{
if (lift > 0.0F)
lift -= 0.05F;
if (lift < 0.0F)
lift += 0.05F;
if (lift < 0.1F && lift > -0.1F)
lift = 0;
if (t_pad.lJoyV <= 100)
velocity = 1;
else if (t_pad.lJoyV >= 200)
velocity = -1;
if (t_pad.lJoyH >= 200)
mesh.rotation.z -= 0.05;
else if (t_pad.lJoyH <= 100)
mesh.rotation.z += 0.05;
if (t_pad.rJoyV >= 200 && lift <= 1)
lift += 0.2F;
else if (t_pad.rJoyV <= 100 && lift >= -1)
lift -= 0.2F;
if (t_pad.isCrossClicked && mesh.getCurrentAnimationFrame() <= 14 && WATER_LEVEL - 15 < mesh.position.y)
{
mesh.setAnimSpeed(1.0F);
mesh.playAnimation(14, 58, 0);
}
if (mesh.getCurrentAnimationFrame() > 25 && mesh.getCurrentAnimationFrame() < 47)
bIsJumping = true;
else
bIsJumping = false;
if (velocity > 0 && mesh.getCurrentAnimationFrame() == 0)
{
mesh.setAnimSpeed(0.05F);
mesh.playAnimation(1, 14, 0);
}
if (mesh.getCurrentAnimationFrame() == 42)
{
if (!bIsImpactingWater)
{
pEngine->audio.setADPCMVolume(50, 2);
pEngine->audio.playADPCM(waterImpact, 2);
}
bIsImpactingWater = true;
}
else if (bIsImpactingWater)
{
bIsImpactingWater = false;
}
velocity *= 60.0F / Dolphin::engineFPS; // Moving by deltatime of last frame.
mesh.position.z +=
Math::cos(mesh.rotation.z) * velocity * (bIsJumping + 1);
mesh.position.x +=
Math::sin(mesh.rotation.z) * velocity * (bIsJumping + 1);
mesh.position.y += lift;
velocity = 0;
}
+43
View File
@@ -0,0 +1,43 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Michał Mostowik <mostek3pl@gmail.com>
*/
#ifndef _PLAYER_
#define _PLAYER_
#define WATER_LEVEL -5.0F
#include "../camera.hpp"
#include <audsrv.h>
#include <modules/pad.hpp>
#include <tamtypes.h>
class Engine;
class Player
{
public:
float gravity, velocity, lift;
Mesh mesh;
Player();
void init(Engine *t_engine);
void update(Pad &t_pad);
const u8 &isJumping() { return bIsJumping; }
const u8 &getLifes() { return lifes; }
void setLife(const u8 &l) { lifes = lifes = l < 4 ? l : 3; }
private:
u8 bIsJumping;
Vector3 playerNextPosition;
u8 lifes;
audsrv_adpcm_t *waterImpact;
Engine *pEngine;
u8 bIsImpactingWater;
};
#endif
+3
View File
@@ -0,0 +1,3 @@
.vscode/
bin/**
fonts/**
+18 -38
View File
@@ -1,59 +1,39 @@
EE_BIN = floors.elf EE_BIN = floors.elf
TYRA_DIR = ./../../engine
EE_OBJS = \ EE_OBJS = \
../../engine/models/math/matrix.o \
../../engine/models/math/plane.o \
../../engine/models/math/point.o \
../../engine/models/math/vector3.o \
../../engine/models/mesh_frame.o \
../../engine/models/mesh_material.o \
../../engine/models/mesh.o \
../../engine/models/mesh_texture.o \
../../engine/modules/audio.o \
../../engine/modules/camera_base.o \
../../engine/modules/gif_sender.o \
../../engine/modules/light.o \
../../engine/modules/pad.o \
../../engine/modules/renderer.o \
../../engine/modules/texture_repository.o \
../../engine/modules/timer.o \
../../engine/modules/vif_sender.o \
../../engine/modules/vu1.o \
../../engine/utils/math.o \
../../engine/utils/string.o \
../../engine/loaders/bmp_loader.o \
../../engine/loaders/dff_loader.o \
../../engine/loaders/md2_loader.o \
../../engine/loaders/obj_loader.o \
../../engine/vu1_progs/draw3D.o \
../../engine/engine.o \
managers/light_manager.o \ managers/light_manager.o \
managers/floor_manager.o \ managers/floor_manager.o \
camera.o \ camera.o \
objects/enemy.o \
objects/floor.o \ objects/floor.o \
objects/player.o \ objects/player.o \
ui.o \
utils.o \ utils.o \
floors.o \ floors.o \
main.o main.o
EE_LIBS = -ldraw -lgraph -lmath3d -lpacket -ldma -lpad -laudsrv -lc -lstdc++ EE_LIBS = -ltyra
EE_INCS := -I./../../engine/include $(EE_INCS)
EE_DVP = dvp-as
EE_VCL = openvcl
all: $(EE_BIN) all: $(EE_BIN)
$(EE_STRIP) --strip-all $(EE_BIN) $(EE_STRIP) --strip-all $(EE_BIN)
mv $(EE_BIN) bin/$(EE_BIN) mv $(EE_BIN) bin/$(EE_BIN)
rm $(EE_OBJS) rm $(EE_OBJS)
%.vsm: %.vcl rebuild-engine:
$(EE_VCL) $< >> $@ cd $(TYRA_DIR) && make clean && make
%.o: %.vsm
$(EE_DVP) $< -o $@
clean: clean:
rm -f $(EE_BIN) $(EE_OBJS) rm -f $(EE_OBJS)
include $(PS2SDK)/samples/Makefile.pref run: $(EE_BIN)
include $(PS2SDK)/samples/Makefile.eeglobal killall -v ps2client || true
ps2client reset
ps2client reset
$(EE_STRIP) --strip-all $(EE_BIN)
mv $(EE_BIN) bin/$(EE_BIN)
rm $(EE_OBJS)
cd bin/ && ps2client execee host:$(EE_BIN)
include $(TYRA_DIR)/Makefile.pref
+10 -5
View File
@@ -1,14 +1,19 @@
## Floors sample ## Floors sample
### Description ### Features
- Box collision
Simple demo which shows lighting using PATH3, and player movement and animation. - 2 animated characters
- Texture tricks showcase
- Background song
- Audio effects - walking, fighting (ADPCM)
- Transparent 2D UI
- Usage of draw() in array mode (for floors, very fast)
### Assets ### Assets
[Download](http://apgcglz.cluster028.hosting.ovh.net/tyra/1.1.0/samples/floors/assets.zip) [Download](http://apgcglz.cluster028.hosting.ovh.net/tyra/1.29.1/samples/floors/assets.zip)
### Screenshot ### Screenshot
[![Floors screenshot][floors-screenshot]](#) [![Floors screenshot][floors-screenshot]](#)
[floors-screenshot]: http://apgcglz.cluster028.hosting.ovh.net/tyra/1.1.0/samples/floors/floors.gif [floors-screenshot]: http://apgcglz.cluster028.hosting.ovh.net/tyra/1.29.1/samples/floors/floors.gif
+4 -19
View File
@@ -19,13 +19,10 @@ const float CAMERA_Y = 30.0F;
// Constructors/Destructors // Constructors/Destructors
// ---- // ----
Camera::Camera(ScreenSettings *t_screen) : CameraBase(t_screen, &position, &up, &unitCirclePosition) Camera::Camera(ScreenSettings *t_screen) : CameraBase(t_screen, &position)
{ {
PRINT_LOG("Initializing camera"); PRINT_LOG("Initializing camera");
verticalLevel = 80.0F; verticalLevel = 80.0F;
up.x = 0.0F;
up.y = 1.0F;
up.z = 0.0F;
PRINT_LOG("Camera initialized!"); PRINT_LOG("Camera initialized!");
} }
@@ -39,8 +36,7 @@ void Camera::update(Pad &t_pad, Mesh &t_mesh)
{ {
rotate(t_pad); rotate(t_pad);
followBy(t_mesh); followBy(t_mesh);
updatePlanes(t_mesh.position); lookAt(t_mesh.position);
worldView.lookAt(up, position, t_mesh.position);
} }
/** Set camera rotation by pad right joy and update unit circle /** Set camera rotation by pad right joy and update unit circle
@@ -49,10 +45,10 @@ void Camera::update(Pad &t_pad, Mesh &t_mesh)
*/ */
void Camera::rotate(Pad &t_pad) void Camera::rotate(Pad &t_pad)
{ {
if (t_pad.rJoyH <= 50) if (t_pad.rJoyH <= 100)
horizontalLevel -= 0.08; horizontalLevel -= 0.08;
else if (t_pad.rJoyH >= 200) else if (t_pad.rJoyH >= 200)
horizontalLevel += 0.04; horizontalLevel += 0.08;
if (t_pad.rJoyV <= 50 && verticalLevel > 25.0F) if (t_pad.rJoyV <= 50 && verticalLevel > 25.0F)
verticalLevel -= 0.9F; verticalLevel -= 0.9F;
else if (t_pad.rJoyV >= 200 && verticalLevel < 80.0F) else if (t_pad.rJoyV >= 200 && verticalLevel < 80.0F)
@@ -68,15 +64,4 @@ void Camera::followBy(Mesh &t_mesh)
position.x = unitCirclePosition.x + t_mesh.position.x; position.x = unitCirclePosition.x + t_mesh.position.x;
position.y = unitCirclePosition.y + t_mesh.position.y; position.y = unitCirclePosition.y + t_mesh.position.y;
position.z = unitCirclePosition.z + t_mesh.position.z; position.z = unitCirclePosition.z + t_mesh.position.z;
if (position.x > (-0.04F * verticalLevel) &&
position.x < 0.0F &&
position.z > (0.998F * verticalLevel))
{
// TODO
// position.x = 0.0F;
// position.y = 0.0F;
// position.z = 0.0F;
// horizontalLevel = 0.0F;
}
} }
-1
View File
@@ -35,7 +35,6 @@ public:
protected: protected:
Vector3 *getPosition() { return &position; }; Vector3 *getPosition() { return &position; };
Vector3 *getUp() { return &up; };
ScreenSettings screen; ScreenSettings screen;
}; };
+67 -23
View File
@@ -14,9 +14,22 @@
// Constructors/Destructors // Constructors/Destructors
// ---- // ----
Floors::Floors() {} const u16 FLOORS_COUNT = 144; // Temp change it also in floor_manager.hpp
Floors::~Floors() {} Floors::Floors(Engine *t_engine)
: engine(t_engine), floorManager(), camera(&t_engine->screen)
{
audioTicks = 0;
skip1Beat = 0;
}
Floors::~Floors()
{
delete enemy;
delete ui;
delete floorManager;
delete player;
}
// ---- // ----
// Methods // Methods
@@ -24,31 +37,62 @@ Floors::~Floors() {}
void Floors::onInit() void Floors::onInit()
{ {
player = new Player(); texRepo = engine->renderer->getTextureRepository();
camera = new Camera(&engine.screen); enemy = new Enemy(texRepo);
engine.renderer->setCameraDefinitions(&camera->worldView, &camera->unitCirclePosition, camera->planes); ui = new Ui(texRepo);
floorManager = new FloorManager(64); // Temp change it also in floor_manager.hpp floorManager = new FloorManager(FLOORS_COUNT, texRepo); // we must init FloorManager before starting audio!
engine.audio.init(2); player = new Player(&engine->audio, texRepo);
engine.audio.addListener(floorManager); setBgColorAndAmbientColor();
engine.audio.addListener(&lightManager); engine->renderer->setCameraDefinitions(&camera.view, &camera.unitCirclePosition, camera.planes);
engine.audio.loadSong("NF-CHILL.WAV"); engine->audio.addSongListener(this);
engine.audio.play(); engine->audio.loadSong("sounds/mafikizolo-loot.wav");
texRepo = engine.renderer->getTextureRepository(); engine->audio.playSong();
texRepo->addByMesh("warrior/", player->mesh); engine->audio.setSongVolume(80);
texRepo->addByMesh("floor/", *floorManager->meshes[0]);
for (size_t i = 1; i < floorManager->floorAmount; i++)
texRepo->getByMesh(floorManager->meshes[0]->getId(), floorManager->meshes[0]->getMaterial(0).getId())
->addLink(floorManager->meshes[i]->getId(), floorManager->meshes[i]->getMaterial(0).getId());
} }
void Floors::onUpdate() void Floors::onUpdate()
{ {
if (engine.pad.isCrossClicked) ui->update(*player);
printf("FPS:%f\n", engine.fps); enemy->update(*floorManager);
lightManager.update(); lightManager.update();
camera->update(engine.pad, player->mesh); camera.update(engine->pad, player->mesh);
floorManager->update(*player); floorManager->update(*player);
player->update(engine.pad, *camera, *floorManager); player->update(engine->pad, camera, *floorManager, *enemy);
engine.renderer->draw(&player->mesh); engine->renderer->draw(player->mesh);
engine.renderer->drawByPath3(floorManager->meshes, floorManager->floorAmount, lightManager.bulbs, lightManager.bulbsCount); engine->renderer->draw(enemy->getMeshes(), enemy->getMeshesCount());
// You can draw array of meshes in draw() function also. It can be A LOT faster than for looping!
// Why? When given mesh is small, is not animated and is not backface culled, vertex data are send once!
engine->renderer->draw(floorManager->getMeshes(), FLOORS_COUNT, lightManager.bulbs, lightManager.bulbsCount);
ui->render(engine->renderer); // 2D rendering ist LAST step, because layers gonna play there.
}
void Floors::onAudioTick()
{
if ((++audioTicks + 20) % 21 == 0)
{
if (skip1Beat)
floorManager->onAudioTick();
lightManager.onAudioTick();
skip1Beat = !skip1Beat;
}
if (audioTicks > 10000)
audioTicks = 0;
}
void Floors::setBgColorAndAmbientColor()
{
color_t bgColor;
bgColor.r = 0x20;
bgColor.g = 0x20;
bgColor.b = 0x20;
engine->renderer->setWorldColor(bgColor);
Vector3 ambient = Vector3(0.003F, 0.003F, 0.003F);
engine->renderer->setAmbientLight(ambient);
}
void Floors::onAudioFinish()
{
audioTicks = 0;
} }
+13 -4
View File
@@ -18,26 +18,35 @@
#include "managers/light_manager.hpp" #include "managers/light_manager.hpp"
#include "modules/texture_repository.hpp" #include "modules/texture_repository.hpp"
#include "objects/player.hpp" #include "objects/player.hpp"
#include "objects/enemy.hpp"
#include "./camera.hpp" #include "./camera.hpp"
#include "./ui.hpp"
class Floors : public Game class Floors : public Game, AudioListener
{ {
public: public:
Floors(); Floors(Engine *t_engine);
~Floors(); ~Floors();
void onInit(); void onInit();
void onUpdate(); void onUpdate();
void onAudioTick();
void onAudioFinish();
Engine engine; Engine *engine;
private: private:
void setBgColorAndAmbientColor();
u32 audioTicks;
u8 skip1Beat;
TextureRepository *texRepo; TextureRepository *texRepo;
LightManager lightManager; LightManager lightManager;
FloorManager *floorManager; FloorManager *floorManager;
Player *player; Player *player;
Camera *camera; Camera camera;
Ui *ui;
Enemy *enemy;
}; };
#endif #endif
+3 -3
View File
@@ -12,9 +12,9 @@
int main() int main()
{ {
Floors game = Floors(); Engine engine = Engine();
game.engine.setDefaultScreen(); Floors game = Floors(&engine);
game.engine.init(&game, 40000); game.engine->init(&game, 128);
SleepThread(); SleepThread();
return 0; return 0;
} }
+81 -21
View File
@@ -20,20 +20,24 @@
/** Calculate square spiral offsets and initialize floors /** Calculate square spiral offsets and initialize floors
* @param floorAmount must be a number from square root table * @param floorAmount must be a number from square root table
*/ */
FloorManager::FloorManager(int t_floorAmount) FloorManager::FloorManager(int t_floorAmount, TextureRepository *t_texRepo)
{ {
meshes = new Mesh *[t_floorAmount];
texRepo = t_texRepo;
floorAmount = t_floorAmount; floorAmount = t_floorAmount;
spirals = new Point[t_floorAmount]; spirals = new Point[t_floorAmount];
int floorSpiralMaxOffset = (int)Math::sqrt(t_floorAmount); int floorSpiralMaxOffset = (int)Math::sqrt(t_floorAmount);
calcSpiral(floorSpiralMaxOffset, floorSpiralMaxOffset); calcSpiral(floorSpiralMaxOffset, floorSpiralMaxOffset);
initFloors(); initFloors();
audioOffset = audioMode = audioTick = 0; trick = 0.0F;
isTimeForChangeTriggerColor = true;
isTimeForChangeDefaultColor = true;
audioOffset = audioMode = audioTick = trickMode = 0;
} }
FloorManager::~FloorManager() FloorManager::~FloorManager()
{ {
delete[] spirals; delete[] spirals;
delete[] meshes;
} }
// ---- // ----
@@ -78,15 +82,17 @@ void FloorManager::calcSpiral(int X, int Y)
void FloorManager::initFloors() void FloorManager::initFloors()
{ {
PRINT_LOG("Initializing floors"); PRINT_LOG("Initializing floors");
meshes = new Mesh *[floorAmount]; floors[0].mesh.loadObj("meshes/floor/", "floor", 3.0F, false);
floors[0].mesh.shouldBeFrustumCulled = true;
meshes[0] = new Mesh(); floors[0].mesh.shouldBeLighted = true;
meshes[0]->loadObj("floor/", "floor", 2.0F, false); meshes[0] = &floors[0].mesh;
meshes[0]->shouldBeFrustumCulled = true; texRepo->addByMesh("meshes/floor/", floors[0].mesh, BMP);
meshes[0]->shouldBeLighted = true; for (u16 i = 1; i < floorAmount; i++)
for (u8 i = 0; i < floorAmount; i++)
{ {
floors[i].init(meshes[0], spirals[i], i); floors[i].mesh.shouldBeFrustumCulled = true;
floors[i].init(floors[0].mesh, spirals[i], i);
texRepo->getByMesh(floors[0].mesh.getId(), floors[0].mesh.getMaterial(0).getId())
->addLink(floors[i].mesh.getId(), floors[i].mesh.getMaterial(0).getId());
meshes[i] = &floors[i].mesh; meshes[i] = &floors[i].mesh;
} }
PRINT_LOG("Floors initialized!"); PRINT_LOG("Floors initialized!");
@@ -99,25 +105,75 @@ void FloorManager::initFloors()
*/ */
void FloorManager::update(Player &t_player) void FloorManager::update(Player &t_player)
{ {
for (u8 i = 0; i < floorAmount; i++) if (isTimeForChangeTriggerColor)
{
isTimeForChangeTriggerColor = false;
trigColor.r = rand() % (128 - 64 + 1) + 64;
trigColor.g = rand() % (128 - 64 + 1) + 64;
trigColor.b = rand() % (128 - 64 + 1) + 64;
}
if (isTimeForChangeDefaultColor)
{
isTimeForChangeDefaultColor = false;
defaultColor.r = rand() % (64 + 1);
defaultColor.g = rand() % (64 + 1);
defaultColor.b = rand() % (64 + 1);
}
doTheTrick();
for (u16 i = 0; i < floorAmount; i++)
{ {
floors[i].animate(t_player); floors[i].animate(t_player);
if (floors[i].isByAudioTriggered == true) if (floors[i].isByAudioTriggered)
floors[i].mesh.color.a = 0x20; {
floors[i].mesh.color.r = trigColor.r;
floors[i].mesh.color.g = trigColor.g;
floors[i].mesh.color.b = trigColor.b;
}
else else
floors[i].mesh.color.a = 0x80; {
floors[i].mesh.color.r = defaultColor.r;
floors[i].mesh.color.g = defaultColor.g;
floors[i].mesh.color.b = defaultColor.b;
}
} }
} }
void FloorManager::doTheTrick()
{
if (trickMode == 0)
{
if (trick > 3.0F)
{
isTimeForChangeTriggerColor = true;
trickMode = 1;
}
trick += 0.01F;
}
else if (trickMode == 1)
{
if (trick <= 0.1F)
{
isTimeForChangeTriggerColor = true;
trickMode = 0;
}
trick -= 0.01F;
}
floors[0].mesh.getFrames()[0].getST(1).set(trick, trick);
floors[0].mesh.getFrames()[0].getST(4).set(trick, trick);
floors[0].mesh.getFrames()[0].getST(7).set(trick, trick);
floors[0].mesh.getFrames()[0].getST(10).set(trick, trick);
floors[0].mesh.getFrames()[0].getST(13).set(trick, trick);
}
/** Called by audio thread */ /** Called by audio thread */
void FloorManager::onAudioTick() void FloorManager::onAudioTick()
{ {
if (audioTick++ > 16) if (audioTick++ > 19)
{ {
if (audioMode == 0) if (audioMode == 0)
{ {
for (u8 i = 0; i < floorAmount; i++) for (u16 i = 0; i < floorAmount; i++)
{ {
if ((i + audioOffset) % 2 == 0) if ((i + audioOffset) % 2 == 0)
floors[i].isByAudioTriggered = true; floors[i].isByAudioTriggered = true;
@@ -127,12 +183,13 @@ void FloorManager::onAudioTick()
if (++audioOffset > 3) if (++audioOffset > 3)
{ {
audioOffset = 0; audioOffset = 0;
isTimeForChangeDefaultColor = true;
audioMode = 1; audioMode = 1;
} }
} }
else if (audioMode == 1) else if (audioMode == 1)
{ {
for (u8 i = 0; i < floorAmount; i++) for (u16 i = 0; i < floorAmount; i++)
{ {
if (i < floorAmount / (audioOffset + 1)) if (i < floorAmount / (audioOffset + 1))
floors[i].isByAudioTriggered = true; floors[i].isByAudioTriggered = true;
@@ -142,12 +199,13 @@ void FloorManager::onAudioTick()
if (++audioOffset > 3) if (++audioOffset > 3)
{ {
audioOffset = 0; audioOffset = 0;
isTimeForChangeDefaultColor = true;
audioMode = 2; audioMode = 2;
} }
} }
else if (audioMode == 2) else if (audioMode == 2)
{ {
for (u8 i = 0; i < floorAmount; i++) for (u16 i = 0; i < floorAmount; i++)
{ {
if ((i + audioOffset) % 4 == 0) if ((i + audioOffset) % 4 == 0)
floors[i].isByAudioTriggered = true; floors[i].isByAudioTriggered = true;
@@ -157,14 +215,15 @@ void FloorManager::onAudioTick()
if (++audioOffset > 3) if (++audioOffset > 3)
{ {
audioOffset = 0; audioOffset = 0;
isTimeForChangeDefaultColor = true;
audioMode = 3; audioMode = 3;
} }
} }
else if (audioMode == 3) else if (audioMode == 3)
{ {
for (u8 i = 0; i < floorAmount; i++) for (u16 i = 0; i < floorAmount; i++)
{ {
if (i + 1 > floorAmount / (audioOffset + 1)) if (u16(i + 1) > floorAmount / (audioOffset + 1))
floors[i].isByAudioTriggered = true; floors[i].isByAudioTriggered = true;
else else
floors[i].isByAudioTriggered = false; floors[i].isByAudioTriggered = false;
@@ -172,6 +231,7 @@ void FloorManager::onAudioTick()
if (++audioOffset > 3) if (++audioOffset > 3)
{ {
audioOffset = 0; audioOffset = 0;
isTimeForChangeDefaultColor = true;
audioMode = 0; audioMode = 0;
} }
} }
+13 -5
View File
@@ -14,29 +14,37 @@
class Player; // Forward definition class Player; // Forward definition
#include <models/math/point.hpp> #include <models/math/point.hpp>
#include <modules/texture_repository.hpp>
#include <modules/camera_base.hpp> #include <modules/camera_base.hpp>
#include <models/audio_listener.hpp> #include <models/audio_listener.hpp>
#include "../objects/floor.hpp" #include "../objects/floor.hpp"
/** Class which is maintaining floors objects */ /** Class which is maintaining floors objects */
class FloorManager : public AudioListener class FloorManager
{ {
public: public:
FloorManager(int t_floorAmount); FloorManager(int t_floorAmount, TextureRepository *t_texRepo);
~FloorManager(); ~FloorManager();
Floor floors[64]; // Temp change it also in floors.cpp Floor floors[144]; // Temp change it also in floors.cpp
int floorAmount; u16 floorAmount;
void update(Player &t_player); void update(Player &t_player);
Mesh **meshes;
void onAudioTick(); void onAudioTick();
Mesh **getMeshes() { return meshes; }
private: private:
Mesh **meshes;
TextureRepository *texRepo;
u8 audioOffset, audioMode; u8 audioOffset, audioMode;
u32 audioTick; u32 audioTick;
float trick;
u8 isTimeForChangeTriggerColor, isTimeForChangeDefaultColor;
color_t trigColor, defaultColor;
u8 trickMode;
Point *spirals; Point *spirals;
void calcSpiral(int X, int Y); void calcSpiral(int X, int Y);
void doTheTrick();
void initFloors(); void initFloors();
}; };
@@ -142,7 +142,7 @@ void LightManager::onAudioTick()
} }
else else
{ {
bulbs[0].intensity += 6; bulbs[0].intensity += 9;
bulbs[1].intensity += 6; bulbs[1].intensity += 9;
} }
} }
@@ -15,7 +15,7 @@
#include <models/audio_listener.hpp> #include <models/audio_listener.hpp>
/** Class which is maintaining floors objects */ /** Class which is maintaining floors objects */
class LightManager : public AudioListener class LightManager
{ {
public: public:

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