Alex Szpakowski avatar Alex Szpakowski committed c9d9c1e Merge

Merged bartbes/love-experiments/Mesh into default

Comments (0)

Files changed (33)

platform/macosx/love-framework.xcodeproj/project.pbxproj

 		FA636D8E171B72A70065623F /* wrap_RandomGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA636D8C171B72A70065623F /* wrap_RandomGenerator.cpp */; };
 		FA636D8F171B72A70065623F /* wrap_RandomGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = FA636D8D171B72A70065623F /* wrap_RandomGenerator.h */; };
 		FA7175AA178E8418001FE7FE /* lua.h in Headers */ = {isa = PBXBuildFile; fileRef = FA7175A9178E8418001FE7FE /* lua.h */; };
+		FA7AA59217F6AC1F00704BE2 /* wrap_Mesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA7AA59017F6AC1F00704BE2 /* wrap_Mesh.cpp */; };
+		FA7AA59317F6AC1F00704BE2 /* wrap_Mesh.h in Headers */ = {isa = PBXBuildFile; fileRef = FA7AA59117F6AC1F00704BE2 /* wrap_Mesh.h */; };
 		FA7C937A16DCC6C2006F2BEE /* wrap_Math.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA7C937516DCC6C2006F2BEE /* wrap_Math.cpp */; };
 		FA7C937B16DCC6C2006F2BEE /* wrap_Math.h in Headers */ = {isa = PBXBuildFile; fileRef = FA7C937616DCC6C2006F2BEE /* wrap_Math.h */; };
 		FA9B4A0816E1578300074F42 /* SDL2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA9B4A0716E1578300074F42 /* SDL2.framework */; };
 		FAC5710117402D1100D147E4 /* BezierCurve.h in Headers */ = {isa = PBXBuildFile; fileRef = FAC570FD17402D1100D147E4 /* BezierCurve.h */; };
 		FAC5710217402D1100D147E4 /* wrap_BezierCurve.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAC570FE17402D1100D147E4 /* wrap_BezierCurve.cpp */; };
 		FAC5710317402D1100D147E4 /* wrap_BezierCurve.h in Headers */ = {isa = PBXBuildFile; fileRef = FAC570FF17402D1100D147E4 /* wrap_BezierCurve.h */; };
-		FAC86E631724552C00EED715 /* wrap_Geometry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAC86E611724552C00EED715 /* wrap_Geometry.cpp */; };
-		FAC86E641724552C00EED715 /* wrap_Geometry.h in Headers */ = {isa = PBXBuildFile; fileRef = FAC86E621724552C00EED715 /* wrap_Geometry.h */; };
-		FAC86E691724555D00EED715 /* DrawGable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAC86E651724555D00EED715 /* DrawGable.cpp */; };
-		FAC86E6A1724555D00EED715 /* DrawGable.h in Headers */ = {isa = PBXBuildFile; fileRef = FAC86E661724555D00EED715 /* DrawGable.h */; };
-		FAC86E6B1724555D00EED715 /* Geometry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAC86E671724555D00EED715 /* Geometry.cpp */; };
-		FAC86E6C1724555D00EED715 /* Geometry.h in Headers */ = {isa = PBXBuildFile; fileRef = FAC86E681724555D00EED715 /* Geometry.h */; };
+		FAC86E631724552C00EED715 /* wrap_Quad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAC86E611724552C00EED715 /* wrap_Quad.cpp */; };
+		FAC86E641724552C00EED715 /* wrap_Quad.h in Headers */ = {isa = PBXBuildFile; fileRef = FAC86E621724552C00EED715 /* wrap_Quad.h */; };
+		FAC86E6A1724555D00EED715 /* DrawQable.h in Headers */ = {isa = PBXBuildFile; fileRef = FAC86E661724555D00EED715 /* DrawQable.h */; };
+		FAC86E6B1724555D00EED715 /* Quad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAC86E671724555D00EED715 /* Quad.cpp */; };
+		FAC86E6C1724555D00EED715 /* Quad.h in Headers */ = {isa = PBXBuildFile; fileRef = FAC86E681724555D00EED715 /* Quad.h */; };
 		FAE010DB170DDE99006F29D0 /* ddsinfo.h in Headers */ = {isa = PBXBuildFile; fileRef = FAE010D8170DDE99006F29D0 /* ddsinfo.h */; };
 		FAE010DC170DDE99006F29D0 /* ddsparse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAE010D9170DDE99006F29D0 /* ddsparse.cpp */; };
 		FAE010DD170DDE99006F29D0 /* ddsparse.h in Headers */ = {isa = PBXBuildFile; fileRef = FAE010DA170DDE99006F29D0 /* ddsparse.h */; };
 		FAF272B616E3D46400CC193A /* Thread.h in Headers */ = {isa = PBXBuildFile; fileRef = FAF272B216E3D46400CC193A /* Thread.h */; };
 		FAF272B716E3D46400CC193A /* threads.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAF272B316E3D46400CC193A /* threads.cpp */; };
 		FAF272B816E3D46400CC193A /* threads.h in Headers */ = {isa = PBXBuildFile; fileRef = FAF272B416E3D46400CC193A /* threads.h */; };
+		FAF4376F17F4AC530074F9E2 /* Mesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAF4376D17F4AC530074F9E2 /* Mesh.cpp */; };
+		FAF4377017F4AC530074F9E2 /* Mesh.h in Headers */ = {isa = PBXBuildFile; fileRef = FAF4376E17F4AC530074F9E2 /* Mesh.h */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXFileReference section */
 		FA636D8C171B72A70065623F /* wrap_RandomGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_RandomGenerator.cpp; sourceTree = "<group>"; };
 		FA636D8D171B72A70065623F /* wrap_RandomGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_RandomGenerator.h; sourceTree = "<group>"; };
 		FA7175A9178E8418001FE7FE /* lua.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lua.h; sourceTree = "<group>"; };
+		FA7AA59017F6AC1F00704BE2 /* wrap_Mesh.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Mesh.cpp; sourceTree = "<group>"; };
+		FA7AA59117F6AC1F00704BE2 /* wrap_Mesh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Mesh.h; sourceTree = "<group>"; };
 		FA7C937516DCC6C2006F2BEE /* wrap_Math.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Math.cpp; sourceTree = "<group>"; };
 		FA7C937616DCC6C2006F2BEE /* wrap_Math.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Math.h; sourceTree = "<group>"; };
 		FA9B4A0716E1578300074F42 /* SDL2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL2.framework; path = /Library/Frameworks/SDL2.framework; sourceTree = "<absolute>"; };
 		FAC570FD17402D1100D147E4 /* BezierCurve.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BezierCurve.h; sourceTree = "<group>"; };
 		FAC570FE17402D1100D147E4 /* wrap_BezierCurve.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_BezierCurve.cpp; sourceTree = "<group>"; };
 		FAC570FF17402D1100D147E4 /* wrap_BezierCurve.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_BezierCurve.h; sourceTree = "<group>"; };
-		FAC86E611724552C00EED715 /* wrap_Geometry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Geometry.cpp; sourceTree = "<group>"; };
-		FAC86E621724552C00EED715 /* wrap_Geometry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Geometry.h; sourceTree = "<group>"; };
-		FAC86E651724555D00EED715 /* DrawGable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DrawGable.cpp; sourceTree = "<group>"; };
-		FAC86E661724555D00EED715 /* DrawGable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DrawGable.h; sourceTree = "<group>"; };
-		FAC86E671724555D00EED715 /* Geometry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Geometry.cpp; sourceTree = "<group>"; };
-		FAC86E681724555D00EED715 /* Geometry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Geometry.h; sourceTree = "<group>"; };
+		FAC86E611724552C00EED715 /* wrap_Quad.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Quad.cpp; sourceTree = "<group>"; };
+		FAC86E621724552C00EED715 /* wrap_Quad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Quad.h; sourceTree = "<group>"; };
+		FAC86E661724555D00EED715 /* DrawQable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DrawQable.h; sourceTree = "<group>"; };
+		FAC86E671724555D00EED715 /* Quad.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Quad.cpp; sourceTree = "<group>"; };
+		FAC86E681724555D00EED715 /* Quad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Quad.h; sourceTree = "<group>"; };
 		FAE010D8170DDE99006F29D0 /* ddsinfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ddsinfo.h; sourceTree = "<group>"; };
 		FAE010D9170DDE99006F29D0 /* ddsparse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ddsparse.cpp; sourceTree = "<group>"; };
 		FAE010DA170DDE99006F29D0 /* ddsparse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ddsparse.h; sourceTree = "<group>"; };
 		FAF272B216E3D46400CC193A /* Thread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Thread.h; sourceTree = "<group>"; };
 		FAF272B316E3D46400CC193A /* threads.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = threads.cpp; sourceTree = "<group>"; };
 		FAF272B416E3D46400CC193A /* threads.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = threads.h; sourceTree = "<group>"; };
+		FAF4376D17F4AC530074F9E2 /* Mesh.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Mesh.cpp; sourceTree = "<group>"; };
+		FAF4376E17F4AC530074F9E2 /* Mesh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Mesh.h; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
 				4941079838020ECA049B5C21 /* Color.h */,
 				58BA2BB460AF3C591B22690E /* Drawable.cpp */,
 				5D93601669875EE06721689E /* Drawable.h */,
-				FAC86E651724555D00EED715 /* DrawGable.cpp */,
-				FAC86E661724555D00EED715 /* DrawGable.h */,
-				FAC86E671724555D00EED715 /* Geometry.cpp */,
-				FAC86E681724555D00EED715 /* Geometry.h */,
+				FAC86E661724555D00EED715 /* DrawQable.h */,
 				03F17FF546D637744E263961 /* Graphics.cpp */,
 				777352284E262F48543E6E7F /* Graphics.h */,
 				58CC50E70A375FDF53EF01B6 /* Image.cpp */,
 				1DA41DFF0869489411A71AFC /* Image.h */,
 				75093EE94918576801F50993 /* opengl */,
+				FAC86E671724555D00EED715 /* Quad.cpp */,
+				FAC86E681724555D00EED715 /* Quad.h */,
 				4B731754147B27AF73AC5358 /* Volatile.cpp */,
 				0CFF64090F0F4F481BB80CF0 /* Volatile.h */,
 			);
 				389E3CEC356050A27784290E /* Graphics.h */,
 				56D6030A0B8F7397715062B9 /* Image.cpp */,
 				3CFE5C4A12D5675E7C9C7BF9 /* Image.h */,
