SpriteBatch.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /**
  2. * Copyright (c) 2006-2010 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. #include "SpriteBatch.h"
  21. // STD
  22. #include <iostream>
  23. // LOVE
  24. #include "Image.h"
  25. #include "Quad.h"
  26. namespace love
  27. {
  28. namespace graphics
  29. {
  30. namespace opengl
  31. {
  32. SpriteBatch::SpriteBatch(Image * image, int size, int usage)
  33. : image(image), size(size), next(0), usage(usage), lockp(0)
  34. {
  35. image->retain();
  36. vertices = new vertex[size*4];
  37. indices = new GLushort[size*6];
  38. for(int i = 0; i<size; i++)
  39. {
  40. indices[i*6+0] = 0+(i*4);
  41. indices[i*6+1] = 1+(i*4);
  42. indices[i*6+2] = 2+(i*4);
  43. indices[i*6+3] = 0+(i*4);
  44. indices[i*6+4] = 2+(i*4);
  45. indices[i*6+5] = 3+(i*4);
  46. }
  47. loadVolatile();
  48. }
  49. SpriteBatch::~SpriteBatch()
  50. {
  51. image->release();
  52. if(vbo[0] != 0 && vbo[1] != 0)
  53. glDeleteBuffers(2, vbo);
  54. delete [] vertices;
  55. delete [] indices;
  56. }
  57. bool SpriteBatch::loadVolatile()
  58. {
  59. // Find out which OpenGL VBO usage hint to use.
  60. gl_usage = GL_STREAM_DRAW;
  61. gl_usage = (usage == USAGE_DYNAMIC) ? GL_DYNAMIC_DRAW : gl_usage;
  62. gl_usage = (usage == USAGE_STATIC) ? GL_STATIC_DRAW : gl_usage;
  63. gl_usage = (usage == USAGE_STREAM) ? GL_STREAM_DRAW : gl_usage;
  64. glGenBuffers(2, vbo);
  65. glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
  66. glBufferData(GL_ARRAY_BUFFER, sizeof(vertex)*size*4, vertices, gl_usage);
  67. glBindBuffer(GL_ARRAY_BUFFER, 0);
  68. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[1]);
  69. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort)*size*6, indices, GL_STATIC_DRAW);
  70. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  71. return true;
  72. }
  73. void SpriteBatch::unloadVolatile()
  74. {
  75. vertex * v = (vertex *)lock();
  76. // Copy to system memory.
  77. memcpy(vertices, v, sizeof(vertex)*size*4);
  78. unlock();
  79. // Delete the buffers.
  80. if(vbo[0] != 0 && vbo[1] != 0)
  81. glDeleteBuffers(2, vbo);
  82. }
  83. void SpriteBatch::add(float x, float y, float a, float sx, float sy, float ox, float oy)
  84. {
  85. // Only do this if there's a free slot.
  86. if(next < size)
  87. {
  88. // Get a pointer to the correct insertion position.
  89. vertex * v = vertices + next*4;
  90. // Needed for texture coordinates.
  91. memcpy(v, image->getVertices(), sizeof(vertex)*4);
  92. // Transform.
  93. Matrix t;
  94. t.setTransformation(x, y, a, sx, sy, ox, oy);
  95. t.transform(v, v, 4);
  96. addv(v);
  97. // Increment counter.
  98. next++;
  99. }
  100. }
  101. void SpriteBatch::addq(Quad * quad, float x, float y, float a, float sx, float sy, float ox, float oy)
  102. {
  103. // Only do this if there's a free slot.
  104. if(next < size)
  105. {
  106. // Get a pointer to the correct insertion position.
  107. vertex * v = vertices + next*4;
  108. // Needed for colors.
  109. memcpy(v, quad->getVertices(), sizeof(vertex)*4);
  110. // Transform.
  111. Matrix t;
  112. t.setTransformation(x, y, a, sx, sy, ox, oy);
  113. t.transform(v, v, 4);
  114. addv(v);
  115. // Increment counter.
  116. next++;
  117. }
  118. }
  119. void SpriteBatch::clear()
  120. {
  121. // Reset the position of the next index.
  122. next = 0;
  123. }
  124. void * SpriteBatch::lock()
  125. {
  126. // If already locked, prevent from locking again.
  127. if(lockp != 0)
  128. return lockp;
  129. glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
  130. lockp = (vertex *)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
  131. return lockp;
  132. }
  133. void SpriteBatch::unlock()
  134. {
  135. glUnmapBuffer(GL_ARRAY_BUFFER);
  136. lockp = 0;
  137. glBindBuffer(GL_ARRAY_BUFFER, 0);
  138. }
  139. void SpriteBatch::draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const
  140. {
  141. static Matrix t;
  142. glPushMatrix();
  143. t.setTransformation(x, y, angle, sx, sy, ox, oy);
  144. glMultMatrixf((const GLfloat*)t.getElements());
  145. image->bind();
  146. // Enable vertex arrays.
  147. glEnableClientState(GL_VERTEX_ARRAY);
  148. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  149. glEnableClientState(GL_COLOR_ARRAY);
  150. // Bind the VBO buffer.
  151. glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
  152. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[1]);
  153. glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(vertex), (GLvoid*)0);
  154. glVertexPointer(2, GL_FLOAT, sizeof(vertex), (GLvoid*)(sizeof(unsigned char)*4));
  155. glTexCoordPointer(2, GL_FLOAT, sizeof(vertex), (GLvoid*)(sizeof(unsigned char)*4+sizeof(float)*2));
  156. glDrawElements(GL_TRIANGLES, next*6, GL_UNSIGNED_SHORT, 0);
  157. // Disable vertex arrays.
  158. glDisableClientState(GL_COLOR_ARRAY);
  159. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  160. glDisableClientState(GL_VERTEX_ARRAY);
  161. glBindBuffer(GL_ARRAY_BUFFER, 0);
  162. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  163. glPopMatrix();
  164. }
  165. void SpriteBatch::addv(const vertex * v)
  166. {
  167. if(lockp != 0)
  168. {
  169. // Copy into mapped memory if buffer is locked.
  170. memcpy(lockp + (next*4), v, sizeof(vertex)*4);
  171. }
  172. else
  173. {
  174. // ... use glBufferSubData otherwise.
  175. glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
  176. glBufferSubData(GL_ARRAY_BUFFER, (next*4)*sizeof(vertex), sizeof(vertex)*4, v);
  177. glBindBuffer(GL_ARRAY_BUFFER, 0);
  178. }
  179. }
  180. } // opengl
  181. } // graphics
  182. } // love