mirror of
https://github.com/love2d/love.git
synced 2026-08-17 11:00:31 +02:00
Meshes now use vertex buffers for more efficient drawing.
--HG-- branch : Mesh
This commit is contained in:
@@ -31,64 +31,131 @@ namespace opengl
|
||||
{
|
||||
|
||||
Mesh::Mesh(const std::vector<Vertex> &verts, Mesh::DrawMode mode)
|
||||
: draw_mode(mode)
|
||||
: vbo(0)
|
||||
, vertex_count(0)
|
||||
, ibo(0)
|
||||
, element_count(0)
|
||||
, draw_mode(mode)
|
||||
, image(0)
|
||||
, colors_enabled(false)
|
||||
{
|
||||
setVertices(verts);
|
||||
}
|
||||
|
||||
Mesh::~Mesh()
|
||||
{
|
||||
delete vbo;
|
||||
delete ibo;
|
||||
}
|
||||
|
||||
void Mesh::setVertices(const std::vector<Vertex> &verts)
|
||||
{
|
||||
if (verts.size() < 3)
|
||||
throw love::Exception("At least 3 vertices are required.");
|
||||
|
||||
vertices = verts;
|
||||
size_t size = sizeof(Vertex) * verts.size();
|
||||
|
||||
if (vbo && size > vbo->getSize())
|
||||
{
|
||||
delete vbo;
|
||||
vbo = 0;
|
||||
}
|
||||
|
||||
if (!vbo)
|
||||
{
|
||||
// Full memory backing because we might access the data at any time.
|
||||
vbo = VertexBuffer::Create(size, GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW, VertexBuffer::BACKING_FULL);
|
||||
}
|
||||
|
||||
vertex_count = verts.size();
|
||||
|
||||
VertexBuffer::Bind vbo_bind(*vbo);
|
||||
VertexBuffer::Mapper vbo_mapper(*vbo);
|
||||
|
||||
// Fill the buffer with the vertices.
|
||||
memcpy(vbo_mapper.get(), &verts[0], size);
|
||||
}
|
||||
|
||||
const std::vector<Vertex> &Mesh::getVertices() const
|
||||
void Mesh::setVertex(size_t index, const Vertex &v)
|
||||
{
|
||||
return vertices;
|
||||
if (index >= vertex_count)
|
||||
throw love::Exception("Invalid vertex index: %ld", index);
|
||||
|
||||
VertexBuffer::Bind vbo_bind(*vbo);
|
||||
|
||||
// We unmap the vertex buffer in Mesh::draw. This lets us coalesce the
|
||||
// buffer transfer calls.
|
||||
Vertex *vertices = (Vertex *) vbo->map();
|
||||
vertices[index] = v;
|
||||
}
|
||||
|
||||
void Mesh::setVertex(size_t i, Vertex v)
|
||||
Vertex Mesh::getVertex(size_t index) const
|
||||
{
|
||||
if (i >= vertices.size())
|
||||
throw love::Exception("Invalid index.");
|
||||
if (index >= vertex_count)
|
||||
throw love::Exception("Invalid vertex index: %ld", index);
|
||||
|
||||
vertices[i] = v;
|
||||
}
|
||||
VertexBuffer::Bind vbo_bind(*vbo);
|
||||
|
||||
Vertex Mesh::getVertex(size_t i) const
|
||||
{
|
||||
if (i >= vertices.size())
|
||||
throw love::Exception("Invalid index.");
|
||||
|
||||
return vertices[i];
|
||||
// We unmap the vertex buffer in Mesh::draw.
|
||||
Vertex *vertices = (Vertex *) vbo->map();
|
||||
return vertices[index];
|
||||
}
|
||||
|
||||
size_t Mesh::getVertexCount() const
|
||||
{
|
||||
return vertices.size();
|
||||
return vertex_count;
|
||||
}
|
||||
|
||||
void Mesh::setVertexMap(const std::vector<uint16> &map)
|
||||
{
|
||||
for (size_t i = 0; i < map.size(); i++)
|
||||
{
|
||||
if (map[i] >= vertices.size())
|
||||
if (map[i] >= vertex_count)
|
||||
throw love::Exception("Invalid vertex map value: %d", map[i]);
|
||||
}
|
||||
|
||||
vertex_map = map;
|
||||
size_t size = sizeof(uint16) * map.size();
|
||||
|
||||
if (ibo && size > ibo->getSize())
|
||||
{
|
||||
delete ibo;
|
||||
ibo = 0;
|
||||
}
|
||||
|
||||
if (!ibo)
|
||||
{
|
||||
// Full memory backing because we might access the data at any time.
|
||||
ibo = VertexBuffer::Create(size, GL_ELEMENT_ARRAY_BUFFER, GL_DYNAMIC_DRAW, VertexBuffer::BACKING_FULL);
|
||||
}
|
||||
|
||||
element_count = map.size();
|
||||
|
||||
if (element_count > 0)
|
||||
{
|
||||
VertexBuffer::Bind ibo_bind(*ibo);
|
||||
VertexBuffer::Mapper ibo_map(*ibo);
|
||||
|
||||
// Fill the buffer.
|
||||
memcpy(ibo_map.get(), &map[0], size);
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<uint16> &Mesh::getVertexMap() const
|
||||
const uint16 *Mesh::getVertexMap() const
|
||||
{
|
||||
return vertex_map;
|
||||
if (ibo && element_count > 0)
|
||||
{
|
||||
VertexBuffer::Bind ibo_bind(*ibo);
|
||||
|
||||
// We unmap the buffer in Mesh::draw and Mesh::setVertexMap.
|
||||
return (uint16 *) ibo->map();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Mesh::~Mesh()
|
||||
size_t Mesh::getVertexMapCount() const
|
||||
{
|
||||
return element_count;
|
||||
}
|
||||
|
||||
void Mesh::setImage(Image *img)
|
||||
@@ -124,9 +191,23 @@ Mesh::DrawMode Mesh::getDrawMode() const
|
||||
return draw_mode;
|
||||
}
|
||||
|
||||
void Mesh::setVertexColors(bool enable)
|
||||
{
|
||||
colors_enabled = enable;
|
||||
}
|
||||
|
||||
bool Mesh::hasVertexColors() const
|
||||
{
|
||||
return colors_enabled;
|
||||
}
|
||||
|
||||
void Mesh::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const
|
||||
{
|
||||
if (vertices.size() == 0)
|
||||
const size_t pos_offset = offsetof(Vertex, x);
|
||||
const size_t tex_offset = offsetof(Vertex, s);
|
||||
const size_t color_offset = offsetof(Vertex, r);
|
||||
|
||||
if (vertex_count == 0)
|
||||
return;
|
||||
|
||||
if (image)
|
||||
@@ -140,29 +221,49 @@ void Mesh::draw(float x, float y, float angle, float sx, float sy, float ox, flo
|
||||
glPushMatrix();
|
||||
glMultMatrixf(m.getElements());
|
||||
|
||||
VertexBuffer::Bind vbo_bind(*vbo);
|
||||
|
||||
// Make sure the VBO isn't mapped when we draw (sends data to GPU if needed.)
|
||||
vbo->unmap();
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vertex), &(vertices[0].x));
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &(vertices[0].s));
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vertex), vbo->getPointer(pos_offset));
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), vbo->getPointer(tex_offset));
|
||||
|
||||
if (hasVertexColors())
|
||||
{
|
||||
// Per-vertex colors.
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &(vertices[0].r));
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), vbo->getPointer(color_offset));
|
||||
}
|
||||
|
||||
GLenum gl_draw_mode = getGLDrawMode(draw_mode);
|
||||
GLenum mode = getGLDrawMode(draw_mode);
|
||||
|
||||
if (vertex_map.size() > 0)
|
||||
glDrawElements(gl_draw_mode, vertex_map.size(), GL_UNSIGNED_SHORT, &vertex_map[0]);
|
||||
if (element_count > 0)
|
||||
{
|
||||
VertexBuffer::Bind ibo_bind(*ibo);
|
||||
|
||||
// Make sure the index buffer isn't mapped (sends data to GPU if needed.)
|
||||
ibo->unmap();
|
||||
|
||||
// Use the custom vertex map to draw the vertices.
|
||||
glDrawElements(mode, element_count, GL_UNSIGNED_SHORT, ibo->getPointer(0));
|
||||
}
|
||||
else
|
||||
glDrawArrays(gl_draw_mode, 0, vertices.size());
|
||||
{
|
||||
// Normal non-indexed drawing (no custom vertex map.)
|
||||
glDrawArrays(mode, 0, vertex_count);
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
if (hasVertexColors())
|
||||
{
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
// Using the color array leaves the GL constant color undefined.
|
||||
gl.setColor(gl.getColor());
|
||||
}
|
||||
|
||||
|
||||
@@ -25,9 +25,9 @@
|
||||
#include "common/int.h"
|
||||
#include "common/math.h"
|
||||
#include "common/StringMap.h"
|
||||
#include "graphics/Volatile.h"
|
||||
#include "graphics/Drawable.h"
|
||||
#include "graphics/opengl/Image.h"
|
||||
#include "Image.h"
|
||||
#include "VertexBuffer.h"
|
||||
|
||||
// C++
|
||||
#include <vector>
|
||||
@@ -41,7 +41,7 @@ namespace opengl
|
||||
|
||||
/**
|
||||
* Holds and draws arbitrary vertex geometry.
|
||||
* Each vertex in a Mesh has a position, texture coordinate, and color.
|
||||
* Each vertex in the Mesh has a position, texture coordinate, and color.
|
||||
**/
|
||||
class Mesh : public Drawable
|
||||
{
|
||||
@@ -71,18 +71,13 @@ public:
|
||||
**/
|
||||
void setVertices(const std::vector<Vertex> &verts);
|
||||
|
||||
/**
|
||||
* Gets a reference to the vertices used in the Mesh.
|
||||
**/
|
||||
const std::vector<Vertex> &getVertices() const;
|
||||
|
||||
/**
|
||||
* Sets an individual vertex in the Mesh.
|
||||
* @param i The index into the list of vertices to use.
|
||||
* @param index The index into the list of vertices to use.
|
||||
* @param v The new vertex.
|
||||
**/
|
||||
void setVertex(size_t i, Vertex v);
|
||||
Vertex getVertex(size_t i) const;
|
||||
void setVertex(size_t index, const Vertex &v);
|
||||
Vertex getVertex(size_t index) const;
|
||||
|
||||
/**
|
||||
* Gets the total number of vertices in the Mesh.
|
||||
@@ -96,7 +91,18 @@ public:
|
||||
* {0, 1, 2, 3, 4, ...}
|
||||
**/
|
||||
void setVertexMap(const std::vector<uint16> &map);
|
||||
const std::vector<uint16> &getVertexMap() const;
|
||||
|
||||
/**
|
||||
* Gets a pointer to the vertex map array. The pointer is only valid until
|
||||
* the next function call in the graphics module.
|
||||
* May return null if the vertex map is empty.
|
||||
**/
|
||||
const uint16 *getVertexMap() const;
|
||||
|
||||
/**
|
||||
* Gets the total number of elements in the vertex map array.
|
||||
**/
|
||||
size_t getVertexMapCount() const;
|
||||
|
||||
/**
|
||||
* Sets the Image used when drawing the Mesh.
|
||||
@@ -120,6 +126,13 @@ public:
|
||||
void setDrawMode(DrawMode mode);
|
||||
DrawMode getDrawMode() const;
|
||||
|
||||
/**
|
||||
* Sets whether per-vertex colors are enabled. If this is disabled, the
|
||||
* global color (love.graphics.setColor) will be used for the entire Mesh.
|
||||
**/
|
||||
void setVertexColors(bool enable);
|
||||
bool hasVertexColors() const;
|
||||
|
||||
// Implements Drawable.
|
||||
void draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const;
|
||||
|
||||
@@ -130,13 +143,21 @@ private:
|
||||
|
||||
GLenum getGLDrawMode(DrawMode mode) const;
|
||||
|
||||
std::vector<Vertex> vertices;
|
||||
std::vector<uint16> vertex_map;
|
||||
// Vertex buffer.
|
||||
VertexBuffer *vbo;
|
||||
size_t vertex_count;
|
||||
|
||||
// Element (vertex index) buffer, for the vertex map.
|
||||
VertexBuffer *ibo;
|
||||
size_t element_count;
|
||||
|
||||
DrawMode draw_mode;
|
||||
|
||||
Image *image;
|
||||
|
||||
// Whether the per-vertex colors are used when drawing.
|
||||
bool colors_enabled;
|
||||
|
||||
static StringMap<DrawMode, DRAW_MODE_MAX_ENUM>::Entry drawModeEntries[];
|
||||
static StringMap<DrawMode, DRAW_MODE_MAX_ENUM> drawModes;
|
||||
|
||||
|
||||
@@ -42,25 +42,27 @@ namespace opengl
|
||||
|
||||
// VertexBuffer
|
||||
|
||||
VertexBuffer *VertexBuffer::Create(size_t size, GLenum target, GLenum usage)
|
||||
VertexBuffer *VertexBuffer::Create(size_t size, GLenum target, GLenum usage, MemoryBacking backing)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Try to create a VBO.
|
||||
return new VBO(size, target, usage);
|
||||
return new VBO(size, target, usage, backing);
|
||||
}
|
||||
catch(const love::Exception &)
|
||||
{
|
||||
// VBO not supported ... create regular array.
|
||||
return new VertexArray(size, target, usage);
|
||||
return new VertexArray(size, target, usage, backing);
|
||||
}
|
||||
}
|
||||
|
||||
VertexBuffer::VertexBuffer(size_t size, GLenum target, GLenum usage)
|
||||
VertexBuffer::VertexBuffer(size_t size, GLenum target, GLenum usage, MemoryBacking backing)
|
||||
: is_bound(false)
|
||||
, is_mapped(false)
|
||||
, size(size)
|
||||
, target(target)
|
||||
, usage(usage)
|
||||
, backing(backing)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -70,8 +72,8 @@ VertexBuffer::~VertexBuffer()
|
||||
|
||||
// VertexArray
|
||||
|
||||
VertexArray::VertexArray(size_t size, GLenum target, GLenum usage)
|
||||
: VertexBuffer(size, target, usage)
|
||||
VertexArray::VertexArray(size_t size, GLenum target, GLenum usage, MemoryBacking backing)
|
||||
: VertexBuffer(size, target, usage, backing)
|
||||
, buf(new char[size])
|
||||
{
|
||||
}
|
||||
@@ -83,11 +85,13 @@ VertexArray::~VertexArray()
|
||||
|
||||
void *VertexArray::map()
|
||||
{
|
||||
is_mapped = true;
|
||||
return buf;
|
||||
}
|
||||
|
||||
void VertexArray::unmap()
|
||||
{
|
||||
is_mapped = false;
|
||||
}
|
||||
|
||||
void VertexArray::bind()
|
||||
@@ -112,20 +116,25 @@ const void *VertexArray::getPointer(size_t offset) const
|
||||
|
||||
// VBO
|
||||
|
||||
VBO::VBO(size_t size, GLenum target, GLenum usage)
|
||||
: VertexBuffer(size, target, usage)
|
||||
VBO::VBO(size_t size, GLenum target, GLenum usage, MemoryBacking backing)
|
||||
: VertexBuffer(size, target, usage, backing)
|
||||
, vbo(0)
|
||||
, memory_map(0)
|
||||
, is_mapped(false)
|
||||
, is_dirty(true)
|
||||
{
|
||||
if (!(GLEE_ARB_vertex_buffer_object || GLEE_VERSION_1_5))
|
||||
throw love::Exception("Not supported");
|
||||
|
||||
if (getMemoryBacking() == BACKING_FULL)
|
||||
memory_map = malloc(getSize());
|
||||
|
||||
bool ok = load(false);
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
free(memory_map);
|
||||
throw love::Exception("Could not load VBO.");
|
||||
}
|
||||
}
|
||||
|
||||
VBO::~VBO()
|
||||
@@ -150,10 +159,12 @@ void *VBO::map()
|
||||
}
|
||||
|
||||
if (is_dirty)
|
||||
{
|
||||
glGetBufferSubDataARB(getTarget(), 0, getSize(), memory_map);
|
||||
is_dirty = false;
|
||||
}
|
||||
|
||||
is_mapped = true;
|
||||
is_dirty = false;
|
||||
|
||||
return memory_map;
|
||||
}
|
||||
@@ -198,11 +209,10 @@ void VBO::unbind()
|
||||
|
||||
void VBO::fill(size_t offset, size_t size, const void *data)
|
||||
{
|
||||
if (is_mapped)
|
||||
{
|
||||
if (is_mapped || getMemoryBacking() == BACKING_FULL)
|
||||
memcpy(static_cast<char *>(memory_map) + offset, data, size);
|
||||
}
|
||||
else
|
||||
|
||||
if (!is_mapped)
|
||||
{
|
||||
// Not all systems have access to some faster paths...
|
||||
if (GLEE_APPLE_flush_buffer_range)
|
||||
@@ -226,7 +236,8 @@ void VBO::fill(size_t offset, size_t size, const void *data)
|
||||
glBufferSubDataARB(getTarget(), offset, size, data);
|
||||
}
|
||||
|
||||
is_dirty = true;
|
||||
if (getMemoryBacking() != BACKING_FULL)
|
||||
is_dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,23 +268,23 @@ bool VBO::load(bool restore)
|
||||
while (GL_NO_ERROR != glGetError())
|
||||
/* clear error messages */;
|
||||
|
||||
// Note that if 'src' is '0', no data will be copied.
|
||||
glBufferDataARB(getTarget(), getSize(), src, getUsage());
|
||||
GLenum err = glGetError();
|
||||
|
||||
// We don't want to flush the entire buffer when we just modify a small
|
||||
// portion of it (VBO::fill without VBO::map), so we'll handle the flushing
|
||||
// ourselves when we can.
|
||||
if (GLEE_APPLE_flush_buffer_range)
|
||||
glBufferParameteriAPPLE(getTarget(), GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE);
|
||||
|
||||
// Note that if 'src' is '0', no data will be copied.
|
||||
glBufferDataARB(getTarget(), getSize(), src, getUsage());
|
||||
GLenum err = glGetError();
|
||||
|
||||
return (GL_NO_ERROR == err);
|
||||
}
|
||||
|
||||
void VBO::unload(bool save)
|
||||
{
|
||||
// Save data before unloading.
|
||||
if (save)
|
||||
// Save data before unloading, if we need to.
|
||||
if (save && getMemoryBacking() == BACKING_PARTIAL)
|
||||
{
|
||||
VertexBuffer::Bind bind(*this);
|
||||
|
||||
|
||||
@@ -48,6 +48,18 @@ class VertexBuffer
|
||||
{
|
||||
public:
|
||||
|
||||
// Different guarantees for VertexBuffer data storage.
|
||||
enum MemoryBacking
|
||||
{
|
||||
// The VertexBuffer is will have a valid copy of its data in main memory
|
||||
// at all times.
|
||||
BACKING_FULL,
|
||||
|
||||
// The VertexBuffer will have a valid copy of its data in main memory
|
||||
// when it needs to be reloaded and when it's mapped.
|
||||
BACKING_PARTIAL
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new VertexBuffer (either a plain vertex array, or a VBO),
|
||||
* based on what's supported on the system.
|
||||
@@ -58,9 +70,10 @@ public:
|
||||
* @param size The size of the VertexBuffer (in bytes).
|
||||
* @param target GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER.
|
||||
* @param usage GL_DYNAMIC_DRAW, etc.
|
||||
* @param backing Determines what guarantees are placed on the data.
|
||||
* @return A new VertexBuffer.
|
||||
*/
|
||||
static VertexBuffer *Create(size_t size, GLenum target, GLenum usage);
|
||||
static VertexBuffer *Create(size_t size, GLenum target, GLenum usage, MemoryBacking backing = BACKING_PARTIAL);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -68,8 +81,9 @@ public:
|
||||
* @param size The size of the VertexBuffer in bytes.
|
||||
* @param target The target VertexBuffer object, e.g. GL_ARRAY_BUFFER.
|
||||
* @param usage Usage hint, e.g. GL_DYNAMIC_DRAW.
|
||||
* @param backing Determines what guarantees are placed on the data.
|
||||
*/
|
||||
VertexBuffer(size_t size, GLenum target, GLenum usage);
|
||||
VertexBuffer(size_t size, GLenum target, GLenum usage, MemoryBacking backing = BACKING_PARTIAL);
|
||||
|
||||
/**
|
||||
* Destructor. Does nothing, but must be declared virtual.
|
||||
@@ -111,6 +125,16 @@ public:
|
||||
return is_bound;
|
||||
}
|
||||
|
||||
bool isMapped() const
|
||||
{
|
||||
return is_mapped;
|
||||
}
|
||||
|
||||
MemoryBacking getMemoryBacking() const
|
||||
{
|
||||
return backing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the VertexBuffer to client memory.
|
||||
*
|
||||
@@ -230,6 +254,9 @@ protected:
|
||||
// Whether the buffer is currently bound.
|
||||
bool is_bound;
|
||||
|
||||
// Whether the buffer is currently mapped to main memory.
|
||||
bool is_mapped;
|
||||
|
||||
private:
|
||||
|
||||
// The size of the buffer, in bytes.
|
||||
@@ -240,6 +267,9 @@ private:
|
||||
|
||||
// Usage hint. GL_[DYNAMIC, STATIC, STREAM]_DRAW.
|
||||
GLenum usage;
|
||||
|
||||
//
|
||||
MemoryBacking backing;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -253,9 +283,9 @@ class VertexArray : public VertexBuffer
|
||||
public:
|
||||
|
||||
/**
|
||||
* @copydoc VertexBuffer(int, GLenum, GLenum)
|
||||
* @copydoc VertexBuffer(int, GLenum, GLenum, Backing)
|
||||
*/
|
||||
VertexArray(size_t size, GLenum target, GLenum usage);
|
||||
VertexArray(size_t size, GLenum target, GLenum usage, MemoryBacking backing);
|
||||
|
||||
/**
|
||||
* Frees the data we've allocated.
|
||||
@@ -281,19 +311,19 @@ private:
|
||||
* This will be used on all systems that support it. It's in general
|
||||
* faster than vertex arrays, but especially in use-cases where there
|
||||
* is no need to update the data every frame.
|
||||
*/
|
||||
**/
|
||||
class VBO : public VertexBuffer, public Volatile
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @copydoc VertexBuffer(size_t, GLenum, GLenum)
|
||||
*/
|
||||
VBO(size_t size, GLenum target, GLenum usage);
|
||||
* @copydoc VertexBuffer(size_t, GLenum, GLenum, Backing)
|
||||
**/
|
||||
VBO(size_t size, GLenum target, GLenum usage, MemoryBacking backing);
|
||||
|
||||
/**
|
||||
* Deletes the VBOs from OpenGL.
|
||||
*/
|
||||
**/
|
||||
virtual ~VBO();
|
||||
|
||||
// Implements VertexBuffer.
|
||||
@@ -332,10 +362,6 @@ private:
|
||||
// call to map().
|
||||
void *memory_map;
|
||||
|
||||
// Set if the vbo currently operates on main instead of gpu
|
||||
// memory.
|
||||
bool is_mapped;
|
||||
|
||||
// Set if the buffer was modified while operating on gpu memory
|
||||
// and needs to be synchronized.
|
||||
bool is_dirty;
|
||||
|
||||
@@ -453,6 +453,8 @@ int w_newMesh(lua_State *L)
|
||||
std::vector<Vertex> vertices;
|
||||
vertices.reserve(vertex_count);
|
||||
|
||||
bool use_colors = false;
|
||||
|
||||
// Get the vertices from the table.
|
||||
for (size_t i = 1; i <= vertex_count; i++)
|
||||
{
|
||||
@@ -477,6 +479,10 @@ int w_newMesh(lua_State *L)
|
||||
v.b = (unsigned char) luaL_optinteger(L, -2, 255);
|
||||
v.a = (unsigned char) luaL_optinteger(L, -1, 255);
|
||||
|
||||
// Enable per-vertex coloring if any color is not the default.
|
||||
if (!use_colors && (v.r != 255 || v.g != 255 || v.b != 255 || v.a != 255))
|
||||
use_colors = true;
|
||||
|
||||
lua_pop(L, 9);
|
||||
vertices.push_back(v);
|
||||
}
|
||||
@@ -487,6 +493,8 @@ int w_newMesh(lua_State *L)
|
||||
if (img)
|
||||
t->setImage(img);
|
||||
|
||||
t->setVertexColors(use_colors);
|
||||
|
||||
luax_pushtype(L, "Mesh", GRAPHICS_MESH_T, t);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -93,48 +93,6 @@ int w_Mesh_getVertex(lua_State *L)
|
||||
return 8;
|
||||
}
|
||||
|
||||
int w_Mesh_getVertices(lua_State *L)
|
||||
{
|
||||
Mesh *t = luax_checkmesh(L, 1);
|
||||
const std::vector<Vertex> &vertices = t->getVertices();
|
||||
|
||||
lua_createtable(L, vertices.size(), 0);
|
||||
|
||||
for (size_t i = 0; i < vertices.size(); i++)
|
||||
{
|
||||
lua_createtable(L, 8, 0);
|
||||
const Vertex &v = vertices[i];
|
||||
|
||||
lua_pushnumber(L, v.x);
|
||||
lua_rawseti(L, -2, 1);
|
||||
|
||||
lua_pushnumber(L, v.y);
|
||||
lua_rawseti(L, -2, 2);
|
||||
|
||||
lua_pushnumber(L, v.s);
|
||||
lua_rawseti(L, -2, 3);
|
||||
|
||||
lua_pushnumber(L, v.t);
|
||||
lua_rawseti(L, -2, 4);
|
||||
|
||||
lua_pushnumber(L, v.r);
|
||||
lua_rawseti(L, -2, 5);
|
||||
|
||||
lua_pushnumber(L, v.g);
|
||||
lua_rawseti(L, -2, 6);
|
||||
|
||||
lua_pushnumber(L, v.b);
|
||||
lua_rawseti(L, -2, 7);
|
||||
|
||||
lua_pushnumber(L, v.a);
|
||||
lua_rawseti(L, -2, 8);
|
||||
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Mesh_getVertexCount(lua_State *L)
|
||||
{
|
||||
Mesh *t = luax_checkmesh(L, 1);
|
||||
@@ -172,12 +130,14 @@ int w_Mesh_getVertexMap(lua_State *L)
|
||||
{
|
||||
Mesh *t = luax_checkmesh(L, 1);
|
||||
|
||||
const std::vector<uint16> &map = t->getVertexMap();
|
||||
lua_createtable(L, map.size(), 0);
|
||||
const uint16 *vertex_map = t->getVertexMap();
|
||||
size_t elements = t->getVertexMapCount();
|
||||
|
||||
for (size_t i = 0; i < map.size(); i++)
|
||||
lua_createtable(L, elements, 0);
|
||||
|
||||
for (size_t i = 0; i < elements; i++)
|
||||
{
|
||||
lua_pushinteger(L, map[i] + 1);
|
||||
lua_pushinteger(L, lua_Integer(vertex_map[i]) + 1);
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
}
|
||||
|
||||
@@ -238,11 +198,24 @@ int w_Mesh_getDrawMode(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Mesh_setVertexColors(lua_State *L)
|
||||
{
|
||||
Mesh *t = luax_checkmesh(L, 1);
|
||||
t->setVertexColors(luax_toboolean(L, 2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_Mesh_hasVertexColors(lua_State *L)
|
||||
{
|
||||
Mesh *t = luax_checkmesh(L, 1);
|
||||
luax_pushboolean(L, t->hasVertexColors());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg functions[] =
|
||||
{
|
||||
{ "setVertex", w_Mesh_setVertex },
|
||||
{ "getVertex", w_Mesh_getVertex },
|
||||
{ "getVertices", w_Mesh_getVertices },
|
||||
{ "getVertexCount", w_Mesh_getVertexCount },
|
||||
{ "setVertexMap", w_Mesh_setVertexMap },
|
||||
{ "getVertexMap", w_Mesh_getVertexMap },
|
||||
@@ -250,6 +223,8 @@ static const luaL_Reg functions[] =
|
||||
{ "getImage", w_Mesh_getImage },
|
||||
{ "setDrawMode", w_Mesh_setDrawMode },
|
||||
{ "getDrawMode", w_Mesh_getDrawMode },
|
||||
{ "setVertexColors", w_Mesh_setVertexColors },
|
||||
{ "hasVertexColors", w_Mesh_hasVertexColors },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
@@ -36,7 +36,6 @@ Mesh *luax_checkmesh(lua_State *L, int idx);
|
||||
|
||||
int w_Mesh_setVertex(lua_State *L);
|
||||
int w_Mesh_getVertex(lua_State *L);
|
||||
int w_Mesh_getVertices(lua_State *L);
|
||||
int w_Mesh_getVertexCount(lua_State *L);
|
||||
int w_Mesh_setVertexMap(lua_State *L);
|
||||
int w_Mesh_getVertexMap(lua_State *L);
|
||||
@@ -44,6 +43,8 @@ int w_Mesh_setImage(lua_State *L);
|
||||
int w_Mesh_getImage(lua_State *L);
|
||||
int w_Mesh_setDrawMode(lua_State *L);
|
||||
int w_Mesh_getDrawMode(lua_State *L);
|
||||
int w_Mesh_setVertexColors(lua_State *L);
|
||||
int w_Mesh_hasVertexColors(lua_State *L);
|
||||
|
||||
extern "C" int luaopen_mesh(lua_State *L);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user