Mesh.cpp 18 KB

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