+				FAF4376D17F4AC530074F9E2 /* Mesh.cpp */,
+				FAF4376E17F4AC530074F9E2 /* Mesh.h */,
 				2E406F8328543EC63EB922C6 /* OpenGL.cpp */,
 				2C87695707B046B536F347D8 /* OpenGL.h */,
 				48A206C9004150640C432100 /* ParticleSystem.cpp */,
 				3AFB3A18384A2D22352262B1 /* wrap_Canvas.h */,
 				7A3B52AF1FBE73FC36AD50C8 /* wrap_Font.cpp */,
 				3CDA3E9B364F17A902384AAC /* wrap_Font.h */,
-				FAC86E611724552C00EED715 /* wrap_Geometry.cpp */,
-				FAC86E621724552C00EED715 /* wrap_Geometry.h */,
+				FAC86E611724552C00EED715 /* wrap_Quad.cpp */,
+				FAC86E621724552C00EED715 /* wrap_Quad.h */,
 				1A9810F758AC1D1E4B6431FD /* wrap_Graphics.cpp */,
 				05DF237B657042515F3B4E52 /* wrap_Graphics.h */,
 				14AE68E14C2C74526A612FA0 /* wrap_Image.cpp */,
 				78A2127828793F7A778D7932 /* wrap_Image.h */,
+				FA7AA59017F6AC1F00704BE2 /* wrap_Mesh.cpp */,
+				FA7AA59117F6AC1F00704BE2 /* wrap_Mesh.h */,
 				5F42052D7C8271A1105541DE /* wrap_ParticleSystem.cpp */,
 				678E42771C9B415628A3234D /* wrap_ParticleSystem.h */,
 				FA577A8716C71CF000860150 /* wrap_Shader.cpp */,
 				FA7C937B16DCC6C2006F2BEE /* wrap_Math.h in Headers */,
 				FAF272A516E3D44400CC193A /* Channel.h in Headers */,
 				FAF272A716E3D44400CC193A /* LuaThread.h in Headers */,
+				FAF4377017F4AC530074F9E2 /* Mesh.h in Headers */,
 				FAF272A916E3D44400CC193A /* ThreadModule.h in Headers */,
 				FAF272AB16E3D44400CC193A /* wrap_Channel.h in Headers */,
 				FAF272AD16E3D44400CC193A /* wrap_LuaThread.h in Headers */,
 				FAE010E1170DE25E006F29D0 /* ddsHandler.h in Headers */,
 				FAE010E5170DF75C006F29D0 /* wrap_CompressedData.h in Headers */,
 				FA0CDE3D1710F9A50056E8D7 /* FormatHandler.h in Headers */,
+				FA7AA59317F6AC1F00704BE2 /* wrap_Mesh.h in Headers */,
 				FAEC808B1710FEA60057279A /* ImageData.h in Headers */,
 				FAEC808F1711E76C0057279A /* CompressedData.h in Headers */,
 				FA636D8B171B70920065623F /* RandomGenerator.h in Headers */,
 				FA636D8F171B72A70065623F /* wrap_RandomGenerator.h in Headers */,
-				FAC86E641724552C00EED715 /* wrap_Geometry.h in Headers */,
-				FAC86E6A1724555D00EED715 /* DrawGable.h in Headers */,
-				FAC86E6C1724555D00EED715 /* Geometry.h in Headers */,
+				FAC86E641724552C00EED715 /* wrap_Quad.h in Headers */,
+				FAC86E6A1724555D00EED715 /* DrawQable.h in Headers */,
+				FAC86E6C1724555D00EED715 /* Quad.h in Headers */,
 				FA03546D1731F3A700284828 /* simplexnoise1234.h in Headers */,
 				FA3D9E0E16E68DE600CA6630 /* Cursor.h in Headers */,
 				FA3D9E1216E68EAE00CA6630 /* Cursor.h in Headers */,
 				FA08F61C16C7541400F007B5 /* Font.cpp in Sources */,
 				FA08F61D16C7541400F007B5 /* GLee.c in Sources */,
 				FA08F61E16C7541400F007B5 /* Graphics.cpp in Sources */,
+				FAF4376F17F4AC530074F9E2 /* Mesh.cpp in Sources */,
 				FA08F61F16C7541400F007B5 /* Image.cpp in Sources */,
 				FA08F62016C7541400F007B5 /* OpenGL.cpp in Sources */,
 				FA08F62116C7541400F007B5 /* ParticleSystem.cpp in Sources */,
 				FA08F63116C7542600F007B5 /* wrap_Image.cpp in Sources */,
 				FA08F63216C7542600F007B5 /* wrap_ImageData.cpp in Sources */,
 				FA08F63416C7542D00F007B5 /* JoystickModule.cpp in Sources */,
+				FA7AA59217F6AC1F00704BE2 /* wrap_Mesh.cpp in Sources */,
 				FA08F63516C7542D00F007B5 /* wrap_JoystickModule.cpp in Sources */,
 				FA08F63616C7543400F007B5 /* Keyboard.cpp in Sources */,
 				FA08F63716C7543400F007B5 /* Keyboard.cpp in Sources */,
 				FAEC808E1711E76C0057279A /* CompressedData.cpp in Sources */,
 				FA636D8A171B70920065623F /* RandomGenerator.cpp in Sources */,
 				FA636D8E171B72A70065623F /* wrap_RandomGenerator.cpp in Sources */,
-				FAC86E631724552C00EED715 /* wrap_Geometry.cpp in Sources */,
-				FAC86E691724555D00EED715 /* DrawGable.cpp in Sources */,
-				FAC86E6B1724555D00EED715 /* Geometry.cpp in Sources */,
+				FAC86E631724552C00EED715 /* wrap_Quad.cpp in Sources */,
+				FAC86E6B1724555D00EED715 /* Quad.cpp in Sources */,
 				FA03546C1731F3A700284828 /* simplexnoise1234.cpp in Sources */,
 				FA3D9E0D16E68DE600CA6630 /* Cursor.cpp in Sources */,
 				FA3D9E1116E68EAE00CA6630 /* Cursor.cpp in Sources */,

src/common/runtime.cpp

 
 	// Graphics
 	{"Drawable", GRAPHICS_DRAWABLE_ID},
-	{"DrawGable", GRAPHICS_DRAWGABLE_ID},
 	{"Image", GRAPHICS_IMAGE_ID},
-	{"Geometry", GRAPHICS_GEOMETRY_ID},
+	{"Quad", GRAPHICS_QUAD_ID},
 	{"Font", GRAPHICS_FONT_ID},
 	{"ParticleSystem", GRAPHICS_PARTICLE_SYSTEM_ID},
 	{"SpriteBatch", GRAPHICS_SPRITE_BATCH_ID},
 	{"Canvas", GRAPHICS_CANVAS_ID},
 	{"Shader", GRAPHICS_SHADER_ID},
+	{"Mesh", GRAPHICS_MESH_ID},
 
 	// Image
 	{"ImageData", IMAGE_IMAGE_DATA_ID},

src/common/types.h

 
 	// Graphics
 	GRAPHICS_DRAWABLE_ID,
-	GRAPHICS_DRAWGABLE_ID,
+	GRAPHICS_DRAWQABLE_ID,
 	GRAPHICS_IMAGE_ID,
-	GRAPHICS_GEOMETRY_ID,
+	GRAPHICS_QUAD_ID,
 	GRAPHICS_FONT_ID,
 	GRAPHICS_PARTICLE_SYSTEM_ID,
 	GRAPHICS_SPRITE_BATCH_ID,
 	GRAPHICS_CANVAS_ID,
 	GRAPHICS_SHADER_ID,
+	GRAPHICS_MESH_ID,
 
 	// Image
 	IMAGE_IMAGE_DATA_ID,
 
 // Graphics.
 const bits GRAPHICS_DRAWABLE_T = (bits(1) << GRAPHICS_DRAWABLE_ID) | OBJECT_T;
-const bits GRAPHICS_DRAWGABLE_T = (bits(1) << GRAPHICS_DRAWGABLE_ID) | GRAPHICS_DRAWABLE_T;
-const bits GRAPHICS_IMAGE_T = (bits(1) << GRAPHICS_IMAGE_ID) | GRAPHICS_DRAWGABLE_T;
-const bits GRAPHICS_GEOMETRY_T = (bits(1) << GRAPHICS_GEOMETRY_ID) | OBJECT_T;
+const bits GRAPHICS_DRAWQABLE_T = (bits(1) << GRAPHICS_DRAWQABLE_ID) | GRAPHICS_DRAWABLE_T;
+const bits GRAPHICS_IMAGE_T = (bits(1) << GRAPHICS_IMAGE_ID) | GRAPHICS_DRAWQABLE_T;
+const bits GRAPHICS_QUAD_T = (bits(1) << GRAPHICS_QUAD_ID) | OBJECT_T;
 const bits GRAPHICS_FONT_T = (bits(1) << GRAPHICS_FONT_ID) | OBJECT_T;
 const bits GRAPHICS_PARTICLE_SYSTEM_T = (bits(1) << GRAPHICS_PARTICLE_SYSTEM_ID) | GRAPHICS_DRAWABLE_T;
 const bits GRAPHICS_SPRITE_BATCH_T = (bits(1) << GRAPHICS_SPRITE_BATCH_ID) | GRAPHICS_DRAWABLE_T;
-const bits GRAPHICS_CANVAS_T = (bits(1) << GRAPHICS_CANVAS_ID) | GRAPHICS_DRAWGABLE_T;
+const bits GRAPHICS_CANVAS_T = (bits(1) << GRAPHICS_CANVAS_ID) | GRAPHICS_DRAWQABLE_T;
 const bits GRAPHICS_SHADER_T = (bits(1) << GRAPHICS_SHADER_ID) | OBJECT_T;
+const bits GRAPHICS_MESH_T = (bits(1) << GRAPHICS_MESH_ID) | GRAPHICS_DRAWABLE_T;
 
 // Image.
 const bits IMAGE_IMAGE_DATA_T = (bits(1) << IMAGE_IMAGE_DATA_ID) | DATA_T;

src/modules/graphics/DrawGable.cpp

-/**
- * Copyright (c) 2006-2013 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 "DrawGable.h"
-
-namespace love
-{
-namespace graphics
-{
-
-DrawGable::~DrawGable()
-{
-}
-
-} // graphics
-} // love

src/modules/graphics/DrawGable.h

-/**
- * Copyright (c) 2006-2013 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.
- **/
-
-#ifndef LOVE_GRAPHICS_DRAWGABLE_H
-#define LOVE_GRAPHICS_DRAWGABLE_H
-
-// LOVE
-#include "Drawable.h"
-#include "Geometry.h"
-
-namespace love
-{
-namespace graphics
-{
-
-/**
- * A DrawGable is anything that be drawn in part with a Geometry object.
- **/
-class DrawGable : public Drawable
-{
-public:
-
-	/**
-	 * Destructor.
-	 **/
-	virtual ~DrawGable();
-
-	/**
-	 * Draws the object with the specified transformation.
-	 *
-	 * @param geom The Geometry object to use to draw the object.
-	 * @param x The position of the object along the x-axis.
-	 * @param y The position of the object along the y-axis.
-	 * @param angle The angle of the object (in radians).
-	 * @param sx The scale factor along the x-axis.
-	 * @param sy The scale factor along the y-axis.
-	 * @param ox The origin offset along the x-axis.
-	 * @param oy The origin offset along the y-axis.
-	 * @param kx Shear along the x-axis.
-	 * @param ky Shear along the y-axis.
-	 **/
-	virtual void drawg(Geometry *geom, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const = 0;
-};
-
-} // graphics
-} // love
-
-#endif // LOVE_GRAPHICS_DRAWGABLE_H

src/modules/graphics/DrawQable.h

+/**
+ * Copyright (c) 2006-2013 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.
+ **/
+
+#ifndef LOVE_GRAPHICS_DRAWQABLE_H
+#define LOVE_GRAPHICS_DRAWQABLE_H
+
+// LOVE
+#include "Drawable.h"
+#include "Quad.h"
+
+namespace love
+{
+namespace graphics
+{
+
+/**
+ * A DrawQable is anything that be drawn in part with a Quad object.
+ **/
+class DrawQable : public Drawable
+{
+public:
+
+	/**
+	 * Destructor.
+	 **/
+	virtual ~DrawQable() {}
+
+	/**
+	 * Draws the object with the specified transformation.
+	 *
+	 * @param quad The Quad object to use to draw the object.
+	 * @param x The position of the object along the x-axis.
+	 * @param y The position of the object along the y-axis.
+	 * @param angle The angle of the object (in radians).
+	 * @param sx The scale factor along the x-axis.
+	 * @param sy The scale factor along the y-axis.
+	 * @param ox The origin offset along the x-axis.
+	 * @param oy The origin offset along the y-axis.
+	 * @param kx Shear along the x-axis.
+	 * @param ky Shear along the y-axis.
+	 **/
+	virtual void drawq(Quad *quad, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const = 0;
+};
+
+} // graphics
+} // love
+
+#endif // LOVE_GRAPHICS_DRAWQABLE_H

src/modules/graphics/Geometry.cpp

-/**
- * Copyright (c) 2006-2013 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 "Geometry.h"
-#include "common/Exception.h"
-#include "common/Vector.h"
-#include "modules/math/MathModule.h"
-
-using love::math::Math;
-
-// STD
-#include <limits>
-#include <algorithm> // for std::swap()
-#include <cstring> // For memcpy
-
-namespace love
-{
-namespace graphics
-{
-
-Geometry::Geometry(const std::vector<Vertex> &polygon, const std::vector<uint16> &elements, Geometry::DrawMode mode)
-	: vertexArray(NULL)
-	, vertexCount(polygon.size())
-	, elementArray(NULL)
-	, elementCount(elements.size())
-	, vertexColors(false)
-	, drawMode(mode)
-{
-	if (polygon.size() < 3)
-		throw love::Exception("At least 3 vertices are needed to create a Geometry.");
-
-	for (size_t i = 0; i < elementCount; i++)
-	{
-		// All values in the element array need to be a valid vertex index.
-		if (elements[i] >= vertexCount)
-			throw love::Exception("Invalid vertex map value");
-	}
-
-	vertexArray = new Vertex[vertexCount];
-	memcpy(vertexArray, &polygon[0], vertexCount * sizeof(Vertex));
-
-	if (elementCount > 0)
-	{
-		elementArray = new uint16[elementCount];
-		memcpy(elementArray, &elements[0], elementCount * sizeof(uint16));
-	}
-}
-
-Geometry::Geometry(float x, float y, float w, float h, float sw, float sh)
-	: vertexArray(NULL)
-	, vertexCount(4)
-	, elementArray(NULL)
-	, elementCount(0)
-	, vertexColors(false)
-	, drawMode(DRAW_MODE_FAN)
-{
-	float s0 = x/sw, s1 = (x+w)/sw, t0 = y/sh, t1 = (y+h)/sh;
-
-	Vertex verts[4] = {
-		{0,0, s0,t0, 255, 255, 255, 255},
-		{w,0, s1,t0, 255, 255, 255, 255},
-		{w,h, s1,t1, 255, 255, 255, 255},
-		{0,h, s0,t1, 255, 255, 255, 255}
-	};
-
-	vertexArray = new Vertex[4];
-
-	for (int i = 0; i < 4; i++)
-		vertexArray[i] = verts[i];
-}
-
-Geometry::Geometry(const Geometry &other)
-	: vertexCount(other.vertexCount)
-	, elementCount(other.elementCount)
-	, vertexColors(other.vertexColors)
-	, drawMode(other.drawMode)
-{
-	vertexArray = new Vertex[vertexCount];
-	memcpy(vertexArray, other.vertexArray, vertexCount * sizeof(Vertex));
-
-	if (elementCount > 0)
-	{
-		elementArray = new uint16[elementCount];
-		memcpy(elementArray, other.elementArray, elementCount * sizeof(uint16));
-	}
-}
-
-Geometry &Geometry::operator=(const Geometry &other)
-{
-	if (this != &other)
-	{
-		Geometry temp(other);
-		std::swap(vertexArray, temp.vertexArray);
-		std::swap(elementArray, temp.elementArray);
-
-		vertexCount  = temp.vertexCount;
-		elementCount = temp.elementCount;
-
-		vertexColors = other.vertexColors;
-		drawMode     = other.drawMode;
-	}
-
-	return *this;
-}
-
-Geometry::~Geometry()
-{
-	delete[] vertexArray;
-	delete[] elementArray;
-}
-
-const Vertex &Geometry::getVertex(size_t i) const
-{
-	if (i >= vertexCount)
-		throw Exception("Invalid vertex index");
-
-	return vertexArray[i];
-}
-
-void Geometry::setVertex(size_t i, const Vertex &v)
-{
-	if (i >= vertexCount)
-		throw Exception("Invalid vertex index");
-
-	vertexArray[i] = v;
-}
-
-
-void Geometry::setElementArray(const uint16 *elements, size_t count)
-{
-	if (count == 0 || elements == NULL)
-	{
-		delete[] elementArray;
-		elementArray = NULL;
-		elementCount = 0;
-		return;
-	}
-
-	for (size_t i = 0; i < count; i++)
-	{
-		if (elements[i] >= vertexCount)
-			throw love::Exception("Invalid vertex map value");
-	}
-
-	if (count > elementCount)
-	{
-		delete[] elementArray;
-		elementArray = new uint16[count];
-	}
-
-	elementCount = count;
-	memcpy(elementArray, elements, elementCount * sizeof(uint16));
-}
-
-void Geometry::setVertexColors(bool on)
-{
-	vertexColors = on;
-}
-
-bool Geometry::getConstant(const char *in, Geometry::DrawMode &out)
-{
-	return drawModes.find(in, out);
-}
-
-bool Geometry::getConstant(Geometry::DrawMode in, const char *&out)
-{
-	return drawModes.find(in, out);
-}
-
-StringMap<Geometry::DrawMode, Geometry::DRAW_MODE_MAX_ENUM>::Entry Geometry::drawModeEntries[] =
-{
-	{"fan", Geometry::DRAW_MODE_FAN},
-	{"strip", Geometry::DRAW_MODE_STRIP},
-	{"triangles", Geometry::DRAW_MODE_TRIANGLES}
-};
-
-StringMap<Geometry::DrawMode, Geometry::DRAW_MODE_MAX_ENUM> Geometry::drawModes(Geometry::drawModeEntries, sizeof(Geometry::drawModeEntries));
-
-} // graphics
-} // love

src/modules/graphics/Geometry.h

-/**
- * Copyright (c) 2006-2013 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.
- **/
-
-#ifndef LOVE_GRAPHICS_GEOMETRY_H
-#define LOVE_GRAPHICS_GEOMETRY_H
-
-// LOVE
-#include "common/Object.h"
-#include "common/math.h"
-#include "common/StringMap.h"
-#include "common/int.h"
-
-// stdlib
-#include <vector>
-
-namespace love
-{
-namespace graphics
-{
-
-class Geometry : public Object
-{
-public:
-
-	// How the Geometry's vertices are used when drawing.
-	// http://escience.anu.edu.au/lecture/cg/surfaceModeling/image/surfaceModeling015.png
-	enum DrawMode
-	{
-		DRAW_MODE_FAN,
-		DRAW_MODE_STRIP,
-		DRAW_MODE_TRIANGLES,
-		DRAW_MODE_MAX_ENUM
-	};
-
-	/**
-	 * Creates a new geometry object from a std::vector<vertex>.
-	 **/
-	Geometry(const std::vector<Vertex> &polygon, const std::vector<uint16> &elements, DrawMode mode = DRAW_MODE_FAN);
-
-	/**
-	 * Creates a new geometry from (texture) quad information.
-	 * @param x Top left position in the image.
-	 * @param y Top left position in the image.
-	 * @param w Width of the quad.
-	 * @param h Height of the quad.
-	 * @param sw The reference width, the width of the Image.
-	 * @param sh The reference height, the height of the Image.
-	 */
-	Geometry(float x, float y, float w, float h, float sw, float sh);
-
-	Geometry(const Geometry &other);
-	Geometry &operator=(const Geometry &other);
-	virtual ~Geometry();
-
-	const Vertex &getVertex(size_t i) const;
-	void setVertex(size_t i, const Vertex &v);
-
-	/**
-	 * Returns a pointer to the vertex array.
-	 **/
-	inline const Vertex *getVertexArray() const
-	{
-		return vertexArray;
-	}
-
-	/**
-	 * Returns the size of the vertex array.
-	 **/
-	inline size_t getVertexCount() const
-	{
-		return vertexCount;
-	}
-
-	inline const uint16 *getElementArray() const
-	{
-		return elementArray;
-	}
-
-	inline size_t getElementCount() const
-	{
-		return elementCount;
-	}
-
-	void setElementArray(const uint16 *elements, size_t count);
-
-	/**
-	 * Sets whether this Geometry will use custom per-vertex colors.
-	 **/
-	void setVertexColors(bool on);
-
-	/**
-	 * Returns whether this Geometry is using custom per-vertex colors.
-	 **/
-	inline bool hasVertexColors() const
-	{
-		return vertexColors;
-	};
-
-	/**
-	 * Returns the mode used when drawing this Geometry.
-	 **/
-	inline DrawMode getDrawMode() const
-	{
-		return drawMode;
-	}
-
-	static bool getConstant(const char *in, DrawMode &out);
-	static bool getConstant(DrawMode in, const char *&out);
-
-private:
-
-	Vertex *vertexArray;
-	size_t vertexCount;
-
-	uint16 *elementArray;
-	size_t elementCount;
-
-	bool vertexColors;
-
-	DrawMode drawMode;
-
-	static StringMap<DrawMode, DRAW_MODE_MAX_ENUM>::Entry drawModeEntries[];
-	static StringMap<DrawMode, DRAW_MODE_MAX_ENUM> drawModes;
-};
-
-} // graphics
-} // love
-
-#endif // LOVE_GRAPHICS_GEOMETRY_H

src/modules/graphics/Image.h

 
 // LOVE
 #include "graphics/Volatile.h"
-#include "graphics/DrawGable.h"
+#include "graphics/DrawQable.h"
 #include "common/StringMap.h"
 
 namespace love
 namespace graphics
 {
 
-class Image : public DrawGable, public Volatile
+class Image : public DrawQable, public Volatile
 {
 public:
 

src/modules/graphics/Quad.cpp

+/**
+ * Copyright (c) 2006-2013 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.
+ **/
+
+// LOVE
+#include "Quad.h"
+
+// C
+#include <cstring> // For memcpy
+
+namespace love
+{
+namespace graphics
+{
+
+Quad::Quad(const Quad::Viewport &v, float sw, float sh)
+	: sw(sw)
+	, sh(sh)
+{
+	memset(vertices, 255, sizeof(Vertex) * NUM_VERTICES);
+	refresh(v, sw, sh);
+}
+
+Quad::~Quad()
+{
+}
+
+void Quad::refresh(const Quad::Viewport &v, float sw, float sh)
+{
+	viewport = v;
+
+	vertices[0].x = 0;
+	vertices[0].y = 0;
+	vertices[1].x = 0;
+	vertices[1].y = v.h;
+	vertices[2].x = v.w;
+	vertices[2].y = v.h;
+	vertices[3].x = v.w;
+	vertices[3].y = 0;
+
+	vertices[0].s = v.x/sw;
+	vertices[0].t = v.y/sh;
+	vertices[1].s = v.x/sw;
+	vertices[1].t = (v.y+v.h)/sh;
+	vertices[2].s = (v.x+v.w)/sw;
+	vertices[2].t = (v.y+v.h)/sh;
+	vertices[3].s = (v.x+v.w)/sw;
+	vertices[3].t = v.y/sh;
+}
+
+void Quad::setViewport(const Quad::Viewport &v)
+{
+	refresh(v, sw, sh);
+}
+
+Quad::Viewport Quad::getViewport() const
+{
+	return viewport;
+}
+
+void Quad::flip(bool x, bool y)
+{
+	Vertex temp[NUM_VERTICES];
+
+	if (x)
+	{
+		memcpy(temp, vertices, sizeof(Vertex) * NUM_VERTICES);
+		vertices[0].s = temp[3].s;
+		vertices[0].t = temp[3].t;
+		vertices[1].s = temp[2].s;
+		vertices[1].t = temp[2].t;
+		vertices[2].s = temp[1].s;
+		vertices[2].t = temp[1].t;
+		vertices[3].s = temp[0].s;
+		vertices[3].t = temp[0].t;
+	}
+
+	if (y)
+	{
+		memcpy(temp, vertices, sizeof(Vertex) * NUM_VERTICES);
+		vertices[0].s = temp[1].s;
+		vertices[0].t = temp[1].t;
+		vertices[1].s = temp[0].s;
+		vertices[1].t = temp[0].t;
+		vertices[2].s = temp[3].s;
+		vertices[2].t = temp[3].t;
+		vertices[3].s = temp[2].s;
+		vertices[3].t = temp[2].t;
+	}
+}
+
+const Vertex *Quad::getVertices() const
+{
+	return vertices;
+}
+
+} // graphics
+} // love

src/modules/graphics/Quad.h

+/**
+ * Copyright (c) 2006-2013 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.
+ **/
+
+#ifndef LOVE_GRAPHICS_QUAD_H
+#define LOVE_GRAPHICS_QUAD_H
+
+// LOVE
+#include "common/Object.h"
+#include "common/math.h"
+
+namespace love
+{
+namespace graphics
+{
+
+class Quad : public Object
+{
+public:
+
+	struct Viewport
+	{
+		float x, y;
+		float w, h;
+	};
+
+	static const size_t NUM_VERTICES = 4;
+
+	Quad(const Viewport &v, float sw, float sh);
+	virtual ~Quad();
+
+	void refresh(const Viewport &v, float sw, float sh);
+	void setViewport(const Viewport &v);
+	Viewport getViewport() const;
+
+	void flip(bool x, bool y);
+
+	const Vertex *getVertices() const;
+
+private:
+
+	Vertex vertices[NUM_VERTICES];
+
+	Viewport viewport;
+	float sw;
+	float sh;
+
+}; // Quad
+
+} // graphics
+} // love
+
+#endif // LOVE_GRAPHICS_QUAD_H

src/modules/graphics/opengl/Canvas.cpp

 	drawv(t, vertices);
 }
 
-void Canvas::drawg(love::graphics::Geometry *geom, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const
+void Canvas::drawq(Quad *quad, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const
 {
 	static Matrix t;
 	t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
 
-	// flip texture coordinates vertically
-	size_t vcount = geom->getVertexCount();
-	const Vertex *w = geom->getVertexArray();
-	Vertex *v = new Vertex[vcount];
-	for (size_t i = 0; i < vcount; ++i)
-	{
-		v[i] = w[i];
-		v[i].t = 1.f - v[i].t;
-	}
+	const Vertex *v = quad->getVertices();
 
-	// use colors stored in geometry (horrible, horrible hack)
-	if (geom->hasVertexColors())
-	{
-		glEnableClientState(GL_COLOR_ARRAY);
-		glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), (GLvoid *)&v->r);
-	}
+	// flip texture coordinates vertically.
+	Vertex w[4];
+	memcpy(w, v, sizeof(Vertex) * 4);
+	for (size_t i = 0; i < 4; i++)
+		w[i].t = 1.0f - w[i].t;
 
-	GLenum glmode;
-	switch (geom->getDrawMode())
-	{
-	case Geometry::DRAW_MODE_FAN:
-	default:
-		glmode = GL_TRIANGLE_FAN;
-		break;
-	case Geometry::DRAW_MODE_STRIP:
-		glmode = GL_TRIANGLE_STRIP;
-		break;
-	case Geometry::DRAW_MODE_TRIANGLES:
-		glmode = GL_TRIANGLES;
-		break;
-	}
-
-	drawv(t, v, vcount, glmode, geom->getElementArray(), geom->getElementCount());
-
-	if (geom->hasVertexColors())
-	{
-		glDisableClientState(GL_COLOR_ARRAY);
-		gl.setColor(gl.getColor());
-	}
-
-	delete[] v;
+	drawv(t, w);
 }
 
 bool Canvas::checkCreateStencil()
 	return height;
 }
 
-void Canvas::drawv(const Matrix &t, const Vertex *v, GLsizei count, GLenum mode, const uint16 *e, GLsizei ecount) const
+void Canvas::drawv(const Matrix &t, const Vertex *v) const
 {
 	glPushMatrix();
 
 	glEnableClientState(GL_VERTEX_ARRAY);
 	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 
-	// XXX: drawg() enables/disables GL_COLOR_ARRAY in order to use the color
-	//      defined in the geometry to draw itself.
-	//      if the drawing method below is changed to use something other than
-	//      glDrawArrays(), drawg() needs to be updated accordingly!
 	glVertexPointer(2, GL_FLOAT, sizeof(Vertex), (GLvoid *)&v[0].x);
 	glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), (GLvoid *)&v[0].s);
 
-	if (e != 0 && ecount > 0)
-		glDrawElements(mode, ecount, GL_UNSIGNED_SHORT, (GLvoid *) e);
-	else
-		glDrawArrays(mode, 0, count);
+	glDrawArrays(GL_QUADS, 0, 4);
 
 	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 	glDisableClientState(GL_VERTEX_ARRAY);

src/modules/graphics/opengl/Canvas.h

 #ifndef LOVE_GRAPHICS_OPENGL_CANVAS_H
 #define LOVE_GRAPHICS_OPENGL_CANVAS_H
 
-#include "graphics/DrawGable.h"
+#include "graphics/DrawQable.h"
 #include "graphics/Volatile.h"
 #include "graphics/Image.h"
 #include "graphics/Color.h"
 namespace opengl
 {
 
-class Canvas : public DrawGable, public Volatile
+class Canvas : public DrawQable, public Volatile
 {
 public:
 
 	virtual void draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const;
 
 	/**
-	 * @copydoc DrawGable::drawg()
+	 * @copydoc DrawQable::drawq()
 	 **/
-	void drawg(love::graphics::Geometry *geom, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const;
+	void drawq(Quad *quad, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const;
 
 	/**
 	 * Create and attach a stencil buffer to this Canvas' framebuffer, if necessary.
 	std::vector<Canvas *> attachedCanvases;
 
 	void setupGrab();
-	void drawv(const Matrix &t, const Vertex *v, GLsizei count = 4, GLenum mode = GL_QUADS, const uint16 *e = 0, GLsizei ecount = 0) const;
+	void drawv(const Matrix &t, const Vertex *v) const;
 
 	static StringMap<TextureType, TYPE_MAX_ENUM>::Entry textureTypeEntries[];
 	static StringMap<TextureType, TYPE_MAX_ENUM> textureTypes;

src/modules/graphics/opengl/Font.cpp

 #include "common/config.h"
 #include "Font.h"
 #include "font/GlyphData.h"
-#include "modules/graphics/Geometry.h"
 #include "Image.h"
 
 #include "libraries/utf8/utf8.h"

src/modules/graphics/opengl/Graphics.cpp

 	return image;
 }
 
-Geometry *Graphics::newGeometry(const std::vector<Vertex> &vertices, const std::vector<uint16> &vertexmap, Geometry::DrawMode mode)
+Quad *Graphics::newQuad(Quad::Viewport v, float sw, float sh)
 {
-	return new Geometry(vertices, vertexmap, mode);
-}
-
-Geometry *Graphics::newQuad(float x, float y, float w, float h, float sw, float sh)
-{
-	return new Geometry(x, y, w, h, sw, sh);
+	return new Quad(v, sw, sh);
 }
 
 Font *Graphics::newFont(love::font::Rasterizer *r, const Image::Filter &filter)
 	return new Shader(sources);
 }
 
+Mesh *Graphics::newMesh(const std::vector<Vertex> &vertices, Mesh::DrawMode mode)
+{
+	return new Mesh(vertices, mode);
+}
+
 void Graphics::setColor(const Color &c)
 {
 	gl.setColor(c);

src/modules/graphics/opengl/Graphics.h

 
 #include "Font.h"
 #include "Image.h"
-#include "graphics/Geometry.h"
+#include "graphics/Quad.h"
 #include "SpriteBatch.h"
 #include "ParticleSystem.h"
 #include "Canvas.h"
 #include "Shader.h"
+#include "Mesh.h"
 
 using love::window::WindowFlags;
 
 	Image *newImage(love::image::ImageData *data);
 	Image *newImage(love::image::CompressedData *cdata);
 
-	/**
-	 * Creates a Geometry object.
-	 **/
-	Geometry *newGeometry(const std::vector<Vertex> &vertices, const std::vector<uint16> &vertexmap, Geometry::DrawMode mode);
-
-	/**
-	 * Creates a quadliteral Geometry object.
-	 **/
-	Geometry *newQuad(float x, float y, float w, float h, float sw, float sh);
+	Quad *newQuad(Quad::Viewport v, float sw, float sh);
 
 	/**
 	 * Creates a Font object.
 
 	Shader *newShader(const Shader::ShaderSources &sources);
 
+	Mesh *newMesh(const std::vector<Vertex> &vertices, Mesh::DrawMode mode = Mesh::DRAW_MODE_FAN);
+
 	/**
 	 * Sets the foreground color.
 	 * @param c The new foreground color.

src/modules/graphics/opengl/Image.cpp

 	, width((float)(data->getWidth()))
 	, height((float)(data->getHeight()))
 	, texture(0)
+	, texCoordScale(1.0, 1.0)
 	, mipmapSharpness(defaultMipmapSharpness)
 	, mipmapsCreated(false)
 	, compressed(false)
 	drawv(t, vertices);
 }
 
-void Image::drawg(love::graphics::Geometry *geom, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const
+void Image::drawq(Quad *quad, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const
 {
 	static Matrix t;
 	t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
 
-	const Vertex *v = geom->getVertexArray();
-	size_t vertcount = geom->getVertexCount();
+	const Vertex *v = quad->getVertices();
+	drawv(t, v);
+}
 
-	// Padded NPOT images require texture coordinate scaling with Geometry.
-	if (!hasNpot())
-		v = scaleNPOT(v, vertcount);
+void Image::predraw() const
+{
+	bind();
 
-	// use colors stored in geometry (horrible, horrible hack)
-	if (geom->hasVertexColors())
+	if (texCoordScale.x < 1.0f || texCoordScale.y < 1.0f)
 	{
-		glEnableClientState(GL_COLOR_ARRAY);
-		glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), (GLvoid *) &v[0].r);
+		// NPOT image but no NPOT support, so the texcoords should be scaled.
+		glMatrixMode(GL_TEXTURE);
+		glPushMatrix();
+		glScalef(texCoordScale.x, texCoordScale.y, 0.0f);
+		glMatrixMode(GL_MODELVIEW);
 	}
+}
 
-	GLenum glmode;
-	switch (geom->getDrawMode())
+void Image::postdraw() const
+{
+	if (texCoordScale.x < 1.0f || texCoordScale.y < 1.0f)
 	{
-	case Geometry::DRAW_MODE_FAN:
-	default:
-		glmode = GL_TRIANGLE_FAN;
-		break;
-	case Geometry::DRAW_MODE_STRIP:
-		glmode = GL_TRIANGLE_STRIP;
-		break;
-	case Geometry::DRAW_MODE_TRIANGLES:
-		glmode = GL_TRIANGLES;
-		break;
+		glMatrixMode(GL_TEXTURE);
+		glPopMatrix();
+		glMatrixMode(GL_MODELVIEW);
 	}
-
-	drawv(t, v, vertcount, glmode, geom->getElementArray(), geom->getElementCount());
-
-	if (geom->hasVertexColors())
-	{
-		glDisableClientState(GL_COLOR_ARRAY);
-		gl.setColor(gl.getColor());
-	}
-
-	// If we made new verts with scaled texcoords then we should clean them up.
-	if (!hasNpot())
-		delete[] v;
 }
 
 void Image::uploadCompressedMipmaps()
 		return true;
 	}
 
-	vertices[1].t = t;
-	vertices[2].t = t;
-	vertices[2].s = s;
-	vertices[3].s = s;
+	texCoordScale.x = s;
+	texCoordScale.y = t;
 
 	// We want this lock to potentially cover mipmap creation as well.
 	love::thread::EmptyLock lock;
 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, px);
 }
 
-love::Vector Image::getTexCoordScale() const
+void Image::drawv(const Matrix &t, const Vertex *v) const
 {
-	// FIXME: this should be changed if Image::loadVolatilePOT changes.
-	return love::Vector(vertices[2].s, vertices[2].t);
-}
-
-Vertex *Image::scaleNPOT(const love::Vertex *v, size_t count) const
-{
-	Vertex *newverts = new Vertex[count];
-	love::Vector scale = getTexCoordScale();
-
-	for (size_t i = 0; i < count; i++)
-	{
-		newverts[i] = v[i];
-		newverts[i].s *= scale.x;
-		newverts[i].t *= scale.y;
-	}
-
-	return newverts;
-}
-
-void Image::drawv(const Matrix &t, const Vertex *v, GLsizei count, GLenum mode, const uint16 *e, GLsizei ecount) const
-{
-	bind();
+	predraw();
 
 	glPushMatrix();
 
 	glEnableClientState(GL_VERTEX_ARRAY);
 	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 
-	// XXX: drawg() enables/disables GL_COLOR_ARRAY in order to use the color
-	//      defined in the geometry to draw itself.
-	//      if the drawing method below is changed to use something other than
-	//      glDrawArrays(), drawg() needs to be updated accordingly!
 	glVertexPointer(2, GL_FLOAT, sizeof(Vertex), (GLvoid *)&v[0].x);
 	glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), (GLvoid *)&v[0].s);
 
-	if (e != 0 && ecount > 0)
-		glDrawElements(mode, ecount, GL_UNSIGNED_SHORT, (GLvoid *) e);
-	else
-		glDrawArrays(mode, 0, count);
+	glDrawArrays(GL_QUADS, 0, 4);
 
 	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 	glDisableClientState(GL_VERTEX_ARRAY);
 
 	glPopMatrix();
+
+	postdraw();
 }
 
 void Image::setDefaultMipmapSharpness(float sharpness)

src/modules/graphics/opengl/Image.h

 	void draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const;
 
 	/**
-	 * @copydoc DrawGable::drawg()
+	 * @copydoc DrawQable::drawq()
 	 **/
-	void drawg(love::graphics::Geometry *geom, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const;
+	void drawq(Quad *quad, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const;
+
+	/**
+	 * Call before using this Image's texture to draw. Binds the texture,
+	 * globally scales texture coordinates if the Image has NPOT dimensions and
+	 * NPOT isn't supported, etc.
+	 **/
+	void predraw() const;
+	void postdraw() const;
 
 	/**
 	 * Sets the filter mode.
 	 **/
 	bool refresh();
 
-	/**
-	 * Gets the texture coordinate scale used for drawing auto-padded NPOT
-	 * images correctly.
-	 **/
-	love::Vector getTexCoordScale() const;
-
 	static void setDefaultMipmapSharpness(float sharpness);
 	static float getDefaultMipmapSharpness();
 	static void setDefaultMipmapFilter(FilterMode f);
 
 private:
 
-	Vertex *scaleNPOT(const Vertex *v, size_t count) const;
 	void uploadDefaultTexture();
 
-	void drawv(const Matrix &t, const Vertex *v, GLsizei count = 4, GLenum mode = GL_QUADS, const uint16 *e = 0, GLsizei ecount = 0) const;
+	void drawv(const Matrix &t, const Vertex *v) const;
 
 	friend class Shader;
 	GLuint getTextureName() const
 	// The source vertices of the image.
 	Vertex vertices[4];
 
+	// The scale applied to texcoords for NPOT images without NPOT support.
+	love::Vector texCoordScale;
+
 	// Mipmap texture LOD bias (sharpness) value.
 	float mipmapSharpness;
 

src/modules/graphics/opengl/Mesh.cpp

+/**
+ * Copyright (c) 2006-2013 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.
+ **/
+
+// LOVE
+#include "Mesh.h"
+#include "common/Matrix.h"
+#include "common/Exception.h"
+
+namespace love
+{
+namespace graphics
+{
+namespace opengl
+{
+
+Mesh::Mesh(const std::vector<Vertex> &verts, Mesh::DrawMode mode)
+	: vbo(nullptr)
+	, vertex_count(0)
+	, ibo(nullptr)
+	, element_count(0)
+	, draw_mode(mode)
+	, image(nullptr)
+	, 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.");
+
+	size_t size = sizeof(Vertex) * verts.size();
+
+	if (vbo && size > vbo->getSize())
+	{
+		delete vbo;
+		vbo = nullptr;
+	}
+
+	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);
+}
+
+void Mesh::setVertex(size_t index, const Vertex &v)
+{
+	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 into just one.
+	Vertex *vertices = (Vertex *) vbo->map();
+	vertices[index] = v;
+}
+
+Vertex Mesh::getVertex(size_t index) const
+{
+	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.
+	Vertex *vertices = (Vertex *) vbo->map();
+	return vertices[index];
+}
+
+size_t Mesh::getVertexCount() const
+{
+	return vertex_count;
+}
+
+void Mesh::setVertexMap(const std::vector<uint32> &map)
+{
+	for (size_t i = 0; i < map.size(); i++)
+	{
+		if (map[i] >= vertex_count)
+			throw love::Exception("Invalid vertex map value: %d", map[i]);
+	}
+
+	size_t size = sizeof(uint32) * map.size();
+
+	if (ibo && size > ibo->getSize())
+	{
+		delete ibo;
+		ibo = nullptr;
+	}
+
+	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 uint32 *Mesh::getVertexMap() const
+{
+	if (ibo && element_count > 0)
+	{
+		VertexBuffer::Bind ibo_bind(*ibo);
+
+		// We unmap the buffer in Mesh::draw and Mesh::setVertexMap.
+		return (uint32 *) ibo->map();
+	}
+
+	return 0;
+}
+
+size_t Mesh::getVertexMapCount() const
+{
+	return element_count;
+}
+
+void Mesh::setImage(Image *img)
+{
+	img->retain();
+
+	if (image)
+		image->release();
+
+	image = img;
+}
+
+void Mesh::setImage()
+{
+	if (image)
+		image->release();
+
+	image = nullptr;
+}
+
+Image *Mesh::getImage() const
+{
+	return image;
+}
+
+void Mesh::setDrawMode(Mesh::DrawMode mode)
+{
+	draw_mode = mode;
+}
+
+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
+{
+	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)
+		image->predraw();
+	else
+		gl.bindTexture(0);
+
+	Matrix m;
+	m.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
+
+	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), 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), vbo->getPointer(color_offset));
+	}
+
+	GLenum mode = getGLDrawMode(draw_mode);
+
+	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_INT, ibo->getPointer(0));
+	}
+	else
+	{
+		// 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());
+	}
+
+	glPopMatrix();
+
+	if (image)
+		image->postdraw();
+}
+
+GLenum Mesh::getGLDrawMode(Mesh::DrawMode mode) const
+{
+	switch (mode)
+	{
+	case DRAW_MODE_FAN:
+		return GL_TRIANGLE_FAN;
+	case DRAW_MODE_STRIP:
+		return GL_TRIANGLE_STRIP;
+	case DRAW_MODE_TRIANGLES:
+		return GL_TRIANGLES;
+	case DRAW_MODE_POINTS:
+		return GL_POINTS;
+	default:
+		break;
+	}
+
+	return GL_TRIANGLES;
+}
+
+bool Mesh::getConstant(const char *in, Mesh::DrawMode &out)
+{
+	return drawModes.find(in, out);
+}
+
+bool Mesh::getConstant(Mesh::DrawMode in, const char *&out)
+{
+	return drawModes.find(in, out);
+}
+
+StringMap<Mesh::DrawMode, Mesh::DRAW_MODE_MAX_ENUM>::Entry Mesh::drawModeEntries[] =
+{
+	{"fan", Mesh::DRAW_MODE_FAN},
+	{"strip", Mesh::DRAW_MODE_STRIP},
+	{"triangles", Mesh::DRAW_MODE_TRIANGLES},
+	{"points", Mesh::DRAW_MODE_POINTS},
+};
+
+StringMap<Mesh::DrawMode, Mesh::DRAW_MODE_MAX_ENUM> Mesh::drawModes(Mesh::drawModeEntries, sizeof(Mesh::drawModeEntries));
+
+} // opengl
+} // graphics
+} // love

