diff --git a/demos/demo1-wireframes/src/main.cpp b/demos/demo1-wireframes/src/main.cpp index fcd8c2d..7891b92 100644 --- a/demos/demo1-wireframes/src/main.cpp +++ b/demos/demo1-wireframes/src/main.cpp @@ -1,11 +1,12 @@ #include -#include +#include #include #include "wirescene.h" int main() { std::shared_ptr engine(new GBAEngine()); + engine.get()->setRenderer(new WiredRenderer()); WireScene* startScene = new WireScene(engine); engine->setScene(startScene); diff --git a/demos/demo1-wireframes/src/wirescene.cpp b/demos/demo1-wireframes/src/wirescene.cpp index db01b35..102e001 100644 --- a/demos/demo1-wireframes/src/wirescene.cpp +++ b/demos/demo1-wireframes/src/wirescene.cpp @@ -3,7 +3,7 @@ // #include -#include +#include #include #include "wirescene.h" @@ -20,7 +20,6 @@ Camera WireScene::camera() { return Camera(VectorFx::fromInt(0, 0, 10), VectorFx::fromInt(0, 0, 0)); } -int msecs = 1; void WireScene::load() { foregroundPalette = std::unique_ptr(new ForegroundPaletteManager()); backgroundPalette = std::unique_ptr(new BackgroundPaletteManager(pal, sizeof(pal))); @@ -48,26 +47,20 @@ void WireScene::load() { cube->addFace({ 0, 4, 7}); cube->addFace({ 4, 5, 6}); cube->addFace({ 4, 6, 7}); - - engine->getTimer()->start(); } +bool wired = true; void WireScene::tick(u16 keys) { - int curmsecs = engine->getTimer()->getMsecs(); - int elapsed = curmsecs - msecs; - msecs = curmsecs; - - TextStream::instance().setText(std::to_string(1000 / elapsed) + std::string(" FPS"), 1, 1); - cube->rotate(2, 2); if(keys & KEY_A) { cube->resetRotation(); } else if(keys & KEY_B) { - if(cube->isWired()) { - cube->unwire(); + wired = !wired; + if(wired) { + engine->setRenderer(new WiredRenderer()); } else { - cube->wire(); + engine->setRenderer(new PixelRenderer()); } } } diff --git a/demos/demo2-blender-import/src/main.cpp b/demos/demo2-blender-import/src/main.cpp index dbb1112..de75970 100644 --- a/demos/demo2-blender-import/src/main.cpp +++ b/demos/demo2-blender-import/src/main.cpp @@ -3,13 +3,14 @@ // #include -#include +#include #include #include "monkey.h" int main() { std::shared_ptr engine(new GBAEngine()); + engine.get()->setRenderer(new WiredRenderer()); MonkeyScene* startScene = new MonkeyScene(engine); engine->setScene(startScene); diff --git a/demos/demo2-blender-import/src/monkey.cpp b/demos/demo2-blender-import/src/monkey.cpp index 08f56bb..d5f3055 100644 --- a/demos/demo2-blender-import/src/monkey.cpp +++ b/demos/demo2-blender-import/src/monkey.cpp @@ -17,23 +17,13 @@ Camera MonkeyScene::camera() { return Camera(VectorFx::fromInt(0, 0, 10), VectorFx::fromInt(0, 0, 0)); } -int msecs = 1; void MonkeyScene::load() { foregroundPalette = std::unique_ptr(new ForegroundPaletteManager()); backgroundPalette = std::unique_ptr(new BackgroundPaletteManager(pal, sizeof(pal))); monkey = std::unique_ptr(createMesh()); - - engine->getTimer()->start(); } void MonkeyScene::tick(u16 keys) { - int curmsecs = engine->getTimer()->getMsecs(); - int elapsed = curmsecs - msecs; - msecs = curmsecs; - int fps = 1000 / elapsed; - - TextStream::instance().setText(std::to_string(fps < 0 ? 0 : fps) + std::string(" FPS"), 1, 1); - monkey->rotate(10, 10); } diff --git a/demos/demo2-blender-import/src/monkey.h b/demos/demo2-blender-import/src/monkey.h index 6318198..95e60cb 100644 --- a/demos/demo2-blender-import/src/monkey.h +++ b/demos/demo2-blender-import/src/monkey.h @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include // forward declaration of generated mesh.cpp file diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index 81a1b31..e890e9b 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -19,7 +19,9 @@ add_library(${PROJECT_NAME} src/gba/tonc_bios.s src/gba/tonc_bmp8.cpp src/background/tonc_font.s - src/gba_engine.cpp + src/renderer/gba_engine.cpp + src/renderer/pixelrenderer.cpp + src/renderer/wirerenderer.cpp src/math.cpp src/sound_control.cpp src/scene.cpp src/timer.cpp src/vectorfx.cpp src/mesh.cpp) diff --git a/engine/include/libgba-sprite-engine/mesh.h b/engine/include/libgba-sprite-engine/mesh.h index c796933..96d9f69 100644 --- a/engine/include/libgba-sprite-engine/mesh.h +++ b/engine/include/libgba-sprite-engine/mesh.h @@ -20,7 +20,6 @@ private: VectorFx pos; VectorFx rot; u8 cIndex; - bool wired; std::vector> verticesArr; std::vector facesArr; @@ -41,9 +40,6 @@ public: inline VectorFx &position() { return pos; } inline VectorFx &rotation() { return rot; } - inline void wire() { wired = true; } - inline void unwire() { wired = false; } - inline bool isWired() const { return wired; } inline u8 colorIndex() const { return cIndex; } inline FIXED rotx() const { return rot.x(); } inline FIXED roty() const { return rot.y(); } @@ -62,7 +58,7 @@ public: rot.setY(rot.y() + y); } - explicit Mesh() : pos(VectorFx()), rot(VectorFx()), cIndex(1), wired(true) {} + explicit Mesh() : pos(VectorFx()), rot(VectorFx()), cIndex(1) {} Mesh(const Mesh&) = delete; Mesh& operator=(const Mesh&) = delete; }; diff --git a/engine/include/libgba-sprite-engine/gba_engine.h b/engine/include/libgba-sprite-engine/renderer/gba_engine.h similarity index 75% rename from engine/include/libgba-sprite-engine/gba_engine.h rename to engine/include/libgba-sprite-engine/renderer/gba_engine.h index 468d613..07088d1 100644 --- a/engine/include/libgba-sprite-engine/gba_engine.h +++ b/engine/include/libgba-sprite-engine/renderer/gba_engine.h @@ -11,9 +11,10 @@ #include #include #include -#include "scene.h" -#include "sound_control.h" -#include "timer.h" +#include +#include "libgba-sprite-engine/scene.h" +#include "libgba-sprite-engine/sound_control.h" +#include "libgba-sprite-engine/timer.h" const unsigned int black[VRAM_PAGE_SIZE] = {}; @@ -25,7 +26,10 @@ private: Camera currentCamera; Scene* sceneToTransitionTo; + bool showfps; + void showFPS(); MatrixFx projectionMatrix; + std::unique_ptr renderer; static std::unique_ptr timer; static std::unique_ptr activeChannelA; @@ -43,7 +47,6 @@ private: void render(); void renderClear(); - inline VectorPx project(const VectorFx &coord, const MatrixFx &transMat); void flipPage(); public: @@ -66,9 +69,12 @@ public: for(int i = 0; i < times; i++){} } - inline void plotPixel(int x, int y, u8 clrId); - inline void plotPixel(const VectorPx &pixel, u8 clrId); - inline void plotLine(const VectorPx &point0, const VectorPx &point1, u8 clrId); + void setRenderer(Renderer* r) { renderer = std::unique_ptr(r); }; + + VectorPx project(const VectorFx &coord, const MatrixFx &transMat); + void plotPixel(int x, int y, u8 clrId); + void plotPixel(const VectorPx &pixel, u8 clrId); + void plotLine(const VectorPx &point0, const VectorPx &point1, u8 clrId); }; diff --git a/engine/include/libgba-sprite-engine/renderer/renderer.h b/engine/include/libgba-sprite-engine/renderer/renderer.h new file mode 100644 index 0000000..66856e3 --- /dev/null +++ b/engine/include/libgba-sprite-engine/renderer/renderer.h @@ -0,0 +1,33 @@ +// +// Created by Wouter Groeneveld on 11/07/20. +// + +#ifndef GBA_BITMAP_ENGINE_PROJECT_RENDERER_H +#define GBA_BITMAP_ENGINE_PROJECT_RENDERER_H + +#include +#include + +class GBAEngine; + +class Renderer { +protected: + std::shared_ptr engine; + +public: + virtual void render(const MatrixFx &transformationMatrix, const Mesh* mesh) = 0; +}; + +class PixelRenderer : public Renderer { +public: + void render(const MatrixFx &transformationMatrix, const Mesh* mesh) override; + +}; + +class WiredRenderer : public Renderer { +public: + void render(const MatrixFx &transformationMatrix, const Mesh* mesh) override; + +}; + +#endif //GBA_BITMAP_ENGINE_PROJECT_RENDERER_H diff --git a/engine/src/gba_engine.cpp b/engine/src/renderer/gba_engine.cpp similarity index 83% rename from engine/src/gba_engine.cpp rename to engine/src/renderer/gba_engine.cpp index be7030a..a81bc61 100644 --- a/engine/src/gba_engine.cpp +++ b/engine/src/renderer/gba_engine.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include #include #include #include @@ -16,6 +16,7 @@ std::unique_ptr GBAEngine::activeChannelB; std::unique_ptr GBAEngine::timer; u16 *vid_page; +int msecs = 1; void GBAEngine::vsync() { while (REG_VCOUNT >= 160); @@ -124,6 +125,7 @@ GBAEngine::GBAEngine() { REG_SNDDSCNT = 0; vid_page = vid_mem_back; projectionMatrix = MatrixFx::perspectiveFovLH(float2fx(0.78), fxdiv(GBA_SCREEN_WIDTH_FX, GBA_SCREEN_HEIGHT_FX), float2fx(0.01), ONE); + showfps = true; } void GBAEngine::update() { @@ -135,27 +137,41 @@ void GBAEngine::update() { // TODO use software interrupt Vsyncing instead of 2 wasteful whiles vsync(); renderClear(); + + if(showfps) { + showFPS(); + } + currentScene->tick(keys); render(); flipPage(); } +void GBAEngine::showFPS() { + int curmsecs = getTimer()->getMsecs(); + int elapsed = curmsecs - msecs; + int fps = 1000 / elapsed; + msecs = curmsecs; + + TextStream::instance().setText(std::to_string(fps > 0 ? fps : 0) + std::string(" FPS"), 1, 1); +} + void GBAEngine::flipPage() { // toggle the write_buffer's page vid_page= (COLOR*)((u32)vid_page ^ VRAM_PAGE_SIZE); REG_DISPCNT ^= DCNT_PAGE; } -inline void GBAEngine::plotPixel(const VectorPx &pixel, u8 clrId) { +void GBAEngine::plotPixel(const VectorPx &pixel, u8 clrId) { m4_plot(pixel.x(), pixel.y(), clrId); } -inline void GBAEngine::plotLine(const VectorPx &point0, const VectorPx &point1, u8 clrId) { +void GBAEngine::plotLine(const VectorPx &point0, const VectorPx &point1, u8 clrId) { // uses tonc's optimalization tricks to get 10 FPS extra compared to standard bline algorithms m4_line(point0.x(), point0.y(), point1.x(), point1.y(), clrId); } -inline VectorPx GBAEngine::project(const VectorFx &coord, const MatrixFx &transMat) { +VectorPx GBAEngine::project(const VectorFx &coord, const MatrixFx &transMat) { auto point = MatrixFx::transformCoordinates(coord, transMat); auto x = fxmul(point.x(), GBA_SCREEN_WIDTH_FX) + fxdiv(GBA_SCREEN_WIDTH_FX, TWO); @@ -171,28 +187,7 @@ void GBAEngine::render() { auto worldMatrix = MatrixFx::rotationYawPitchRoll(mesh->roty(), mesh->rotx(), mesh->rotz()) * MatrixFx::translation(mesh->position()); auto transformMatrix = worldMatrix * viewMatrix * projectionMatrix; - if(mesh->isWired()) { - // triangular faces wireframes - for(auto& face : mesh->faces()) { - auto& vertexA = mesh->vertices()[face.a]; - auto& vertexB = mesh->vertices()[face.b]; - auto& vertexC = mesh->vertices()[face.c]; - - auto pixelA = project(*vertexA.get(), transformMatrix); - auto pixelB = project(*vertexB.get(), transformMatrix); - auto pixelC = project(*vertexC.get(), transformMatrix); - - plotLine(pixelA, pixelB, mesh->colorIndex()); - plotLine(pixelB, pixelC, mesh->colorIndex()); - plotLine(pixelC, pixelA, mesh->colorIndex()); - } - } else { - // pixel-only - for (auto &vertex : mesh->vertices()) { - auto projectedPoint = project(*vertex.get(), transformMatrix); - plotPixel(projectedPoint, mesh->colorIndex()); - } - } + renderer->render(transformMatrix, mesh); } } @@ -212,6 +207,7 @@ void GBAEngine::setScene(Scene* scene) { cleanupPreviousScene(); } scene->load(); + getTimer()->start(); auto fgPalette = scene->getForegroundPalette(); fgPalette->persist(); diff --git a/engine/src/renderer/pixelrenderer.cpp b/engine/src/renderer/pixelrenderer.cpp new file mode 100644 index 0000000..25ce634 --- /dev/null +++ b/engine/src/renderer/pixelrenderer.cpp @@ -0,0 +1,13 @@ +// +// Created by Wouter Groeneveld on 11/07/20. +// + +#include +#include + +void PixelRenderer::render(const MatrixFx &transformationMatrix, const Mesh* mesh) { + for (auto &vertex : mesh->vertices()) { + auto projectedPoint = engine->project(*vertex.get(), transformationMatrix); + engine->plotPixel(projectedPoint, mesh->colorIndex()); + } +} diff --git a/engine/src/renderer/wirerenderer.cpp b/engine/src/renderer/wirerenderer.cpp new file mode 100644 index 0000000..ae42614 --- /dev/null +++ b/engine/src/renderer/wirerenderer.cpp @@ -0,0 +1,22 @@ +// +// Created by Wouter Groeneveld on 11/07/20. +// + +#include +#include + +void WiredRenderer::render(const MatrixFx &transformationMatrix, const Mesh* mesh) { + for (auto &face : mesh->faces()) { + auto &vertexA = mesh->vertices()[face.a]; + auto &vertexB = mesh->vertices()[face.b]; + auto &vertexC = mesh->vertices()[face.c]; + + auto pixelA = engine->project(*vertexA.get(), transformationMatrix); + auto pixelB = engine->project(*vertexB.get(), transformationMatrix); + auto pixelC = engine->project(*vertexC.get(), transformationMatrix); + + engine->plotLine(pixelA, pixelB, mesh->colorIndex()); + engine->plotLine(pixelB, pixelC, mesh->colorIndex()); + engine->plotLine(pixelC, pixelA, mesh->colorIndex()); + } +} diff --git a/engine/src/scene.cpp b/engine/src/scene.cpp index ad9c42d..fde8575 100644 --- a/engine/src/scene.cpp +++ b/engine/src/scene.cpp @@ -3,5 +3,5 @@ // #include -#include +#include diff --git a/test/matrixfxtest.cpp b/test/matrixfxtest.cpp index 1af4989..bc33c02 100644 --- a/test/matrixfxtest.cpp +++ b/test/matrixfxtest.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include class MatrixFxSuite : public ::testing::Test { protected: