💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

402 lines
10 KiB

7 years ago
7 years ago
7 years ago
7 years ago
  1. /*
  2. * Copyright (C) 2017 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper Source Code.
  5. *
  6. * Antkeeper Source Code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper Source Code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "mesh.hpp"
  20. #include <algorithm>
  21. #include <iostream>
  22. #include <fstream>
  23. #include <map>
  24. #include <string>
  25. #include <sstream>
  26. #include <vector>
  27. #include <limits>
  28. bool loadHeightmap(const std::string& filename, glm::vec3 scale, WingedEdge* mesh)
  29. {
  30. int width;
  31. int height;
  32. int components;
  33. // Load image data
  34. unsigned char* pixels = stbi_load(filename.c_str(), &width, &height, &components, 1);
  35. if (!pixels)
  36. {
  37. std::cerr << "Failed to load heightmap image \"" << filename << "\"\n";
  38. return false;
  39. }
  40. std::size_t vertexCount = width * height;
  41. std::size_t triangleCount = (width - 1) * (height - 1) * 2;
  42. std::size_t indexCount = triangleCount * 3;
  43. std::vector<glm::vec3> vertices(vertexCount);
  44. std::vector<std::size_t> indices(indexCount);
  45. // Adjust scale
  46. scale.x *= 1.0f / ((float)width - 1);
  47. scale.y *= 1.0f / 255.0f;
  48. scale.z *= 1.0f / ((float)height - 1);
  49. if (width > height) scale.z *= (float)height / (float) width;
  50. else if (height > width) scale.x *= (float)width / (float)height;
  51. // Calculate centered offset
  52. glm::vec3 offset;
  53. offset.x = (float)width * -0.5f * scale.x;
  54. offset.y = 0.0f;
  55. offset.z = (float)height * -0.5f * scale.z;
  56. // Calculate vertex positions
  57. for (int i = 0; i < height; ++i)
  58. {
  59. for (int j = 0; j < width; ++j)
  60. {
  61. std::size_t index = i * width + j;
  62. glm::vec3* vertex = &vertices[index];
  63. vertex->x = (float)j * scale.x + offset.x;
  64. vertex->y = (float)pixels[index] * scale.y;
  65. vertex->z = (float)i * scale.z + offset.z;
  66. }
  67. }
  68. // Free loaded image
  69. stbi_image_free(pixels);
  70. // Generate indices
  71. for (int i = 0; i < height - 1; ++i)
  72. {
  73. for (int j = 0; j < width - 1; ++j)
  74. {
  75. std::size_t a = i * width + j;
  76. std::size_t b = (i + 1) * width + j;
  77. std::size_t c = i * width + j + 1;
  78. std::size_t d = (i + 1) * width + j + 1;
  79. std::size_t index = (i * (width - 1) + j) * 2 * 3;
  80. indices[index] = a;
  81. indices[index + 1] = b;
  82. indices[index + 2] = c;
  83. indices[index + 3] = c;
  84. indices[index + 4] = b;
  85. indices[index + 5] = d;
  86. }
  87. }
  88. return mesh->create(vertices, indices);
  89. }
  90. bool loadHeightmapBase(const std::string& filename, glm::vec3 scale, float floor, WingedEdge* mesh)
  91. {
  92. int width;
  93. int height;
  94. int components;
  95. // Load image data
  96. unsigned char* pixels = stbi_load(filename.c_str(), &width, &height, &components, 1);
  97. if (!pixels)
  98. {
  99. std::cerr << "Failed to load heightmap image \"" << filename << "\"\n";
  100. return false;
  101. }
  102. std::size_t vertexCount = width * 4 + height * 4;
  103. std::size_t triangleCount = (width - 1) * 4 + (height - 1) * 4;
  104. std::size_t indexCount = triangleCount * 3;
  105. std::vector<glm::vec3> vertices(vertexCount);
  106. std::vector<std::size_t> indices(indexCount);
  107. // Adjust scale
  108. scale.x *= 1.0f / ((float)width - 1);
  109. scale.y *= 1.0f / 255.0f;
  110. scale.z *= 1.0f / ((float)height - 1);
  111. if (width > height) scale.z *= (float)height / (float) width;
  112. else if (height > width) scale.x *= (float)width / (float)height;
  113. // Calculate centered offset
  114. glm::vec3 offset;
  115. offset.x = (float)width * -0.5f * scale.x;
  116. offset.y = 0.0f;
  117. offset.z = (float)height * -0.5f * scale.z;
  118. glm::vec3* vertex = &vertices[0];
  119. // Top row
  120. for (int j = 0; j < width; ++j)
  121. {
  122. int i = 0;
  123. std::size_t index = i * width + j;
  124. vertex->x = (float)j * scale.x + offset.x;
  125. vertex->y = (float)pixels[index] * scale.y;
  126. vertex->z = (float)i * scale.z + offset.z;
  127. ++vertex;
  128. vertex->x = (float)j * scale.x + offset.x;
  129. vertex->y = floor;
  130. vertex->z = (float)i * scale.z + offset.z;
  131. ++vertex;
  132. }
  133. // Bottom row
  134. for (int j = 0; j < width; ++j)
  135. {
  136. int i = (height - 1);
  137. std::size_t index = i * width + j;
  138. vertex->x = (float)j * scale.x + offset.x;
  139. vertex->y = (float)pixels[index] * scale.y;
  140. vertex->z = (float)i * scale.z + offset.z;
  141. ++vertex;
  142. vertex->x = (float)j * scale.x + offset.x;
  143. vertex->y = floor;
  144. vertex->z = (float)i * scale.z + offset.z;
  145. ++vertex;
  146. }
  147. // Left column
  148. for (int i = 0; i < height; ++i)
  149. {
  150. int j = 0;
  151. std::size_t index = i * width + j;
  152. vertex->x = (float)j * scale.x + offset.x;
  153. vertex->y = (float)pixels[index] * scale.y;
  154. vertex->z = (float)i * scale.z + offset.z;
  155. ++vertex;;
  156. vertex->x = (float)j * scale.x + offset.x;
  157. vertex->y = floor;
  158. vertex->z = (float)i * scale.z + offset.z;
  159. ++vertex;
  160. }
  161. // Right column
  162. for (int i = 0; i < height; ++i)
  163. {
  164. int j = (width - 1);
  165. std::size_t index = i * width + j;
  166. vertex->x = (float)j * scale.x + offset.x;
  167. vertex->y = (float)pixels[index] * scale.y;
  168. vertex->z = (float)i * scale.z + offset.z;
  169. ++vertex;
  170. vertex->x = (float)j * scale.x + offset.x;
  171. vertex->y = floor;
  172. vertex->z = (float)i * scale.z + offset.z;
  173. ++vertex;
  174. }
  175. // Free loaded image
  176. stbi_image_free(pixels);
  177. // Generate indices
  178. std::size_t* index = &indices[0];
  179. for (int i = 0; i < width - 1; ++i)
  180. {
  181. std::size_t a = i * 2;
  182. std::size_t b = i * 2 + 1;
  183. std::size_t c = (i + 1) * 2;
  184. std::size_t d = (i + 1) * 2 + 1;
  185. (*(index++)) = b;
  186. (*(index++)) = a;
  187. (*(index++)) = c;
  188. (*(index++)) = b;
  189. (*(index++)) = c;
  190. (*(index++)) = d;
  191. a += width * 2;
  192. b += width * 2;
  193. c += width * 2;
  194. d += width * 2;
  195. (*(index++)) = a;
  196. (*(index++)) = b;
  197. (*(index++)) = c;
  198. (*(index++)) = c;
  199. (*(index++)) = b;
  200. (*(index++)) = d;
  201. }
  202. for (int i = 0; i < height - 1; ++i)
  203. {
  204. std::size_t a = width * 4 + i * 2;
  205. std::size_t b = width * 4 + i * 2 + 1;
  206. std::size_t c = width * 4 + (i + 1) * 2;
  207. std::size_t d = width * 4 + (i + 1) * 2 + 1;
  208. (*(index++)) = a;
  209. (*(index++)) = b;
  210. (*(index++)) = c;
  211. (*(index++)) = c;
  212. (*(index++)) = b;
  213. (*(index++)) = d;
  214. a += height * 2;
  215. b += height * 2;
  216. c += height * 2;
  217. d += height * 2;
  218. (*(index++)) = b;
  219. (*(index++)) = a;
  220. (*(index++)) = c;
  221. (*(index++)) = b;
  222. (*(index++)) = c;
  223. (*(index++)) = d;
  224. }
  225. return mesh->create(vertices, indices);
  226. }
  227. void move(const WingedEdge* mesh, WingedEdge::Triangle* triangle, const glm::vec3& start, const glm::vec3& target, std::vector<WingedEdge::Triangle*>* visited, glm::vec3* end)
  228. {
  229. // Add triangle to visited list
  230. visited->push_back(triangle);
  231. // Grab triangle coordinates
  232. const glm::vec3& a = triangle->edge->vertex->position;
  233. const glm::vec3& b = triangle->edge->next->vertex->position;
  234. const glm::vec3& c = triangle->edge->previous->vertex->position;
  235. // Project target onto triangle
  236. glm::vec3 closestPoint;
  237. int edgeIndex = -1;
  238. WingedEdge::Edge* closestEdge = nullptr;
  239. project_on_triangle(target, a, b, c, &closestPoint, &edgeIndex);
  240. *end = closestPoint;
  241. // Determine if projected target is on an edge
  242. switch (edgeIndex)
  243. {
  244. case -1:
  245. // Projected target inside triangle
  246. return;
  247. case 0:
  248. closestEdge = triangle->edge;
  249. break;
  250. case 1:
  251. closestEdge = triangle->edge->next;
  252. break;
  253. case 2:
  254. closestEdge = triangle->edge->previous;
  255. break;
  256. }
  257. // If edge is not loose, repeat with connected triangle
  258. if (closestEdge->symmetric != nullptr)
  259. {
  260. for (std::size_t i = 0; i < visited->size() - 1; ++i)
  261. {
  262. if ((*visited)[i] == closestEdge->symmetric->triangle)
  263. return;
  264. }
  265. move(mesh, closestEdge->symmetric->triangle, closestPoint, target, visited, end);
  266. }
  267. }
  268. std::tuple<bool, float, float, float> intersects(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& a, const glm::vec3& b, const glm::vec3& c)
  269. {
  270. // Find edges
  271. glm::vec3 edge10 = b - a;
  272. glm::vec3 edge20 = c - a;
  273. // Calculate determinant
  274. glm::vec3 pv = glm::cross(direction, edge20);
  275. float det = glm::dot(edge10, pv);
  276. if (!det)
  277. {
  278. return std::make_tuple(false, std::numeric_limits<float>::infinity(), 0.0f, 0.0f);
  279. }
  280. float inverseDet = 1.0f / det;
  281. // Calculate u
  282. glm::vec3 tv = origin - a;
  283. float u = glm::dot(tv, pv) * inverseDet;
  284. if (u < 0.0f || u > 1.0f)
  285. {
  286. return std::make_tuple(false, std::numeric_limits<float>::infinity(), 0.0f, 0.0f);
  287. }
  288. // Calculate v
  289. glm::vec3 qv = glm::cross(tv, edge10);
  290. float v = glm::dot(direction, qv) * inverseDet;
  291. if (v < 0.0f || u + v > 1.0f)
  292. {
  293. return std::make_tuple(false, std::numeric_limits<float>::infinity(), 0.0f, 0.0f);
  294. }
  295. // Calculate t
  296. float t = glm::dot(edge20, qv) * inverseDet;
  297. if (t > 0.0f)
  298. {
  299. return std::make_tuple(true, t, u, v);
  300. }
  301. return std::make_tuple(false, std::numeric_limits<float>::infinity(), 0.0f, 0.0f);
  302. }
  303. std::tuple<bool, float, float, std::size_t, std::size_t> intersects(const glm::vec3& origin, const glm::vec3& direction, const WingedEdge& mesh)
  304. {
  305. const std::vector<WingedEdge::Triangle*>* triangles = mesh.getTriangles();
  306. bool intersection = false;
  307. float t0 = std::numeric_limits<float>::infinity();
  308. float t1 = -std::numeric_limits<float>::infinity();
  309. std::size_t index0 = triangles->size();
  310. std::size_t index1 = index0;
  311. for (std::size_t i = 0; i < triangles->size(); ++i)
  312. {
  313. const WingedEdge::Triangle* triangle = (*triangles)[i];
  314. const glm::vec3& a = triangle->edge->vertex->position;
  315. const glm::vec3& b = triangle->edge->next->vertex->position;
  316. const glm::vec3& c = triangle->edge->previous->vertex->position;
  317. auto result = intersects(origin, direction, a, b, c);
  318. if (std::get<0>(result))
  319. {
  320. intersection = true;
  321. float t = std::get<1>(result);
  322. float cosTheta = glm::dot(direction, triangle->normal);
  323. if (cosTheta <= 0.0f)
  324. {
  325. // Front-facing
  326. t0 = std::min<float>(t0, t);
  327. index0 = i;
  328. }
  329. else
  330. {
  331. // Back-facing
  332. t1 = std::max<float>(t1, t);
  333. index1 = i;
  334. }
  335. }
  336. }
  337. return std::make_tuple(intersection, t0, t1, index0, index1);
  338. }