Implement basic rendering with cube example
This commit is contained in:
Daniel Ramírez 2025-04-17 17:33:15 +02:00
parent b9ee14cc40
commit 4aef21edd5
13 changed files with 270 additions and 64 deletions

View File

@ -3,11 +3,16 @@ cmake_minimum_required(VERSION 3.15)
project(xrbDS)
include_directories(
engine
include/xrbds
)
file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS
engine/*.cpp
)
add_library(xrbds
engine/core/engine.cpp
${SOURCES}
)
add_subdirectory(samples/hello_world)

View File

@ -1,3 +1,57 @@
#include "core/engine.h"
Engine::Engine() {}
#include <nds.h>
#include <stdio.h>
#include <memory>
// Main program function
int main(void) {
// Initialize engine
std::unique_ptr<Engine> engine = Engine::Create();
if (!engine)
exit(1);
engine->run();
engine->shutdown();
return 0;
}
std::unique_ptr<Engine> Engine::Create() {
return std::unique_ptr<Engine>(new Engine());
}
void Engine::run() {
isRunning = true;
while (pmMainLoop()) {
processInput();
update();
renderer->render();
swiWaitForVBlank();
}
}
void Engine::shutdown() { isRunning = false; }
void Engine::processInput() {
scanKeys();
int keys = keysDown();
}
void Engine::update() {
// Update
}
Engine::Engine() {
isRunning = false;
// Debug
// consoleDemoInit();
// Initialize the graphics renderer
renderer = Renderer::Create();
if (!renderer)
exit(2);
}

View File

@ -1,20 +0,0 @@
#ifndef MAIN_LOOP_H
#define MAIN_LOOP_H
class MainLoop {
public:
MainLoop();
~MainLoop();
virtual void initialize();
virtual void iterationPrepare() {}
virtual bool physicsProcess(double p_time);
virtual void iterationEnd() {}
virtual bool process(double p_time);
virtual void finalize();
private:
void processFrame();
};
#endif // MAIN_LOOP_H

View File

@ -0,0 +1,16 @@
#ifndef OBJECT_H
#define OBJECT_H
class Object {
public:
Object();
virtual ~Object();
virtual void update();
virtual void render();
protected:
int id;
};
#endif // OBJECT_H

View File

@ -0,0 +1,105 @@
#include "renderer.h"
#include <nds.h>
#include <stdio.h>
std::unique_ptr<Renderer> Renderer::Create() {
return std::unique_ptr<Renderer>(new Renderer());
}
void Renderer::render() {
// clearScreen(); // Clear the screen
beginFrame(); // Prepare for rendering
glLoadIdentity(); // Load the identity matrix
// Render scene
glTranslatef(0.0f, 0.0f, -4.0f); // Move the camera back
glRotatef(45, 1, 1, 0); // Rotation
drawCube(1.0f); // Draw a cube
endFrame(); // Finish rendering
}
void Renderer::beginFrame() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(70, 256.0 / 192.0, 0.1, 100);
glMatrixMode(GL_MODELVIEW);
glPushMatrix(); // Save the current matrix state
glPolyFmt(POLY_ALPHA(31) | POLY_CULL_BACK);
}
void Renderer::endFrame() {
glFlush(0); // Flush the rendering pipeline
}
void Renderer::clearScreen() {
// glClearColor(15, 0, 0, 0); // Clear to black
}
void Renderer::drawCube(float size) {
glBegin(GL_QUADS);
// Front face
glColor3f(1.0, 0.0, 0.0); // Red
glVertex3f(-size, -size, size);
glVertex3f(size, -size, size);
glVertex3f(size, size, size);
glVertex3f(-size, size, size);
// Back face
glColor3f(0.0, 1.0, 0.0); // Green
glVertex3f(-size, -size, -size);
glVertex3f(-size, size, -size);
glVertex3f(size, size, -size);
glVertex3f(size, -size, -size);
// Left face
glColor3f(0.0, 0.0, 1.0); // Blue
glVertex3f(-size, -size, -size);
glVertex3f(-size, -size, size);
glVertex3f(-size, size, size);
glVertex3f(-size, size, -size);
// Right face
glColor3f(1.0, 1.0, 0.0); // Yellow
glVertex3f(size, -size, -size);
glVertex3f(size, size, -size);
glVertex3f(size, size, size);
glVertex3f(size, -size, size);
// Top face
glColor3f(1.0, 0.0, 1.0); // Magenta
glVertex3f(-size, size, -size);
glVertex3f(-size, size, size);
glVertex3f(size, size, size);
glVertex3f(size, size, -size);
// Bottom face
glColor3f(0.0, 1.0, 1.0); // Cyan
glVertex3f(-size, -size, -size);
glVertex3f(size, -size, -size);
glVertex3f(size, -size, size);
glVertex3f(-size, -size, size);
glEnd();
glPopMatrix(1);
}
Renderer::Renderer() {
// Initialize the video subsystem
lcdMainOnTop(); // Set the main screen on top
videoSetMode(MODE_0_3D); // Set 3D rendering mode
videoSetModeSub(MODE_5_2D); // Set 2D rendering mode for the sub-screen
vramSetBankA(VRAM_A_MAIN_BG); // Allocate VRAM for textures
// Initialize the 3D engine
glInit();
glEnable(GL_ANTIALIAS);
glClearColor(0, 0, 0, 31); // Set clear color (black)
glClearPolyID(63); // Set default polygon ID
glClearDepth(GL_MAX_DEPTH); // Set clear depth
glViewport(0, 0, 255, 191); // Set viewport
}

View File

@ -0,0 +1,26 @@
#ifndef RENDERER_H
#define RENDERER_H
#include <memory>
class Renderer {
public:
virtual ~Renderer() = default;
static std::unique_ptr<Renderer> Create();
void render();
private:
void beginFrame();
void endFrame();
void clearScreen();
void drawCube(float size);
Renderer();
};
#endif // RENDERER_H

21
engine/input/input.cpp Normal file
View File

@ -0,0 +1,21 @@
#include "input/input.h"
#include <nds.h>
Input::Input() {
// Initialize input system
scanKeys();
}
void Input::update() {
// Update key states
scanKeys();
keysHeldState = keysHeld();
keysDownState = keysDown();
keysUpState = keysUp();
}
bool Input::isKeyHeld(int key) const { return keysHeldState & key; }
bool Input::isKeyDown(int key) const { return keysDownState & key; }
bool Input::isKeyUp(int key) const { return keysUpState & key; }

View File

@ -1,15 +1,18 @@
#ifndef XRBDS_CORE_ENGINE_H
#define XRBDS_CORE_ENGINE_H
#include <string>
#include <memory>
#include "graphics/renderer.h"
class MainLoop;
class Renderer;
class Engine {
public:
Engine();
~Engine();
virtual ~Engine() = default;
// Initialize the engine
bool initialize(const std::string &title, int width, int height);
static std::unique_ptr<Engine> Create();
// Run the main game loop
void run();
@ -23,7 +26,10 @@ private:
// Internal methods for the game loop
void processInput();
void update();
void render();
std::unique_ptr<Renderer> renderer;
Engine();
};
#endif // XRBDS_CORE_ENGINE_H

View File

@ -0,0 +1,24 @@
#ifndef XRBDS_INPUT_H
#define XRBDS_INPUT_H
#include <calico/types.h>
class Input {
public:
Input();
void update();
bool isKeyHeld(int key) const;
bool isKeyDown(int key) const;
bool isKeyUp(int key) const;
private:
u32 keysHeldState = 0;
u32 keysDownState = 0;
u32 keysUpState = 0;
};
#endif // XRBDS_INPUT_H

View File

@ -1,5 +1,5 @@
add_executable(hello_world
main.cpp
hello_world.cpp
)
target_link_libraries(hello_world

View File

@ -0,0 +1,4 @@
#include <nds.h>
#include <stdio.h>
#include "core/engine.h"

View File

@ -1,35 +0,0 @@
#include <nds.h>
#include <stdio.h>
#include "core/engine.h"
static volatile int frame = 0;
static void Vblank() { frame++; }
int main(void) {
touchPosition touchXY;
irqSet(IRQ_VBLANK, Vblank);
consoleDemoInit();
iprintf("\x1b[4;7HxrbDS Hello World\n");
while (pmMainLoop()) {
swiWaitForVBlank();
scanKeys();
int keys = keysDown();
if (keys & KEY_START)
break;
touchRead(&touchXY);
// print at using ansi escape sequence \x1b[line;columnH
iprintf("\x1b[10;0HFrame = %d", frame);
iprintf("\x1b[16;0HTouch x = %04X, %04X\n", touchXY.rawx, touchXY.px);
iprintf("Touch y = %04X, %04X\n", touchXY.rawy, touchXY.py);
}
return 0;
}