src/modules/graphics/opengl/Mesh.h

+/**
+ * Copyright (c) 2006-2013 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.
+ **/
+
+#ifndef LOVE_GRAPHICS_OPENGL_MESH_H
+#define LOVE_GRAPHICS_OPENGL_MESH_H
+
+// LOVE
+#include "common/int.h"
+#include "common/math.h"
+#include "common/StringMap.h"
+#include "graphics/Drawable.h"
+#include "Image.h"
+#include "VertexBuffer.h"
+
+// C++
+#include <vector>
+
+namespace love
+{
+namespace graphics
+{
+namespace opengl
+{
+
+/**
+ * Holds and draws arbitrary vertex geometry.
+ * Each vertex in the Mesh has a position, texture coordinate, and color.
+ **/
+class Mesh : public Drawable
+{
+public:
+
+	// How the Mesh's vertices are used when drawing.
+	// http://escience.anu.edu.au/lecture/cg/surfaceModeling/image/surfaceModeling015.png
+	enum DrawMode
+	{
+		DRAW_MODE_FAN,
+		DRAW_MODE_STRIP,
+		DRAW_MODE_TRIANGLES,
+		DRAW_MODE_POINTS,
+		DRAW_MODE_MAX_ENUM
+	};
+
+	/**
+	 * Constructor.
+	 * @param verts The vertices to use in the Mesh.
+	 * @param mode The draw mode to use when drawing the Mesh.
+	 **/
+	Mesh(const std::vector<Vertex> &verts, DrawMode mode = DRAW_MODE_FAN);
+	virtual ~Mesh();
+
+	/**
+	 * Replaces all the vertices in the Mesh with a new set of vertices.
+	 **/
+	void setVertices(const std::vector<Vertex> &verts);
+
+	/**
+	 * Sets an individual vertex in the Mesh.
+	 * @param index The index into the list of vertices to use.
+	 * @param v The new vertex.
+	 **/
+	void setVertex(size_t index, const Vertex &v);
+	Vertex getVertex(size_t index) const;
+
+	/**
+	 * Gets the total number of vertices in the Mesh.
+	 **/
+	size_t getVertexCount() const;
+
+	/**
+	 * Sets the vertex map to use when drawing the Mesh. The vertex map
+	 * determines the order in which vertices are used by the draw mode.
+	 * A 0-element vector is equivalent to the default vertex map:
+	 * {0, 1, 2, 3, 4, ...}
+	 **/
+	void setVertexMap(const std::vector<uint32> &map);
+
+	/**
+	 * 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 uint32 *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.
+	 **/
+	void setImage(Image *img);
+
+	/**
+	 * Disables any Image from being used when drawing the Mesh.
+	 **/
+	void setImage();
+
+	/**
+	 * Gets the Image used when drawing the Mesh. May return null if no Image is
+	 * set.
+	 **/
+	Image *getImage() const;
+
+	/**
+	 * Sets the draw mode used when drawing the Mesh.
+	 **/
+	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;
+
+	static bool getConstant(const char *in, DrawMode &out);
+	static bool getConstant(DrawMode in, const char *&out);
+
+private:
+
+	GLenum getGLDrawMode(DrawMode mode) const;
+
+	// 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;
+
+}; // Mesh
+
+} // opengl
+} // graphics
+} // love
+
+#endif // LOVE_GRAPHICS_OPENGL_MESH_H

