summaryrefslogtreecommitdiff
path: root/model.cpp
blob: 0087c05e1de6f08fcf13702f772a6346142186fb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include "model.h"

#include <iostream>
#include <stdexcept>

namespace models {

Mesh::Mesh(const aiScene *scene, const aiMesh *mesh, std::map<std::string, GLuint>& scene_textures) {
	aiMaterial *mat = scene->mMaterials[mesh->mMaterialIndex];
	unsigned int texture_count = mat->GetTextureCount(aiTextureType_DIFFUSE);
	for(unsigned int j = 0; j < texture_count; j++) {
		aiString ai_path;
		if(mat->GetTexture(aiTextureType_DIFFUSE, j, &ai_path) == AI_SUCCESS) {
			std::string path(ai_path.data, ai_path.length);
			GLuint tex = scene_textures[path];
			textures.push_back(tex);
		}
	}

	glGenBuffers(1, &vbo);
	glBindBuffer(GL_ARRAY_BUFFER, vbo);

	vertices = 0;

	for(unsigned int i = 0; i < mesh->mNumFaces; i++)
		vertices += mesh->mFaces[i].mNumIndices;

	glBufferData(GL_ARRAY_BUFFER, vertices*3*2*3 * sizeof(float), NULL, GL_STATIC_DRAW);

	float *buffer = (float*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);

	unsigned int index = 0;

	for(unsigned int i = 0; i < mesh->mNumFaces; i++) {
		aiFace *face = &mesh->mFaces[i];

		for(unsigned int j = 0; j < face->mNumIndices; j++) {
			aiVector3D *texcoord = &mesh->mTextureCoords[0][face->mIndices[j]];
			aiVector3D *vertex = &mesh->mVertices[face->mIndices[j]];
			aiVector3D *normal = &mesh->mNormals[face->mIndices[j]];

			buffer[index++] = vertex->x;
			buffer[index++] = vertex->y;
			buffer[index++] = vertex->z;

			buffer[index++] = texcoord->x;
			buffer[index++] = 2 - texcoord->y;

			buffer[index++] = normal->x;
			buffer[index++] = normal->y;
			buffer[index++] = normal->z;
		}
	}

	glUnmapBuffer(GL_ARRAY_BUFFER);
}

Mesh::~Mesh() {
	glDeleteBuffers(1, &vbo);
}

void Mesh::render() {
	GLenum tex_i = GL_TEXTURE0;
	for(std::vector<GLuint>::iterator it = textures.begin(); it != textures.end(); it++) {
		glActiveTexture(tex_i++);
		glBindTexture(GL_TEXTURE_2D, *it);
	}
	glActiveTexture(GL_TEXTURE0);

	glBindBuffer(GL_ARRAY_BUFFER, vbo);

	glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);

	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glEnableClientState(GL_NORMAL_ARRAY);

	glVertexPointer(3, GL_FLOAT, 8*sizeof(float), NULL);
	glTexCoordPointer(2, GL_FLOAT, 8*sizeof(float), (const GLvoid*)(sizeof(float)*3));
	glNormalPointer(GL_FLOAT, 8*sizeof(float), (const GLvoid*)(sizeof(float)*5));
	glDrawArrays(GL_TRIANGLES, 0, vertices);

	glPopClientAttrib();

	glBindBuffer(GL_ARRAY_BUFFER, 0);
}

Tree::Tree(const aiScene *scene, std::map<std::string, GLuint>& scene_textures) {
	trunk = new Mesh(scene, scene->mMeshes[22], scene_textures);
	leaves = new Mesh(scene, scene->mMeshes[3], scene_textures);
}

Tree::~Tree() {
	delete trunk;
	delete leaves;
}

void Tree::render() {
	trunk->render();
	glTranslatef(0.786, 2.845, 5.1);
	leaves->render();
}

/* ModelManager */

ModelManager *ModelManager::model_mgr = NULL;

void ModelManager::add_model(const std::string name, Model::p model) {
	models.insert(std::pair<const std::string, Model::p>(name, model));
}

Model::p ModelManager::get_model(const std::string name) {
	std::map<const std::string, Model::p>::iterator it = models.find(name);
	if(it != models.end())
		return it->second;

	return Model::p();
}

ModelManager& ModelManager::get_instance() {
	if(!model_mgr)
		model_mgr = new ModelManager();

	return *model_mgr;
}

} // namespace models