xoreos  0.0.5
walkmesh.cpp
Go to the documentation of this file.
1 /* xoreos - A reimplementation of BioWare's Aurora engine
2  *
3  * xoreos is the legal property of its developers, whose names
4  * can be found in the AUTHORS file distributed with this source
5  * distribution.
6  *
7  * xoreos 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 3
10  * of the License, or (at your option) any later version.
11  *
12  * xoreos 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 xoreos. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
25 #include "glm/gtc/type_ptr.hpp"
26 #include "glm/gtx/intersect.hpp"
27 
28 #include "src/common/maths.h"
29 #include "src/common/util.h"
30 
32 
33 namespace Graphics {
34 
35 namespace Aurora {
36 
39  _highlightFaceIndex(-1),
40  _invisible(true) {
41 }
42 
43 float Walkmesh::getElevationAt(float x, float y, uint32 &faceIndex) const {
44  if (_indicesWalkable.empty())
45  return FLT_MIN;
46 
47  size_t faceCount = _indicesWalkable.size() / 3;
48  const float *vertices = _vertices.data();
49  uint32 index = 0;
50 
51  glm::vec3 v0, v1, v2, intersection;
52  glm::vec3 orig = glm::vec3(x, y, 1000.0f);
53 
54  for (size_t i = 0; i < faceCount; ++i) {
55  v0 = glm::make_vec3(vertices + 3 * _indicesWalkable[index + 0]);
56  v1 = glm::make_vec3(vertices + 3 * _indicesWalkable[index + 1]);
57  v2 = glm::make_vec3(vertices + 3 * _indicesWalkable[index + 2]);
58  index += 3;
59 
60  if (glm::intersectRayTriangle(orig, glm::vec3(0.0f, 0.0f, -1.0f), v0, v1, v2, intersection)) {
61  faceIndex = i;
62  return (v0 * (1.0f - intersection.x - intersection.y) +
63  v1 * intersection.x +
64  v2 * intersection.y).z;
65  }
66  }
67 
68  return FLT_MIN;
69 }
70 
71 bool Walkmesh::testCollision(const glm::vec3 &orig, const glm::vec3 &dest) const {
72  if (_indicesNonWalkable.empty())
73  return false;
74 
75  size_t faceCount = _indicesNonWalkable.size() / 3;
76  const float *vertices = _vertices.data();
77  uint32 index = 0;
78 
79  glm::vec3 adjDest = glm::vec3(dest.x, dest.y, 1000.0f);
80  glm::vec3 v0, v1, v2, intersection;
81  glm::vec3 dir = glm::normalize(dest - orig);
82 
83  for (size_t i = 0; i < faceCount; ++i) {
84  v0 = glm::make_vec3(vertices + 3 * _indicesNonWalkable[index + 0]);
85  v1 = glm::make_vec3(vertices + 3 * _indicesNonWalkable[index + 1]);
86  v2 = glm::make_vec3(vertices + 3 * _indicesNonWalkable[index + 2]);
87  index += 3;
88 
89  // Intersection with horizontal objects
90  if (glm::intersectRayTriangle(adjDest, glm::vec3(0.0f, 0.0f, -1.0f), v0, v1, v2, intersection))
91  return true;
92 
93  // Intersection with vertical objects
94  if (glm::intersectRayTriangle(orig, dir, v0, v1, v2, intersection)) {
95  glm::vec3 absIntersection(v0 * (1.0f - intersection.x - intersection.y) +
96  v1 * intersection.x +
97  v2 * intersection.y);
98  if (glm::distance(orig, absIntersection) <= glm::distance(orig, dest))
99  return true;
100  }
101  }
102 
103  return false;
104 }
105 
107  _highlightFaceIndex = index;
108 }
109 
110 void Walkmesh::setInvisible(bool invisible) {
111  _invisible = invisible;
112 }
113 
115 }
116 
119  return;
120 
121  glVertexPointer(3, GL_FLOAT, 0, _vertices.data());
122  glEnableClientState(GL_VERTEX_ARRAY);
123 
124  glColor4f(1.0f, 0.0f, 0.0f, 0.5f);
125  glDrawElements(GL_TRIANGLES, _indicesNonWalkable.size(), GL_UNSIGNED_INT, _indicesNonWalkable.data());
126 
127  glColor4f(0.0f, 1.0f, 0.0f, 0.5f);
128  glDrawElements(GL_TRIANGLES, _indicesWalkable.size(), GL_UNSIGNED_INT, _indicesWalkable.data());
129 
130  glDisableClientState(GL_VERTEX_ARRAY);
131 
132  // Render highlighted face
133  if (_highlightFaceIndex > -1) {
134  glColor4f(0.0f, 1.0f, 1.0f, 0.5f);
135  glBegin(GL_TRIANGLES);
136  uint32 index = 3 * _highlightFaceIndex;
137  glVertex3fv(&_vertices[3 * _indicesWalkable[index + 0]]);
138  glVertex3fv(&_vertices[3 * _indicesWalkable[index + 1]]);
139  glVertex3fv(&_vertices[3 * _indicesWalkable[index + 2]]);
140  glEnd();
141  }
142 
143  glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
144 }
145 
147  _indicesWalkable.clear();
148  _indicesNonWalkable.clear();
149 
150  size_t faceCount = _indices.size() / 3;
151  size_t index = 0;
152 
153  for (size_t i = 0; i < faceCount; ++i) {
154  float i0 = _indices[index + 0];
155  float i1 = _indices[index + 1];
156  float i2 = _indices[index + 2];
157 
158  if (_faceWalkableMap[i]) {
159  _indicesWalkable.push_back(i0);
160  _indicesWalkable.push_back(i1);
161  _indicesWalkable.push_back(i2);
162  } else {
163  _indicesNonWalkable.push_back(i0);
164  _indicesNonWalkable.push_back(i1);
165  _indicesNonWalkable.push_back(i2);
166  }
167 
168  index += 3;
169  }
170 }
171 
172 } // End of namespace Aurora
173 
174 } // End of namespace Graphics
bool testCollision(const glm::vec3 &orig, const glm::vec3 &dest) const
Definition: walkmesh.cpp:71
Only render transparent parts.
Definition: types.h:99
std::vector< uint32 > _indices
Definition: walkmesh.h:70
Mathematical helpers.
std::vector< bool > _faceWalkableMap
Definition: walkmesh.h:71
void setInvisible(bool invisible)
Definition: walkmesh.cpp:110
RenderPass
Definition: types.h:97
void render(Graphics::RenderPass pass)
Render the object.
Definition: walkmesh.cpp:117
Utility templates and functions.
std::vector< float > _vertices
Definition: walkmesh.h:69
void highlightFace(uint32 index)
Highlight face with specified index.
Definition: walkmesh.cpp:106
std::vector< uint32 > _indicesNonWalkable
Definition: walkmesh.h:73
An object that can be displayed by the graphics manager.
Definition: renderable.h:42
uint32_t uint32
Definition: types.h:204
#define FLT_MIN
Definition: maths.h:43
std::vector< uint32 > _indicesWalkable
Definition: walkmesh.h:72
#define pass
Definition: fft.cpp:257
Generic renderable walkmesh.
float getElevationAt(float x, float y, uint32 &faceIndex) const
Return elevation at given coordinates or FLT_MIN if can&#39;t walk there.
Definition: walkmesh.cpp:43
void calculateDistance()
Calculate the object&#39;s distance.
Definition: walkmesh.cpp:114