src/modules/graphics/opengl/ParticleSystem.cpp

 		p = p->next;
 	}
 
-	image->bind();
+	image->predraw();
 
 	glEnableClientState(GL_COLOR_ARRAY);
 	glEnableClientState(GL_VERTEX_ARRAY);
 	glDisableClientState(GL_VERTEX_ARRAY);
 	glDisableClientState(GL_COLOR_ARRAY);
 
+	image->postdraw();
+
 	glPopMatrix();
 
 	gl.setColor(curcolor);

src/modules/graphics/opengl/SpriteBatch.cpp

 
 // LOVE
 #include "Image.h"
-#include "modules/graphics/Geometry.h"
 #include "VertexBuffer.h"
 
 // C++
 	if (color)
 		setColorv(sprite, *color);
 
-	// Auto-padded NPOT images require texcoord scaling for their vertices.
-	scaleNPOT(sprite, 4);
-
 	addv(sprite, (index == -1) ? next : index);
 
 	// Increment counter.
 	return index;
 }
 
-int SpriteBatch::addg(Geometry *geom, float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky, int index /*= -1*/)
+int SpriteBatch::addq(Quad *quad, float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky, int index /*= -1*/)
 {
 	// Only do this if there's a free slot.
 	if ((index == -1 && next >= size) || index < -1 || index >= next)
 		return -1;
 
-	size_t vertexcount = geom->getVertexCount();
-	if (vertexcount > 4)
-		throw love::Exception("Cannot add Geometries with more than 4 vertices to SpriteBatch");
-
-	// Which vertices to add to the SpriteBatch.
-	size_t vertex_indices[4] = {0, 1, 2, 3};
-
-	if (geom->getDrawMode() == Geometry::DRAW_MODE_STRIP)
-	{
-		// We have to do some vertex reordering shenanigans to get 4-vertex
-		// triangle strip Geometries to render properly.
-		std::swap(vertex_indices[0], vertex_indices[1]);
-	}
-
-	// If the Geometry has 3 vertices, then 2 triangles will be added to the
-	// SpriteBatch: 0-1-2 and 0-2-0. 0-2-0 will get ignored during rasterization.
-	for (size_t i = geom->getVertexCount(); i < 4; i++)
-		vertex_indices[i] = vertex_indices[0];
-
-	for (size_t i = 0; i < 4; i++)
-		sprite[i] = geom->getVertex(vertex_indices[i]);
+	// Needed for colors.
+	memcpy(sprite, quad->getVertices(), sizeof(Vertex) * 4);
 
 	static Matrix t;
 	t.setTransformation(x, y, a, sx, sy, ox, oy, kx, ky);
 	t.transform(sprite, sprite, 4);
 
-	if (color && !geom->hasVertexColors())
+	if (color)
 		setColorv(sprite, *color);
 
-	// Auto-padded NPOT images require texcoord scaling for their vertices.
-	scaleNPOT(sprite, 4);
-
 	addv(sprite, (index == -1) ? next : index);
 
-	// Make sure SpriteBatch colors are enabled if the Geometry has custom colors.
-	if (!color && geom->hasVertexColors())
-		setColor(Color(255, 255, 255, 255));
-
 	// Increment counter.
 	if (index == -1)
 		return next++;
 	t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
 	glMultMatrixf((const GLfloat *)t.getElements());
 
-	image->bind();
+	image->predraw();
 
 	VertexBuffer::Bind array_bind(*array_buf);
 	VertexBuffer::Bind element_bind(*element_buf->getVertexBuffer());
 		gl.setColor(curcolor);
 	}
 
