Mesh.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785
  1. /**
  2. * Copyright (c) 2006-2015 LOVE Development Team
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. *
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute it
  10. * freely, subject to the following restrictions:
  11. *
  12. * 1. The origin of this software must not be misrepresented; you must not
  13. * claim that you wrote the original software. If you use this software
  14. * in a product, an acknowledgment in the product documentation would be
  15. * appreciated but is not required.
  16. * 2. Altered source versions must be plainly marked as such, and must not be
  17. * misrepresented as being the original software.
  18. * 3. This notice may not be removed or altered from any source distribution.
  19. **/
  20. // LOVE
  21. #include "Mesh.h"
  22. #include "common/Matrix.h"
  23. #include "common/Exception.h"
  24. #include "Shader.h"
  25. // C++
  26. #include <algorithm>
  27. #include <limits>
  28. namespace love
  29. {
  30. namespace graphics
  31. {
  32. namespace opengl
  33. {
  34. static const char *getBuiltinAttribName(VertexAttribID attribid)
  35. {
  36. const char *name = "";
  37. Shader::getConstant(attribid, name);
  38. return name;
  39. }
  40. static_assert(offsetof(Vertex, x) == sizeof(float) * 0, "Incorrect position offset in Vertex struct");
  41. static_assert(offsetof(Vertex, s) == sizeof(float) * 2, "Incorrect texture coordinate offset in Vertex struct");
  42. static_assert(offsetof(Vertex, r) == sizeof(float) * 4, "Incorrect color offset in Vertex struct");
  43. static std::vector<Mesh::AttribFormat> getDefaultVertexFormat()
  44. {
  45. // Corresponds to the love::Vertex struct.
  46. std::vector<Mesh::AttribFormat> vertexformat = {
  47. {getBuiltinAttribName(ATTRIB_POS), Mesh::DATA_FLOAT, 2},
  48. {getBuiltinAttribName(ATTRIB_TEXCOORD), Mesh::DATA_FLOAT, 2},
  49. {getBuiltinAttribName(ATTRIB_COLOR), Mesh::DATA_BYTE, 4},
  50. };
  51. return vertexformat;
  52. }
  53. Mesh::Mesh(const std::vector<AttribFormat> &vertexformat, const void *data, size_t datasize, DrawMode drawmode, Usage usage)
  54. : vertexFormat(vertexformat)
  55. , vbo(nullptr)
  56. , vertexCount(0)
  57. , vertexStride(0)
  58. , vboUsedOffset(0)
  59. , vboUsedSize(0)
  60. , ibo(nullptr)
  61. , elementCount(0)
  62. , elementDataType(0)
  63. , drawMode(drawmode)
  64. , rangeMin(-1)
  65. , rangeMax(-1)
  66. {
  67. setupAttachedAttributes();
  68. calculateAttributeSizes();
  69. vertexCount = datasize / vertexStride;
  70. elementDataType = getGLDataTypeFromMax(vertexCount);
  71. if (vertexCount == 0)
  72. throw love::Exception("Data size is too small for specified vertex attribute formats.");
  73. vbo = new GLBuffer(datasize, data, GL_ARRAY_BUFFER, getGLBufferUsage(usage));
  74. vertexScratchBuffer = new char[vertexStride];
  75. }
  76. Mesh::Mesh(const std::vector<AttribFormat> &vertexformat, int vertexcount, DrawMode drawmode, Usage usage)
  77. : vertexFormat(vertexformat)
  78. , vbo(nullptr)
  79. , vertexCount((size_t) vertexcount)
  80. , vertexStride(0)
  81. , vboUsedOffset(0)
  82. , vboUsedSize(0)
  83. , ibo(nullptr)
  84. , elementCount(0)
  85. , elementDataType(getGLDataTypeFromMax(vertexcount))
  86. , drawMode(drawmode)
  87. , rangeMin(-1)
  88. , rangeMax(-1)
  89. {
  90. if (vertexcount <= 0)
  91. throw love::Exception("Invalid number of vertices (%d).", vertexcount);
  92. setupAttachedAttributes();
  93. calculateAttributeSizes();
  94. size_t buffersize = vertexCount * vertexStride;
  95. vbo = new GLBuffer(buffersize, nullptr, GL_ARRAY_BUFFER, getGLBufferUsage(usage));
  96. // Initialize the buffer's contents to 0.
  97. GLBuffer::Bind bind(*vbo);
  98. memset(vbo->map(), 0, buffersize);
  99. vbo->unmap();
  100. vertexScratchBuffer = new char[vertexStride];
  101. }
  102. Mesh::Mesh(const std::vector<Vertex> &vertices, DrawMode drawmode, Usage usage)
  103. : Mesh(getDefaultVertexFormat(), &vertices[0], vertices.size() * sizeof(Vertex), drawmode, usage)
  104. {
  105. }
  106. Mesh::Mesh(int vertexcount, DrawMode drawmode, Usage usage)
  107. : Mesh(getDefaultVertexFormat(), vertexcount, drawmode, usage)
  108. {
  109. }
  110. Mesh::~Mesh()
  111. {
  112. delete vbo;
  113. delete ibo;
  114. delete vertexScratchBuffer;
  115. for (const auto &attrib : attachedAttributes)
  116. {
  117. if (attrib.second.mesh != this)
  118. attrib.second.mesh->release();
  119. }
  120. }
  121. void Mesh::setupAttachedAttributes()
  122. {
  123. for (size_t i = 0; i < vertexFormat.size(); i++)
  124. {
  125. const std::string &name = vertexFormat[i].name;
  126. if (attachedAttributes.find(name) != attachedAttributes.end())
  127. throw love::Exception("Duplicate vertex attribute name: %s", name.c_str());
  128. attachedAttributes[name] = {this, i, true};
  129. }
  130. }
  131. void Mesh::calculateAttributeSizes()
  132. {
  133. size_t stride = 0;
  134. for (const AttribFormat &format : vertexFormat)
  135. {
  136. // Hardware really doesn't like attributes that aren't 32 bit-aligned.
  137. if (format.type == DATA_BYTE && format.components != 4)
  138. throw love::Exception("byte vertex attributes must have 4 components.");
  139. if (format.components <= 0 || format.components > 4)
  140. throw love::Exception("Vertex attributes must have between 1 and 4 components.");
  141. // Total size in bytes of each attribute in a single vertex.
  142. attributeSizes.push_back(getAttribFormatSize(format));
  143. stride += attributeSizes.back();
  144. }
  145. vertexStride = stride;
  146. }
  147. size_t Mesh::getAttributeOffset(size_t attribindex) const
  148. {
  149. size_t offset = 0;
  150. for (size_t i = 0; i < attribindex; i++)
  151. offset += attributeSizes[i];
  152. return offset;
  153. }
  154. void Mesh::setVertex(size_t vertindex, const void *data, size_t datasize)
  155. {
  156. if (vertindex >= vertexCount)
  157. throw love::Exception("Invalid vertex index: %ld", vertindex + 1);
  158. size_t offset = vertindex * vertexStride;
  159. size_t size = std::min(datasize, vertexStride);
  160. GLBuffer::Bind bind(*vbo);
  161. uint8 *bufferdata = (uint8 *) vbo->map();
  162. memcpy(bufferdata + offset, data, size);
  163. vboUsedOffset = std::min(vboUsedOffset, offset);
  164. vboUsedSize = std::max(vboUsedSize, (offset + size) - vboUsedOffset);
  165. }
  166. size_t Mesh::getVertex(size_t vertindex, void *data, size_t datasize)
  167. {
  168. if (vertindex >= vertexCount)
  169. throw love::Exception("Invalid vertex index: %ld", vertindex + 1);
  170. size_t offset = vertindex * vertexStride;
  171. size_t size = std::min(datasize, vertexStride);
  172. // We're relying on vbo->map() returning read/write data... ew.
  173. GLBuffer::Bind bind(*vbo);
  174. const uint8 *bufferdata = (const uint8 *) vbo->map();
  175. memcpy(data, bufferdata + offset, size);
  176. if (vboUsedSize == 0)
  177. {
  178. vboUsedOffset = std::min(vboUsedOffset, offset);
  179. vboUsedSize = std::max(vboUsedSize, (offset + size) - vboUsedOffset);
  180. }
  181. return size;
  182. }
  183. void *Mesh::getVertexScratchBuffer()
  184. {
  185. return vertexScratchBuffer;
  186. }
  187. void Mesh::setVertexAttribute(size_t vertindex, int attribindex, const void *data, size_t datasize)
  188. {
  189. if (vertindex >= vertexCount)
  190. throw love::Exception("Invalid vertex index: %ld", vertindex + 1);
  191. if (attribindex >= (int) vertexFormat.size())
  192. throw love::Exception("Invalid vertex attribute index: %d", attribindex + 1);
  193. size_t offset = vertindex * vertexStride + getAttributeOffset(attribindex);
  194. size_t size = std::min(datasize, attributeSizes[attribindex]);
  195. GLBuffer::Bind bind(*vbo);
  196. uint8 *bufferdata = (uint8 *) vbo->map();
  197. memcpy(bufferdata + offset, data, size);
  198. vboUsedOffset = std::min(vboUsedOffset, offset);
  199. vboUsedSize = std::max(vboUsedSize, (offset + size) - vboUsedOffset);
  200. }
  201. size_t Mesh::getVertexAttribute(size_t vertindex, int attribindex, void *data, size_t datasize)
  202. {
  203. if (vertindex >= vertexCount)
  204. throw love::Exception("Invalid vertex index: %ld", vertindex + 1);
  205. if (attribindex >= (int) vertexFormat.size())
  206. throw love::Exception("Invalid vertex attribute index: %d", attribindex + 1);
  207. size_t offset = vertindex * vertexStride + getAttributeOffset(attribindex);
  208. size_t size = std::min(datasize, attributeSizes[attribindex]);
  209. // We're relying on vbo->map() returning read/write data... ew.
  210. GLBuffer::Bind bind(*vbo);
  211. const uint8 *bufferdata = (const uint8 *) vbo->map();
  212. memcpy(data, bufferdata + offset, size);
  213. if (vboUsedSize == 0)
  214. {
  215. vboUsedOffset = std::min(vboUsedOffset, offset);
  216. vboUsedSize = std::max(vboUsedSize, (offset + size) - vboUsedOffset);
  217. }
  218. return size;
  219. }
  220. size_t Mesh::getVertexCount() const
  221. {
  222. return vertexCount;
  223. }
  224. size_t Mesh::getVertexStride() const
  225. {
  226. return vertexStride;
  227. }
  228. const std::vector<Mesh::AttribFormat> &Mesh::getVertexFormat() const
  229. {
  230. return vertexFormat;
  231. }
  232. Mesh::DataType Mesh::getAttributeInfo(int attribindex, int &components) const
  233. {
  234. if (attribindex < 0 || attribindex >= (int) vertexFormat.size())
  235. throw love::Exception("Invalid vertex attribute index: %d", attribindex + 1);
  236. DataType type = vertexFormat[attribindex].type;
  237. components = vertexFormat[attribindex].components;
  238. return type;
  239. }
  240. void Mesh::setAttributeEnabled(const std::string &name, bool enable)
  241. {
  242. auto it = attachedAttributes.find(name);
  243. if (it == attachedAttributes.end())
  244. throw love::Exception("Mesh does not have an attached vertex attribute named '%s'", name.c_str());
  245. it->second.enabled = enable;
  246. }
  247. bool Mesh::isAttributeEnabled(const std::string &name) const
  248. {
  249. const auto it = attachedAttributes.find(name);
  250. if (it == attachedAttributes.end())
  251. throw love::Exception("Mesh does not have an attached vertex attribute named '%s'", name.c_str());
  252. return it->second.enabled;
  253. }
  254. void Mesh::attachAttribute(const std::string &name, Mesh *mesh)
  255. {
  256. if (mesh != this)
  257. {
  258. for (const auto &it : mesh->attachedAttributes)
  259. {
  260. // If the supplied Mesh has attached attributes of its own, then we
  261. // prevent it from being attached to avoid reference cycles.
  262. if (it.second.mesh != mesh)
  263. throw love::Exception("Cannot attach a Mesh which has attached Meshes of its own.");
  264. }
  265. }
  266. AttachedAttribute oldattrib = {};
  267. AttachedAttribute newattrib = {};
  268. auto it = attachedAttributes.find(name);
  269. if (it != attachedAttributes.end())
  270. oldattrib = it->second;
  271. newattrib.mesh = mesh;
  272. newattrib.index = std::numeric_limits<size_t>::max();
  273. newattrib.enabled = oldattrib.mesh ? oldattrib.enabled : true;
  274. // Find the index of the attribute in the mesh.
  275. for (size_t i = 0; i < mesh->vertexFormat.size(); i++)
  276. {
  277. if (mesh->vertexFormat[i].name == name)
  278. {
  279. newattrib.index = i;
  280. break;
  281. }
  282. }
  283. if (newattrib.index == std::numeric_limits<size_t>::max())
  284. throw love::Exception("The specified mesh does not have a vertex attribute named '%s'", name.c_str());
  285. if (newattrib.mesh != this)
  286. newattrib.mesh->retain();
  287. attachedAttributes[name] = newattrib;
  288. if (oldattrib.mesh && oldattrib.mesh != this)
  289. oldattrib.mesh->release();
  290. }
  291. void *Mesh::mapVertexData()
  292. {
  293. GLBuffer::Bind bind(*vbo);
  294. return vbo->map();
  295. }
  296. void Mesh::unmapVertexData()
  297. {
  298. // Assume the whole buffer was modified.
  299. GLBuffer::Bind bind(*vbo);
  300. vbo->unmap();
  301. vboUsedOffset = vboUsedSize = 0;
  302. }
  303. void Mesh::flush()
  304. {
  305. {
  306. GLBuffer::Bind vbobind(*vbo);
  307. vbo->unmap(vboUsedOffset, vboUsedSize);
  308. vboUsedOffset = vboUsedSize = 0;
  309. }
  310. if (ibo != nullptr)
  311. {
  312. GLBuffer::Bind ibobind(*ibo);
  313. ibo->unmap();
  314. }
  315. }
  316. /**
  317. * Copies index data from a vector to a mapped index buffer.
  318. **/
  319. template <typename T>
  320. static void copyToIndexBuffer(const std::vector<uint32> &indices, GLBuffer::Mapper &buffermap, size_t maxval)
  321. {
  322. T *elems = (T *) buffermap.get();
  323. for (size_t i = 0; i < indices.size(); i++)
  324. {
  325. if (indices[i] >= maxval)
  326. throw love::Exception("Invalid vertex map value: %d", indices[i] + 1);
  327. elems[i] = (T) indices[i];
  328. }
  329. }
  330. void Mesh::setVertexMap(const std::vector<uint32> &map)
  331. {
  332. size_t maxval = getVertexCount();
  333. GLenum datatype = getGLDataTypeFromMax(maxval);
  334. // Calculate the size in bytes of the index buffer data.
  335. size_t size = map.size() * getGLDataTypeSize(datatype);
  336. if (ibo && size > ibo->getSize())
  337. {
  338. delete ibo;
  339. ibo = nullptr;
  340. }
  341. if (!ibo && size > 0)
  342. ibo = new GLBuffer(size, nullptr, GL_ELEMENT_ARRAY_BUFFER, vbo->getUsage());
  343. elementCount = map.size();
  344. if (!ibo || elementCount == 0)
  345. return;
  346. GLBuffer::Bind ibobind(*ibo);
  347. GLBuffer::Mapper ibomap(*ibo);
  348. // Fill the buffer with the index values from the vector.
  349. switch (datatype)
  350. {
  351. case GL_UNSIGNED_SHORT:
  352. copyToIndexBuffer<uint16>(map, ibomap, maxval);
  353. break;
  354. case GL_UNSIGNED_INT:
  355. default:
  356. copyToIndexBuffer<uint32>(map, ibomap, maxval);
  357. break;
  358. }
  359. elementDataType = datatype;
  360. }
  361. /**
  362. * Copies index data from a mapped buffer to a vector.
  363. **/
  364. template <typename T>
  365. static void copyFromIndexBuffer(void *buffer, size_t count, std::vector<uint32> &indices)
  366. {
  367. T *elems = (T *) buffer;
  368. for (size_t i = 0; i < count; i++)
  369. indices.push_back((uint32) elems[i]);
  370. }
  371. void Mesh::getVertexMap(std::vector<uint32> &map) const
  372. {
  373. if (!ibo || elementCount == 0)
  374. return;
  375. map.clear();
  376. map.reserve(elementCount);
  377. GLBuffer::Bind ibobind(*ibo);
  378. // We unmap the buffer in Mesh::draw, Mesh::setVertexMap, and Mesh::flush.
  379. void *buffer = ibo->map();
  380. // Fill the vector from the buffer.
  381. switch (elementDataType)
  382. {
  383. case GL_UNSIGNED_SHORT:
  384. copyFromIndexBuffer<uint16>(buffer, elementCount, map);
  385. break;
  386. case GL_UNSIGNED_INT:
  387. default:
  388. copyFromIndexBuffer<uint32>(buffer, elementCount, map);
  389. break;
  390. }
  391. }
  392. size_t Mesh::getVertexMapCount() const
  393. {
  394. return elementCount;
  395. }
  396. void Mesh::setTexture(Texture *tex)
  397. {
  398. texture.set(tex);
  399. }
  400. void Mesh::setTexture()
  401. {
  402. texture.set(nullptr);
  403. }
  404. Texture *Mesh::getTexture() const
  405. {
  406. return texture.get();
  407. }
  408. void Mesh::setDrawMode(DrawMode mode)
  409. {
  410. drawMode = mode;
  411. }
  412. Mesh::DrawMode Mesh::getDrawMode() const
  413. {
  414. return drawMode;
  415. }
  416. void Mesh::setDrawRange(int min, int max)
  417. {
  418. if (min < 0 || max < 0 || min > max)
  419. throw love::Exception("Invalid draw range.");
  420. rangeMin = min;
  421. rangeMax = max;
  422. }
  423. void Mesh::setDrawRange()
  424. {
  425. rangeMin = rangeMax = -1;
  426. }
  427. void Mesh::getDrawRange(int &min, int &max) const
  428. {
  429. min = rangeMin;
  430. max = rangeMax;
  431. }
  432. void Mesh::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
  433. {
  434. OpenGL::TempDebugGroup debuggroup("Mesh draw");
  435. uint32 enabledattribs = 0;
  436. for (const auto &attrib : attachedAttributes)
  437. {
  438. if (!attrib.second.enabled)
  439. continue;
  440. Mesh *mesh = attrib.second.mesh;
  441. const AttribFormat &format = mesh->vertexFormat[attrib.second.index];
  442. GLint attriblocation = -1;
  443. // If the attribute is one of the LOVE-defined ones, use the constant
  444. // attribute index for it, otherwise query the index from the shader.
  445. VertexAttribID builtinattrib;
  446. if (Shader::getConstant(format.name.c_str(), builtinattrib))
  447. attriblocation = (GLint) builtinattrib;
  448. else if (Shader::current)
  449. attriblocation = Shader::current->getAttribLocation(format.name);
  450. // The active shader might not use this vertex attribute name.
  451. if (attriblocation < 0)
  452. continue;
  453. // Needed for unmap and glVertexAttribPointer.
  454. GLBuffer::Bind vbobind(*mesh->vbo);
  455. // Make sure the buffer isn't mapped (sends data to GPU if needed.)
  456. mesh->vbo->unmap(mesh->vboUsedOffset, mesh->vboUsedSize);
  457. mesh->vboUsedOffset = mesh->vboUsedSize = 0;
  458. size_t offset = mesh->getAttributeOffset(attrib.second.index);
  459. const void *gloffset = mesh->vbo->getPointer(offset);
  460. GLenum datatype = getGLDataType(format.type);
  461. GLboolean normalized = (datatype == GL_UNSIGNED_BYTE);
  462. glVertexAttribPointer(attriblocation, format.components, datatype, normalized, mesh->vertexStride, gloffset);
  463. enabledattribs |= 1 << uint32(attriblocation);
  464. }
  465. if (!(enabledattribs & ATTRIBFLAG_POS))
  466. {
  467. // Not supported on all platforms or GL versions at least, I believe.
  468. throw love::Exception("Mesh must have an enabled VertexPosition attribute to be drawn.");
  469. }
  470. gl.useVertexAttribArrays(enabledattribs);
  471. if (texture.get())
  472. gl.bindTexture(*(GLuint *) texture->getHandle());
  473. else
  474. gl.bindTexture(gl.getDefaultTexture());
  475. Matrix4 m(x, y, angle, sx, sy, ox, oy, kx, ky);
  476. OpenGL::TempTransform transform(gl);
  477. transform.get() *= m;
  478. gl.prepareDraw();
  479. if (ibo && elementCount > 0)
  480. {
  481. // Use the custom vertex map (index buffer) to draw the vertices.
  482. GLBuffer::Bind ibo_bind(*ibo);
  483. // Make sure the index buffer isn't mapped (sends data to GPU if needed.)
  484. ibo->unmap();
  485. int max = (int) elementCount - 1;
  486. if (rangeMax >= 0)
  487. max = std::min(rangeMax, max);
  488. int min = 0;
  489. if (rangeMin >= 0)
  490. min = std::min(rangeMin, max);
  491. GLenum type = elementDataType;
  492. const void *indices = ibo->getPointer(min * getGLDataTypeSize(type));
  493. gl.drawElements(getGLDrawMode(drawMode), max - min + 1, type, indices);
  494. }
  495. else
  496. {
  497. int max = (int) vertexCount - 1;
  498. if (rangeMax >= 0)
  499. max = std::min(rangeMax, max);
  500. int min = 0;
  501. if (rangeMin >= 0)
  502. min = std::min(rangeMin, max);
  503. // Normal non-indexed drawing (no custom vertex map.)
  504. gl.drawArrays(getGLDrawMode(drawMode), min, max - min + 1);
  505. }
  506. }
  507. size_t Mesh::getAttribFormatSize(const AttribFormat &format)
  508. {
  509. switch (format.type)
  510. {
  511. case DATA_BYTE:
  512. return format.components * sizeof(uint8);
  513. case DATA_FLOAT:
  514. return format.components * sizeof(float);
  515. default:
  516. return 0;
  517. }
  518. }
  519. GLenum Mesh::getGLDrawMode(DrawMode mode)
  520. {
  521. switch (mode)
  522. {
  523. case DRAWMODE_FAN:
  524. return GL_TRIANGLE_FAN;
  525. case DRAWMODE_STRIP:
  526. return GL_TRIANGLE_STRIP;
  527. case DRAWMODE_TRIANGLES:
  528. default:
  529. return GL_TRIANGLES;
  530. case DRAWMODE_POINTS:
  531. return GL_POINTS;
  532. }
  533. }
  534. GLenum Mesh::getGLDataType(DataType type)
  535. {
  536. switch (type)
  537. {
  538. case DATA_BYTE:
  539. return GL_UNSIGNED_BYTE;
  540. case DATA_FLOAT:
  541. return GL_FLOAT;
  542. default:
  543. return 0;
  544. }
  545. }
  546. GLenum Mesh::getGLDataTypeFromMax(size_t maxvalue)
  547. {
  548. if (maxvalue > LOVE_UINT16_MAX)
  549. return GL_UNSIGNED_INT;
  550. else
  551. return GL_UNSIGNED_SHORT;
  552. }
  553. size_t Mesh::getGLDataTypeSize(GLenum datatype)
  554. {
  555. switch (datatype)
  556. {
  557. case GL_UNSIGNED_BYTE:
  558. return sizeof(uint8);
  559. case GL_UNSIGNED_SHORT:
  560. return sizeof(uint16);
  561. case GL_UNSIGNED_INT:
  562. return sizeof(uint32);
  563. default:
  564. return 0;
  565. }
  566. }
  567. GLenum Mesh::getGLBufferUsage(Usage usage)
  568. {
  569. switch (usage)
  570. {
  571. case USAGE_STREAM:
  572. return GL_STREAM_DRAW;
  573. case USAGE_DYNAMIC:
  574. return GL_DYNAMIC_DRAW;
  575. case USAGE_STATIC:
  576. return GL_STATIC_DRAW;
  577. default:
  578. return 0;
  579. }
  580. }
  581. bool Mesh::getConstant(const char *in, Usage &out)
  582. {
  583. return usages.find(in, out);
  584. }
  585. bool Mesh::getConstant(Usage in, const char *&out)
  586. {
  587. return usages.find(in, out);
  588. }
  589. bool Mesh::getConstant(const char *in, Mesh::DrawMode &out)
  590. {
  591. return drawModes.find(in, out);
  592. }
  593. bool Mesh::getConstant(Mesh::DrawMode in, const char *&out)
  594. {
  595. return drawModes.find(in, out);
  596. }
  597. bool Mesh::getConstant(const char *in, DataType &out)
  598. {
  599. return dataTypes.find(in, out);
  600. }
  601. bool Mesh::getConstant(DataType in, const char *&out)
  602. {
  603. return dataTypes.find(in, out);
  604. }
  605. StringMap<Mesh::Usage, Mesh::USAGE_MAX_ENUM>::Entry Mesh::usageEntries[] =
  606. {
  607. {"stream", USAGE_STREAM},
  608. {"dynamic", USAGE_DYNAMIC},
  609. {"static", USAGE_STATIC},
  610. };
  611. StringMap<Mesh::Usage, Mesh::USAGE_MAX_ENUM> Mesh::usages(Mesh::usageEntries, sizeof(Mesh::usageEntries));
  612. StringMap<Mesh::DrawMode, Mesh::DRAWMODE_MAX_ENUM>::Entry Mesh::drawModeEntries[] =
  613. {
  614. {"fan", DRAWMODE_FAN},
  615. {"strip", DRAWMODE_STRIP},
  616. {"triangles", DRAWMODE_TRIANGLES},
  617. {"points", DRAWMODE_POINTS},
  618. };
  619. StringMap<Mesh::DrawMode, Mesh::DRAWMODE_MAX_ENUM> Mesh::drawModes(Mesh::drawModeEntries, sizeof(Mesh::drawModeEntries));
  620. StringMap<Mesh::DataType, Mesh::DATA_MAX_ENUM>::Entry Mesh::dataTypeEntries[] =
  621. {
  622. {"byte", DATA_BYTE},
  623. {"float", DATA_FLOAT},
  624. };
  625. StringMap<Mesh::DataType, Mesh::DATA_MAX_ENUM> Mesh::dataTypes(Mesh::dataTypeEntries, sizeof(Mesh::dataTypeEntries));
  626. } // opengl
  627. } // graphics
  628. } // love