diff --git a/ROADMAP.txt b/ROADMAP.txt index 3a242f4..a6f2a85 100644 --- a/ROADMAP.txt +++ b/ROADMAP.txt @@ -5,7 +5,7 @@ - [Tutorials] 7 - [Tutorials] 8 - [Tutorials] 9. -- [Renderer] Check ee clipping on de_dust2, add decimate to de_dust2? + - [General] Check all left TODOs -> Github issues - [General] Readme Credits: clipping, obj loader - [Video] How to setup environment @@ -19,6 +19,7 @@ - [Demo] BBox constructors - [General] Add cpp lint checker in GitHub / static code analysis - [General] Smart pointers and std::array instead of raw pointers +- [Renderer] Check ee clipping on de_dust2, add decimate to de_dust2? - [General] Control generated id to avoid duplication. Maybe Just increment from 0? Add interface IIdentificable? - [renderer] fog - [General] CI in Github via docker image diff --git a/tutorials/02-sprite/bin/tyra.png b/tutorials/02-sprite/bin/tyra.png new file mode 100644 index 0000000..016f830 Binary files /dev/null and b/tutorials/02-sprite/bin/tyra.png differ diff --git a/tutorials/05-animation/inc/tutorial_05.hpp b/tutorials/05-animation/inc/tutorial_05.hpp index 60a6289..21c7bc3 100644 --- a/tutorials/05-animation/inc/tutorial_05.hpp +++ b/tutorials/05-animation/inc/tutorial_05.hpp @@ -23,7 +23,18 @@ class Tutorial05 : public Game { void loop(); private: + void loadZombieMesh(); + void loadWarriorMesh(); + void warriorAnimationCallback(const AnimationSequenceCallback& callback); + Engine* engine; + + Vec4 cameraPosition, cameraLookAt; + + std::unique_ptr warriorMesh; + std::unique_ptr zombieMesh; + DynamicPipeline dynpip; + DynPipOptions renderOptions; }; } // namespace Tyra diff --git a/tutorials/05-animation/src/tutorial_05.cpp b/tutorials/05-animation/src/tutorial_05.cpp index 3eb49b6..b0ae989 100644 --- a/tutorials/05-animation/src/tutorial_05.cpp +++ b/tutorials/05-animation/src/tutorial_05.cpp @@ -17,8 +17,91 @@ Tutorial05::Tutorial05(Engine* t_engine) : engine(t_engine) {} Tutorial05::~Tutorial05() {} -void Tutorial05::init() {} +void Tutorial05::init() { + dynpip.setRenderer(&engine->renderer.core); -void Tutorial05::loop() {} + cameraPosition = Vec4(0.0F, 0.0F, -10.0F); + cameraLookAt.unit(); + + loadZombieMesh(); + loadWarriorMesh(); +} + +void Tutorial05::loop() { + zombieMesh->update(); // update animation state + warriorMesh->update(); + + engine->renderer.beginFrame(CameraInfo3D(&cameraPosition, &cameraLookAt)); + { + engine->renderer.renderer3D.usePipeline(dynpip); + + dynpip.render(zombieMesh.get(), renderOptions); + dynpip.render(warriorMesh.get(), renderOptions); + } + engine->renderer.endFrame(); +} + +void Tutorial05::loadZombieMesh() { + ObjLoaderOptions options; + options.scale = 20.0F; + options.flipUVs = true; + + /** If count is > 1, loader will automatically add _00000X suffix */ + options.animation.count = 6; + + /** Starting file suffix index. It means that 1 will start from _000001.obj */ + options.animation.startingIndex = 1; + + /** If you want to know how to cook this file, please watch tutorial video */ + auto data = ObjLoader::load(FileUtils::fromCwd("zombie/zombie.obj"), options); + + zombieMesh = std::make_unique(data.get()); + + zombieMesh->translation.translate(Vec4(-3.0F, -5.0F, 0.0F)); + zombieMesh->rotation.rotateY(3.0F); + + /** + * Tyra will play all frames by default. + * If you want to arrange animation frames by yourself, you can use this + * method. + */ + zombieMesh->animation.setSequence({3, 4, 5}); // fight animation + // zombieMesh->animation.setSequence({0, 1, 2}); // walk animation + + zombieMesh->animation.loop = true; + + engine->renderer.getTextureRepository().addByMesh( + zombieMesh.get(), FileUtils::fromCwd("zombie/"), "png"); +} + +void Tutorial05::loadWarriorMesh() { + MD2LoaderOptions options; + options.scale = .08F; + + auto data = + MD2Loader::load(FileUtils::fromCwd("warrior/warrior.md2"), options); + + warriorMesh = std::make_unique(data.get()); + + warriorMesh->translation.translate(Vec4(3.0F, -4.0F, 0.0F)); + warriorMesh->rotation.rotateX(-1.566F); + warriorMesh->rotation.rotateY(1.566F); + + warriorMesh->animation.speed = 0.2F; + + /** Callback can return useful animation informations */ + warriorMesh->animation.setCallback(std::bind( + &Tutorial05::warriorAnimationCallback, this, std::placeholders::_1)); + + engine->renderer.getTextureRepository().addByMesh( + warriorMesh.get(), FileUtils::fromCwd("warrior/"), "png"); +} + +void Tutorial05::warriorAnimationCallback( + const AnimationSequenceCallback& callback) { + if (callback == AnimationSequenceCallback_Loop) { + TYRA_LOG("Warrior animation sequence is starting from beginning!"); + } +} } // namespace Tyra