mirror of
https://github.com/love2d/love.git
synced 2026-08-17 11:00:31 +02:00
Replace line drawing via GL_LINE with custom line drawing (issue #153)
Allows for correctly scaleable lines, (very) big line widths. Corners in rectangles/triangles/... join up nicely (issue #197). --HG-- branch : minor
This commit is contained in:
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include <common/config.h>
|
#include <common/config.h>
|
||||||
#include <common/math.h>
|
#include <common/math.h>
|
||||||
|
#include <common/Vector.h>
|
||||||
|
|
||||||
#include "Graphics.h"
|
#include "Graphics.h"
|
||||||
|
|
||||||
@@ -36,7 +37,7 @@ namespace opengl
|
|||||||
{
|
{
|
||||||
|
|
||||||
Graphics::Graphics()
|
Graphics::Graphics()
|
||||||
: currentFont(0)
|
: currentFont(0), lineWidth(1)
|
||||||
{
|
{
|
||||||
// Indicates that there is no screen
|
// Indicates that there is no screen
|
||||||
// created yet.
|
// created yet.
|
||||||
@@ -100,19 +101,8 @@ namespace opengl
|
|||||||
//get color mode
|
//get color mode
|
||||||
glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &mode);
|
glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &mode);
|
||||||
s.colorMode = (mode == GL_MODULATE) ? Graphics::COLOR_MODULATE : Graphics::COLOR_REPLACE;
|
s.colorMode = (mode == GL_MODULATE) ? Graphics::COLOR_MODULATE : Graphics::COLOR_REPLACE;
|
||||||
//get the line width (directly to corresponding variable)
|
|
||||||
glGetFloatv(GL_LINE_WIDTH, &s.lineWidth);
|
|
||||||
//get line style
|
//get line style
|
||||||
s.lineStyle = (glIsEnabled(GL_LINE_SMOOTH) == GL_TRUE) ? Graphics::LINE_SMOOTH : Graphics::LINE_ROUGH;
|
s.lineStyle = (glIsEnabled(GL_POLYGON_SMOOTH) == GL_TRUE) ? Graphics::LINE_SMOOTH : Graphics::LINE_ROUGH;
|
||||||
//get line stipple
|
|
||||||
s.stipple = (glIsEnabled(GL_LINE_STIPPLE) == GL_TRUE);
|
|
||||||
if (s.stipple)
|
|
||||||
{
|
|
||||||
//get the stipple repeat
|
|
||||||
glGetIntegerv(GL_LINE_STIPPLE_REPEAT, &s.stippleRepeat);
|
|
||||||
//get the stipple pattern
|
|
||||||
glGetIntegerv(GL_LINE_STIPPLE_PATTERN, &s.stipplePattern);
|
|
||||||
}
|
|
||||||
//get the point size
|
//get the point size
|
||||||
glGetFloatv(GL_POINT_SIZE, &s.pointSize);
|
glGetFloatv(GL_POINT_SIZE, &s.pointSize);
|
||||||
//get point style
|
//get point style
|
||||||
@@ -136,11 +126,7 @@ namespace opengl
|
|||||||
setBackgroundColor(s.backgroundColor);
|
setBackgroundColor(s.backgroundColor);
|
||||||
setBlendMode(s.blendMode);
|
setBlendMode(s.blendMode);
|
||||||
setColorMode(s.colorMode);
|
setColorMode(s.colorMode);
|
||||||
setLine(s.lineWidth, s.lineStyle);
|
setLine(lineWidth, s.lineStyle);
|
||||||
if (s.stipple)
|
|
||||||
setLineStipple(s.stipplePattern, s.stippleRepeat);
|
|
||||||
else
|
|
||||||
setLineStipple();
|
|
||||||
setPoint(s.pointSize, s.pointStyle);
|
setPoint(s.pointSize, s.pointStyle);
|
||||||
if (s.scissor)
|
if (s.scissor)
|
||||||
setScissor(s.scissorBox[0], s.scissorBox[1], s.scissorBox[2], s.scissorBox[3]);
|
setScissor(s.scissorBox[0], s.scissorBox[1], s.scissorBox[2], s.scissorBox[3]);
|
||||||
@@ -260,8 +246,7 @@ namespace opengl
|
|||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
// Enable line/point smoothing.
|
// Enable line/point smoothing.
|
||||||
glEnable(GL_LINE_SMOOTH);
|
setLineStyle(LINE_SMOOTH);
|
||||||
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
|
|
||||||
glEnable(GL_POINT_SMOOTH);
|
glEnable(GL_POINT_SMOOTH);
|
||||||
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
|
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
|
||||||
|
|
||||||
@@ -608,45 +593,30 @@ namespace opengl
|
|||||||
|
|
||||||
void Graphics::setLineWidth( float width )
|
void Graphics::setLineWidth( float width )
|
||||||
{
|
{
|
||||||
glLineWidth(width);
|
lineWidth = width;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::setLineStyle(Graphics::LineStyle style )
|
void Graphics::setLineStyle(Graphics::LineStyle style )
|
||||||
{
|
{
|
||||||
|
// XXX: actually enables antialiasing for _all_ polygons.
|
||||||
|
// may need investigation if wanted or not
|
||||||
|
// maybe rename to something else?
|
||||||
if(style == LINE_ROUGH)
|
if(style == LINE_ROUGH)
|
||||||
glDisable (GL_LINE_SMOOTH);
|
glDisable (GL_POLYGON_SMOOTH);
|
||||||
else // type == LINE_SMOOTH
|
else // type == LINE_SMOOTH
|
||||||
{
|
{
|
||||||
glEnable (GL_LINE_SMOOTH);
|
glEnable (GL_POLYGON_SMOOTH);
|
||||||
glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);
|
glHint (GL_POLYGON_SMOOTH_HINT, GL_NICEST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::setLine( float width, Graphics::LineStyle style )
|
void Graphics::setLine( float width, Graphics::LineStyle style )
|
||||||
{
|
{
|
||||||
glLineWidth(width);
|
setLineWidth(width);
|
||||||
|
|
||||||
if(style == 0)
|
if(style == 0)
|
||||||
return;
|
return;
|
||||||
|
setLineStyle(style);
|
||||||
if(style == LINE_ROUGH)
|
|
||||||
glDisable (GL_LINE_SMOOTH);
|
|
||||||
else // type == LINE_SMOOTH
|
|
||||||
{
|
|
||||||
glEnable (GL_LINE_SMOOTH);
|
|
||||||
glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Graphics::setLineStipple()
|
|
||||||
{
|
|
||||||
glDisable(GL_LINE_STIPPLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Graphics::setLineStipple(unsigned short pattern, int repeat)
|
|
||||||
{
|
|
||||||
glEnable(GL_LINE_STIPPLE);
|
|
||||||
glLineStipple((GLint)repeat, (GLshort)pattern);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float Graphics::getLineWidth()
|
float Graphics::getLineWidth()
|
||||||
@@ -658,25 +628,12 @@ namespace opengl
|
|||||||
|
|
||||||
Graphics::LineStyle Graphics::getLineStyle()
|
Graphics::LineStyle Graphics::getLineStyle()
|
||||||
{
|
{
|
||||||
if(glIsEnabled(GL_LINE_SMOOTH) == GL_TRUE)
|
if(glIsEnabled(GL_POLYGON_SMOOTH) == GL_TRUE)
|
||||||
return LINE_SMOOTH;
|
return LINE_SMOOTH;
|
||||||
else
|
else
|
||||||
return LINE_ROUGH;
|
return LINE_ROUGH;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Graphics::getLineStipple(lua_State * L)
|
|
||||||
{
|
|
||||||
if(glIsEnabled(GL_LINE_STIPPLE) == GL_FALSE)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
GLint factor, pattern;
|
|
||||||
glGetIntegerv(GL_LINE_STIPPLE_PATTERN, &pattern);
|
|
||||||
glGetIntegerv(GL_LINE_STIPPLE_REPEAT, &factor);
|
|
||||||
lua_pushinteger(L, pattern);
|
|
||||||
lua_pushinteger(L, factor);
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Graphics::setPointSize( float size )
|
void Graphics::setPointSize( float size )
|
||||||
{
|
{
|
||||||
glPointSize((GLfloat)size);
|
glPointSize((GLfloat)size);
|
||||||
@@ -805,149 +762,90 @@ namespace opengl
|
|||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::line( float x1, float y1, float x2, float y2 )
|
// calculate line boundary intersection vertices for current line
|
||||||
|
// dependent on the current *and next* line segment
|
||||||
|
static void pushIntersectionPoints(Vector *vertices, int pos, float halfwidth, const Vector& p, const Vector& q, const Vector& r)
|
||||||
{
|
{
|
||||||
glDisable(GL_TEXTURE_2D);
|
// calculate line directions
|
||||||
glPushMatrix();
|
Vector s = (q - p);
|
||||||
glBegin(GL_LINES);
|
Vector t = (r - q);
|
||||||
glVertex2f(x1, y1);
|
|
||||||
glVertex2f(x2, y2);
|
// calculate vertex displacement vectors
|
||||||
glEnd();
|
Vector d1 = s.getNormal();
|
||||||
glPopMatrix();
|
Vector d2 = t.getNormal();
|
||||||
glEnable(GL_TEXTURE_2D);
|
d1.normalize();
|
||||||
|
d2.normalize();
|
||||||
|
float det_norm = d1 ^ d2;
|
||||||
|
d1 *= halfwidth;
|
||||||
|
d2 *= halfwidth;
|
||||||
|
|
||||||
|
// lines parallel -> assume intersection at displacement points
|
||||||
|
if (fabs(det_norm) <= .03) {
|
||||||
|
vertices[pos] = q - d2;
|
||||||
|
vertices[pos + 1] = q + d2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// real intersection -> calculate boundary intersection points
|
||||||
|
float det = s ^ t;
|
||||||
|
Vector d = d1 - d2;
|
||||||
|
Vector b = s - d; // s = q - p
|
||||||
|
Vector c = s + d;
|
||||||
|
float lambda = (b ^ t) / det;
|
||||||
|
float mu = (c ^ t) / det;
|
||||||
|
|
||||||
|
// ordering for GL_TRIANGLE_STRIP
|
||||||
|
vertices[pos] = p - d1 + s * mu;
|
||||||
|
vertices[pos+1] = p + d1 + s * lambda;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Graphics::polyline( lua_State * L)
|
void Graphics::polyline(const float* coords, size_t count, bool looping)
|
||||||
{
|
{
|
||||||
// Get number of params.
|
Vector *vertices = new Vector[count]; // two vertices for every line end-point
|
||||||
int args = lua_gettop(L);
|
Vector p,q,r;
|
||||||
bool table = false;
|
|
||||||
|
|
||||||
if (args == 1) { // we've got a table, hopefully
|
r = Vector(coords[0], coords[1]);
|
||||||
int type = lua_type(L, 1);
|
if (looping) q = Vector(coords[count-4], coords[count-3]);
|
||||||
if (type != LUA_TTABLE)
|
else q = r * 2 - Vector(coords[2], coords[3]);
|
||||||
return luaL_error(L, "Function requires a table or series of numbers");
|
|
||||||
table = true;
|
for (size_t i = 0; i+3 < count; i += 2) {
|
||||||
args = lua_objlen(L, 1);
|
p = q;
|
||||||
|
q = r;
|
||||||
|
r = Vector(coords[i+2], coords[i+3]);
|
||||||
|
pushIntersectionPoints(vertices, i, lineWidth/2, p,q,r);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args % 2) // an odd number of arguments, no good for a polyline
|
p = q;
|
||||||
return luaL_error(L, "Number of vertices must be a multiple of two");
|
q = r;
|
||||||
else if (args < 4)
|
if (looping) r = Vector(coords[2], coords[3]);
|
||||||
return luaL_error(L, "Need at least two vertices to draw a line");
|
else r += (q-p);
|
||||||
|
pushIntersectionPoints(vertices, count-2, lineWidth/2, p,q,r);
|
||||||
|
|
||||||
// right, let's draw this polyline, then
|
|
||||||
glDisable(GL_TEXTURE_2D);
|
glDisable(GL_TEXTURE_2D);
|
||||||
glBegin(GL_LINE_STRIP);
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
if (table) {
|
glVertexPointer(2, GL_FLOAT, 0, (const GLvoid*)vertices);
|
||||||
for (int i = 1; i < args; i += 2) {
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, count);
|
||||||
lua_pushnumber(L, i); // x coordinate
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
lua_rawget(L, 1);
|
|
||||||
lua_pushnumber(L, i+1); // y coordinate
|
|
||||||
lua_rawget(L, 1);
|
|
||||||
glVertex2f((GLfloat)lua_tonumber(L, -2), (GLfloat)lua_tonumber(L, -1));
|
|
||||||
lua_pop(L, 2);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int i = 1; i < args; i+=2) {
|
|
||||||
glVertex2f((GLfloat)lua_tonumber(L, i), (GLfloat)lua_tonumber(L, i+1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
glEnd();
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
return 0;
|
|
||||||
|
delete[] vertices;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::triangle(DrawMode mode, float x1, float y1, float x2, float y2, float x3, float y3 )
|
void Graphics::triangle(DrawMode mode, float x1, float y1, float x2, float y2, float x3, float y3 )
|
||||||
{
|
{
|
||||||
glDisable(GL_TEXTURE_2D);
|
float coords[] = { x1,y1, x2,y2, x3,y3, x1,y1 };
|
||||||
glPushMatrix();
|
polygon(mode, coords, 4 * 2);
|
||||||
|
|
||||||
switch(mode)
|
|
||||||
{
|
|
||||||
case DRAW_LINE:
|
|
||||||
glBegin(GL_LINE_LOOP);
|
|
||||||
glVertex2f(x1, y1);
|
|
||||||
glVertex2f(x2, y2);
|
|
||||||
glVertex2f(x3, y3);
|
|
||||||
glEnd();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
case DRAW_FILL:
|
|
||||||
glBegin(GL_TRIANGLES);
|
|
||||||
glVertex2f(x1, y1);
|
|
||||||
glVertex2f(x2, y2);
|
|
||||||
glVertex2f(x3, y3);
|
|
||||||
glEnd();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
glPopMatrix();
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::rectangle(DrawMode mode, float x, float y, float w, float h)
|
void Graphics::rectangle(DrawMode mode, float x, float y, float w, float h)
|
||||||
{
|
{
|
||||||
glDisable(GL_TEXTURE_2D);
|
quad(mode, x,y, x,y+h, x+w,y+h, x+w,y);
|
||||||
glPushMatrix();
|
|
||||||
|
|
||||||
switch(mode)
|
|
||||||
{
|
|
||||||
case DRAW_LINE:
|
|
||||||
// offsets here because OpenGL is being a bitch about line drawings
|
|
||||||
glBegin(GL_LINE_LOOP);
|
|
||||||
glVertex2f(x, y);
|
|
||||||
glVertex2f(x, y+h-1);
|
|
||||||
glVertex2f(x+w-1, y+h-1);
|
|
||||||
glVertex2f(x+w-1, y);
|
|
||||||
glEnd();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
case DRAW_FILL:
|
|
||||||
glBegin(GL_QUADS);
|
|
||||||
glVertex2f(x, y);
|
|
||||||
glVertex2f(x, y+h);
|
|
||||||
glVertex2f(x+w, y+h);
|
|
||||||
glVertex2f(x+w, y);
|
|
||||||
glEnd();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
glPopMatrix();
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::quad(DrawMode mode, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4 )
|
void Graphics::quad(DrawMode mode, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4 )
|
||||||
{
|
{
|
||||||
glDisable(GL_TEXTURE_2D);
|
float coords[] = { x1,y1, x2,y2, x3,y3, x4,y4, x1,y1 };
|
||||||
glPushMatrix();
|
polygon(mode, coords, 5 * 2);
|
||||||
|
|
||||||
switch(mode)
|
|
||||||
{
|
|
||||||
case DRAW_LINE:
|
|
||||||
glBegin(GL_LINE_LOOP);
|
|
||||||
glVertex2f(x1, y1);
|
|
||||||
glVertex2f(x2, y2);
|
|
||||||
glVertex2f(x3, y3);
|
|
||||||
glVertex2f(x4, y4);
|
|
||||||
glEnd();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
case DRAW_FILL:
|
|
||||||
glBegin(GL_QUADS);
|
|
||||||
glVertex2f(x1, y1);
|
|
||||||
glVertex2f(x2, y2);
|
|
||||||
glVertex2f(x3, y3);
|
|
||||||
glVertex2f(x4, y4);
|
|
||||||
glEnd();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
glPopMatrix();
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::circle(DrawMode mode, float x, float y, float radius, int points)
|
void Graphics::circle(DrawMode mode, float x, float y, float radius, int points)
|
||||||
@@ -955,144 +853,77 @@ namespace opengl
|
|||||||
float two_pi = static_cast<float>(LOVE_M_PI * 2);
|
float two_pi = static_cast<float>(LOVE_M_PI * 2);
|
||||||
if(points <= 0) points = 1;
|
if(points <= 0) points = 1;
|
||||||
float angle_shift = (two_pi / points);
|
float angle_shift = (two_pi / points);
|
||||||
|
float phi = .0f;
|
||||||
|
|
||||||
glDisable(GL_TEXTURE_2D);
|
float *coords = new float[2 * (points + 1)];
|
||||||
glPushMatrix();
|
for (int i = 0; i < points; ++i, phi += angle_shift) {
|
||||||
|
coords[2*i] = x + radius * cos(phi);
|
||||||
glTranslatef(x, y, 0.0f);
|
coords[2*i+1] = y + radius * sin(phi);
|
||||||
|
|
||||||
switch(mode)
|
|
||||||
{
|
|
||||||
case DRAW_LINE:
|
|
||||||
glBegin(GL_LINE_LOOP);
|
|
||||||
|
|
||||||
for(float i = 0; i < two_pi; i+= angle_shift)
|
|
||||||
glVertex2f(radius * sin(i),radius * cos(i));
|
|
||||||
|
|
||||||
glEnd();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
case DRAW_FILL:
|
|
||||||
glBegin(GL_TRIANGLE_FAN);
|
|
||||||
|
|
||||||
for(float i = 0; i < two_pi; i+= angle_shift)
|
|
||||||
glVertex2f(radius * sin(i),radius * cos(i));
|
|
||||||
|
|
||||||
glEnd();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glPopMatrix();
|
coords[2*points] = coords[0];
|
||||||
glEnable(GL_TEXTURE_2D);
|
coords[2*points+1] = coords[1];
|
||||||
|
|
||||||
|
polygon(mode, coords, (points + 1) * 2);
|
||||||
|
|
||||||
|
delete[] coords;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::arc(DrawMode mode, float x, float y, float radius, float angle1, float angle2, int points)
|
void Graphics::arc(DrawMode mode, float x, float y, float radius, float angle1, float angle2, int points)
|
||||||
{
|
{
|
||||||
float angle = angle2 - angle1;
|
angle1 = fmod(angle1, 2 * LOVE_M_PI);
|
||||||
if (angle == 0) return;
|
angle2 = fmod(angle2, 2 * LOVE_M_PI);
|
||||||
while (angle < 0) angle += LOVE_M_PI * 2;
|
if (angle1 == angle2)
|
||||||
|
return;
|
||||||
|
else if (angle1 > angle2)
|
||||||
|
angle2 += LOVE_M_PI * 2;
|
||||||
|
|
||||||
|
|
||||||
if(points <= 0) points = 1;
|
if(points <= 0) points = 1;
|
||||||
float angle_shift = (angle / points);
|
float angle_shift = ((angle2 - angle1) / points);
|
||||||
|
float phi = angle1;
|
||||||
glDisable(GL_TEXTURE_2D);
|
|
||||||
glPushMatrix();
|
// GL_POLYGON can only fill-draw convex polygons, so we need to do stuff manually here
|
||||||
|
if (mode == DRAW_LINE) {
|
||||||
glTranslatef(x, y, 0.0f);
|
float *coords = new float[(points + 3) * 2];
|
||||||
|
coords[0] = coords[2 * points + 4] = x;
|
||||||
switch(mode)
|
coords[1] = coords[2 * points + 5] = y;
|
||||||
{
|
for (int i = 0; i <= points; ++i, phi += angle_shift) {
|
||||||
case DRAW_LINE:
|
coords[2 * (i+1)] = x + radius * cos(phi);
|
||||||
glBegin(GL_LINE_LOOP);
|
coords[2 * (i+1) + 1] = y - radius * sin(phi);
|
||||||
|
}
|
||||||
glVertex2f(0, 0);
|
polyline(coords, (points + 3) * 2); // artifacts at sharp angles if set to looping
|
||||||
|
|
||||||
for(float i = 0; i <= angle+angle_shift/2; i+= angle_shift)
|
delete[] coords;
|
||||||
glVertex2f(radius * cos(i+angle1),radius * sin(i+angle1));
|
} else {
|
||||||
|
glDisable(GL_TEXTURE_2D);
|
||||||
glEnd();
|
glBegin(GL_TRIANGLE_FAN);
|
||||||
break;
|
glVertex2f(x, y);
|
||||||
|
for (int i = 0; i <= points; ++i, phi += angle_shift)
|
||||||
default:
|
glVertex2f(x + radius * cos(phi), y - radius * sin(phi));
|
||||||
case DRAW_FILL:
|
glEnd();
|
||||||
glBegin(GL_TRIANGLE_FAN);
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
glVertex2f(0, 0);
|
|
||||||
|
|
||||||
for(float i = 0; i <= angle+angle_shift/2; i+= angle_shift)
|
|
||||||
glVertex2f(radius * cos(i+angle1),radius * sin(i+angle1));
|
|
||||||
|
|
||||||
glEnd();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glPopMatrix();
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Graphics::polygon( lua_State * L )
|
/// @param mode the draw mode
|
||||||
|
/// @param coords the coordinate array
|
||||||
|
/// @param count the number of coordinates/size of the array
|
||||||
|
void Graphics::polygon(DrawMode mode, const float* coords, size_t count)
|
||||||
{
|
{
|
||||||
// Get number of params.
|
// coords is an array of a closed loop of vertices, i.e.
|
||||||
int n = lua_gettop(L);
|
// coords[count-2] = coords[0], coords[count-1] = coords[1]
|
||||||
|
if (mode == DRAW_LINE) {
|
||||||
// Need at least two params.
|
polyline(coords, count, true);
|
||||||
if( n < 2 )
|
} else {
|
||||||
return luaL_error(L, "Error: function needs at least two parameters.");
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
DrawMode mode;
|
glVertexPointer(2, GL_FLOAT, 0, (const GLvoid*)coords);
|
||||||
|
glDrawArrays(GL_POLYGON, 0, count / 2); // opengl will close the polygon for us
|
||||||
const char * str = luaL_checkstring(L, 1);
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
if(!getConstant(str, mode))
|
glEnable(GL_TEXTURE_2D);
|
||||||
return luaL_error(L, "Invalid draw mode: %s", str);
|
|
||||||
|
|
||||||
// Get the type of the second argument.
|
|
||||||
int luatype = lua_type(L, 2);
|
|
||||||
|
|
||||||
// Perform additional type checking.
|
|
||||||
switch(luatype)
|
|
||||||
{
|
|
||||||
case LUA_TNUMBER:
|
|
||||||
if( n-1 < 6 ) return luaL_error(L, "Error: function requires at least 3 vertices.");
|
|
||||||
if( ((n-1)%2) != 0 ) return luaL_error(L, "Error: number of vertices must be a multiple of two.");
|
|
||||||
break;
|
|
||||||
case LUA_TTABLE:
|
|
||||||
if( (lua_objlen(L, 2)%2) != 0 ) return luaL_error(L, "Error: number of vertices must be a multiple of two.");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return luaL_error(L, "Error: number type or table expected.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
glDisable(GL_TEXTURE_2D);
|
|
||||||
|
|
||||||
glBegin((mode==DRAW_LINE) ? GL_LINE_LOOP : GL_POLYGON);
|
|
||||||
|
|
||||||
switch(luatype)
|
|
||||||
{
|
|
||||||
case LUA_TNUMBER:
|
|
||||||
for(int i = 2; i<n; i+=2)
|
|
||||||
glVertex2f((GLfloat)lua_tonumber(L, i), (GLfloat)lua_tonumber(L, i+1));
|
|
||||||
break;
|
|
||||||
case LUA_TTABLE:
|
|
||||||
lua_pushnil(L);
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if(lua_next(L, 2) == 0) break;
|
|
||||||
GLfloat x = (GLfloat)lua_tonumber(L, -1);
|
|
||||||
lua_pop(L, 1); // pop value
|
|
||||||
if(lua_next(L, 2) == 0) break;
|
|
||||||
GLfloat y = (GLfloat)lua_tonumber(L, -1);
|
|
||||||
lua_pop(L, 1); // pop value
|
|
||||||
glVertex2f(x, y);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
glEnd();
|
|
||||||
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
love::image::ImageData * Graphics::newScreenshot(love::image::Image * image)
|
love::image::ImageData * Graphics::newScreenshot(love::image::Image * image)
|
||||||
|
|||||||
@@ -76,11 +76,7 @@ namespace opengl
|
|||||||
Graphics::ColorMode colorMode;
|
Graphics::ColorMode colorMode;
|
||||||
|
|
||||||
// Line.
|
// Line.
|
||||||
float lineWidth;
|
|
||||||
Graphics::LineStyle lineStyle;
|
Graphics::LineStyle lineStyle;
|
||||||
bool stipple;
|
|
||||||
GLint stippleRepeat;
|
|
||||||
GLint stipplePattern;
|
|
||||||
|
|
||||||
// Point.
|
// Point.
|
||||||
float pointSize;
|
float pointSize;
|
||||||
@@ -107,9 +103,7 @@ namespace opengl
|
|||||||
backgroundColor.a = 255;
|
backgroundColor.a = 255;
|
||||||
blendMode = Graphics::BLEND_ALPHA;
|
blendMode = Graphics::BLEND_ALPHA;
|
||||||
colorMode = Graphics::COLOR_MODULATE;
|
colorMode = Graphics::COLOR_MODULATE;
|
||||||
lineWidth = 1.0f;
|
|
||||||
lineStyle = Graphics::LINE_SMOOTH;
|
lineStyle = Graphics::LINE_SMOOTH;
|
||||||
stipple = false;
|
|
||||||
pointSize = 1.0f;
|
pointSize = 1.0f;
|
||||||
pointStyle = Graphics::POINT_SMOOTH;
|
pointStyle = Graphics::POINT_SMOOTH;
|
||||||
scissor = false;
|
scissor = false;
|
||||||
@@ -126,6 +120,8 @@ namespace opengl
|
|||||||
Font * currentFont;
|
Font * currentFont;
|
||||||
DisplayMode currentMode;
|
DisplayMode currentMode;
|
||||||
|
|
||||||
|
float lineWidth;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Graphics();
|
Graphics();
|
||||||
@@ -335,16 +331,6 @@ namespace opengl
|
|||||||
**/
|
**/
|
||||||
void setLine(float width, LineStyle style);
|
void setLine(float width, LineStyle style);
|
||||||
|
|
||||||
/**
|
|
||||||
* Disables line stippling.
|
|
||||||
**/
|
|
||||||
void setLineStipple();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a line stipple pattern.
|
|
||||||
**/
|
|
||||||
void setLineStipple(unsigned short pattern, int repeat = 1);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the line width.
|
* Gets the line width.
|
||||||
**/
|
**/
|
||||||
@@ -355,13 +341,6 @@ namespace opengl
|
|||||||
**/
|
**/
|
||||||
LineStyle getLineStyle();
|
LineStyle getLineStyle();
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the line stipple pattern and repeat factor.
|
|
||||||
* @return pattern The stipplie bit-pattern.
|
|
||||||
* @return repeat The reapeat factor.
|
|
||||||
**/
|
|
||||||
int getLineStipple(lua_State * L);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the size of points.
|
* Sets the size of points.
|
||||||
**/
|
**/
|
||||||
@@ -423,20 +402,13 @@ namespace opengl
|
|||||||
**/
|
**/
|
||||||
void point(float x, float y);
|
void point(float x, float y);
|
||||||
|
|
||||||
/**
|
|
||||||
* Draws a line from (x1,y1) to (x2,y2).
|
|
||||||
* @param x1 First x-coordinate.
|
|
||||||
* @param y1 First y-coordinate.
|
|
||||||
* @param x2 Second x-coordinate.
|
|
||||||
* @param y2 Second y-coordinate.
|
|
||||||
**/
|
|
||||||
void line(float x1, float y1, float x2, float y2);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws a series of lines connecting the given vertices.
|
* Draws a series of lines connecting the given vertices.
|
||||||
* @param ... Vertex components (x1, y1, x2, y2, etc.)
|
* @param coords Vertex components (x1, y1, x2, y2, etc.)
|
||||||
|
* @param count Coord array size
|
||||||
|
* @param looping Wether the line is joining itself
|
||||||
**/
|
**/
|
||||||
int polyline(lua_State * L);
|
void polyline(const float* coords, size_t count, bool looping = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws a triangle using the three coordinates passed.
|
* Draws a triangle using the three coordinates passed.
|
||||||
@@ -488,9 +460,10 @@ namespace opengl
|
|||||||
/**
|
/**
|
||||||
* Draws a polygon with an arbitrary number of vertices.
|
* Draws a polygon with an arbitrary number of vertices.
|
||||||
* @param type The type of drawing (line/filled).
|
* @param type The type of drawing (line/filled).
|
||||||
* @param ... Vertex components (x1, y1, x2, y2, etc).
|
* @param coords Vertex components (x1, y1, x2, y2, etc.)
|
||||||
|
* @param count Coord array size
|
||||||
**/
|
**/
|
||||||
int polygon(lua_State * L);
|
void polygon(DrawMode mode, const float* coords, size_t count);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a screenshot of the view and saves it to the default folder.
|
* Creates a screenshot of the view and saves it to the default folder.
|
||||||
|
|||||||
@@ -556,20 +556,6 @@ namespace opengl
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int w_setLineStipple(lua_State * L)
|
|
||||||
{
|
|
||||||
if(lua_gettop(L) == 0)
|
|
||||||
{
|
|
||||||
instance->setLineStipple();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned short pattern = (unsigned short)luaL_checkint(L, 1);
|
|
||||||
int repeat = luaL_optint(L, 2, 1);
|
|
||||||
instance->setLineStipple(pattern, repeat);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int w_getLineWidth(lua_State * L)
|
int w_getLineWidth(lua_State * L)
|
||||||
{
|
{
|
||||||
lua_pushnumber(L, instance->getLineWidth());
|
lua_pushnumber(L, instance->getLineWidth());
|
||||||
@@ -585,11 +571,6 @@ namespace opengl
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int w_getLineStipple(lua_State * L)
|
|
||||||
{
|
|
||||||
return instance->getLineStipple(L);
|
|
||||||
}
|
|
||||||
|
|
||||||
int w_setPointSize(lua_State * L)
|
int w_setPointSize(lua_State * L)
|
||||||
{
|
{
|
||||||
float size = (float)luaL_checknumber(L, 1);
|
float size = (float)luaL_checknumber(L, 1);
|
||||||
@@ -776,15 +757,32 @@ namespace opengl
|
|||||||
int w_line(lua_State * L)
|
int w_line(lua_State * L)
|
||||||
{
|
{
|
||||||
int args = lua_gettop(L);
|
int args = lua_gettop(L);
|
||||||
if( args == 1 || args > 4) {
|
bool is_table = false;
|
||||||
instance->polyline(L);
|
if (args == 1 && lua_istable(L, 1)) {
|
||||||
} else {
|
args = lua_objlen(L, 1);
|
||||||
float x1 = (float)luaL_checknumber(L, 1);
|
is_table = true;
|
||||||
float y1 = (float)luaL_checknumber(L, 2);
|
|
||||||
float x2 = (float)luaL_checknumber(L, 3);
|
|
||||||
float y2 = (float)luaL_checknumber(L, 4);
|
|
||||||
instance->line(x1, y1, x2, y2);
|
|
||||||
}
|
}
|
||||||
|
if (args % 2 != 0)
|
||||||
|
return luaL_error(L, "Number of vertices must be a multiple of two");
|
||||||
|
else if (args < 4)
|
||||||
|
return luaL_error(L, "Need at least two vertices to draw a line");
|
||||||
|
|
||||||
|
float* coords = new float[args];
|
||||||
|
if (is_table) {
|
||||||
|
for (int i = 0; i < args; ++i) {
|
||||||
|
lua_pushnumber(L, i + 1);
|
||||||
|
lua_rawget(L, 1);
|
||||||
|
coords[i] = lua_tonumber(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < args; ++i)
|
||||||
|
coords[i] = lua_tonumber(L, i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
instance->polyline(coords, args);
|
||||||
|
|
||||||
|
delete[] coords;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -873,7 +871,46 @@ namespace opengl
|
|||||||
|
|
||||||
int w_polygon(lua_State * L)
|
int w_polygon(lua_State * L)
|
||||||
{
|
{
|
||||||
return instance->polygon(L);
|
int args = lua_gettop(L) - 1;
|
||||||
|
|
||||||
|
Graphics::DrawMode mode;
|
||||||
|
const char * str = luaL_checkstring(L, 1);
|
||||||
|
if(!Graphics::getConstant(str, mode))
|
||||||
|
return luaL_error(L, "Invalid draw mode: %s", str);
|
||||||
|
|
||||||
|
bool is_table = false;
|
||||||
|
float* coords;
|
||||||
|
if (args == 1 && lua_istable(L, 2)) {
|
||||||
|
args = lua_objlen(L, 2);
|
||||||
|
is_table = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args % 2 != 0)
|
||||||
|
return luaL_error(L, "Number of vertices must be a multiple of two");
|
||||||
|
else if (args < 6)
|
||||||
|
return luaL_error(L, "Need at least three vertices to draw a polygon");
|
||||||
|
|
||||||
|
// fetch coords
|
||||||
|
coords = new float[args + 2];
|
||||||
|
if (is_table) {
|
||||||
|
for (int i = 0; i < args; ++i) {
|
||||||
|
lua_pushnumber(L, i + 1);
|
||||||
|
lua_rawget(L, 2);
|
||||||
|
coords[i] = lua_tonumber(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < args; ++i)
|
||||||
|
coords[i] = lua_tonumber(L, i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// make a closed loop
|
||||||
|
coords[args] = coords[0];
|
||||||
|
coords[args+1] = coords[1];
|
||||||
|
instance->polygon(mode, coords, args+2);
|
||||||
|
delete[] coords;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int w_push(lua_State *)
|
int w_push(lua_State *)
|
||||||
@@ -950,10 +987,8 @@ namespace opengl
|
|||||||
{ "setLineWidth", w_setLineWidth },
|
{ "setLineWidth", w_setLineWidth },
|
||||||
{ "setLineStyle", w_setLineStyle },
|
{ "setLineStyle", w_setLineStyle },
|
||||||
{ "setLine", w_setLine },
|
{ "setLine", w_setLine },
|
||||||
{ "setLineStipple", w_setLineStipple },
|
|
||||||
{ "getLineWidth", w_getLineWidth },
|
{ "getLineWidth", w_getLineWidth },
|
||||||
{ "getLineStyle", w_getLineStyle },
|
{ "getLineStyle", w_getLineStyle },
|
||||||
{ "getLineStipple", w_getLineStipple },
|
|
||||||
{ "setPointSize", w_setPointSize },
|
{ "setPointSize", w_setPointSize },
|
||||||
{ "setPointStyle", w_setPointStyle },
|
{ "setPointStyle", w_setPointStyle },
|
||||||
{ "setPoint", w_setPoint },
|
{ "setPoint", w_setPoint },
|
||||||
|
|||||||
Reference in New Issue
Block a user