mesh.cpp 4.67 KB
Newer Older
Georg Schaefer's avatar
Georg Schaefer committed
1
2
3
4
#include <graphics/graphics_system.hpp>
#include <graphics/program.hpp>
#include <graphics/texture.hpp>
#include <graphics/texture_manager.hpp>
Georg Schaefer's avatar
Georg Schaefer committed
5
#include <graphics/vertex_layout.hpp>
Georg Schaefer's avatar
Georg Schaefer committed
6
7
#include <rendering/mesh.hpp>
#include <rendering/mesh_vertex.hpp>
8
#include <util/logger.hpp>
Georg Schaefer's avatar
Georg Schaefer committed
9
#include <util/id.hpp>
Georg Schaefer's avatar
Georg Schaefer committed
10
11

namespace gdw {
Georg Schaefer's avatar
Georg Schaefer committed
12
	mesh::mesh(vertex_layout& vertex_layout, graphics_system& graphics_system, const std::vector<char>& source, const std::string filename)
Georg Schaefer's avatar
Georg Schaefer committed
13
	: vbo_(GL_STATIC_DRAW), ibo_(GL_STATIC_DRAW), id_(id_generator<mesh>()) {
Georg Schaefer's avatar
Georg Schaefer committed
14
15
		auto data_ptr = source.data();

16
17
18
		header head;
		head.magic = *reinterpret_cast<const uint32_t*>(data_ptr);
		data_ptr += sizeof(uint32_t);
Georg Schaefer's avatar
Georg Schaefer committed
19
20
21
		if (head.magic != 0x4D574447) {
			throw std::runtime_error(filename + " is not gdw mesh file");
		}
22
23
24
25
26
27
		head.vertex_count = *reinterpret_cast<const uint64_t*>(data_ptr);
		data_ptr += sizeof(uint64_t);
		head.index_count = *reinterpret_cast<const uint64_t*>(data_ptr);
		data_ptr += sizeof(uint64_t);
		head.submesh_count = *reinterpret_cast<const uint64_t*>(data_ptr);
		data_ptr += sizeof(uint64_t);
Georg Schaefer's avatar
Georg Schaefer committed
28

29
30
		auto header_size = sizeof(uint32_t) + 3 * sizeof(uint64_t);
		auto vertex_size = head.vertex_count * (sizeof(glm::vec3) * 3 + sizeof(glm::vec2));
Georg Schaefer's avatar
Georg Schaefer committed
31
		auto index_size = head.index_count * sizeof(uint32_t);
32
33
		auto submesh_size = head.submesh_count * (sizeof(uint64_t) * 5 + sizeof(glm::vec3));
		auto size = header_size
Georg Schaefer's avatar
Georg Schaefer committed
34
35
			+ vertex_size
			+ index_size
36
			+ submesh_size;
Georg Schaefer's avatar
Georg Schaefer committed
37
38
39
40
41
42
43
44
45
46
47
48
49
50

		if (size != source.size()) {
			throw std::runtime_error(filename + " has not the apropriate size. expected size: "
				+ std::to_string(source.size()) + " calculated size: " + std::to_string(size));
		}

		vbo_.bind();
		vbo_.data(vertex_size, data_ptr);
		data_ptr += vertex_size;

		ibo_.bind();
		ibo_.data(index_size, data_ptr);
		data_ptr += index_size;

51
		for (auto i = 0u; i < head.submesh_count; ++i) {
Georg Schaefer's avatar
Georg Schaefer committed
52
53
54
55
56
57
58
59
60
			submesh s;

			s.index_count = *reinterpret_cast<const uint64_t*>(data_ptr);
			data_ptr += sizeof(uint64_t);
			s.offset = *reinterpret_cast<const uint64_t*>(data_ptr);
			data_ptr += sizeof(uint64_t);
			s.color = *reinterpret_cast<const glm::vec3*>(data_ptr);
			data_ptr += sizeof(glm::vec3);

61
62
			uint64_t texture_id;
			texture_id = *reinterpret_cast<const uint64_t*>(data_ptr);
Georg Schaefer's avatar
Georg Schaefer committed
63
64
65
66
67
68
69
70
71
			auto texture_name = std::to_string(texture_id) + ".dds";
			if (texture_id > 0) {
				s.diffuse = graphics_system.texture_manager().load("texture/" + texture_name);
				if (!s.diffuse) {
					throw std::runtime_error("could not load texure " + texture_name);
				}
			}
			data_ptr += sizeof(uint64_t);

72
			texture_id = *reinterpret_cast<const uint64_t*>(data_ptr);
Georg Schaefer's avatar
Georg Schaefer committed
73
74
75
76
77
78
79
80
81
			texture_name = std::to_string(texture_id) + ".dds";
			if (texture_id > 0) {
				s.normal = graphics_system.texture_manager().load("texture/" + texture_name);
				if (!s.normal) {
					throw std::runtime_error("could not load texure " + texture_name);
				}
			}
			data_ptr += sizeof(uint64_t);

82
			texture_id = *reinterpret_cast<const uint64_t*>(data_ptr);
Georg Schaefer's avatar
Georg Schaefer committed
83
84
85
86
87
88
89
90
91
92
93
94
95
			texture_name = std::to_string(texture_id) + ".dds";
			if (texture_id > 0) {
				s.material = graphics_system.texture_manager().load("texture/" + texture_name);
				if (!s.material) {
					throw std::runtime_error("could not load texure " + texture_name);
				}
			}
			data_ptr += sizeof(uint64_t);

			submeshes_.emplace_back(s);
		}

		vao_.bind_index_buffer(ibo_);
Georg Schaefer's avatar
Georg Schaefer committed
96
		vertex_layout.setup_layout(vao_, &vbo_);
Georg Schaefer's avatar
Georg Schaefer committed
97
98
	}

Georg Schaefer's avatar
Georg Schaefer committed
99
	void mesh::draw(program& program) const noexcept {
Georg Schaefer's avatar
Georg Schaefer committed
100
101
		vao_.bind();
		for (auto& submesh : submeshes_) {
Georg Schaefer's avatar
Georg Schaefer committed
102
			if (submesh.diffuse && submesh.normal && submesh.material) {
Georg Schaefer's avatar
Georg Schaefer committed
103
				program.uniform("no_textures", false);
Georg Schaefer's avatar
Georg Schaefer committed
104
105
106
				program.uniform("albedo_texture", 0);
				program.uniform("normal_texture", 1);
				program.uniform("material_texture", 2);
Georg Schaefer's avatar
Georg Schaefer committed
107
108
109
110
111
112
113
114
115
116
				submesh.diffuse->bind(0);
				submesh.normal->bind(1);
				submesh.material->bind(2);
			} else {
				program.uniform("no_textures", true);
				program.uniform("color", submesh.color);
			}
			glDrawElements(GL_TRIANGLES, submesh.index_count, GL_UNSIGNED_INT, reinterpret_cast<void*>(submesh.offset * sizeof(uint32_t)));
		}
	}
Georg Schaefer's avatar
Georg Schaefer committed
117

Georg Schaefer's avatar
Georg Schaefer committed
118
	void mesh::draw_instanced(program& program, unsigned int count) const noexcept {
Georg Schaefer's avatar
Georg Schaefer committed
119
120
		vao_.bind();
		for (auto& submesh : submeshes_) {
Georg Schaefer's avatar
Georg Schaefer committed
121
			if (submesh.diffuse && submesh.normal && submesh.material) {
Georg Schaefer's avatar
Georg Schaefer committed
122
				program.uniform("no_textures", false);
Georg Schaefer's avatar
Georg Schaefer committed
123
124
125
				program.uniform("albedo_texture", 0);
				program.uniform("normal_texture", 1);
				program.uniform("material_texture", 2);
Georg Schaefer's avatar
Georg Schaefer committed
126
127
128
129
130
131
132
133
134
135
				submesh.diffuse->bind(0);
				submesh.normal->bind(1);
				submesh.material->bind(2);
			} else {
				program.uniform("no_textures", true);
				program.uniform("color", submesh.color);
			}
			glDrawElementsInstanced(GL_TRIANGLES, submesh.index_count, GL_UNSIGNED_INT, reinterpret_cast<void*>(submesh.offset * sizeof(uint32_t)), count);
		}
	}
Georg Schaefer's avatar
Georg Schaefer committed
136
}