+	image->postdraw();
+
 	glPopMatrix();
 }
 
-void SpriteBatch::scaleNPOT(Vertex *v, size_t count)
-{
-	if (Image::hasNpot())
-		return;
-
-	love::Vector scale = image->getTexCoordScale();
-
-	if (scale.x == 1.0f && scale.y == 1.0f)
-		return;
-
-	for (size_t i = 0; i < count; i++)
-	{
-		v[i].s *= scale.x;
-		v[i].t *= scale.y;
-	}
-}
-
 void SpriteBatch::addv(const Vertex *v, int index)
 {
 	static const int sprite_size = 4 * sizeof(Vertex); // bytecount

src/modules/graphics/opengl/SpriteBatch.h

 #include "graphics/Drawable.h"
 #include "graphics/Volatile.h"
 #include "graphics/Color.h"
-#include "graphics/Geometry.h"
+#include "graphics/Quad.h"
 
 namespace love
 {
 	virtual ~SpriteBatch();
 
 	int add(float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky, int index = -1);
-	int addg(Geometry *geom, float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky, int index = -1);
+	int addq(Quad *quad, float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky, int index = -1);
 	void clear();
 
 	void *lock();
 	Image *getImage();
 
 	/**
-	 * Set the current color for this SpriteBatch. The geometry added
+	 * Set the current color for this SpriteBatch. The sprites added
 	 * after this call will use this color. Note that global color
 	 * will not longer apply to the SpriteBatch if this is used.
 	 *
-	 * @param color The color to use for the following geometry.
+	 * @param color The color to use for the following sprites.
 	 */
 	void setColor(const Color &color);
 
 	/**
-	 * Disable per-geometry colors for this SpriteBatch. The next call to
+	 * Disable per-sprite colors for this SpriteBatch. The next call to
 	 * draw will use the global color for all sprites.
 	 */
 	void setColor();
 
 private:
 
-	void scaleNPOT(Vertex *v, size_t count);
-
 	void addv(const Vertex *v, int index);
 
 	/**
 	Vertex sprite[4];
 
 	// Current color. This color, if present, will be applied to the next
-	// added geometry.
+	// added sprite.
 	Color *color;
 
 	VertexBuffer *array_buf;