3 #include "client/object.h"
4 #include "client/scene.h"
5 #define OBJECT_VERTEX_ATTRIBUTES 5
7 static VertexAttribute vertex_attributes[OBJECT_VERTEX_ATTRIBUTES] = {
12 .size = sizeof(Vertex3DPosition),
18 .size = sizeof(Vertex3DNormal),
24 .size = sizeof(Vertex3DTextureIndex),
30 .size = sizeof(Vertex3DTextureCoordinates),
37 .size = sizeof(Vertex3DColor),
41 static VertexLayout vertex_layout = {
42 .attributes = vertex_attributes,
43 .count = OBJECT_VERTEX_ATTRIBUTES,
44 .size = sizeof(Vertex3D),
47 Object *object_create()
49 Object *obj = malloc(sizeof(Object));
50 obj->pos = (v3f32) {0.0f, 0.0f, 0.0f};
51 obj->rot = (v3f32) {0.0f, 0.0f, 0.0f};
52 obj->scale = (v3f32) {1.0f, 1.0f, 1.0f};
56 obj->meshes_count = 0;
58 obj->wireframe = false;
59 obj->box = (aabb3f32) {{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}};
60 obj->frustum_culling = false;
61 obj->current_face = NULL;
62 obj->faces = array_create(sizeof(ObjectFace));
63 obj->on_render = NULL;
69 void object_delete(Object *obj)
71 for (size_t i = 0; i < obj->meshes_count; i++)
72 mesh_delete(obj->meshes[i]);
77 void object_set_texture(Object *obj, Texture *texture)
79 if (obj->current_face && obj->current_face->texture == texture->id)
83 .texture = texture->id,
84 .vertices = array_create(sizeof(Vertex3D)),
87 array_append(&obj->faces, &face);
88 obj->current_face = &((ObjectFace *) obj->faces.ptr)[obj->faces.siz - 1];
91 void object_add_vertex(Object *obj, Vertex3D *vertex)
93 array_append(&obj->current_face->vertices, vertex);
96 static int qsort_compare_faces(const void *f1, const void *f2)
98 return ((ObjectFace *) f1)->texture - ((ObjectFace *) f2)->texture;
101 static void add_mesh(Array *meshes, Array *vertices, Array *textures)
103 if (vertices->siz > 0) {
104 Mesh *mesh = mesh_create();
105 mesh->vertices = vertices->ptr;
106 mesh->vertices_count = vertices->siz;
107 mesh->free_vertices = true;
108 mesh->free_textures = true;
109 mesh->layout = &vertex_layout;
110 size_t textures_count;
111 array_copy(textures, (void *) &mesh->textures, &textures_count);
112 mesh->textures_count = textures_count;
116 array_append(meshes, &mesh);
119 *vertices = array_create(sizeof(Vertex3D));
120 *textures = array_create(sizeof(GLuint));
123 bool object_add_to_scene(Object *obj)
125 if (obj->faces.siz == 0)
128 object_transform(obj);
130 qsort(obj->faces.ptr, obj->faces.siz, sizeof(ObjectFace), &qsort_compare_faces);
132 GLuint max_texture_units = scene_get_max_texture_units();
134 Array meshes = array_create(sizeof(Mesh *));
136 Array vertices = array_create(sizeof(Vertex3D));
137 Array textures = array_create(sizeof(GLuint));
139 GLuint texture_id = 0;
140 GLuint texture_index = max_texture_units;
142 for (size_t f = 0; f < obj->faces.siz; f++) {
143 ObjectFace *face = &((ObjectFace *) obj->faces.ptr)[f];
145 if (face->texture != texture_id) {
146 if (++texture_index >= max_texture_units) {
147 add_mesh(&meshes, &vertices, &textures);
151 texture_id = face->texture;
152 array_append(&textures, &texture_id);
155 for (size_t v = 0; v < face->vertices.siz; v++) {
156 Vertex3D *vertex = &((Vertex3D *) face->vertices.ptr)[v];
157 vertex->textureIndex = texture_index;
158 array_append(&vertices, vertex);
161 free(face->vertices.ptr);
163 add_mesh(&meshes, &vertices, &textures);
164 free(obj->faces.ptr);
166 array_copy(&meshes, (void *) &obj->meshes, &obj->meshes_count);
169 scene_add_object(obj);
174 void object_transform(Object *obj)
176 mat4x4_translate(obj->transform, obj->pos.x, obj->pos.y, obj->pos.z);
177 #pragma GCC diagnostic push
178 #pragma GCC diagnostic ignored "-Wpedantic"
179 mat4x4_rotate(obj->transform, obj->transform, obj->rot.x, obj->rot.y, obj->rot.z, obj->angle);
180 mat4x4_scale_aniso(obj->transform, obj->transform, obj->scale.x, obj->scale.y, obj->scale.z);
181 #pragma GCC diagnostic pop
183 #pragma GCC diagnostic push
184 #pragma GCC diagnostic ignored "-Wpedantic"
185 static bool inside_frustum(aabb3f32 box, mat4x4 MVP)
187 for (int x = 0; x <= 1; x++) {
188 for (int y = 0; y <= 1; y++) {
189 for (int z = 0; z <= 1; z++) {
190 vec4 point = {x ? box.min.x : box.max.x, y ? box.min.y : box.max.y, z ? box.min.z : box.max.z, 1.0};
192 mat4x4_mul_vec4(point_NDC, MVP, point);
194 for (int j = 0; j < 3; j++) {
195 float f = point_NDC[j];
197 if (f > -1.0f && f > 1.0f)
206 #pragma GCC diagnostic pop
209 void object_render(Object *obj, f64 dtime)
212 obj->on_render(obj, dtime);
217 if (obj->frustum_culling) {
220 #pragma GCC diagnostic push
221 #pragma GCC diagnostic ignored "-Wpedantic"
222 mat4x4_mul(MVP, scene.VP, obj->transform);
223 #pragma GCC diagnostic pop
225 if (! inside_frustum(obj->box, MVP))
229 glUniformMatrix4fv(scene.loc_model, 1, GL_FALSE, obj->transform[0]);
232 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
234 for (size_t i = 0; i < obj->meshes_count; i++)
235 mesh_render(obj->meshes[i]);
238 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);