mirror of
https://github.com/love2d/love.git
synced 2026-08-16 16:20:42 +02:00
Added Mesh:setDrawRange(min, max) and Mesh:getDrawRange().
If no vertex map is set, this restricts the drawn vertices to those whose indices in the vertex array are between [min, max] inclusive. If a vertex map is set, this restricts the values used in the vertex map to those whose indices in the vertex map array are between [min, max] inclusive. Added Mesh constructor variant: love.graphics.newMesh(vertexcount, texture, drawmode). Creates a Mesh with a certain number of vertices with x,y,u,v,r,g,b,a values of (0,0,0,0,255,255,255,255).
This commit is contained in:
@@ -460,6 +460,11 @@ Mesh *Graphics::newMesh(const std::vector<Vertex> &vertices, Mesh::DrawMode mode
|
||||
return new Mesh(vertices, mode);
|
||||
}
|
||||
|
||||
Mesh *Graphics::newMesh(int vertexcount, Mesh::DrawMode mode)
|
||||
{
|
||||
return new Mesh(vertexcount, mode);
|
||||
}
|
||||
|
||||
void Graphics::setColor(const Color &c)
|
||||
{
|
||||
gl.setColor(c);
|
||||
|
||||
@@ -213,6 +213,7 @@ public:
|
||||
Shader *newShader(const Shader::ShaderSources &sources);
|
||||
|
||||
Mesh *newMesh(const std::vector<Vertex> &vertices, Mesh::DrawMode mode = Mesh::DRAW_MODE_FAN);
|
||||
Mesh *newMesh(int vertexcount, Mesh::DrawMode mode = Mesh::DRAW_MODE_FAN);
|
||||
|
||||
/**
|
||||
* Sets the foreground color.
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
#include "common/Matrix.h"
|
||||
#include "common/Exception.h"
|
||||
|
||||
// C++
|
||||
#include <algorithm>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace graphics
|
||||
@@ -37,6 +40,8 @@ Mesh::Mesh(const std::vector<Vertex> &verts, Mesh::DrawMode mode)
|
||||
, element_count(0)
|
||||
, instance_count(1)
|
||||
, draw_mode(mode)
|
||||
, range_min(-1)
|
||||
, range_max(-1)
|
||||
, texture(nullptr)
|
||||
, colors_enabled(false)
|
||||
, wireframe(false)
|
||||
@@ -44,6 +49,35 @@ Mesh::Mesh(const std::vector<Vertex> &verts, Mesh::DrawMode mode)
|
||||
setVertices(verts);
|
||||
}
|
||||
|
||||
Mesh::Mesh(int vertexcount, Mesh::DrawMode mode)
|
||||
: vbo(nullptr)
|
||||
, vertex_count(0)
|
||||
, ibo(nullptr)
|
||||
, element_count(0)
|
||||
, draw_mode(mode)
|
||||
, range_min(-1)
|
||||
, range_max(-1)
|
||||
, texture(nullptr)
|
||||
, colors_enabled(false)
|
||||
, wireframe(false)
|
||||
{
|
||||
if (vertexcount < 1)
|
||||
throw love::Exception("Invalid number of vertices.");
|
||||
|
||||
std::vector<Vertex> verts(vertexcount);
|
||||
|
||||
// Default-initialized vertices should have a white opaque color.
|
||||
for (size_t i = 0; i < verts.size(); i++)
|
||||
{
|
||||
verts[i].r = 255;
|
||||
verts[i].g = 255;
|
||||
verts[i].b = 255;
|
||||
verts[i].a = 255;
|
||||
}
|
||||
|
||||
setVertices(verts);
|
||||
}
|
||||
|
||||
Mesh::~Mesh()
|
||||
{
|
||||
delete vbo;
|
||||
@@ -163,7 +197,7 @@ const uint32 *Mesh::getVertexMap() const
|
||||
return (uint32 *) ibo->map();
|
||||
}
|
||||
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t Mesh::getVertexMapCount() const
|
||||
@@ -173,10 +207,7 @@ size_t Mesh::getVertexMapCount() const
|
||||
|
||||
void Mesh::setInstanceCount(int count)
|
||||
{
|
||||
if (count < 1)
|
||||
count = 1;
|
||||
|
||||
instance_count = count;
|
||||
instance_count = std::max(count, 1);
|
||||
}
|
||||
|
||||
int Mesh::getInstanceCount() const
|
||||
@@ -217,6 +248,26 @@ Mesh::DrawMode Mesh::getDrawMode() const
|
||||
return draw_mode;
|
||||
}
|
||||
|
||||
void Mesh::setDrawRange(int min, int max)
|
||||
{
|
||||
if (min < 0 || max < 0 || min > max)
|
||||
throw love::Exception("Invalid draw range.");
|
||||
|
||||
range_min = min;
|
||||
range_max = max;
|
||||
}
|
||||
|
||||
void Mesh::setDrawRange()
|
||||
{
|
||||
range_min = range_max = -1;
|
||||
}
|
||||
|
||||
void Mesh::getDrawRange(int &min, int &max) const
|
||||
{
|
||||
min = range_min;
|
||||
max = range_max;
|
||||
}
|
||||
|
||||
void Mesh::setVertexColors(bool enable)
|
||||
{
|
||||
colors_enabled = enable;
|
||||
@@ -290,21 +341,37 @@ void Mesh::draw(float x, float y, float angle, float sx, float sy, float ox, flo
|
||||
// Make sure the index buffer isn't mapped (sends data to GPU if needed.)
|
||||
ibo->unmap();
|
||||
|
||||
const void *indices = ibo->getPointer(0);
|
||||
const GLenum type = GL_UNSIGNED_INT;
|
||||
int max = element_count - 1;
|
||||
if (range_max >= 0)
|
||||
max = std::min(std::max(range_max, 0), (int) element_count - 1);
|
||||
|
||||
int min = 0;
|
||||
if (range_min >= 0)
|
||||
min = std::min(std::max(range_min, 0), max);
|
||||
|
||||
const void *indices = ibo->getPointer(min * sizeof(uint32));
|
||||
GLenum type = GL_UNSIGNED_INT;
|
||||
|
||||
if (instance_count > 1)
|
||||
gl.drawElementsInstanced(mode, element_count, type, indices, instance_count);
|
||||
gl.drawElementsInstanced(mode, max - min + 1, type, indices, instance_count);
|
||||
else
|
||||
glDrawElements(mode, element_count, type, indices);
|
||||
glDrawElements(mode, max - min + 1, type, indices);
|
||||
}
|
||||
else
|
||||
{
|
||||
int max = vertex_count - 1;
|
||||
if (range_max >= 0)
|
||||
max = std::min(std::max(range_max, 0), (int) vertex_count - 1);
|
||||
|
||||
int min = 0;
|
||||
if (range_min >= 0)
|
||||
min = std::min(std::max(range_min, 0), max);
|
||||
|
||||
// Normal non-indexed drawing (no custom vertex map.)
|
||||
if (instance_count > 1)
|
||||
gl.drawArraysInstanced(mode, 0, vertex_count, instance_count);
|
||||
gl.drawArraysInstanced(mode, min, max - min + 1, instance_count);
|
||||
else
|
||||
glDrawArrays(mode, 0, vertex_count);
|
||||
glDrawArrays(mode, min, max - min + 1);
|
||||
}
|
||||
|
||||
if (wireframe)
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#define LOVE_GRAPHICS_OPENGL_MESH_H
|
||||
|
||||
// LOVE
|
||||
#include "common/config.h"
|
||||
#include "common/int.h"
|
||||
#include "common/math.h"
|
||||
#include "common/StringMap.h"
|
||||
@@ -64,6 +65,16 @@ public:
|
||||
* @param mode The draw mode to use when drawing the Mesh.
|
||||
**/
|
||||
Mesh(const std::vector<Vertex> &verts, DrawMode mode = DRAW_MODE_FAN);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Creates a Mesh with a certain number of default-initialized (hidden)
|
||||
* vertices.
|
||||
* @param vertexcount The number of vertices to use in the Mesh.
|
||||
* @param mode The draw mode to use when drawing the Mesh.
|
||||
**/
|
||||
Mesh(int vertexcount, DrawMode mode = DRAW_MODE_FAN);
|
||||
|
||||
virtual ~Mesh();
|
||||
|
||||
/**
|
||||
@@ -140,6 +151,10 @@ public:
|
||||
void setDrawMode(DrawMode mode);
|
||||
DrawMode getDrawMode() const;
|
||||
|
||||
void setDrawRange(int min, int max);
|
||||
void setDrawRange();
|
||||
void getDrawRange(int &min, int &max) 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.
|
||||
@@ -178,6 +193,9 @@ private:
|
||||
|
||||
DrawMode draw_mode;
|
||||
|
||||
int range_min;
|
||||
int range_max;
|
||||
|
||||
Texture *texture;
|
||||
|
||||
// Whether the per-vertex colors are used when drawing.
|
||||
|
||||
@@ -440,8 +440,10 @@ int w_newShader(lua_State *L)
|
||||
|
||||
int w_newMesh(lua_State *L)
|
||||
{
|
||||
// Check first argument: mandatory table of vertices.
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
// Check first argument: table of vertices or number of vertices.
|
||||
int ttype = lua_type(L, 1);
|
||||
if (ttype != LUA_TTABLE && ttype != LUA_TNUMBER)
|
||||
luaL_argerror(L, 1, "table or number expected");
|
||||
|
||||
// Second argument: optional texture.
|
||||
Texture *tex = nullptr;
|
||||
@@ -456,52 +458,60 @@ int w_newMesh(lua_State *L)
|
||||
if (str && !Mesh::getConstant(str, mode))
|
||||
return luaL_error(L, "Invalid mesh draw mode: %s", str);
|
||||
|
||||
size_t vertex_count = lua_objlen(L, 1);
|
||||
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++)
|
||||
{
|
||||
lua_rawgeti(L, 1, i);
|
||||
|
||||
if (lua_type(L, -1) != LUA_TTABLE)
|
||||
return luax_typerror(L, 1, "table of tables");
|
||||
|
||||
for (int j = 1; j <= 8; j++)
|
||||
lua_rawgeti(L, -j, j);
|
||||
|
||||
Vertex v;
|
||||
|
||||
v.x = (float) luaL_checknumber(L, -8);
|
||||
v.y = (float) luaL_checknumber(L, -7);
|
||||
|
||||
v.s = (float) luaL_checknumber(L, -6);
|
||||
v.t = (float) luaL_checknumber(L, -5);
|
||||
|
||||
v.r = (unsigned char) luaL_optinteger(L, -4, 255);
|
||||
v.g = (unsigned char) luaL_optinteger(L, -3, 255);
|
||||
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);
|
||||
}
|
||||
|
||||
Mesh *t = nullptr;
|
||||
EXCEPT_GUARD(t = instance->newMesh(vertices, mode);)
|
||||
|
||||
if (ttype == LUA_TTABLE)
|
||||
{
|
||||
size_t vertex_count = lua_objlen(L, 1);
|
||||
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++)
|
||||
{
|
||||
lua_rawgeti(L, 1, i);
|
||||
|
||||
if (lua_type(L, -1) != LUA_TTABLE)
|
||||
return luax_typerror(L, 1, "table of tables");
|
||||
|
||||
for (int j = 1; j <= 8; j++)
|
||||
lua_rawgeti(L, -j, j);
|
||||
|
||||
Vertex v;
|
||||
|
||||
v.x = (float) luaL_checknumber(L, -8);
|
||||
v.y = (float) luaL_checknumber(L, -7);
|
||||
|
||||
v.s = (float) luaL_checknumber(L, -6);
|
||||
v.t = (float) luaL_checknumber(L, -5);
|
||||
|
||||
v.r = (unsigned char) luaL_optinteger(L, -4, 255);
|
||||
v.g = (unsigned char) luaL_optinteger(L, -3, 255);
|
||||
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);
|
||||
}
|
||||
|
||||
EXCEPT_GUARD(t = instance->newMesh(vertices, mode);)
|
||||
t->setVertexColors(use_colors);
|
||||
}
|
||||
else
|
||||
{
|
||||
int count = luaL_checkint(L, 1);
|
||||
EXCEPT_GUARD(t = instance->newMesh(count, mode);)
|
||||
}
|
||||
|
||||
if (tex)
|
||||
t->setTexture(tex);
|
||||
|
||||
t->setVertexColors(use_colors);
|
||||
|
||||
luax_pushtype(L, "Mesh", GRAPHICS_MESH_T, t);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -315,6 +315,38 @@ int w_Mesh_getDrawMode(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Mesh_setDrawRange(lua_State *L)
|
||||
{
|
||||
Mesh *t = luax_checkmesh(L, 1);
|
||||
|
||||
if (lua_isnoneornil(L, 2))
|
||||
t->setDrawRange();
|
||||
else
|
||||
{
|
||||
int rangemin = luaL_checkint(L, 2) - 1;
|
||||
int rangemax = luaL_checkint(L, 3) - 1;
|
||||
EXCEPT_GUARD(t->setDrawRange(rangemin, rangemax);)
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_Mesh_getDrawRange(lua_State *L)
|
||||
{
|
||||
Mesh *t = luax_checkmesh(L, 1);
|
||||
|
||||
int rangemin = -1;
|
||||
int rangemax = -1;
|
||||
t->getDrawRange(rangemin, rangemax);
|
||||
|
||||
if (rangemin < 0 || rangemax < 0)
|
||||
return 0;
|
||||
|
||||
lua_pushinteger(L, rangemin + 1);
|
||||
lua_pushinteger(L, rangemax + 1);
|
||||
return 2;
|
||||
}
|
||||
|
||||
int w_Mesh_setVertexColors(lua_State *L)
|
||||
{
|
||||
Mesh *t = luax_checkmesh(L, 1);
|
||||
@@ -358,6 +390,8 @@ static const luaL_Reg functions[] =
|
||||
{ "getTexture", w_Mesh_getTexture },
|
||||
{ "setDrawMode", w_Mesh_setDrawMode },
|
||||
{ "getDrawMode", w_Mesh_getDrawMode },
|
||||
{ "setDrawRange", w_Mesh_setDrawRange },
|
||||
{ "getDrawRange", w_Mesh_getDrawRange },
|
||||
{ "setVertexColors", w_Mesh_setVertexColors },
|
||||
{ "hasVertexColors", w_Mesh_hasVertexColors },
|
||||
{ "setWireframe", w_Mesh_setWireframe },
|
||||
|
||||
@@ -47,6 +47,8 @@ int w_Mesh_setTexture(lua_State *L);
|
||||
int w_Mesh_getTexture(lua_State *L);
|
||||
int w_Mesh_setDrawMode(lua_State *L);
|
||||
int w_Mesh_getDrawMode(lua_State *L);
|
||||
int w_Mesh_setDrawRange(lua_State *L);
|
||||
int w_Mesh_getDrawRange(lua_State *L);
|
||||
int w_Mesh_setVertexColors(lua_State *L);
|
||||
int w_Mesh_hasVertexColors(lua_State *L);
|
||||
int w_Mesh_setWireframe(lua_State *L);
|
||||
|
||||
Reference in New Issue
Block a user