]> git.lizzy.rs Git - shadowclad.git/blob - src/engine/render.c
Add minimal, wonky scene tree system
[shadowclad.git] / src / engine / render.c
1 #include <GL/glut.h>
2 #include <stdbool.h>
3
4 #include "game/level.h"
5 #include "game/player.h"
6
7 #include "geometry.h"
8 #include "performance.h"
9 #include "scene.h"
10
11 const float AXIS_RADIUS = 5.0f;
12
13 static void setupCamera();
14 static void moveCameraTo(const Vector3D pos);
15 static void drawAxes();
16 static void renderBlockGrid(const BlockGrid grid);
17 static void renderCharacter(const Character* character, const Vector3D pos);
18 static void drawSolid(const Solid* solid);
19
20 float viewportAspectRatio = 1.0f;
21
22 void initRender() {
23         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
24         
25         GLfloat light0_ambient[] = {0.1f, 0.1f, 0.1f, 1.0f};
26         GLfloat light0_diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};
27         GLfloat light0_specular[] = {0.96f, 0.98f, 1.0f, 1.0f};
28         GLfloat light0_position[] = {5.0f, 10.0f, 5.0f, 0.0f}; // (w == 0.0f) == directional
29         
30         glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
31         glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
32         glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);
33         glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
34         
35         glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1.0f);
36         glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05f);
37         glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.005f);
38 }
39
40
41
42 void renderSceneNew(const Scene*);
43
44 void renderFrame() {
45         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
46         
47         glEnable(GL_NORMALIZE);
48         glEnable(GL_CULL_FACE);
49         glEnable(GL_DEPTH_TEST);
50         
51         setupCamera();
52         moveCameraTo(playerPos);
53         
54         renderSceneNew(currentScene);
55         
56         glFlush();
57         glutSwapBuffers();
58         frameRendered();
59         glutPostRedisplay();
60 }
61
62 void renderSceneNew(const Scene* scene) {
63         if (!scene) {
64                 return;
65         }
66
67         glMatrixMode(GL_MODELVIEW);
68         glLoadMatrixf((const GLfloat*) &scene->transform);
69
70         glDisable(GL_LIGHTING);
71         drawAxes();
72         glEnable(GL_LIGHTING);
73
74         if (scene->solid) {
75                 glEnable(GL_LIGHT0);
76                 glEnable(GL_TEXTURE_2D);
77                 drawSolid(scene->solid);
78                 glDisable(GL_TEXTURE_2D);
79                 glDisable(GL_LIGHT0);
80         }
81
82         for (size_t i = 0; i < scene->numChildren; ++i) {
83                 renderSceneNew(scene->children[i]);
84         }
85 }
86
87
88
89 void renderScene() {
90         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
91         
92         glEnable(GL_NORMALIZE);
93         glEnable(GL_CULL_FACE);
94         glEnable(GL_DEPTH_TEST);
95         
96         setupCamera();
97         moveCameraTo(playerPos);
98         
99         glDisable(GL_LIGHTING);
100         drawAxes();
101         glEnable(GL_LIGHTING);
102         
103         glEnable(GL_LIGHT0);
104         glEnable(GL_TEXTURE_2D);
105         renderBlockGrid(levelGrid);
106         renderCharacter(&playerCharacter, playerPos);
107         glDisable(GL_TEXTURE_2D);
108         glDisable(GL_LIGHT0);
109         
110         glFlush();
111         glutSwapBuffers();
112         frameRendered();
113         glutPostRedisplay();
114 }
115
116 static void setupCamera() {
117         glMatrixMode(GL_PROJECTION);
118         glLoadIdentity();
119         glOrtho(-16.0,
120                 16.0,
121                 -16.0/viewportAspectRatio,
122                 16.0/viewportAspectRatio,
123                 -128.0,
124                 128.0);
125         glRotatef(45.0f, 1.0f, 0.0f, 0.0f);
126         glRotatef(45.0f, 0.0f, 1.0f, 0.0f);
127 }
128
129 static void moveCameraTo(const Vector3D pos) {
130         glMatrixMode(GL_PROJECTION);
131         glTranslatef(-pos.x, -pos.y, -pos.z);
132 }
133
134 static void drawAxes() {
135         glMatrixMode(GL_MODELVIEW);
136         // X axis
137         glColor3f(1.0f, 0.0f, 0.0f);
138         glBegin(GL_LINES);
139         glVertex3f(0.0f, 0.0f, 0.0f);
140         glVertex3f(AXIS_RADIUS, 0.0f, 0.0f);
141         glEnd();
142         // Y axis
143         glColor3f(0.0f, 1.0f, 0.0f);
144         glBegin(GL_LINES);
145         glVertex3f(0.0f, 0.0f, 0.0f);
146         glVertex3f(0.0f, AXIS_RADIUS, 0.0f);
147         glEnd();
148         // Z axis
149         glColor3f(0.0f, 0.0f, 1.0f);
150         glBegin(GL_LINES);
151         glVertex3f(0.0f, 0.0f, 0.0f);
152         glVertex3f(0.0f, 0.0f, AXIS_RADIUS);
153         glEnd();
154 }
155
156 static void renderBlockGrid(const BlockGrid grid) {
157         glMatrixMode(GL_MODELVIEW);
158         for (size_t z = 0; z < grid.depth; ++z) {
159                 glLoadIdentity();
160                 glTranslatef(0.0f, 0.0f, z * BLOCKGRID_CELL_SIZE);
161                 for (size_t x = 0; x < grid.width; ++x) {
162                         drawSolid(getBlockFromGrid(grid, x, z)->solid);
163                         glTranslatef(BLOCKGRID_CELL_SIZE, 0.0f, 0.0f);
164                 }
165         }
166         glLoadIdentity();
167 }
168
169 static void renderCharacter(const Character* character, const Vector3D pos) {
170         glMatrixMode(GL_MODELVIEW);
171         glTranslatef(pos.x, pos.y, pos.z);
172         drawSolid(character->solid);
173         glLoadIdentity();
174 }
175
176 static void drawSolid(const Solid* solid) {
177         if (solid == NULL) {
178                 return;
179         }
180         
181         glMatrixMode(GL_MODELVIEW);
182         glColor3f(0.5f, 1.0f, 0.0f);
183         
184         for (size_t meshIndex = 0; meshIndex < solid->numMeshes; ++meshIndex) {
185                 const Mesh mesh = solid->meshes[meshIndex];
186                 glBindTexture(GL_TEXTURE_2D,
187                               solid->materials[mesh.materialIndex].textureId);
188                 bool hasNormals = mesh.normals != NULL;
189                 bool hasTextureCoords = mesh.textureCoords != NULL;
190                 
191                 for (size_t faceIndex = 0; faceIndex < mesh.numFaces; ++faceIndex) {
192                         const Face face = mesh.faces[faceIndex];
193                         
194                         GLenum faceMode;
195                         switch (face.numIndices) {
196                                 case 1: faceMode = GL_POINTS; break;
197                                 case 2: faceMode = GL_LINES; break;
198                                 case 3: faceMode = GL_TRIANGLES; break;
199                                 default: faceMode = GL_POLYGON; break;
200                         }
201                         
202                         glBegin(faceMode);
203                         
204                         for (size_t i = 0; i < face.numIndices; ++i) {
205                                 size_t vertIndex = face.indices[i];
206                                 if (hasNormals) {
207                                         if (hasTextureCoords) {
208                                                 Vector3D coords = mesh.textureCoords[vertIndex];
209                                                 glTexCoord2f(coords.x, coords.y);
210                                         }
211                                         Vector3D normal = mesh.normals[vertIndex];
212                                         glNormal3f(normal.x, normal.y, normal.z);
213                                 }
214                                 Vector3D vertex = mesh.vertices[vertIndex];
215                                 glVertex3f(vertex.x, vertex.y, vertex.z);
216                         }
217                         
218                         glEnd();
219                 }
220         }
221         glBindTexture(GL_TEXTURE_2D, 0);
222 }