1 /* ResidualVM - A 3D game interpreter
2 *
3 * ResidualVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the AUTHORS
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "engines/stark/gfx/openglsprop.h"
24
25 #include "engines/stark/gfx/driver.h"
26 #include "engines/stark/gfx/texture.h"
27 #include "engines/stark/formats/biffmesh.h"
28 #include "engines/stark/scene.h"
29 #include "engines/stark/services/services.h"
30
31 #include "graphics/opengl/shader.h"
32
33 namespace Stark {
34 namespace Gfx {
35
OpenGLSPropRenderer(Driver * gfx)36 OpenGLSPropRenderer::OpenGLSPropRenderer(Driver *gfx) :
37 VisualProp(),
38 _gfx(gfx),
39 _faceVBO(-1) {
40 static const char* attributes[] = { "position", "normal", "texcoord", nullptr };
41 _shader = OpenGL::Shader::fromFiles("stark_prop", attributes);
42 }
43
~OpenGLSPropRenderer()44 OpenGLSPropRenderer::~OpenGLSPropRenderer() {
45 clearVertices();
46
47 delete _shader;
48 }
49
render(const Math::Vector3d position,float direction)50 void OpenGLSPropRenderer::render(const Math::Vector3d position, float direction) {
51 if (_faceVBO == -1) {
52 // Update the OpenGL Buffer Objects if required
53 clearVertices();
54 uploadVertices();
55 }
56
57 _gfx->set3DMode();
58
59 Math::Matrix4 model = getModelMatrix(position, direction);
60 Math::Matrix4 view = StarkScene->getViewMatrix();
61 Math::Matrix4 projection = StarkScene->getProjectionMatrix();
62
63 Math::Matrix4 mvp = projection * view * model;
64 mvp.transpose();
65
66 _shader->enableVertexAttribute("position", _faceVBO, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), 0);
67 _shader->enableVertexAttribute("normal", _faceVBO, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), 12);
68 _shader->enableVertexAttribute("texcoord", _faceVBO, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), 24);
69 _shader->use(true);
70 _shader->setUniform("mvp", mvp);
71
72 const Common::Array<Face> &faces = _model->getFaces();
73 const Common::Array<Material> &materials = _model->getMaterials();
74
75 for (Common::Array<Face>::const_iterator face = faces.begin(); face != faces.end(); ++face) {
76 const Material &material = materials[face->materialId];
77
78 // For each face draw its vertices from the VBO, indexed by the EBO
79 const Gfx::Texture *tex = _texture->getTexture(material.texture);
80 if (tex) {
81 tex->bind();
82 } else {
83 glBindTexture(GL_TEXTURE_2D, 0);
84 }
85
86 _shader->setUniform("textured", tex != nullptr);
87 _shader->setUniform("color", Math::Vector3d(material.r, material.g, material.b));
88
89 GLuint ebo = _faceEBO[face];
90 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
91 glDrawElements(GL_TRIANGLES, face->vertexIndices.size(), GL_UNSIGNED_INT, 0);
92 }
93
94 _shader->unbind();
95 }
96
clearVertices()97 void OpenGLSPropRenderer::clearVertices() {
98 OpenGL::Shader::freeBuffer(_faceVBO);
99 _faceVBO = -1;
100
101 for (FaceBufferMap::iterator it = _faceEBO.begin(); it != _faceEBO.end(); ++it) {
102 OpenGL::Shader::freeBuffer(it->_value);
103 }
104
105 _faceEBO.clear();
106 }
107
uploadVertices()108 void OpenGLSPropRenderer::uploadVertices() {
109 _faceVBO = createFaceVBO();
110
111 const Common::Array<Face> &faces = _model->getFaces();
112 for (Common::Array<Face>::const_iterator face = faces.begin(); face != faces.end(); ++face) {
113 _faceEBO[face] = createFaceEBO(face);
114 }
115 }
116
createFaceVBO()117 uint32 OpenGLSPropRenderer::createFaceVBO() {
118 const Common::Array<Formats::BiffMesh::Vertex> &vertices = _model->getVertices();
119
120 return OpenGL::Shader::createBuffer(GL_ARRAY_BUFFER, sizeof(float) * 9 * vertices.size(), &vertices.front());
121 }
122
createFaceEBO(const Face * face)123 uint32 OpenGLSPropRenderer::createFaceEBO(const Face *face) {
124 return OpenGL::Shader::createBuffer(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint32) * face->vertexIndices.size(), &face->vertexIndices.front());
125 }
126
127 } // End of namespace Gfx
128 } // End of namespace Stark
129