Mesh.cpp 19 KB

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