|
@@ -20,6 +20,7 @@
|
|
|
|
|
|
#include <common/config.h>
|
|
|
#include <common/math.h>
|
|
|
+#include <common/Vector.h>
|
|
|
|
|
|
#include "Graphics.h"
|
|
|
|
|
@@ -36,7 +37,7 @@ namespace opengl
|
|
|
{
|
|
|
|
|
|
Graphics::Graphics()
|
|
|
- : currentFont(0)
|
|
|
+ : currentFont(0), lineWidth(1)
|
|
|
{
|
|
|
// Indicates that there is no screen
|
|
|
// created yet.
|
|
@@ -81,16 +82,10 @@ namespace opengl
|
|
|
float color[4];
|
|
|
//get the color
|
|
|
glGetFloatv(GL_CURRENT_COLOR, color);
|
|
|
- s.color.r = (GLubyte)(color[0]*255.0f);
|
|
|
- s.color.g = (GLubyte)(color[1]*255.0f);
|
|
|
- s.color.b = (GLubyte)(color[2]*255.0f);
|
|
|
- s.color.a = (GLubyte)(color[3]*255.0f);
|
|
|
+ s.color.set( (color[0]*255.0f), (color[1]*255.0f), (color[2]*255.0f), (color[3]*255.0f) );
|
|
|
//get the background color
|
|
|
glGetFloatv(GL_COLOR_CLEAR_VALUE, color);
|
|
|
- s.backgroundColor.r = (GLubyte)(color[0]*255.0f);
|
|
|
- s.backgroundColor.g = (GLubyte)(color[1]*255.0f);
|
|
|
- s.backgroundColor.b = (GLubyte)(color[2]*255.0f);
|
|
|
- s.backgroundColor.a = (GLubyte)(color[3]*255.0f);
|
|
|
+ s.backgroundColor.set( color[0]*255.0f, color[1]*255.0f, color[2]*255.0f, color[3]*255.0f );
|
|
|
//store modes here
|
|
|
GLint mode;
|
|
|
//get blend mode
|
|
@@ -100,19 +95,8 @@ namespace opengl
|
|
|
//get color mode
|
|
|
glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &mode);
|
|
|
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
|
|
|
- s.lineStyle = (glIsEnabled(GL_LINE_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);
|
|
|
- }
|
|
|
+ s.lineStyle = (glIsEnabled(GL_POLYGON_SMOOTH) == GL_TRUE) ? Graphics::LINE_SMOOTH : Graphics::LINE_ROUGH;
|
|
|
//get the point size
|
|
|
glGetFloatv(GL_POINT_SIZE, &s.pointSize);
|
|
|
//get point style
|
|
@@ -136,11 +120,7 @@ namespace opengl
|
|
|
setBackgroundColor(s.backgroundColor);
|
|
|
setBlendMode(s.blendMode);
|
|
|
setColorMode(s.colorMode);
|
|
|
- setLine(s.lineWidth, s.lineStyle);
|
|
|
- if (s.stipple)
|
|
|
- setLineStipple(s.stipplePattern, s.stippleRepeat);
|
|
|
- else
|
|
|
- setLineStipple();
|
|
|
+ setLine(lineWidth, s.lineStyle);
|
|
|
setPoint(s.pointSize, s.pointStyle);
|
|
|
if (s.scissor)
|
|
|
setScissor(s.scissorBox[0], s.scissorBox[1], s.scissorBox[2], s.scissorBox[3]);
|
|
@@ -193,6 +173,7 @@ namespace opengl
|
|
|
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 0);
|
|
|
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
|
|
SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, (vsync ? 1 : 0));
|
|
|
+ SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1);
|
|
|
|
|
|
// FSAA
|
|
|
if(fsaa > 0)
|
|
@@ -260,8 +241,7 @@ namespace opengl
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
|
|
// Enable line/point smoothing.
|
|
|
- glEnable(GL_LINE_SMOOTH);
|
|
|
- glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
|
|
|
+ setLineStyle(LINE_SMOOTH);
|
|
|
glEnable(GL_POINT_SMOOTH);
|
|
|
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
|
|
|
|
|
@@ -281,6 +261,9 @@ namespace opengl
|
|
|
// Reset modelview matrix
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
glLoadIdentity();
|
|
|
+
|
|
|
+ // Set pixel row alignment
|
|
|
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
|
|
|
|
|
|
// Set the new display mode as the current display mode.
|
|
|
currentMode.width = width;
|
|
@@ -314,6 +297,8 @@ namespace opengl
|
|
|
void Graphics::reset()
|
|
|
{
|
|
|
DisplayState s;
|
|
|
+ discardMask();
|
|
|
+ Framebuffer::bindDefaultBuffer();
|
|
|
restoreState(s);
|
|
|
}
|
|
|
|
|
@@ -443,6 +428,28 @@ namespace opengl
|
|
|
return 4;
|
|
|
}
|
|
|
|
|
|
+ void Graphics::defineMask()
|
|
|
+ {
|
|
|
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
|
|
+ glEnable(GL_STENCIL_TEST);
|
|
|
+ glClear(GL_STENCIL_BUFFER_BIT);
|
|
|
+ glStencilFunc(GL_ALWAYS, 1, 1);
|
|
|
+ glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
|
|
+ }
|
|
|
+
|
|
|
+ void Graphics::useMask()
|
|
|
+ {
|
|
|
+ glStencilFunc(GL_EQUAL, 1, 1);
|
|
|
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
|
|
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
|
|
+ }
|
|
|
+
|
|
|
+ void Graphics::discardMask()
|
|
|
+ {
|
|
|
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
|
|
+ glDisable(GL_STENCIL_TEST);
|
|
|
+ }
|
|
|
+
|
|
|
Image * Graphics::newImage(love::image::ImageData * data)
|
|
|
{
|
|
|
// Create the image.
|
|
@@ -472,9 +479,9 @@ namespace opengl
|
|
|
return new Quad(v, sw, sh);
|
|
|
}
|
|
|
|
|
|
- Font * Graphics::newFont(love::font::FontData * data, const Image::Filter& filter)
|
|
|
+ Font * Graphics::newFont(love::font::Rasterizer * r, const Image::Filter& filter)
|
|
|
{
|
|
|
- Font * font = new Font(data, filter);
|
|
|
+ Font * font = new Font(r, filter);
|
|
|
|
|
|
// Load it and check for errors.
|
|
|
if(!font)
|
|
@@ -501,7 +508,7 @@ namespace opengl
|
|
|
return new Framebuffer(width, height);
|
|
|
}
|
|
|
|
|
|
- void Graphics::setColor(Color c)
|
|
|
+ void Graphics::setColor(const Color& c)
|
|
|
{
|
|
|
glColor4ubv(&c.r);
|
|
|
}
|
|
@@ -520,9 +527,9 @@ namespace opengl
|
|
|
return t;
|
|
|
}
|
|
|
|
|
|
- void Graphics::setBackgroundColor(Color c)
|
|
|
+ void Graphics::setBackgroundColor(const Color& c)
|
|
|
{
|
|
|
- glClearColor((float)c.r/255.0f, (float)c.g/255.0f, (float)c.b/255.0f, 1.0f);
|
|
|
+ glClearColor((float)c.r/255.0f, (float)c.g/255.0f, (float)c.b/255.0f, (float)c.a/255.0f);
|
|
|
}
|
|
|
|
|
|
Color Graphics::getBackgroundColor()
|
|
@@ -610,45 +617,30 @@ namespace opengl
|
|
|
|
|
|
void Graphics::setLineWidth( float width )
|
|
|
{
|
|
|
- glLineWidth(width);
|
|
|
+ lineWidth = width;
|
|
|
}
|
|
|
|
|
|
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)
|
|
|
- glDisable (GL_LINE_SMOOTH);
|
|
|
+ glDisable (GL_POLYGON_SMOOTH);
|
|
|
else // type == LINE_SMOOTH
|
|
|
{
|
|
|
- glEnable (GL_LINE_SMOOTH);
|
|
|
- glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);
|
|
|
+ glEnable (GL_POLYGON_SMOOTH);
|
|
|
+ glHint (GL_POLYGON_SMOOTH_HINT, GL_NICEST);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void Graphics::setLine( float width, Graphics::LineStyle style )
|
|
|
{
|
|
|
- glLineWidth(width);
|
|
|
+ setLineWidth(width);
|
|
|
|
|
|
if(style == 0)
|
|
|
return;
|
|
|
-
|
|
|
- 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);
|
|
|
+ setLineStyle(style);
|
|
|
}
|
|
|
|
|
|
float Graphics::getLineWidth()
|
|
@@ -660,25 +652,12 @@ namespace opengl
|
|
|
|
|
|
Graphics::LineStyle Graphics::getLineStyle()
|
|
|
{
|
|
|
- if(glIsEnabled(GL_LINE_SMOOTH) == GL_TRUE)
|
|
|
+ if(glIsEnabled(GL_POLYGON_SMOOTH) == GL_TRUE)
|
|
|
return LINE_SMOOTH;
|
|
|
else
|
|
|
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 )
|
|
|
{
|
|
|
glPointSize((GLfloat)size);
|
|
@@ -807,251 +786,168 @@ namespace opengl
|
|
|
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);
|
|
|
- glPushMatrix();
|
|
|
- glBegin(GL_LINES);
|
|
|
- glVertex2f(x1, y1);
|
|
|
- glVertex2f(x2, y2);
|
|
|
- glEnd();
|
|
|
- glPopMatrix();
|
|
|
- glEnable(GL_TEXTURE_2D);
|
|
|
+ // calculate line directions
|
|
|
+ Vector s = (q - p);
|
|
|
+ Vector t = (r - q);
|
|
|
+
|
|
|
+ // calculate vertex displacement vectors
|
|
|
+ Vector d1 = s.getNormal();
|
|
|
+ Vector d2 = t.getNormal();
|
|
|
+ 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.
|
|
|
- int args = lua_gettop(L);
|
|
|
- bool table = false;
|
|
|
+ Vector *vertices = new Vector[count]; // two vertices for every line end-point
|
|
|
+ Vector p,q,r;
|
|
|
|
|
|
- if (args == 1) { // we've got a table, hopefully
|
|
|
- int type = lua_type(L, 1);
|
|
|
- if (type != LUA_TTABLE)
|
|
|
- return luaL_error(L, "Function requires a table or series of numbers");
|
|
|
- table = true;
|
|
|
- args = lua_objlen(L, 1);
|
|
|
+ r = Vector(coords[0], coords[1]);
|
|
|
+ if (looping) q = Vector(coords[count-4], coords[count-3]);
|
|
|
+ else q = r * 2 - Vector(coords[2], coords[3]);
|
|
|
+
|
|
|
+ for (size_t i = 0; i+3 < count; i += 2) {
|
|
|
+ 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
|
|
|
- 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");
|
|
|
+ p = q;
|
|
|
+ q = r;
|
|
|
+ if (looping) r = Vector(coords[2], coords[3]);
|
|
|
+ else r += (q-p);
|
|
|
+ pushIntersectionPoints(vertices, count-2, lineWidth/2, p,q,r);
|
|
|
|
|
|
- // right, let's draw this polyline, then
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
- glBegin(GL_LINE_STRIP);
|
|
|
- if (table) {
|
|
|
- for (int i = 1; i < args; i += 2) {
|
|
|
- lua_pushnumber(L, i); // x coordinate
|
|
|
- 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();
|
|
|
+ glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
+ glVertexPointer(2, GL_FLOAT, 0, (const GLvoid*)vertices);
|
|
|
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, count);
|
|
|
+ glDisableClientState(GL_VERTEX_ARRAY);
|
|
|
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 )
|
|
|
{
|
|
|
- glDisable(GL_TEXTURE_2D);
|
|
|
- glPushMatrix();
|
|
|
-
|
|
|
- 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);
|
|
|
+ float coords[] = { x1,y1, x2,y2, x3,y3, x1,y1 };
|
|
|
+ polygon(mode, coords, 4 * 2);
|
|
|
}
|
|
|
|
|
|
void Graphics::rectangle(DrawMode mode, float x, float y, float w, float h)
|
|
|
{
|
|
|
- glDisable(GL_TEXTURE_2D);
|
|
|
- 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);
|
|
|
+ quad(mode, x,y, x,y+h, x+w,y+h, x+w,y);
|
|
|
}
|
|
|
|
|
|
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);
|
|
|
- glPushMatrix();
|
|
|
-
|
|
|
- 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);
|
|
|
+ float coords[] = { x1,y1, x2,y2, x3,y3, x4,y4, x1,y1 };
|
|
|
+ polygon(mode, coords, 5 * 2);
|
|
|
}
|
|
|
|
|
|
- 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)
|
|
|
{
|
|
|
float two_pi = static_cast<float>(LOVE_M_PI * 2);
|
|
|
if(points <= 0) points = 1;
|
|
|
float angle_shift = (two_pi / points);
|
|
|
+ float phi = .0f;
|
|
|
|
|
|
- glDisable(GL_TEXTURE_2D);
|
|
|
- glPushMatrix();
|
|
|
-
|
|
|
- glTranslatef(x, y, 0.0f);
|
|
|
+ float *coords = new float[2 * (points + 1)];
|
|
|
+ for (int i = 0; i < points; ++i, phi += angle_shift) {
|
|
|
+ coords[2*i] = x + radius * cos(phi);
|
|
|
+ coords[2*i+1] = y + radius * sin(phi);
|
|
|
+ }
|
|
|
|
|
|
- switch(mode)
|
|
|
- {
|
|
|
- case DRAW_LINE:
|
|
|
- glBegin(GL_LINE_LOOP);
|
|
|
+ coords[2*points] = coords[0];
|
|
|
+ coords[2*points+1] = coords[1];
|
|
|
|
|
|
- for(float i = 0; i < two_pi; i+= angle_shift)
|
|
|
- glVertex2f(radius * sin(i),radius * cos(i));
|
|
|
+ polygon(mode, coords, (points + 1) * 2);
|
|
|
|
|
|
- glEnd();
|
|
|
- break;
|
|
|
+ delete[] coords;
|
|
|
+ }
|
|
|
+
|
|
|
+ void Graphics::arc(DrawMode mode, float x, float y, float radius, float angle1, float angle2, int points)
|
|
|
+ {
|
|
|
+ angle1 = fmod(angle1, 2.0f * (float)LOVE_M_PI);
|
|
|
+ angle2 = fmod(angle2, 2.0f * (float)LOVE_M_PI);
|
|
|
+ if (angle1 == angle2)
|
|
|
+ return;
|
|
|
+ else if (angle1 > angle2)
|
|
|
+ angle2 += (float)LOVE_M_PI * 2.0f;
|
|
|
|
|
|
- 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));
|
|
|
+ if(points <= 0) points = 1;
|
|
|
+ float angle_shift = ((angle2 - angle1) / points);
|
|
|
+ float phi = angle1;
|
|
|
+
|
|
|
+ // GL_POLYGON can only fill-draw convex polygons, so we need to do stuff manually here
|
|
|
+ if (mode == DRAW_LINE) {
|
|
|
+ float *coords = new float[(points + 3) * 2];
|
|
|
+ coords[0] = coords[2 * points + 4] = x;
|
|
|
+ coords[1] = coords[2 * points + 5] = y;
|
|
|
+ for (int i = 0; i <= points; ++i, phi += angle_shift) {
|
|
|
+ coords[2 * (i+1)] = x + radius * cos(phi);
|
|
|
+ coords[2 * (i+1) + 1] = y - radius * sin(phi);
|
|
|
+ }
|
|
|
+ polyline(coords, (points + 3) * 2); // artifacts at sharp angles if set to looping
|
|
|
|
|
|
+ delete[] coords;
|
|
|
+ } else {
|
|
|
+ glDisable(GL_TEXTURE_2D);
|
|
|
+ glBegin(GL_TRIANGLE_FAN);
|
|
|
+ glVertex2f(x, y);
|
|
|
+ for (int i = 0; i <= points; ++i, phi += angle_shift)
|
|
|
+ glVertex2f(x + radius * cos(phi), y - radius * sin(phi));
|
|
|
glEnd();
|
|
|
- break;
|
|
|
+ glEnable(GL_TEXTURE_2D);
|
|
|
}
|
|
|
|
|
|
- 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.
|
|
|
- int n = lua_gettop(L);
|
|
|
-
|
|
|
- // Need at least two params.
|
|
|
- if( n < 2 )
|
|
|
- return luaL_error(L, "Error: function needs at least two parameters.");
|
|
|
-
|
|
|
- DrawMode mode;
|
|
|
-
|
|
|
- const char * str = luaL_checkstring(L, 1);
|
|
|
- if(!getConstant(str, mode))
|
|
|
- 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;
|
|
|
+ // coords is an array of a closed loop of vertices, i.e.
|
|
|
+ // coords[count-2] = coords[0], coords[count-1] = coords[1]
|
|
|
+ if (mode == DRAW_LINE) {
|
|
|
+ polyline(coords, count, true);
|
|
|
+ } else {
|
|
|
+ glDisable(GL_TEXTURE_2D);
|
|
|
+ glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
+ glVertexPointer(2, GL_FLOAT, 0, (const GLvoid*)coords);
|
|
|
+ glDrawArrays(GL_POLYGON, 0, count/2-1); // opengl will close the polygon for us
|
|
|
+ glDisableClientState(GL_VERTEX_ARRAY);
|
|
|
+ glEnable(GL_TEXTURE_2D);
|
|
|
}
|
|
|
-
|
|
|
- glEnd();
|
|
|
-
|
|
|
- glEnable(GL_TEXTURE_2D);
|
|
|
-
|
|
|
- return 0;
|
|
|
}
|
|
|
|
|
|
love::image::ImageData * Graphics::newScreenshot(love::image::Image * image)
|