Terrain.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. /*
  2. Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
  3. Permission is hereby granted, free of charge, to any person
  4. obtaining a copy of this software and associated documentation
  5. files (the "Software"), to deal in the Software without
  6. restriction, including without limitation the rights to use,
  7. copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. copies of the Software, and to permit persons to whom the
  9. Software is furnished to do so, subject to the following
  10. conditions:
  11. The above copyright notice and this permission notice shall be
  12. included in all copies or substantial portions of the Software.
  13. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  14. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  15. OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  16. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  17. HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  18. WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20. OTHER DEALINGS IN THE SOFTWARE.
  21. */
  22. #include "Terrain.h"
  23. #include "Device.h"
  24. #include "Renderer.h"
  25. #include "MathUtils.h"
  26. #include <GL/glew.h>
  27. #include "Log.h"
  28. #include <cstdio>
  29. #include "Vec2.h"
  30. #include "Interpolation.h"
  31. #include <cmath>
  32. namespace crown
  33. {
  34. Terrain::Terrain() :
  35. mHeights(NULL),
  36. mMinHeight(-10.0f),
  37. mMaxHeight(10.0f),
  38. mVertices(NULL),
  39. mNormals(NULL),
  40. mTexCoords(NULL),
  41. mIndices(NULL)
  42. {
  43. }
  44. Terrain::~Terrain()
  45. {
  46. if (mHeights != NULL)
  47. {
  48. delete[] mHeights;
  49. }
  50. delete[] mVertices;
  51. delete[] mNormals;
  52. delete[] mTexCoords;
  53. delete[] mIndices;
  54. }
  55. void Terrain::CreateTerrain(uint32_t xSize, uint32_t zSize, uint32_t tilePerMeter, float initialHeight)
  56. {
  57. assert(xSize > 0);
  58. assert(zSize > 0);
  59. assert(tilePerMeter > 0);
  60. mSizeX = xSize;
  61. mSizeZ = zSize;
  62. mTilePerMeter = tilePerMeter;
  63. float tileStep = +(float)mSizeX / ((float)mSizeX * (float)mTilePerMeter); // Tile step is the same for both x and z ;)
  64. mTilesInSizeX = ((float)mSizeX / tileStep);
  65. mTilesInSizeZ = ((float)mSizeZ / tileStep);
  66. mVerticesInSizeX = mTilesInSizeX + 1;
  67. mVerticesInSizeZ = mTilesInSizeZ + 1;
  68. printf("Vertices in size x/z: %d %d\n", mVerticesInSizeX, mVerticesInSizeZ);
  69. uint32_t heightsCount = mVerticesInSizeX * mVerticesInSizeZ;
  70. mHeights = new float[heightsCount];
  71. // Init heights
  72. for (uint32_t i = 0; i < heightsCount; i++)
  73. {
  74. mHeights[i] = initialHeight;
  75. }
  76. // Construct drawing data
  77. mVertices = new Vec3[heightsCount]; // There are as many vertices as heights
  78. mVertexCount = heightsCount;
  79. mNormals = new Vec3[heightsCount]; // Same as vertices
  80. mNormalCount = heightsCount;
  81. mTexCoords = new Vec2[heightsCount]; // Same as vertices
  82. mTexCoordCount = heightsCount;
  83. mIndices = new uint16_t[mTilesInSizeX * mTilesInSizeZ * 6]; //
  84. mIndexCount = mTilesInSizeX * mTilesInSizeZ * 6;
  85. // Populate vertex list (generate a grid lying on the xz-plane and facing upwards)
  86. float xStart = -(float)mSizeX * 0.5f;
  87. float zStart = +(float)mSizeZ * 0.5f;
  88. mOffsetX = xStart;
  89. mOffsetZ = zStart;
  90. uint32_t vIndex = 0; // Just because I'm lazy
  91. float xCurrent; // Keeps track of current x position
  92. float zCurrent = zStart; // Keeps track of current z position
  93. for (uint32_t z = 0; z < mVerticesInSizeZ; z++)
  94. {
  95. xCurrent = xStart;
  96. for (uint32_t x = 0; x < mVerticesInSizeX; x++)
  97. {
  98. mVertices[vIndex].x = xCurrent;
  99. mVertices[vIndex].y = mHeights[vIndex];
  100. mVertices[vIndex].z = zCurrent;
  101. mNormals[vIndex].x = 0.0f;
  102. mNormals[vIndex].y = 1.0f;
  103. mNormals[vIndex].z = 0.0f;
  104. mTexCoords[vIndex].x = (float)x;
  105. mTexCoords[vIndex].y = (float)z;
  106. vIndex++;
  107. xCurrent += tileStep;
  108. }
  109. zCurrent -= tileStep;
  110. }
  111. // Populate index list
  112. uint32_t iIndex = 0;
  113. for (uint32_t z = 0; z < mTilesInSizeZ; z++)
  114. {
  115. for (uint32_t x = 0; x < mTilesInSizeX; x++)
  116. {
  117. uint32_t firstRow = z * mVerticesInSizeX + x;
  118. uint32_t secondRow = (z + 1) * mVerticesInSizeX + x;
  119. mIndices[iIndex + 0] = firstRow;
  120. mIndices[iIndex + 1] = secondRow + 1;
  121. mIndices[iIndex + 2] = secondRow;
  122. mIndices[iIndex + 3] = firstRow;
  123. mIndices[iIndex + 4] = firstRow + 1;
  124. mIndices[iIndex + 5] = secondRow + 1;
  125. iIndex += 6;
  126. }
  127. }
  128. }
  129. void Terrain::UpdateVertexBuffer(bool recomputeNormals)
  130. {
  131. uint32_t vIndex = 0;
  132. for (uint32_t z = 0; z < mVerticesInSizeZ; z++)
  133. {
  134. for (uint32_t x = 0; x < mVerticesInSizeX; x++)
  135. {
  136. mVertices[vIndex].y = mHeights[vIndex];
  137. vIndex++;
  138. }
  139. }
  140. if (recomputeNormals)
  141. {
  142. for (uint32_t i = 0; i < mIndexCount; i += 3)
  143. {
  144. Vec3 normal;
  145. Vec3 v1;
  146. Vec3 v2;
  147. v1 = mVertices[mIndices[i + 0]] - mVertices[mIndices[i + 1]];
  148. v2 = mVertices[mIndices[i + 2]] - mVertices[mIndices[i + 1]];
  149. normal = v2.cross(v1).normalize();
  150. mNormals[mIndices[i + 0]] = normal;
  151. mNormals[mIndices[i + 1]] = normal;
  152. mNormals[mIndices[i + 2]] = normal;
  153. }
  154. }
  155. }
  156. float Terrain::GetHeightAt(uint32_t x, uint32_t z) const
  157. {
  158. if (x > mVerticesInSizeX) return 0.0f;
  159. if (z > mVerticesInSizeZ) return 0.0f;
  160. return mHeights[z * mVerticesInSizeX + x];
  161. }
  162. float Terrain::GetHeightAt(const Vec3& xyz) const
  163. {
  164. uint32_t x, z;
  165. WorldToHeight(xyz, x, z);
  166. return GetHeightAt(x, z);
  167. }
  168. void Terrain::SetHeightAt(uint32_t x, uint32_t z, float height)
  169. {
  170. if (x >= mVerticesInSizeX) return;
  171. if (z >= mVerticesInSizeZ) return;
  172. mHeights[z * mVerticesInSizeX + x] += height;
  173. mHeights[z * mVerticesInSizeX + x] = math::clamp_to_range(mMinHeight, mMaxHeight, mHeights[z * mVerticesInSizeX + x]);
  174. }
  175. void Terrain::SetHeightAt(const Vec3& xyz, float height)
  176. {
  177. uint32_t x, z;
  178. WorldToHeight(xyz, x, z);
  179. SetHeightAt(x + 0, z + 0, height);
  180. }
  181. void Terrain::WorldToHeight(const Vec3& xyz, uint32_t& x, uint32_t& z) const
  182. {
  183. Vec3 offsetted = xyz + Vec3(-mOffsetX, 0.0f, mOffsetZ);
  184. offsetted.z = (float)mSizeZ - offsetted.z;
  185. x = (uint32_t)offsetted.x;
  186. z = (uint32_t)offsetted.z;
  187. }
  188. bool Terrain::TraceRay(const Ray& ray, Triangle& result, Triangle& /*tri2*/, real& dist)
  189. {
  190. bool hit = false;
  191. real minDist = 9999999.0f;
  192. for (uint32_t i = 0; i < mIndexCount; i += 3)
  193. {
  194. Triangle tri;
  195. tri.v1 = mVertices[mIndices[i + 0]];
  196. tri.v2 = mVertices[mIndices[i + 1]];
  197. tri.v3 = mVertices[mIndices[i + 2]];
  198. real ret;
  199. Vec3 int32_tersectionPoint32_t;
  200. if (Intersection::TestRayTriangle(ray, tri, ret, int32_tersectionPoint32_t))
  201. {
  202. if (ret < minDist)
  203. {
  204. minDist = ret;
  205. result = tri;
  206. }
  207. hit = true;
  208. }
  209. }
  210. dist = minDist;
  211. return hit;
  212. }
  213. uint32_t Terrain::SnapToGrid(const Vec3& vertex)
  214. {
  215. float minDist = 9999999.0f;
  216. uint32_t indexToSnapped;
  217. // Find the snapped point32_t to input vertex
  218. for (uint32_t i = 0; i < mVertexCount; i++)
  219. {
  220. Vec3 tmp = mVertices[i];
  221. Vec3 vertex2 = vertex;
  222. tmp.y = vertex2.y = 0.0f;
  223. if (tmp.get_distance_to(vertex2) < minDist)
  224. {
  225. indexToSnapped = i;
  226. minDist = tmp.get_distance_to(vertex2);
  227. }
  228. }
  229. return indexToSnapped;
  230. }
  231. void Terrain::Render()
  232. {
  233. //Renderer* renderer = GetDevice()->GetRenderer();
  234. glBindBuffer(GL_ARRAY_BUFFER, 0);
  235. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  236. glEnableClientState(GL_VERTEX_ARRAY);
  237. glEnableClientState(GL_NORMAL_ARRAY);
  238. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  239. glVertexPointer(3, GL_FLOAT, 0, mVertices);
  240. glNormalPointer(GL_FLOAT, 0, mNormals);
  241. glTexCoordPointer(2, GL_FLOAT, 0, mTexCoords);
  242. glDrawElements(GL_TRIANGLES, mTilesInSizeX * mTilesInSizeZ * 6, GL_UNSIGNED_SHORT, mIndices);
  243. glDisableClientState(GL_VERTEX_ARRAY);
  244. glDisableClientState(GL_NORMAL_ARRAY);
  245. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  246. }
  247. float Terrain::GaussDist(float x, float y, float sigma)
  248. {
  249. float gauss = 1.0f / math::TWO_PI * (sigma * sigma);
  250. float e = 2.71828183f;
  251. float exponent = ((x * x) + (y * y)) / (2.0f * (sigma * sigma));
  252. return gauss * pow(e, -exponent);
  253. }
  254. void Terrain::BuildBrush(uint32_t width, uint32_t height, float smooth)
  255. {
  256. assert(width < MAX_BRUSH_SIZE);
  257. assert(height < MAX_BRUSH_SIZE);
  258. mBrushWidth = width;
  259. mBrushHeight = height;
  260. float xStart = -(float)width * 0.5f;
  261. float yStart = -(float)height * 0.5f;
  262. float xCurrent = xStart;
  263. for (uint32_t i = 0; i <= width; i++)
  264. {
  265. float yCurrent = yStart;
  266. for (uint32_t j = 0; j <= height; j++)
  267. {
  268. mBrush[j * MAX_BRUSH_SIZE + i] = GaussDist(xCurrent, yCurrent, smooth);
  269. yCurrent += 1.0f;
  270. }
  271. xCurrent += 1.0f;
  272. }
  273. }
  274. void Terrain::PlotCircle(int32_t xx, int32_t yy, int32_t radius, int32_t i)
  275. {
  276. for (int32_t j = 0; j < 256 * 256; j++)
  277. {
  278. mBrush[j] = 0;
  279. }
  280. int32_t x, y;
  281. mBrushWidth = radius * 2;
  282. mBrushHeight = radius * 2;
  283. for (y = -radius; y <= radius; y++)
  284. for (x = -radius; x <= radius; x++)
  285. if ((x * x) + (y * y) <= (radius * radius))
  286. {
  287. float rDist = 1.0 - math::sqrt(x * x + y * y) / radius;
  288. if (i == 0)
  289. {
  290. mBrush[(y + yy) * MAX_BRUSH_SIZE + (x + xx)] = Interpolation::linear(0.0f, 1.0f, rDist);
  291. }
  292. else if (i == 1)
  293. {
  294. mBrush[(y + yy) * MAX_BRUSH_SIZE + (x + xx)] = Interpolation::cosine(0.0f, 1.0f, rDist);
  295. }
  296. else if (i == 2)
  297. {
  298. mBrush[(y + yy) * MAX_BRUSH_SIZE + (x + xx)] = Interpolation::cubic(0.0f, 1.0f, rDist);
  299. }
  300. }
  301. }
  302. void Terrain::ApplyBrush(uint32_t x, uint32_t z, float scale)
  303. {
  304. uint32_t offsetX = mBrushWidth / 2;
  305. uint32_t offsetY = mBrushHeight / 2;
  306. for (uint32_t i = 0; i < mBrushWidth; i++)
  307. {
  308. for (uint32_t j = 0; j < mBrushHeight; j++)
  309. {
  310. SetHeightAt((x - offsetX) + i, (z - offsetY) + j, scale * mBrush[j * MAX_BRUSH_SIZE + i]);
  311. }
  312. }
  313. }
  314. void Terrain::ApplyBrush(const Vec3& xyz, float scale)
  315. {
  316. uint32_t x, z;
  317. WorldToHeight(xyz, x, z);
  318. ApplyBrush(x, z, scale);
  319. }
  320. } // namespace crown