1 /*
2  * This software is licensed under the terms of the MIT License.
3  * See COPYING for further information.
4  * ---
5  * Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>.
6  * Copyright (c) 2012-2019, Andrei Alexeyev <akari@taisei-project.org>.
7  */
8 
9 #include "taisei.h"
10 
11 #include "models.h"
12 #include "../api.h"
13 #include "resource/model.h"
14 
15 static struct {
16 	VertexBuffer *vbuf;
17 	IndexBuffer *ibuf;
18 	VertexArray *varr;
19 	Model quad;
20 } _r_models;
21 
_r_models_init(void)22 void _r_models_init(void) {
23 	VertexAttribFormat fmt[3];
24 
25 	r_vertex_attrib_format_interleaved(3, (VertexAttribSpec[]) {
26 		{ 3, VA_FLOAT, VA_CONVERT_FLOAT }, // position
27 		{ 3, VA_FLOAT, VA_CONVERT_FLOAT }, // normal
28 		{ 2, VA_FLOAT, VA_CONVERT_FLOAT }, // texcoord
29 	}, fmt, 0);
30 
31 	GenericModelVertex quad[4] = {
32 		{ {  0.5, -0.5,  0.0 }, { 0, 0, 1 }, { 1, 1 } },
33 		{ { -0.5, -0.5,  0.0 }, { 0, 0, 1 }, { 0, 1 } },
34 		{ {  0.5,  0.5,  0.0 }, { 0, 0, 1 }, { 1, 0 } },
35 		{ { -0.5,  0.5,  0.0 }, { 0, 0, 1 }, { 0, 0 } },
36 	};
37 
38 	const size_t max_vertices = 8192;
39 
40 	_r_models.vbuf = r_vertex_buffer_create(max_vertices * sizeof(GenericModelVertex), NULL);
41 	r_vertex_buffer_set_debug_label(_r_models.vbuf, "Static models vertex buffer");
42 
43 	_r_models.ibuf = r_index_buffer_create(max_vertices);
44 	r_index_buffer_set_debug_label(_r_models.ibuf, "Static models index buffer");
45 
46 	_r_models.varr = r_vertex_array_create();
47 	r_vertex_array_set_debug_label(_r_models.varr, "Static models vertex array");
48 	r_vertex_array_layout(_r_models.varr, 3, fmt);
49 	r_vertex_array_attach_vertex_buffer(_r_models.varr, _r_models.vbuf, 0);
50 	r_vertex_array_attach_index_buffer(_r_models.varr, _r_models.ibuf);
51 
52 	r_model_add_static(&_r_models.quad, PRIM_TRIANGLE_STRIP, 4, quad, NULL);
53 }
54 
_r_models_shutdown(void)55 void _r_models_shutdown(void) {
56 	r_vertex_array_destroy(_r_models.varr);
57 	r_vertex_buffer_destroy(_r_models.vbuf);
58 }
59 
r_model_add_static(Model * out_mdl,Primitive prim,size_t num_vertices,GenericModelVertex vertices[num_vertices],uint indices[num_vertices])60 void r_model_add_static(Model *out_mdl, Primitive prim, size_t num_vertices, GenericModelVertex vertices[num_vertices], uint indices[num_vertices]) {
61 	out_mdl->vertex_array = _r_models.varr;
62 	out_mdl->num_vertices = num_vertices;
63 	out_mdl->primitive = prim;
64 
65 	SDL_RWops *vert_stream = r_vertex_buffer_get_stream(_r_models.vbuf);
66 	size_t vert_ofs = SDL_RWtell(vert_stream) / sizeof(GenericModelVertex);
67 
68 	if(indices != NULL) {
69 		out_mdl->offset = r_index_buffer_get_offset(_r_models.ibuf);
70 		r_index_buffer_add_indices(_r_models.ibuf, vert_ofs, num_vertices, indices);
71 		out_mdl->indexed = true;
72 	} else {
73 		out_mdl->offset = vert_ofs;
74 		out_mdl->indexed = false;
75 	}
76 
77 	SDL_RWwrite(vert_stream, vertices, sizeof(GenericModelVertex), num_vertices);
78 }
79 
r_vertex_buffer_static_models(void)80 VertexBuffer* r_vertex_buffer_static_models(void) {
81 	return _r_models.vbuf;
82 }
83 
r_vertex_array_static_models(void)84 VertexArray* r_vertex_array_static_models(void) {
85 	return _r_models.varr;
86 }
87 
r_draw_quad(void)88 void r_draw_quad(void) {
89 	r_draw_model_ptr(&_r_models.quad, 0, 0);
90 }
91 
r_draw_quad_instanced(uint instances)92 void r_draw_quad_instanced(uint instances) {
93 	r_draw_model_ptr(&_r_models.quad, instances, 0);
94 }
95 
r_draw_model_ptr(Model * model,uint instances,uint base_instance)96 void r_draw_model_ptr(Model *model, uint instances, uint base_instance) {
97 	(model->indexed ? r_draw_indexed : r_draw)(
98 		model->vertex_array,
99 		model->primitive,
100 		model->offset, model->num_vertices,
101 		instances,
102 		base_instance
103 	);
104 }
105