123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- /**
- * Copyright (c) 2006-2011 LOVE Development Team
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- **/
- #include "SpriteBatch.h"
- // STD
- #include <iostream>
- // LOVE
- #include "Image.h"
- #include "Quad.h"
- namespace love
- {
- namespace graphics
- {
- namespace opengl
- {
- SpriteBatch::SpriteBatch(Image * image, int size, int usage)
- : image(image), size(size), next(0), usage(usage), lockp(0)
- {
- if (!(GLEE_ARB_vertex_buffer_object || GLEE_VERSION_1_5))
- throw love::Exception("Your OpenGL version does not support SpriteBatches. Go upgrade!");
- image->retain();
- vertices = new vertex[size*4];
- indices = new GLushort[size*6];
- for(int i = 0; i<size; i++)
- {
- indices[i*6+0] = 0+(i*4);
- indices[i*6+1] = 1+(i*4);
- indices[i*6+2] = 2+(i*4);
- indices[i*6+3] = 0+(i*4);
- indices[i*6+4] = 2+(i*4);
- indices[i*6+5] = 3+(i*4);
- }
- loadVolatile();
- }
- SpriteBatch::~SpriteBatch()
- {
- image->release();
- if(vbo[0] != 0 && vbo[1] != 0)
- glDeleteBuffers(2, vbo);
- delete [] vertices;
- delete [] indices;
- }
- bool SpriteBatch::loadVolatile()
- {
- // Find out which OpenGL VBO usage hint to use.
- gl_usage = GL_STREAM_DRAW_ARB;
- gl_usage = (usage == USAGE_DYNAMIC) ? GL_DYNAMIC_DRAW_ARB : gl_usage;
- gl_usage = (usage == USAGE_STATIC) ? GL_STATIC_DRAW_ARB : gl_usage;
- gl_usage = (usage == USAGE_STREAM) ? GL_STREAM_DRAW_ARB : gl_usage;
- glGenBuffersARB(2, vbo);
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo[0]);
- glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vertex)*size*4, vertices, gl_usage);
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vbo[1]);
- glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, sizeof(GLushort)*size*6, indices, GL_STATIC_DRAW_ARB);
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
- return true;
- }
- void SpriteBatch::unloadVolatile()
- {
- vertex * v = (vertex *)lock();
- // Copy to system memory.
- memcpy(vertices, v, sizeof(vertex)*size*4);
- unlock();
- // Delete the buffers.
- if(vbo[0] != 0 && vbo[1] != 0)
- glDeleteBuffersARB(2, vbo);
- }
- void SpriteBatch::add(float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky)
- {
- // Only do this if there's a free slot.
- if(next < size)
- {
- // Get a pointer to the correct insertion position.
- vertex * v = vertices + next*4;
- // Needed for texture coordinates.
- memcpy(v, image->getVertices(), sizeof(vertex)*4);
- // Transform.
- Matrix t;
- t.setTransformation(x, y, a, sx, sy, ox, oy, kx, ky);
- t.transform(v, v, 4);
- addv(v);
- // Increment counter.
- next++;
- }
- }
- void SpriteBatch::addq(Quad * quad, float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky)
- {
- // Only do this if there's a free slot.
- if(next < size)
- {
- // Get a pointer to the correct insertion position.
- vertex * v = vertices + next*4;
- // Needed for colors.
- memcpy(v, quad->getVertices(), sizeof(vertex)*4);
- // Transform.
- Matrix t;
- t.setTransformation(x, y, a, sx, sy, ox, oy, kx, ky);
- t.transform(v, v, 4);
- addv(v);
- // Increment counter.
- next++;
- }
- }
- void SpriteBatch::clear()
- {
- // Reset the position of the next index.
- next = 0;
- }
- void * SpriteBatch::lock()
- {
- // If already locked, prevent from locking again.
- if(lockp != 0)
- return lockp;
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo[0]);
- lockp = (vertex *)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_WRITE_ARB);
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
- return lockp;
- }
- void SpriteBatch::unlock()
- {
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo[0]);
- glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
- lockp = 0;
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
- }
- void SpriteBatch::setImage(Image * newimage)
- {
- image->release();
- image = newimage;
- image->retain();
- }
- void SpriteBatch::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const
- {
- static Matrix t;
- glPushMatrix();
- t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
- glMultMatrixf((const GLfloat*)t.getElements());
- image->bind();
- // Enable vertex arrays.
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- // Bind the VBO buffer.
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo[0]);
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vbo[1]);
- glVertexPointer(2, GL_FLOAT, sizeof(vertex), (GLvoid*)(sizeof(unsigned char)*4));
- glTexCoordPointer(2, GL_FLOAT, sizeof(vertex), (GLvoid*)(sizeof(unsigned char)*4+sizeof(float)*2));
-
- glDrawElements(GL_TRIANGLES, next*6, GL_UNSIGNED_SHORT, 0);
- // Disable vertex arrays.
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- glDisableClientState(GL_VERTEX_ARRAY);
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
- glPopMatrix();
- }
- void SpriteBatch::addv(const vertex * v)
- {
- if(lockp != 0)
- {
- // Copy into mapped memory if buffer is locked.
- memcpy(lockp + (next*4), v, sizeof(vertex)*4);
- }
- else
- {
- // ... use glBufferSubData otherwise.
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo[0]);
- glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, (next*4)*sizeof(vertex), sizeof(vertex)*4, v);
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
- }
- }
- } // opengl
- } // graphics
- } // love
|