refactor specific rendering out of gba engine
This commit is contained in:
parent
ede8465a9b
commit
d3bd172d96
|
@ -1,11 +1,12 @@
|
|||
#include <libgba-sprite-engine/scene.h>
|
||||
#include <libgba-sprite-engine/gba_engine.h>
|
||||
#include <libgba-sprite-engine/renderer/gba_engine.h>
|
||||
#include <libgba-sprite-engine/palette/palette_manager.h>
|
||||
|
||||
#include "wirescene.h"
|
||||
|
||||
int main() {
|
||||
std::shared_ptr<GBAEngine> engine(new GBAEngine());
|
||||
engine.get()->setRenderer(new WiredRenderer());
|
||||
|
||||
WireScene* startScene = new WireScene(engine);
|
||||
engine->setScene(startScene);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
//
|
||||
|
||||
#include <libgba-sprite-engine/gba/tonc_memdef.h>
|
||||
#include <libgba-sprite-engine/gba_engine.h>
|
||||
#include <libgba-sprite-engine/renderer/gba_engine.h>
|
||||
#include <libgba-sprite-engine/background/text_stream.h>
|
||||
#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<ForegroundPaletteManager>(new ForegroundPaletteManager());
|
||||
backgroundPalette = std::unique_ptr<BackgroundPaletteManager>(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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,13 +3,14 @@
|
|||
//
|
||||
|
||||
#include <libgba-sprite-engine/scene.h>
|
||||
#include <libgba-sprite-engine/gba_engine.h>
|
||||
#include <libgba-sprite-engine/renderer/gba_engine.h>
|
||||
#include <libgba-sprite-engine/palette/palette_manager.h>
|
||||
|
||||
#include "monkey.h"
|
||||
|
||||
int main() {
|
||||
std::shared_ptr<GBAEngine> engine(new GBAEngine());
|
||||
engine.get()->setRenderer(new WiredRenderer());
|
||||
|
||||
MonkeyScene* startScene = new MonkeyScene(engine);
|
||||
engine->setScene(startScene);
|
||||
|
|
|
@ -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<ForegroundPaletteManager>(new ForegroundPaletteManager());
|
||||
backgroundPalette = std::unique_ptr<BackgroundPaletteManager>(new BackgroundPaletteManager(pal, sizeof(pal)));
|
||||
|
||||
monkey = std::unique_ptr<Mesh>(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);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <libgba-sprite-engine/scene.h>
|
||||
#include <libgba-sprite-engine/mesh.h>
|
||||
#include <libgba-sprite-engine/camera.h>
|
||||
#include <libgba-sprite-engine/gba_engine.h>
|
||||
#include <libgba-sprite-engine/renderer/gba_engine.h>
|
||||
#include <memory>
|
||||
|
||||
// forward declaration of generated mesh.cpp file
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@ private:
|
|||
VectorFx pos;
|
||||
VectorFx rot;
|
||||
u8 cIndex;
|
||||
bool wired;
|
||||
|
||||
std::vector<std::unique_ptr<VectorFx>> verticesArr;
|
||||
std::vector<Face> 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;
|
||||
};
|
||||
|
|
|
@ -11,9 +11,10 @@
|
|||
#include <libgba-sprite-engine/vectorfx.h>
|
||||
#include <libgba-sprite-engine/vectorpx.h>
|
||||
#include <libgba-sprite-engine/matrixfx.h>
|
||||
#include "scene.h"
|
||||
#include "sound_control.h"
|
||||
#include "timer.h"
|
||||
#include <libgba-sprite-engine/renderer/renderer.h>
|
||||
#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> renderer;
|
||||
|
||||
static std::unique_ptr<Timer> timer;
|
||||
static std::unique_ptr<SoundControl> 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<Renderer>(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);
|
||||
};
|
||||
|
||||
|
|
@ -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 <libgba-sprite-engine/matrixfx.h>
|
||||
#include <libgba-sprite-engine/mesh.h>
|
||||
|
||||
class GBAEngine;
|
||||
|
||||
class Renderer {
|
||||
protected:
|
||||
std::shared_ptr<GBAEngine> 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
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include <libgba-sprite-engine/gba/tonc_memdef.h>
|
||||
#include <libgba-sprite-engine/gba/tonc_video.h>
|
||||
#include <libgba-sprite-engine/gba_engine.h>
|
||||
#include <libgba-sprite-engine/renderer/gba_engine.h>
|
||||
#include <cstring>
|
||||
#include <libgba-sprite-engine/gba/tonc_core.h>
|
||||
#include <libgba-sprite-engine/matrixfx.h>
|
||||
|
@ -16,6 +16,7 @@ std::unique_ptr<SoundControl> GBAEngine::activeChannelB;
|
|||
std::unique_ptr<Timer> 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();
|
|
@ -0,0 +1,13 @@
|
|||
//
|
||||
// Created by Wouter Groeneveld on 11/07/20.
|
||||
//
|
||||
|
||||
#include <libgba-sprite-engine/renderer/renderer.h>
|
||||
#include <libgba-sprite-engine/renderer/gba_engine.h>
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
//
|
||||
// Created by Wouter Groeneveld on 11/07/20.
|
||||
//
|
||||
|
||||
#include <libgba-sprite-engine/renderer/renderer.h>
|
||||
#include <libgba-sprite-engine/renderer/gba_engine.h>
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
|
@ -3,5 +3,5 @@
|
|||
//
|
||||
|
||||
#include <libgba-sprite-engine/scene.h>
|
||||
#include <libgba-sprite-engine/gba_engine.h>
|
||||
#include <libgba-sprite-engine/renderer/gba_engine.h>
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <libgba-sprite-engine/math.h>
|
||||
#include <libgba-sprite-engine/mesh.h>
|
||||
#include <libgba-sprite-engine/camera.h>
|
||||
#include <libgba-sprite-engine/gba_engine.h>
|
||||
#include <libgba-sprite-engine/renderer/gba_engine.h>
|
||||
|
||||
class MatrixFxSuite : public ::testing::Test {
|
||||
protected:
|
||||
|
|
Loading…
Reference in New Issue