#include <GL/glut.h>
#include <stdbool.h>
-#include "game/level.h"
-#include "game/player.h"
-
#include "geometry.h"
#include "performance.h"
#include "scene.h"
-const float AXIS_RADIUS = 5.0f;
+float viewportAspectRatio = 1.0f;
+const Scene* cameraAnchor;
+
+static const float AXIS_RADIUS = 5.0f;
+static void renderScene(const Scene*);
static void setupCamera();
-static void moveCameraTo(const Vector3D pos);
+static void moveCameraTo(const Scene* scene);
static void drawAxes();
-static void renderBlockGrid(const BlockGrid grid);
-static void renderCharacter(const Character* character, const Vector3D pos);
static void drawSolid(const Solid* solid);
-float viewportAspectRatio = 1.0f;
+
void initRender() {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.005f);
}
-
-
-void renderSceneNew(const Scene*);
-
void renderFrame() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
+
glEnable(GL_NORMALIZE);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
-
+
setupCamera();
- moveCameraTo(playerPos);
-
- renderSceneNew(currentScene);
-
+ moveCameraTo(cameraAnchor);
+
+ renderScene(currentScene);
+
glFlush();
glutSwapBuffers();
frameRendered();
glutPostRedisplay();
}
-void renderSceneNew(const Scene* scene) {
+void renderScene(const Scene* scene) {
if (!scene) {
return;
}
}
for (size_t i = 0; i < scene->numChildren; ++i) {
- renderSceneNew(scene->children[i]);
+ renderScene(scene->children[i]);
}
}
-
-
-void renderScene() {
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- glEnable(GL_NORMALIZE);
- glEnable(GL_CULL_FACE);
- glEnable(GL_DEPTH_TEST);
-
- setupCamera();
- moveCameraTo(playerPos);
-
- glDisable(GL_LIGHTING);
- drawAxes();
- glEnable(GL_LIGHTING);
-
- glEnable(GL_LIGHT0);
- glEnable(GL_TEXTURE_2D);
- renderBlockGrid(levelGrid);
- renderCharacter(&playerCharacter, playerPos);
- glDisable(GL_TEXTURE_2D);
- glDisable(GL_LIGHT0);
-
- glFlush();
- glutSwapBuffers();
- frameRendered();
- glutPostRedisplay();
-}
-
static void setupCamera() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glRotatef(45.0f, 0.0f, 1.0f, 0.0f);
}
-static void moveCameraTo(const Vector3D pos) {
+static void moveCameraTo(const Scene* anchor) {
glMatrixMode(GL_PROJECTION);
+ // TODO This needs to account for parent nodes as well
+ Vector3D pos = translationOf(anchor->transform);
glTranslatef(-pos.x, -pos.y, -pos.z);
}
glEnd();
}
-static void renderBlockGrid(const BlockGrid grid) {
- glMatrixMode(GL_MODELVIEW);
- for (size_t z = 0; z < grid.depth; ++z) {
- glLoadIdentity();
- glTranslatef(0.0f, 0.0f, z * BLOCKGRID_CELL_SIZE);
- for (size_t x = 0; x < grid.width; ++x) {
- drawSolid(getBlockFromGrid(grid, x, z)->solid);
- glTranslatef(BLOCKGRID_CELL_SIZE, 0.0f, 0.0f);
- }
- }
- glLoadIdentity();
-}
-
-static void renderCharacter(const Character* character, const Vector3D pos) {
- glMatrixMode(GL_MODELVIEW);
- glTranslatef(pos.x, pos.y, pos.z);
- drawSolid(character->solid);
- glLoadIdentity();
-}
-
static void drawSolid(const Solid* solid) {
if (solid == NULL) {
return;
#include "scene.h"
float viewportAspectRatio;
+const Scene* cameraAnchor;
void initRender();
void renderFrame();
-void renderScene();
#endif
Scene* currentScene = NULL;
-static Transform identity = { .a1 = 1.0f, .a2 = 0.0f, .a3 = 0.0f, .a4 = 0.0f,
- .b1 = 0.0f, .b2 = 1.0f, .b3 = 0.0f, .b4 = 0.0f,
- .c1 = 0.0f, .c2 = 0.0f, .c3 = 1.0f, .c4 = 0.0f,
- .d1 = 0.0f, .d2 = 0.0f, .d3 = 0.0f, .d4 = 1.0f };
+
+
+Transform identity() {
+ return (Transform) { .a1 = 1.0f, .a2 = 0.0f, .a3 = 0.0f, .a4 = 0.0f,
+ .b1 = 0.0f, .b2 = 1.0f, .b3 = 0.0f, .b4 = 0.0f,
+ .c1 = 0.0f, .c2 = 0.0f, .c3 = 1.0f, .c4 = 0.0f,
+ .d1 = 0.0f, .d2 = 0.0f, .d3 = 0.0f, .d4 = 1.0f };
+}
void multiply(Transform* transform, Transform by) {
GLfloat* a = (GLfloat*) &by;
.d1 = 0.0f, .d2 = 0.0f, .d3 = 0.0f, .d4 = 1.0f });
}
+Vector3D translationOf(Transform transform) {
+ return (Vector3D) { transform.a4, transform.b4, transform.c4 };
+}
+
Scene* newScene() {
Scene* scene = malloc(sizeof(Scene));
*scene = (Scene) { .parent = NULL,
.numChildren = 0u,
.children = NULL,
- .transform = identity,
+ .transform = identity(),
.solid = NULL };
return scene;
}
newChild->parent = scene;
}
+
+void reparentScene(Scene* scene, Scene* newParent) {
+ if (!scene) {
+ return;
+ }
+
+ if (scene->parent) {
+ Scene* parent = scene->parent;
+ size_t indexInParent = parent->numChildren;
+ for (size_t i = 0; i < parent->numChildren; ++i) {
+ if (parent->children[i] == scene) {
+ indexInParent = i;
+ break;
+ }
+ }
+ // This includes the hopefully impossible case where parent->numChildren == 0
+ if (indexInParent == parent->numChildren) {
+ logError("Scene %p not found in children of parent %p", scene, parent);
+ }
+ else {
+ for (size_t i = indexInParent; i < parent->numChildren - 1; ++i) {
+ parent->children[i] = parent->children[i + 1];
+ }
+ parent->children = realloc(parent->children, --(parent->numChildren) * sizeof(Scene*));
+ }
+ }
+
+ scene->parent = NULL;
+
+ insertChildScene(newParent, scene);
+}
Scene* currentScene;
+Transform identity();
void translate(Transform* transform, Vector3D vec);
+Vector3D translationOf(Transform transform);
+
Scene* newScene();
void insertChildScene(Scene* scene, Scene* newChild);
+void reparentScene(Scene* scene, Scene* newParent);
#endif // SCENE_H_
#include "level.h"
#include "player.h"
+BlockGrid levelGrid;
+
static Block blockEmpty = { .type = BLOCKTYPE_SPACE,
.solid = NULL };
static Block blockWall01 = { .type = BLOCKTYPE_OBSTACLE,
.solid = NULL };
-static Block* testBlocks[9] = { &blockWall01, &blockWall01, &blockWall01,
- &blockEmpty, &blockEmpty, &blockEmpty,
- &blockWall01, &blockEmpty, &blockWall01 };
-
-BlockGrid levelGrid = { .width = 3,
- .depth = 3,
- .blocks = testBlocks };
-
-#define DEFAULT_PLAYER_SPAWN_POS { -BLOCKGRID_CELL_SIZE, 0.0f, -BLOCKGRID_CELL_SIZE }
-Vector3D playerSpawnPos = DEFAULT_PLAYER_SPAWN_POS;
+static Transform playerSpawnTransform;
void initLevel() {
+ playerSpawnTransform = identity();
+ translate(&playerSpawnTransform, (Vector3D) { .x = -BLOCKGRID_CELL_SIZE,
+ .y = 0.0f,
+ .z = -BLOCKGRID_CELL_SIZE });
+
blockWall01.solid = importSolid("assets/wall01.3ds");
-
+
buildLevelFromImage(readTga("assets/level01.tga"));
-
+
Scene* levelScene = newScene();
-
+
for (size_t z = 0; z < levelGrid.depth; ++z) {
for (size_t x = 0; x < levelGrid.width; ++x) {
Scene* blockScene = newScene();
currentScene = levelScene;
}
+void startLevel() {
+ spawnPlayer(playerSpawnTransform);
+}
+
void buildLevelFromImage(TgaImage* image) {
if (image == NULL) {
logError("Null image received, cannot build level");
.blocks = malloc(image->header.imageWidth
* image->header.imageHeight
* sizeof(Block*)) };
- playerSpawnPos = (Vector3D) DEFAULT_PLAYER_SPAWN_POS;
for (size_t row = 0; row < newGrid.depth; ++row) {
for (size_t x = 0; x < newGrid.width; ++x) {
break;
case 0xFF00FFFF:
block = &blockEmpty;
- playerSpawnPos = (Vector3D) { x * BLOCKGRID_CELL_SIZE, 0.0f, z * BLOCKGRID_CELL_SIZE };
+ playerSpawnTransform = identity();
+ translate(&playerSpawnTransform, (Vector3D) { .x = x * BLOCKGRID_CELL_SIZE,
+ .y = 0.0f,
+ .z = z * BLOCKGRID_CELL_SIZE });
break;
default:
block = &blockEmpty;
}
levelGrid = newGrid;
- spawnPlayer();
}
#define BLOCKGRID_CELL_SIZE 2.5f
BlockGrid levelGrid;
-Vector3D playerSpawnPos;
void initLevel();
+void startLevel();
void buildLevelFromImage(TgaImage* image);
static inline Block* getBlockFromGrid(BlockGrid grid, size_t x, size_t z) {
-#include "engine/logger.h"
+#include "engine/asset.h"
+#include "engine/render.h"
-#include "level.h"
#include "player.h"
-Character playerCharacter = { .solid = NULL };
+Scene* playerCharacter;
void initPlayer() {
- playerCharacter.solid = importSolid("assets/playercharacter.3ds");
+ playerCharacter = newScene();
+ cameraAnchor = playerCharacter;
+ playerCharacter->solid = importSolid("assets/playercharacter.3ds");
}
-void spawnPlayer() {
- playerPos = playerSpawnPos;
+void spawnPlayer(Transform transform) {
+ playerCharacter->transform = transform;
+ reparentScene(playerCharacter, currentScene);
}
#include <GL/gl.h>
-#include "engine/asset.h"
+#include "engine/geometry.h"
+#include "engine/scene.h"
-typedef struct {
- const Solid* solid;
-} Character;
-
-Character playerCharacter;
-Vector3D playerPos;
+Scene* playerCharacter;
void initPlayer();
-void spawnPlayer();
+void spawnPlayer(Transform transform);
#endif
//initPerformanceMetering();
initLevel();
initPlayer();
+ startLevel();
glutMainLoop();
return 0;