Move backend-agnostic Mesh and SpriteBatch code out of the opengl implementation folder.

--HG--
branch : minor
This commit is contained in:
Alex Szpakowski
2017-01-29 01:05:20 -04:00
parent 3616470a0a
commit c0e66eba83
22 changed files with 1440 additions and 1246 deletions
+14 -8
View File
@@ -476,6 +476,10 @@ set(LOVE_SRC_MODULE_GRAPHICS_ROOT
src/modules/graphics/Font.h
src/modules/graphics/Graphics.cpp
src/modules/graphics/Graphics.h
src/modules/graphics/Image.cpp
src/modules/graphics/Image.h
src/modules/graphics/Mesh.cpp
src/modules/graphics/Mesh.h
src/modules/graphics/ParticleSystem.cpp
src/modules/graphics/ParticleSystem.h
src/modules/graphics/Polyline.cpp
@@ -484,6 +488,8 @@ set(LOVE_SRC_MODULE_GRAPHICS_ROOT
src/modules/graphics/Quad.h
src/modules/graphics/Shader.cpp
src/modules/graphics/Shader.h
src/modules/graphics/SpriteBatch.cpp
src/modules/graphics/SpriteBatch.h
src/modules/graphics/StreamBuffer.cpp
src/modules/graphics/StreamBuffer.h
src/modules/graphics/Text.cpp
@@ -500,10 +506,18 @@ set(LOVE_SRC_MODULE_GRAPHICS_ROOT
src/modules/graphics/wrap_Canvas.h
src/modules/graphics/wrap_Font.cpp
src/modules/graphics/wrap_Font.h
src/modules/graphics/wrap_Image.cpp
src/modules/graphics/wrap_Image.h
src/modules/graphics/wrap_Mesh.cpp
src/modules/graphics/wrap_Mesh.h
src/modules/graphics/wrap_ParticleSystem.cpp
src/modules/graphics/wrap_ParticleSystem.h
src/modules/graphics/wrap_Quad.cpp
src/modules/graphics/wrap_Quad.h
src/modules/graphics/wrap_Shader.cpp
src/modules/graphics/wrap_Shader.h
src/modules/graphics/wrap_SpriteBatch.cpp
src/modules/graphics/wrap_SpriteBatch.h
src/modules/graphics/wrap_Texture.cpp
src/modules/graphics/wrap_Texture.h
src/modules/graphics/wrap_Text.cpp
@@ -543,14 +557,6 @@ set(LOVE_SRC_MODULE_GRAPHICS_OPENGL
src/modules/graphics/opengl/Video.h
src/modules/graphics/opengl/wrap_Graphics.cpp
src/modules/graphics/opengl/wrap_Graphics.h
src/modules/graphics/opengl/wrap_Image.cpp
src/modules/graphics/opengl/wrap_Image.h
src/modules/graphics/opengl/wrap_Mesh.cpp
src/modules/graphics/opengl/wrap_Mesh.h
src/modules/graphics/opengl/wrap_ParticleSystem.cpp
src/modules/graphics/opengl/wrap_ParticleSystem.h
src/modules/graphics/opengl/wrap_SpriteBatch.cpp
src/modules/graphics/opengl/wrap_SpriteBatch.h
)
set(LOVE_SRC_MODULE_GRAPHICS
@@ -459,15 +459,6 @@
FA0B7D5E1A95902C000E1D17 /* wrap_Graphics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BAA1A95902C000E1D17 /* wrap_Graphics.cpp */; };
FA0B7D5F1A95902C000E1D17 /* wrap_Graphics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BAA1A95902C000E1D17 /* wrap_Graphics.cpp */; };
FA0B7D601A95902C000E1D17 /* wrap_Graphics.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7BAB1A95902C000E1D17 /* wrap_Graphics.h */; };
FA0B7D641A95902C000E1D17 /* wrap_Mesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BAE1A95902C000E1D17 /* wrap_Mesh.cpp */; };
FA0B7D651A95902C000E1D17 /* wrap_Mesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BAE1A95902C000E1D17 /* wrap_Mesh.cpp */; };
FA0B7D661A95902C000E1D17 /* wrap_Mesh.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7BAF1A95902C000E1D17 /* wrap_Mesh.h */; };
FA0B7D671A95902C000E1D17 /* wrap_ParticleSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BB01A95902C000E1D17 /* wrap_ParticleSystem.cpp */; };
FA0B7D681A95902C000E1D17 /* wrap_ParticleSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BB01A95902C000E1D17 /* wrap_ParticleSystem.cpp */; };
FA0B7D691A95902C000E1D17 /* wrap_ParticleSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7BB11A95902C000E1D17 /* wrap_ParticleSystem.h */; };
FA0B7D701A95902C000E1D17 /* wrap_SpriteBatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BB61A95902C000E1D17 /* wrap_SpriteBatch.cpp */; };
FA0B7D711A95902C000E1D17 /* wrap_SpriteBatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BB61A95902C000E1D17 /* wrap_SpriteBatch.cpp */; };
FA0B7D721A95902C000E1D17 /* wrap_SpriteBatch.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7BB71A95902C000E1D17 /* wrap_SpriteBatch.h */; };
FA0B7D791A95902C000E1D17 /* Quad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BBC1A95902C000E1D17 /* Quad.cpp */; };
FA0B7D7A1A95902C000E1D17 /* Quad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BBC1A95902C000E1D17 /* Quad.cpp */; };
FA0B7D7B1A95902C000E1D17 /* Quad.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7BBD1A95902C000E1D17 /* Quad.h */; };
@@ -1024,6 +1015,21 @@
FADF541B1E3DA46C00012CC0 /* wrap_Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FADF54191E3DA46C00012CC0 /* wrap_Image.cpp */; };
FADF541C1E3DA46C00012CC0 /* wrap_Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FADF54191E3DA46C00012CC0 /* wrap_Image.cpp */; };
FADF541D1E3DA46C00012CC0 /* wrap_Image.h in Headers */ = {isa = PBXBuildFile; fileRef = FADF541A1E3DA46C00012CC0 /* wrap_Image.h */; };
FADF54201E3DA52C00012CC0 /* wrap_ParticleSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FADF541E1E3DA52C00012CC0 /* wrap_ParticleSystem.cpp */; };
FADF54211E3DA52C00012CC0 /* wrap_ParticleSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FADF541E1E3DA52C00012CC0 /* wrap_ParticleSystem.cpp */; };
FADF54221E3DA52C00012CC0 /* wrap_ParticleSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = FADF541F1E3DA52C00012CC0 /* wrap_ParticleSystem.h */; };
FADF54251E3DA5BA00012CC0 /* Mesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FADF54231E3DA5BA00012CC0 /* Mesh.cpp */; };
FADF54261E3DA5BA00012CC0 /* Mesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FADF54231E3DA5BA00012CC0 /* Mesh.cpp */; };
FADF54271E3DA5BA00012CC0 /* Mesh.h in Headers */ = {isa = PBXBuildFile; fileRef = FADF54241E3DA5BA00012CC0 /* Mesh.h */; };
FADF542A1E3DAADA00012CC0 /* wrap_Mesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FADF54281E3DAADA00012CC0 /* wrap_Mesh.cpp */; };
FADF542B1E3DAADA00012CC0 /* wrap_Mesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FADF54281E3DAADA00012CC0 /* wrap_Mesh.cpp */; };
FADF542C1E3DAADA00012CC0 /* wrap_Mesh.h in Headers */ = {isa = PBXBuildFile; fileRef = FADF54291E3DAADA00012CC0 /* wrap_Mesh.h */; };
FADF542F1E3DABF600012CC0 /* SpriteBatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FADF542D1E3DABF600012CC0 /* SpriteBatch.cpp */; };
FADF54301E3DABF600012CC0 /* SpriteBatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FADF542D1E3DABF600012CC0 /* SpriteBatch.cpp */; };
FADF54311E3DABF600012CC0 /* SpriteBatch.h in Headers */ = {isa = PBXBuildFile; fileRef = FADF542E1E3DABF600012CC0 /* SpriteBatch.h */; };
FADF54341E3DAE6E00012CC0 /* wrap_SpriteBatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FADF54321E3DAE6E00012CC0 /* wrap_SpriteBatch.cpp */; };
FADF54351E3DAE6E00012CC0 /* wrap_SpriteBatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FADF54321E3DAE6E00012CC0 /* wrap_SpriteBatch.cpp */; };
FADF54361E3DAE6E00012CC0 /* wrap_SpriteBatch.h in Headers */ = {isa = PBXBuildFile; fileRef = FADF54331E3DAE6E00012CC0 /* wrap_SpriteBatch.h */; };
FAE272521C05A15B00A67640 /* ParticleSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAE272501C05A15B00A67640 /* ParticleSystem.cpp */; };
FAE272531C05A15B00A67640 /* ParticleSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = FAE272511C05A15B00A67640 /* ParticleSystem.h */; };
FAF140531E20934C00F898D2 /* CodeGen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAF13FC21E20934C00F898D2 /* CodeGen.cpp */; };
@@ -1467,12 +1473,6 @@
FA0B7BA51A95902C000E1D17 /* Buffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Buffer.h; sourceTree = "<group>"; };
FA0B7BAA1A95902C000E1D17 /* wrap_Graphics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Graphics.cpp; sourceTree = "<group>"; };
FA0B7BAB1A95902C000E1D17 /* wrap_Graphics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Graphics.h; sourceTree = "<group>"; };
FA0B7BAE1A95902C000E1D17 /* wrap_Mesh.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Mesh.cpp; sourceTree = "<group>"; };
FA0B7BAF1A95902C000E1D17 /* wrap_Mesh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Mesh.h; sourceTree = "<group>"; };
FA0B7BB01A95902C000E1D17 /* wrap_ParticleSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_ParticleSystem.cpp; sourceTree = "<group>"; };
FA0B7BB11A95902C000E1D17 /* wrap_ParticleSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_ParticleSystem.h; sourceTree = "<group>"; };
FA0B7BB61A95902C000E1D17 /* wrap_SpriteBatch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_SpriteBatch.cpp; sourceTree = "<group>"; };
FA0B7BB71A95902C000E1D17 /* wrap_SpriteBatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_SpriteBatch.h; sourceTree = "<group>"; };
FA0B7BBC1A95902C000E1D17 /* Quad.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Quad.cpp; sourceTree = "<group>"; };
FA0B7BBD1A95902C000E1D17 /* Quad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Quad.h; sourceTree = "<group>"; };
FA0B7BBE1A95902C000E1D17 /* Texture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = Texture.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
@@ -1854,6 +1854,16 @@
FADF54151E3DA08E00012CC0 /* Image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Image.h; sourceTree = "<group>"; };
FADF54191E3DA46C00012CC0 /* wrap_Image.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Image.cpp; sourceTree = "<group>"; };
FADF541A1E3DA46C00012CC0 /* wrap_Image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Image.h; sourceTree = "<group>"; };
FADF541E1E3DA52C00012CC0 /* wrap_ParticleSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_ParticleSystem.cpp; sourceTree = "<group>"; };
FADF541F1E3DA52C00012CC0 /* wrap_ParticleSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_ParticleSystem.h; sourceTree = "<group>"; };
FADF54231E3DA5BA00012CC0 /* Mesh.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Mesh.cpp; sourceTree = "<group>"; };
FADF54241E3DA5BA00012CC0 /* Mesh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Mesh.h; sourceTree = "<group>"; };
FADF54281E3DAADA00012CC0 /* wrap_Mesh.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Mesh.cpp; sourceTree = "<group>"; };
FADF54291E3DAADA00012CC0 /* wrap_Mesh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Mesh.h; sourceTree = "<group>"; };
FADF542D1E3DABF600012CC0 /* SpriteBatch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpriteBatch.cpp; sourceTree = "<group>"; };
FADF542E1E3DABF600012CC0 /* SpriteBatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatch.h; sourceTree = "<group>"; };
FADF54321E3DAE6E00012CC0 /* wrap_SpriteBatch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_SpriteBatch.cpp; sourceTree = "<group>"; };
FADF54331E3DAE6E00012CC0 /* wrap_SpriteBatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_SpriteBatch.h; sourceTree = "<group>"; };
FAE272501C05A15B00A67640 /* ParticleSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParticleSystem.cpp; sourceTree = "<group>"; };
FAE272511C05A15B00A67640 /* ParticleSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParticleSystem.h; sourceTree = "<group>"; };
FAF13FC21E20934C00F898D2 /* CodeGen.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeGen.cpp; sourceTree = "<group>"; };
@@ -2649,6 +2659,8 @@
FA0B7B8B1A95902C000E1D17 /* Graphics.h */,
FADF54141E3DA08E00012CC0 /* Image.cpp */,
FADF54151E3DA08E00012CC0 /* Image.h */,
FADF54231E3DA5BA00012CC0 /* Mesh.cpp */,
FADF54241E3DA5BA00012CC0 /* Mesh.h */,
FA0B7B8C1A95902C000E1D17 /* opengl */,
FAE272501C05A15B00A67640 /* ParticleSystem.cpp */,
FAE272511C05A15B00A67640 /* ParticleSystem.h */,
@@ -2658,6 +2670,8 @@
FA0B7BBD1A95902C000E1D17 /* Quad.h */,
FA1BA0AF1E16FD0800AA2803 /* Shader.cpp */,
FA1BA0B01E16FD0800AA2803 /* Shader.h */,
FADF542D1E3DABF600012CC0 /* SpriteBatch.cpp */,
FADF542E1E3DABF600012CC0 /* SpriteBatch.h */,
FA29C0041E12355B00268CD8 /* StreamBuffer.cpp */,
FA2AF6721DAD62710032B62C /* StreamBuffer.h */,
FADF53FB1E3D74F200012CC0 /* Text.cpp */,
@@ -2676,10 +2690,16 @@
FA1BA0A11E16D97500AA2803 /* wrap_Font.h */,
FADF54191E3DA46C00012CC0 /* wrap_Image.cpp */,
FADF541A1E3DA46C00012CC0 /* wrap_Image.h */,
FADF54281E3DAADA00012CC0 /* wrap_Mesh.cpp */,
FADF54291E3DAADA00012CC0 /* wrap_Mesh.h */,
FADF541E1E3DA52C00012CC0 /* wrap_ParticleSystem.cpp */,
FADF541F1E3DA52C00012CC0 /* wrap_ParticleSystem.h */,
FA620A2E1AA2F8DB005DB4C2 /* wrap_Quad.cpp */,
FA620A2F1AA2F8DB005DB4C2 /* wrap_Quad.h */,
FA1BA0B51E17043400AA2803 /* wrap_Shader.cpp */,
FA1BA0B61E17043400AA2803 /* wrap_Shader.h */,
FADF54321E3DAE6E00012CC0 /* wrap_SpriteBatch.cpp */,
FADF54331E3DAE6E00012CC0 /* wrap_SpriteBatch.h */,
FADF54001E3D77B500012CC0 /* wrap_Text.cpp */,
FADF54011E3D77B500012CC0 /* wrap_Text.h */,
FA620A301AA2F8DB005DB4C2 /* wrap_Texture.cpp */,
@@ -2725,12 +2745,6 @@
FA0B7BAA1A95902C000E1D17 /* wrap_Graphics.cpp */,
FA0B7BAB1A95902C000E1D17 /* wrap_Graphics.h */,
FA6AE6041B3335EC00583D5C /* wrap_Graphics.lua */,
FA0B7BAE1A95902C000E1D17 /* wrap_Mesh.cpp */,
FA0B7BAF1A95902C000E1D17 /* wrap_Mesh.h */,
FA0B7BB01A95902C000E1D17 /* wrap_ParticleSystem.cpp */,
FA0B7BB11A95902C000E1D17 /* wrap_ParticleSystem.h */,
FA0B7BB61A95902C000E1D17 /* wrap_SpriteBatch.cpp */,
FA0B7BB71A95902C000E1D17 /* wrap_SpriteBatch.h */,
);
path = opengl;
sourceTree = "<group>";
@@ -3491,6 +3505,7 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
FADF54221E3DA52C00012CC0 /* wrap_ParticleSystem.h in Headers */,
217DFC0A1D9F6D490055D849 /* unix.h in Headers */,
FA0B7D7E1A95902C000E1D17 /* Texture.h in Headers */,
FA0B7E561A95902C000E1D17 /* wrap_GearJoint.h in Headers */,
@@ -3520,6 +3535,7 @@
FA0B7DC61A95902C000E1D17 /* wrap_JoystickModule.h in Headers */,
FA0B7D201A95902C000E1D17 /* ImageRasterizer.h in Headers */,
FA0B7D241A95902C000E1D17 /* Vera.ttf.h in Headers */,
FADF54311E3DABF600012CC0 /* SpriteBatch.h in Headers */,
FA0B7E5F1A95902C000E1D17 /* wrap_MouseJoint.h in Headers */,
FAB17BED1ABFAF1800F9BA27 /* CompressedData.h in Headers */,
217DFC0C1D9F6D490055D849 /* unixtcp.h in Headers */,
@@ -3538,7 +3554,6 @@
FA0B7E901A95902C000E1D17 /* GmeDecoder.h in Headers */,
FA0B7D0E1A95902C000E1D17 /* wrap_Filesystem.h in Headers */,
FA0B7EE41A95902D000E1D17 /* Window.h in Headers */,
FA0B7D721A95902C000E1D17 /* wrap_SpriteBatch.h in Headers */,
FA0B7CFC1A95902C000E1D17 /* Filesystem.h in Headers */,
FA0B7AD81A958EA3000E1D17 /* lua-enet.h in Headers */,
FA0B7A3A1A958EA3000E1D17 /* b2DynamicTree.h in Headers */,
@@ -3546,6 +3561,7 @@
FA0B7EBA1A95902C000E1D17 /* Channel.h in Headers */,
FA0B7D3E1A95902C000E1D17 /* Image.h in Headers */,
FA0B7ECA1A95902C000E1D17 /* threads.h in Headers */,
FADF54361E3DAE6E00012CC0 /* wrap_SpriteBatch.h in Headers */,
FA0B7DB01A95902C000E1D17 /* wrap_CompressedImageData.h in Headers */,
FA0B7AC11A958EA3000E1D17 /* callbacks.h in Headers */,
FA0B7D8F1A95902C000E1D17 /* ddsHandler.h in Headers */,
@@ -3629,6 +3645,7 @@
FA0B7DCC1A95902C000E1D17 /* Keyboard.h in Headers */,
FA620A341AA2F8DB005DB4C2 /* wrap_Quad.h in Headers */,
FA0B7EA51A95902C000E1D17 /* SoundData.h in Headers */,
FADF54271E3DA5BA00012CC0 /* Mesh.h in Headers */,
FAF1405E1E20934C00F898D2 /* PoolAlloc.h in Headers */,
FA0B7A821A958EA3000E1D17 /* b2EdgeAndCircleContact.h in Headers */,
FA0B79341A958E3B000E1D17 /* Object.h in Headers */,
@@ -3673,7 +3690,6 @@
FA0B7A2B1A958EA3000E1D17 /* b2BroadPhase.h in Headers */,
217DFBFD1D9F6D490055D849 /* smtp.lua.h in Headers */,
FA27B39F1B498151008A9DCE /* Video.h in Headers */,
FA0B7D661A95902C000E1D17 /* wrap_Mesh.h in Headers */,
FA0B7AAC1A958EA3000E1D17 /* b2WeldJoint.h in Headers */,
217DFC041D9F6D490055D849 /* timeout.h in Headers */,
FA0B7E7A1A95902C000E1D17 /* wrap_WheelJoint.h in Headers */,
@@ -3808,7 +3824,6 @@
FA0B7B2E1A958EA3000E1D17 /* unchecked.h in Headers */,
FA0B7D081A95902C000E1D17 /* wrap_File.h in Headers */,
FA0B79451A958E3B000E1D17 /* Variant.h in Headers */,
FA0B7D691A95902C000E1D17 /* wrap_ParticleSystem.h in Headers */,
FA0B7E5C1A95902C000E1D17 /* wrap_MotorJoint.h in Headers */,
FA4F2BA91DE1E36400CA37D7 /* wrap_RecordingDevice.h in Headers */,
FA0B7A7C1A958EA3000E1D17 /* b2Contact.h in Headers */,
@@ -3818,6 +3833,7 @@
FA0B7DED1A95902C000E1D17 /* Cursor.h in Headers */,
FA0B7E501A95902C000E1D17 /* wrap_Fixture.h in Headers */,
FA28EBD71E352DB5003446F4 /* BufferSync.h in Headers */,
FADF542C1E3DAADA00012CC0 /* wrap_Mesh.h in Headers */,
FAA3A9B01B7D465A00CED060 /* android.h in Headers */,
217DFBDE1D9F6D490055D849 /* compat.h in Headers */,
FA0B7A491A958EA3000E1D17 /* b2PolygonShape.h in Headers */,
@@ -3978,6 +3994,7 @@
FADF54081E3D78F700012CC0 /* Video.cpp in Sources */,
FA9D8DD81DEF8411002CD881 /* Data.cpp in Sources */,
FA0B7E8F1A95902C000E1D17 /* GmeDecoder.cpp in Sources */,
FADF542B1E3DAADA00012CC0 /* wrap_Mesh.cpp in Sources */,
FA0B7CD71A95902C000E1D17 /* Audio.cpp in Sources */,
FA0B7AC01A958EA3000E1D17 /* host.c in Sources */,
FA0B7EB01A95902C000E1D17 /* System.cpp in Sources */,
@@ -4057,6 +4074,7 @@
FA0B7A3F1A958EA3000E1D17 /* b2ChainShape.cpp in Sources */,
FA0B7E921A95902C000E1D17 /* ModPlugDecoder.cpp in Sources */,
FA0B7E521A95902C000E1D17 /* wrap_FrictionJoint.cpp in Sources */,
FADF54351E3DAE6E00012CC0 /* wrap_SpriteBatch.cpp in Sources */,
FA4F2BB51DE1E4C300CA37D7 /* wrap_RecordingDevice.cpp in Sources */,
FA0B7A311A958EA3000E1D17 /* b2CollidePolygon.cpp in Sources */,
FA4F2C111DE936FE00CA37D7 /* unix.c in Sources */,
@@ -4079,6 +4097,7 @@
FA0B7A901A958EA3000E1D17 /* b2FrictionJoint.cpp in Sources */,
FA0B7DFB1A95902C000E1D17 /* Body.cpp in Sources */,
FA0B7ED21A95902C000E1D17 /* wrap_ThreadModule.cpp in Sources */,
FADF54261E3DA5BA00012CC0 /* Mesh.cpp in Sources */,
FA0B7EE01A95902D000E1D17 /* wrap_Touch.cpp in Sources */,
FA0B7A3C1A958EA3000E1D17 /* b2TimeOfImpact.cpp in Sources */,
FA4F2C081DE936DD00CA37D7 /* io.c in Sources */,
@@ -4095,11 +4114,9 @@
FA0B7DAF1A95902C000E1D17 /* wrap_CompressedImageData.cpp in Sources */,
FA0B7A481A958EA3000E1D17 /* b2PolygonShape.cpp in Sources */,
FA0B7A991A958EA3000E1D17 /* b2MotorJoint.cpp in Sources */,
FA0B7D681A95902C000E1D17 /* wrap_ParticleSystem.cpp in Sources */,
FA0B7AD51A958EA3000E1D17 /* unix.c in Sources */,
FAB17BE71ABFAA9000F9BA27 /* lz4.c in Sources */,
FA4F2BE71DE6650D00CA37D7 /* Transform.cpp in Sources */,
FA0B7D651A95902C000E1D17 /* wrap_Mesh.cpp in Sources */,
FA0B7A531A958EA3000E1D17 /* b2Math.cpp in Sources */,
FAF140A11E20934C00F898D2 /* RemoveTree.cpp in Sources */,
FA0B7CDA1A95902C000E1D17 /* Pool.cpp in Sources */,
@@ -4162,6 +4179,7 @@
FA0B7D071A95902C000E1D17 /* wrap_File.cpp in Sources */,
FA0B7AD01A958EA3000E1D17 /* peer.c in Sources */,
FA27B3C11B4985BF008A9DCE /* wrap_VideoStream.cpp in Sources */,
FADF54211E3DA52C00012CC0 /* wrap_ParticleSystem.cpp in Sources */,
FA0B791C1A958E3B000E1D17 /* b64.cpp in Sources */,
FA1E88851DF363E100E808AA /* Filter.cpp in Sources */,
FA0B7D941A95902C000E1D17 /* Image.cpp in Sources */,
@@ -4187,6 +4205,7 @@
FA4F2C0B1DE936EA00CA37D7 /* options.c in Sources */,
FA4F2C0D1DE936F100CA37D7 /* serial.c in Sources */,
FA0B7E0A1A95902C000E1D17 /* EdgeShape.cpp in Sources */,
FADF54301E3DABF600012CC0 /* SpriteBatch.cpp in Sources */,
FAB17BF11ABFB37500F9BA27 /* wrap_CompressedData.cpp in Sources */,
FA0B7CF81A95902C000E1D17 /* FileData.cpp in Sources */,
FA0B7DA61A95902C000E1D17 /* PNGHandler.cpp in Sources */,
@@ -4211,7 +4230,6 @@
FA0B79411A958E3B000E1D17 /* utf8.cpp in Sources */,
FAB17BE11ABFAA2000F9BA27 /* Compressor.cpp in Sources */,
FA0B7ADF1A958EA3000E1D17 /* lodepng.cpp in Sources */,
FA0B7D711A95902C000E1D17 /* wrap_SpriteBatch.cpp in Sources */,
FA0B7D341A95902C000E1D17 /* Canvas.cpp in Sources */,
FAF140761E20934C00F898D2 /* IntermTraverse.cpp in Sources */,
FA0B7E8C1A95902C000E1D17 /* FLACDecoder.cpp in Sources */,
@@ -4335,6 +4353,7 @@
FADF54071E3D78F700012CC0 /* Video.cpp in Sources */,
217DFC031D9F6D490055D849 /* timeout.c in Sources */,
FA9D8DD71DEF8411002CD881 /* Data.cpp in Sources */,
FADF542A1E3DAADA00012CC0 /* wrap_Mesh.cpp in Sources */,
FA0B7D2B1A95902C000E1D17 /* wrap_Rasterizer.cpp in Sources */,
FA0B7E8E1A95902C000E1D17 /* GmeDecoder.cpp in Sources */,
FA0B7CD61A95902C000E1D17 /* Audio.cpp in Sources */,
@@ -4414,6 +4433,7 @@
FA0B7E911A95902C000E1D17 /* ModPlugDecoder.cpp in Sources */,
FA0B7E511A95902C000E1D17 /* wrap_FrictionJoint.cpp in Sources */,
FA0B7AD61A958EA3000E1D17 /* win32.c in Sources */,
FADF54341E3DAE6E00012CC0 /* wrap_SpriteBatch.cpp in Sources */,
FA0B7E0C1A95902C000E1D17 /* Fixture.cpp in Sources */,
FA0B7D181A95902C000E1D17 /* TrueTypeRasterizer.cpp in Sources */,
FA0B7CFA1A95902C000E1D17 /* Filesystem.cpp in Sources */,
@@ -4436,6 +4456,7 @@
FA0B7EDF1A95902D000E1D17 /* wrap_Touch.cpp in Sources */,
FA0B794A1A958E3B000E1D17 /* wrap_Data.cpp in Sources */,
217DFBFB1D9F6D490055D849 /* serial.c in Sources */,
FADF54251E3DA5BA00012CC0 /* Mesh.cpp in Sources */,
FA4F2BE51DE6650600CA37D7 /* wrap_Transform.cpp in Sources */,
217DFC0D1D9F6D490055D849 /* unixudp.c in Sources */,
FA0B7CDC1A95902C000E1D17 /* Source.cpp in Sources */,
@@ -4451,11 +4472,9 @@
FA0B7DAE1A95902C000E1D17 /* wrap_CompressedImageData.cpp in Sources */,
FA0B7A6E1A958EA3000E1D17 /* b2WorldCallbacks.cpp in Sources */,
FA0B7A831A958EA3000E1D17 /* b2EdgeAndPolygonContact.cpp in Sources */,
FA0B7D671A95902C000E1D17 /* wrap_ParticleSystem.cpp in Sources */,
FA0B7AA11A958EA3000E1D17 /* b2PulleyJoint.cpp in Sources */,
FAB17BE61ABFAA9000F9BA27 /* lz4.c in Sources */,
FA0B7B211A958EA3000E1D17 /* luasocket.cpp in Sources */,
FA0B7D641A95902C000E1D17 /* wrap_Mesh.cpp in Sources */,
FA0B7A5B1A958EA3000E1D17 /* b2Timer.cpp in Sources */,
FA0B7CD91A95902C000E1D17 /* Pool.cpp in Sources */,
FAF140A01E20934C00F898D2 /* RemoveTree.cpp in Sources */,
@@ -4519,6 +4538,7 @@
FA0B7A4E1A958EA3000E1D17 /* b2Draw.cpp in Sources */,
FA27B3C01B4985BF008A9DCE /* wrap_VideoStream.cpp in Sources */,
FA0B7D931A95902C000E1D17 /* Image.cpp in Sources */,
FADF54201E3DA52C00012CC0 /* wrap_ParticleSystem.cpp in Sources */,
FA0B7D9F1A95902C000E1D17 /* KTXHandler.cpp in Sources */,
FA1E88831DF363DB00E808AA /* Filter.cpp in Sources */,
FA0B7A2C1A958EA3000E1D17 /* b2CollideCircle.cpp in Sources */,
@@ -4544,6 +4564,7 @@
FA4F2B791DE0125B00CA37D7 /* xxhash.c in Sources */,
FA0B7E361A95902C000E1D17 /* WheelJoint.cpp in Sources */,
FA0B7A471A958EA3000E1D17 /* b2PolygonShape.cpp in Sources */,
FADF542F1E3DABF600012CC0 /* SpriteBatch.cpp in Sources */,
FA0B7D8D1A95902C000E1D17 /* ddsHandler.cpp in Sources */,
FA0B7DFD1A95902C000E1D17 /* ChainShape.cpp in Sources */,
FA0B79201A958E3B000E1D17 /* delay.cpp in Sources */,
@@ -4562,7 +4583,6 @@
FA0B7AD41A958EA3000E1D17 /* unix.c in Sources */,
FA0B7A771A958EA3000E1D17 /* b2CircleContact.cpp in Sources */,
FAB17BE01ABFAA2000F9BA27 /* Compressor.cpp in Sources */,
FA0B7D701A95902C000E1D17 /* wrap_SpriteBatch.cpp in Sources */,
FA0B7D331A95902C000E1D17 /* Canvas.cpp in Sources */,
FA0B7E941A95902C000E1D17 /* Mpg123Decoder.cpp in Sources */,
FA0B7E8B1A95902C000E1D17 /* FLACDecoder.cpp in Sources */,
+5
View File
@@ -694,6 +694,11 @@ void Graphics::draw(Texture *texture, Quad *quad, const Matrix4 &m)
texture->drawq(this, quad, m);
}
void Graphics::drawInstanced(Mesh *mesh, const Matrix4 &m, int instancecount)
{
mesh->drawInstanced(this, m, instancecount);
}
/**
* Primitives (points, shapes, lines).
**/
+14
View File
@@ -34,6 +34,7 @@
#include "Font.h"
#include "Shader.h"
#include "Quad.h"
#include "Mesh.h"
#include "math/Transform.h"
#include "font/Rasterizer.h"
#include "video/VideoStream.h"
@@ -50,6 +51,8 @@ class Reference;
namespace graphics
{
class SpriteBatch;
class ParticleSystem;
class Text;
class Video;
class Buffer;
@@ -314,6 +317,10 @@ public:
Quad *newQuad(Quad::Viewport v, double sw, double sh);
virtual SpriteBatch *newSpriteBatch(Texture *texture, int size, vertex::Usage usage) = 0;
virtual ParticleSystem *newParticleSystem(Texture *texture, int size) = 0;
virtual Font *newFont(love::font::Rasterizer *data, const Texture::Filter &filter = Texture::defaultFilter) = 0;
virtual Canvas *newCanvas(int width, int height, const Canvas::Settings &settings) = 0;
@@ -324,6 +331,12 @@ public:
virtual Buffer *newBuffer(size_t size, const void *data, BufferType type, vertex::Usage usage, uint32 mapflags) = 0;
virtual Mesh *newMesh(const std::vector<Vertex> &vertices, Mesh::DrawMode drawmode, vertex::Usage usage) = 0;
virtual Mesh *newMesh(int vertexcount, Mesh::DrawMode drawmode, vertex::Usage usage) = 0;
virtual Mesh *newMesh(const std::vector<Mesh::AttribFormat> &vertexformat, int vertexcount, Mesh::DrawMode drawmode, vertex::Usage usage) = 0;
virtual Mesh *newMesh(const std::vector<Mesh::AttribFormat> &vertexformat, const void *data, size_t datasize, Mesh::DrawMode drawmode, vertex::Usage usage) = 0;
virtual Text *newText(Font *font, const std::vector<Font::ColoredString> &text = {}) = 0;
bool validateShader(bool gles, const Shader::ShaderSource &source, std::string &err);
@@ -546,6 +559,7 @@ public:
void draw(Drawable *drawable, const Matrix4 &m);
void draw(Texture *texture, Quad *quad, const Matrix4 &m);
void drawInstanced(Mesh *mesh, const Matrix4 &m, int instancecount);
/**
* Draws text at the specified coordinates
+642
View File
@@ -0,0 +1,642 @@
/**
* Copyright (c) 2006-2017 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"
#include "Shader.h"
#include "Graphics.h"
// C++
#include <algorithm>
#include <limits>
namespace love
{
namespace graphics
{
static const char *getBuiltinAttribName(VertexAttribID attribid)
{
const char *name = "";
vertex::getConstant(attribid, name);
return name;
}
static_assert(offsetof(Vertex, x) == sizeof(float) * 0, "Incorrect position offset in Vertex struct");
static_assert(offsetof(Vertex, s) == sizeof(float) * 2, "Incorrect texture coordinate offset in Vertex struct");
static_assert(offsetof(Vertex, color.r) == sizeof(float) * 4, "Incorrect color offset in Vertex struct");
std::vector<Mesh::AttribFormat> Mesh::getDefaultVertexFormat()
{
// Corresponds to the love::Vertex struct.
std::vector<Mesh::AttribFormat> vertexformat = {
{getBuiltinAttribName(ATTRIB_POS), Mesh::DATA_FLOAT, 2},
{getBuiltinAttribName(ATTRIB_TEXCOORD), Mesh::DATA_FLOAT, 2},
{getBuiltinAttribName(ATTRIB_COLOR), Mesh::DATA_BYTE, 4},
};
return vertexformat;
}
love::Type Mesh::type("Mesh", &Drawable::type);
Mesh::Mesh(graphics::Graphics *gfx, const std::vector<AttribFormat> &vertexformat, const void *data, size_t datasize, DrawMode drawmode, vertex::Usage usage)
: vertexFormat(vertexformat)
, vbo(nullptr)
, vertexCount(0)
, vertexStride(0)
, ibo(nullptr)
, useIndexBuffer(false)
, elementCount(0)
, elementDataType(INDEX_UINT16)
, drawMode(drawmode)
, rangeStart(-1)
, rangeCount(-1)
{
setupAttachedAttributes();
calculateAttributeSizes();
vertexCount = datasize / vertexStride;
elementDataType = vertex::getIndexDataTypeFromMax(vertexCount);
if (vertexCount == 0)
throw love::Exception("Data size is too small for specified vertex attribute formats.");
vbo = gfx->newBuffer(datasize, data, BUFFER_VERTEX, usage, Buffer::MAP_EXPLICIT_RANGE_MODIFY | Buffer::MAP_READ);
vertexScratchBuffer = new char[vertexStride];
}
Mesh::Mesh(graphics::Graphics *gfx, const std::vector<AttribFormat> &vertexformat, int vertexcount, DrawMode drawmode, vertex::Usage usage)
: vertexFormat(vertexformat)
, vbo(nullptr)
, vertexCount((size_t) vertexcount)
, vertexStride(0)
, ibo(nullptr)
, useIndexBuffer(false)
, elementCount(0)
, elementDataType(vertex::getIndexDataTypeFromMax(vertexcount))
, drawMode(drawmode)
, rangeStart(-1)
, rangeCount(-1)
{
if (vertexcount <= 0)
throw love::Exception("Invalid number of vertices (%d).", vertexcount);
setupAttachedAttributes();
calculateAttributeSizes();
size_t buffersize = vertexCount * vertexStride;
vbo = gfx->newBuffer(buffersize, nullptr, BUFFER_VERTEX, usage, Buffer::MAP_EXPLICIT_RANGE_MODIFY | Buffer::MAP_READ);
// Initialize the buffer's contents to 0.
memset(vbo->map(), 0, buffersize);
vbo->setMappedRangeModified(0, vbo->getSize());
vbo->unmap();
vertexScratchBuffer = new char[vertexStride];
}
Mesh::~Mesh()
{
delete vbo;
delete ibo;
delete vertexScratchBuffer;
for (const auto &attrib : attachedAttributes)
{
if (attrib.second.mesh != this)
attrib.second.mesh->release();
}
}
void Mesh::setupAttachedAttributes()
{
for (size_t i = 0; i < vertexFormat.size(); i++)
{
const std::string &name = vertexFormat[i].name;
if (attachedAttributes.find(name) != attachedAttributes.end())
throw love::Exception("Duplicate vertex attribute name: %s", name.c_str());
attachedAttributes[name] = {this, (int) i, STEP_PER_VERTEX, true};
}
}
void Mesh::calculateAttributeSizes()
{
size_t stride = 0;
for (const AttribFormat &format : vertexFormat)
{
// Hardware really doesn't like attributes that aren't 32 bit-aligned.
if (format.type == DATA_BYTE && format.components != 4)
throw love::Exception("byte vertex attributes must have 4 components.");
if (format.components <= 0 || format.components > 4)
throw love::Exception("Vertex attributes must have between 1 and 4 components.");
// Total size in bytes of each attribute in a single vertex.
attributeSizes.push_back(getAttribFormatSize(format));
stride += attributeSizes.back();
}
vertexStride = stride;
}
size_t Mesh::getAttributeOffset(size_t attribindex) const
{
size_t offset = 0;
for (size_t i = 0; i < attribindex; i++)
offset += attributeSizes[i];
return offset;
}
void Mesh::setVertex(size_t vertindex, const void *data, size_t datasize)
{
if (vertindex >= vertexCount)
throw love::Exception("Invalid vertex index: %ld", vertindex + 1);
size_t offset = vertindex * vertexStride;
size_t size = std::min(datasize, vertexStride);
uint8 *bufferdata = (uint8 *) vbo->map();
memcpy(bufferdata + offset, data, size);
vbo->setMappedRangeModified(offset, size);
}
size_t Mesh::getVertex(size_t vertindex, void *data, size_t datasize)
{
if (vertindex >= vertexCount)
throw love::Exception("Invalid vertex index: %ld", vertindex + 1);
size_t offset = vertindex * vertexStride;
size_t size = std::min(datasize, vertexStride);
// We're relying on vbo->map() returning read/write data... ew.
const uint8 *bufferdata = (const uint8 *) vbo->map();
memcpy(data, bufferdata + offset, size);
return size;
}
void *Mesh::getVertexScratchBuffer()
{
return vertexScratchBuffer;
}
void Mesh::setVertexAttribute(size_t vertindex, int attribindex, const void *data, size_t datasize)
{
if (vertindex >= vertexCount)
throw love::Exception("Invalid vertex index: %ld", vertindex + 1);
if (attribindex >= (int) vertexFormat.size())
throw love::Exception("Invalid vertex attribute index: %d", attribindex + 1);
size_t offset = vertindex * vertexStride + getAttributeOffset(attribindex);
size_t size = std::min(datasize, attributeSizes[attribindex]);
uint8 *bufferdata = (uint8 *) vbo->map();
memcpy(bufferdata + offset, data, size);
vbo->setMappedRangeModified(offset, size);
}
size_t Mesh::getVertexAttribute(size_t vertindex, int attribindex, void *data, size_t datasize)
{
if (vertindex >= vertexCount)
throw love::Exception("Invalid vertex index: %ld", vertindex + 1);
if (attribindex >= (int) vertexFormat.size())
throw love::Exception("Invalid vertex attribute index: %d", attribindex + 1);
size_t offset = vertindex * vertexStride + getAttributeOffset(attribindex);
size_t size = std::min(datasize, attributeSizes[attribindex]);
// We're relying on vbo->map() returning read/write data... ew.
const uint8 *bufferdata = (const uint8 *) vbo->map();
memcpy(data, bufferdata + offset, size);
return size;
}
size_t Mesh::getVertexCount() const
{
return vertexCount;
}
size_t Mesh::getVertexStride() const
{
return vertexStride;
}
const std::vector<Mesh::AttribFormat> &Mesh::getVertexFormat() const
{
return vertexFormat;
}
Mesh::DataType Mesh::getAttributeInfo(int attribindex, int &components) const
{
if (attribindex < 0 || attribindex >= (int) vertexFormat.size())
throw love::Exception("Invalid vertex attribute index: %d", attribindex + 1);
DataType type = vertexFormat[attribindex].type;
components = vertexFormat[attribindex].components;
return type;
}
int Mesh::getAttributeIndex(const std::string &name) const
{
for (int i = 0; i < (int) vertexFormat.size(); i++)
{
if (vertexFormat[i].name == name)
return i;
}
return -1;
}
void Mesh::setAttributeEnabled(const std::string &name, bool enable)
{
auto it = attachedAttributes.find(name);
if (it == attachedAttributes.end())
throw love::Exception("Mesh does not have an attached vertex attribute named '%s'", name.c_str());
it->second.enabled = enable;
}
bool Mesh::isAttributeEnabled(const std::string &name) const
{
const auto it = attachedAttributes.find(name);
if (it == attachedAttributes.end())
throw love::Exception("Mesh does not have an attached vertex attribute named '%s'", name.c_str());
return it->second.enabled;
}
void Mesh::attachAttribute(const std::string &name, Mesh *mesh, const std::string &attachname, AttributeStep step)
{
auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS);
if (step == STEP_PER_INSTANCE && !gfx->isSupported(Graphics::FEATURE_INSTANCING))
throw love::Exception("Vertex attribute instancing is not supported on this system.");
if (mesh != this)
{
for (const auto &it : mesh->attachedAttributes)
{
// If the supplied Mesh has attached attributes of its own, then we
// prevent it from being attached to avoid reference cycles.
if (it.second.mesh != mesh)
throw love::Exception("Cannot attach a Mesh which has attached Meshes of its own.");
}
}
AttachedAttribute oldattrib = {};
AttachedAttribute newattrib = {};
auto it = attachedAttributes.find(name);
if (it != attachedAttributes.end())
oldattrib = it->second;
newattrib.mesh = mesh;
newattrib.enabled = oldattrib.mesh ? oldattrib.enabled : true;
newattrib.index = mesh->getAttributeIndex(attachname);
newattrib.step = step;
if (newattrib.index < 0)
throw love::Exception("The specified mesh does not have a vertex attribute named '%s'", attachname.c_str());
if (newattrib.mesh != this)
newattrib.mesh->retain();
attachedAttributes[name] = newattrib;
if (oldattrib.mesh && oldattrib.mesh != this)
oldattrib.mesh->release();
}
bool Mesh::detachAttribute(const std::string &name)
{
auto it = attachedAttributes.find(name);
if (it != attachedAttributes.end() && it->second.mesh != this)
{
it->second.mesh->release();
attachedAttributes.erase(it);
if (getAttributeIndex(name) != -1)
attachAttribute(name, this, name);
return true;
}
return false;
}
void *Mesh::mapVertexData()
{
return vbo->map();
}
void Mesh::unmapVertexData(size_t modifiedoffset, size_t modifiedsize)
{
vbo->setMappedRangeModified(modifiedoffset, modifiedsize);
vbo->unmap();
}
void Mesh::flush()
{
vbo->unmap();
if (ibo != nullptr)
ibo->unmap();
}
/**
* Copies index data from a vector to a mapped index buffer.
**/
template <typename T>
static void copyToIndexBuffer(const std::vector<uint32> &indices, Buffer::Mapper &buffermap, size_t maxval)
{
T *elems = (T *) buffermap.get();
for (size_t i = 0; i < indices.size(); i++)
{
if (indices[i] >= maxval)
throw love::Exception("Invalid vertex map value: %d", indices[i] + 1);
elems[i] = (T) indices[i];
}
}
void Mesh::setVertexMap(const std::vector<uint32> &map)
{
size_t maxval = getVertexCount();
IndexDataType datatype = vertex::getIndexDataTypeFromMax(maxval);
// Calculate the size in bytes of the index buffer data.
size_t size = map.size() * vertex::getIndexDataSize(datatype);
if (ibo && size > ibo->getSize())
{
delete ibo;
ibo = nullptr;
}
if (!ibo && size > 0)
{
auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
ibo = gfx->newBuffer(size, nullptr, BUFFER_INDEX, vbo->getUsage(), Buffer::MAP_READ);
}
useIndexBuffer = true;
elementCount = map.size();
if (!ibo || elementCount == 0)
return;
Buffer::Mapper ibomap(*ibo);
// Fill the buffer with the index values from the vector.
switch (datatype)
{
case INDEX_UINT16:
copyToIndexBuffer<uint16>(map, ibomap, maxval);
break;
case INDEX_UINT32:
default:
copyToIndexBuffer<uint32>(map, ibomap, maxval);
break;
}
elementDataType = datatype;
}
void Mesh::setVertexMap(IndexDataType datatype, const void *data, size_t datasize)
{
if (ibo && datasize > ibo->getSize())
{
delete ibo;
ibo = nullptr;
}
if (!ibo && datasize > 0)
{
auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
ibo = gfx->newBuffer(datasize, nullptr, BUFFER_INDEX, vbo->getUsage(), Buffer::MAP_READ);
}
elementCount = datasize / vertex::getIndexDataSize(datatype);
if (!ibo || elementCount == 0)
return;
Buffer::Mapper ibomap(*ibo);
memcpy(ibomap.get(), data, datasize);
useIndexBuffer = true;
elementDataType = datatype;
}
void Mesh::setVertexMap()
{
useIndexBuffer = false;
}
/**
* Copies index data from a mapped buffer to a vector.
**/
template <typename T>
static void copyFromIndexBuffer(void *buffer, size_t count, std::vector<uint32> &indices)
{
T *elems = (T *) buffer;
for (size_t i = 0; i < count; i++)
indices.push_back((uint32) elems[i]);
}
bool Mesh::getVertexMap(std::vector<uint32> &map) const
{
if (!useIndexBuffer)
return false;
map.clear();
map.reserve(elementCount);
if (!ibo || elementCount == 0)
return true;
// We unmap the buffer in Mesh::draw, Mesh::setVertexMap, and Mesh::flush.
void *buffer = ibo->map();
// Fill the vector from the buffer.
switch (elementDataType)
{
case INDEX_UINT16:
copyFromIndexBuffer<uint16>(buffer, elementCount, map);
break;
case INDEX_UINT32:
default:
copyFromIndexBuffer<uint32>(buffer, elementCount, map);
break;
}
return true;
}
size_t Mesh::getVertexMapCount() const
{
return elementCount;
}
void Mesh::setTexture(Texture *tex)
{
texture.set(tex);
}
void Mesh::setTexture()
{
texture.set(nullptr);
}
Texture *Mesh::getTexture() const
{
return texture.get();
}
void Mesh::setDrawMode(DrawMode mode)
{
drawMode = mode;
}
Mesh::DrawMode Mesh::getDrawMode() const
{
return drawMode;
}
void Mesh::setDrawRange(int start, int count)
{
if (start < 0 || count <= 0)
throw love::Exception("Invalid draw range.");
rangeStart = start;
rangeCount = count;
}
void Mesh::setDrawRange()
{
rangeStart = rangeCount = -1;
}
bool Mesh::getDrawRange(int &start, int &count) const
{
if (rangeStart < 0 || rangeCount <= 0)
return false;
start = rangeStart;
count = rangeCount;
return true;
}
void Mesh::draw(love::graphics::Graphics *gfx, const love::Matrix4 &m)
{
drawInstanced(gfx, m, 1);
}
size_t Mesh::getAttribFormatSize(const AttribFormat &format)
{
switch (format.type)
{
case DATA_BYTE:
return format.components * sizeof(uint8);
case DATA_FLOAT:
return format.components * sizeof(float);
default:
return 0;
}
}
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);
}
bool Mesh::getConstant(const char *in, DataType &out)
{
return dataTypes.find(in, out);
}
bool Mesh::getConstant(DataType in, const char *&out)
{
return dataTypes.find(in, out);
}
bool Mesh::getConstant(const char *in, AttributeStep &out)
{
return attributeSteps.find(in, out);
}
bool Mesh::getConstant(AttributeStep in, const char *&out)
{
return attributeSteps.find(in, out);
}
StringMap<Mesh::DrawMode, Mesh::DRAWMODE_MAX_ENUM>::Entry Mesh::drawModeEntries[] =
{
{ "fan", DRAWMODE_FAN },
{ "strip", DRAWMODE_STRIP },
{ "triangles", DRAWMODE_TRIANGLES },
{ "points", DRAWMODE_POINTS },
};
StringMap<Mesh::DrawMode, Mesh::DRAWMODE_MAX_ENUM> Mesh::drawModes(Mesh::drawModeEntries, sizeof(Mesh::drawModeEntries));
StringMap<Mesh::DataType, Mesh::DATA_MAX_ENUM>::Entry Mesh::dataTypeEntries[] =
{
{ "byte", DATA_BYTE },
{ "float", DATA_FLOAT },
};
StringMap<Mesh::DataType, Mesh::DATA_MAX_ENUM> Mesh::dataTypes(Mesh::dataTypeEntries, sizeof(Mesh::dataTypeEntries));
StringMap<Mesh::AttributeStep, Mesh::STEP_MAX_ENUM>::Entry Mesh::attributeStepEntries[] =
{
{ "pervertex", STEP_PER_VERTEX },
{ "perinstance", STEP_PER_INSTANCE },
};
StringMap<Mesh::AttributeStep, Mesh::STEP_MAX_ENUM> Mesh::attributeSteps(Mesh::attributeStepEntries, sizeof(Mesh::attributeStepEntries));
} // graphics
} // love
+270
View File
@@ -0,0 +1,270 @@
/**
* Copyright (c) 2006-2017 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.
**/
#pragma once
// LOVE
#include "common/config.h"
#include "common/int.h"
#include "common/math.h"
#include "common/StringMap.h"
#include "Drawable.h"
#include "Texture.h"
#include "vertex.h"
#include "Buffer.h"
// C++
#include <vector>
#include <unordered_map>
namespace love
{
namespace graphics
{
class Graphics;
/**
* Holds and draws arbitrary vertex geometry.
* Each vertex in the Mesh has a collection of vertex attributes specified on
* creation.
**/
class Mesh : public Drawable
{
public:
static love::Type type;
// How the Mesh's vertices are used when drawing.
// http://escience.anu.edu.au/lecture/cg/surfaceModeling/image/surfaceModeling015.png
enum DrawMode
{
DRAWMODE_FAN,
DRAWMODE_STRIP,
DRAWMODE_TRIANGLES,
DRAWMODE_POINTS,
DRAWMODE_MAX_ENUM
};
// The type of data a vertex attribute can store.
enum DataType
{
DATA_BYTE,
DATA_FLOAT,
DATA_MAX_ENUM
};
enum AttributeStep
{
STEP_PER_VERTEX,
STEP_PER_INSTANCE,
STEP_MAX_ENUM
};
struct AttribFormat
{
std::string name;
DataType type;
int components; // max 4
};
Mesh(Graphics *gfx, const std::vector<AttribFormat> &vertexformat, const void *data, size_t datasize, DrawMode drawmode, vertex::Usage usage);
Mesh(Graphics *gfx, const std::vector<AttribFormat> &vertexformat, int vertexcount, DrawMode drawmode, vertex::Usage usage);
virtual ~Mesh();
/**
* Sets the values of all attributes at a specific vertex index in the Mesh.
* The size of the data must be less than or equal to the total size of all
* vertex attributes.
**/
void setVertex(size_t vertindex, const void *data, size_t datasize);
size_t getVertex(size_t vertindex, void *data, size_t datasize);
void *getVertexScratchBuffer();
/**
* Sets the values for a single attribute at a specific vertex index in the
* Mesh. The size of the data must be less than or equal to the size of the
* attribute.
**/
void setVertexAttribute(size_t vertindex, int attribindex, const void *data, size_t datasize);
size_t getVertexAttribute(size_t vertindex, int attribindex, void *data, size_t datasize);
/**
* Gets the total number of vertices that can be used when drawing the Mesh.
**/
size_t getVertexCount() const;
/**
* Gets the size in bytes of the start of one vertex to the start of the
* next, in the buffer.
**/
size_t getVertexStride() const;
/**
* Gets the format of each vertex attribute stored in the Mesh.
**/
const std::vector<AttribFormat> &getVertexFormat() const;
DataType getAttributeInfo(int attribindex, int &components) const;
int getAttributeIndex(const std::string &name) const;
/**
* Sets whether a specific vertex attribute is used when drawing the Mesh.
**/
void setAttributeEnabled(const std::string &name, bool enable);
bool isAttributeEnabled(const std::string &name) const;
/**
* Attaches a vertex attribute from another Mesh to this one. The attribute
* will be used when drawing this Mesh.
**/
void attachAttribute(const std::string &name, Mesh *mesh, const std::string &attachname, AttributeStep step = STEP_PER_VERTEX);
bool detachAttribute(const std::string &name);
void *mapVertexData();
void unmapVertexData(size_t modifiedoffset = 0, size_t modifiedsize = -1);
/**
* Flushes all modified data to the GPU.
**/
void flush();
/**
* 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);
void setVertexMap(IndexDataType datatype, const void *data, size_t datasize);
void setVertexMap();
/**
* Fills the uint32 vector passed into the method with the previously set
* vertex map (index buffer) values.
**/
bool getVertexMap(std::vector<uint32> &map) const;
/**
* Gets the total number of elements in the vertex map array.
**/
size_t getVertexMapCount() const;
/**
* Sets the texture used when drawing the Mesh.
**/
void setTexture(Texture *texture);
/**
* Disables any texture from being used when drawing the Mesh.
**/
void setTexture();
/**
* Gets the texture used when drawing the Mesh. May return null if no
* texture is set.
**/
Texture *getTexture() const;
/**
* Sets the draw mode used when drawing the Mesh.
**/
void setDrawMode(DrawMode mode);
DrawMode getDrawMode() const;
void setDrawRange(int start, int count);
void setDrawRange();
bool getDrawRange(int &start, int &count) const;
virtual int bindAttributeToShaderInput(int attributeindex, const std::string &inputname) = 0;
virtual void drawInstanced(Graphics *gfx, const Matrix4 &m, int instancecount) = 0;
// Implements Drawable.
void draw(Graphics *gfx, const Matrix4 &m) override;
static bool getConstant(const char *in, DrawMode &out);
static bool getConstant(DrawMode in, const char *&out);
static bool getConstant(const char *in, DataType &out);
static bool getConstant(DataType in, const char *&out);
static bool getConstant(const char *in, AttributeStep &out);
static bool getConstant(AttributeStep in, const char *&out);
protected:
struct AttachedAttribute
{
Mesh *mesh;
int index;
AttributeStep step;
bool enabled;
};
void setupAttachedAttributes();
void calculateAttributeSizes();
size_t getAttributeOffset(size_t attribindex) const;
static size_t getAttribFormatSize(const AttribFormat &format);
static std::vector<AttribFormat> getDefaultVertexFormat();
std::vector<AttribFormat> vertexFormat;
std::vector<size_t> attributeSizes;
std::unordered_map<std::string, AttachedAttribute> attachedAttributes;
// Vertex buffer, for the vertex data.
Buffer *vbo;
size_t vertexCount;
size_t vertexStride;
// Block of memory whose size is at least as large as a single vertex. Helps
// avoid memory allocations when using Mesh::setVertex etc.
char *vertexScratchBuffer;
// Element (vertex index) buffer, for the vertex map.
Buffer *ibo;
bool useIndexBuffer;
size_t elementCount;
IndexDataType elementDataType;
DrawMode drawMode;
int rangeStart;
int rangeCount;
StrongRef<Texture> texture;
private:
static StringMap<DrawMode, DRAWMODE_MAX_ENUM>::Entry drawModeEntries[];
static StringMap<DrawMode, DRAWMODE_MAX_ENUM> drawModes;
static StringMap<DataType, DATA_MAX_ENUM>::Entry dataTypeEntries[];
static StringMap<DataType, DATA_MAX_ENUM> dataTypes;
static StringMap<AttributeStep, STEP_MAX_ENUM>::Entry attributeStepEntries[];
static StringMap<AttributeStep, STEP_MAX_ENUM> attributeSteps;
}; // Mesh
} // graphics
} // love
+258
View File
@@ -0,0 +1,258 @@
/**
* Copyright (c) 2006-2017 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 "common/config.h"
#include "SpriteBatch.h"
// LOVE
#include "Texture.h"
#include "Quad.h"
#include "Graphics.h"
#include "Buffer.h"
// C++
#include <algorithm>
// C
#include <stddef.h>
namespace love
{
namespace graphics
{
love::Type SpriteBatch::type("SpriteBatch", &Drawable::type);
SpriteBatch::SpriteBatch(Graphics *gfx, Texture *texture, int size, vertex::Usage usage)
: texture(texture)
, size(size)
, next(0)
, color(0)
, array_buf(nullptr)
, quad_indices(gfx, size)
, range_start(-1)
, range_count(-1)
{
if (size <= 0)
throw love::Exception("Invalid SpriteBatch size.");
size_t vertex_size = sizeof(Vertex) * 4 * size;
array_buf = gfx->newBuffer(vertex_size, nullptr, BUFFER_VERTEX, usage, Buffer::MAP_EXPLICIT_RANGE_MODIFY);
}
SpriteBatch::~SpriteBatch()
{
delete color;
delete array_buf;
}
int SpriteBatch::add(const Matrix4 &m, int index /*= -1*/)
{
if (index < -1 || index >= size)
throw love::Exception("Invalid sprite index: %d", index + 1);
if (index == -1 && next >= size)
setBufferSize(size * 2);
addv(texture->getVertices(), m, (index == -1) ? next : index);
// Increment counter.
if (index == -1)
return next++;
return index;
}
int SpriteBatch::addq(Quad *quad, const Matrix4 &m, int index /*= -1*/)
{
if (index < -1 || index >= size)
throw love::Exception("Invalid sprite index: %d", index + 1);
if (index == -1 && next >= size)
setBufferSize(size * 2);
addv(quad->getVertices(), m, (index == -1) ? next : index);
// Increment counter.
if (index == -1)
return next++;
return index;
}
void SpriteBatch::clear()
{
// Reset the position of the next index.
next = 0;
}
void SpriteBatch::flush()
{
array_buf->unmap();
}
void SpriteBatch::setTexture(Texture *newtexture)
{
texture.set(newtexture);
}
Texture *SpriteBatch::getTexture() const
{
return texture.get();
}
void SpriteBatch::setColor(const Color &color)
{
if (!this->color)
this->color = new Color(color);
else
*(this->color) = color;
}
void SpriteBatch::setColor()
{
delete color;
color = nullptr;
}
const Color *SpriteBatch::getColor() const
{
return color;
}
int SpriteBatch::getCount() const
{
return next;
}
void SpriteBatch::setBufferSize(int newsize)
{
if (newsize <= 0)
throw love::Exception("Invalid SpriteBatch size.");
if (newsize == size)
return;
size_t vertex_size = sizeof(Vertex) * 4 * newsize;
love::graphics::Buffer *new_array_buf = nullptr;
int new_next = std::min(next, newsize);
try
{
auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
new_array_buf = gfx->newBuffer(vertex_size, nullptr, array_buf->getType(), array_buf->getUsage(), array_buf->getMapFlags());
// Copy as much of the old data into the new GLBuffer as can fit.
size_t copy_size = sizeof(Vertex) * 4 * new_next;
array_buf->copyTo(0, copy_size, new_array_buf, 0);
quad_indices = QuadIndices(gfx, newsize);
}
catch (love::Exception &)
{
delete new_array_buf;
throw;
}
// We don't need to unmap the old GLBuffer since we're deleting it.
delete array_buf;
array_buf = new_array_buf;
size = newsize;
next = new_next;
}
int SpriteBatch::getBufferSize() const
{
return size;
}
void SpriteBatch::attachAttribute(const std::string &name, Mesh *mesh)
{
AttachedAttribute oldattrib = {};
AttachedAttribute newattrib = {};
if (mesh->getVertexCount() < (size_t) next * 4)
throw love::Exception("Mesh has too few vertices to be attached to this SpriteBatch (at least %d vertices are required)", next*4);
auto it = attached_attributes.find(name);
if (it != attached_attributes.end())
oldattrib = it->second;
newattrib.index = mesh->getAttributeIndex(name);
if (newattrib.index < 0)
throw love::Exception("The specified mesh does not have a vertex attribute named '%s'", name.c_str());
newattrib.mesh = mesh;
attached_attributes[name] = newattrib;
}
void SpriteBatch::setDrawRange(int start, int count)
{
if (start < 0 || count <= 0)
throw love::Exception("Invalid draw range.");
range_start = start;
range_count = count;
}
void SpriteBatch::setDrawRange()
{
range_start = range_count = -1;
}
bool SpriteBatch::getDrawRange(int &start, int &count) const
{
if (range_start < 0 || range_count <= 0)
return false;
start = range_start;
count = range_count;
return true;
}
void SpriteBatch::addv(const Vertex *v, const Matrix4 &m, int index)
{
// Needed for colors.
Vertex sprite[4] = {v[0], v[1], v[2], v[3]};
const size_t sprite_size = 4 * sizeof(Vertex); // bytecount
m.transform(sprite, sprite, 4);
if (color != nullptr)
{
for (int i = 0; i < 4; i++)
sprite[i].color = *color;
}
// Always keep the VBO mapped when adding data for now (it'll be unmapped
// on draw.)
array_buf->map();
array_buf->fill(index * sprite_size, sprite_size, sprite);
}
} // graphics
} // love
+145
View File
@@ -0,0 +1,145 @@
/**
* Copyright (c) 2006-2017 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.
**/
#pragma once
// C
#include <cstring>
// C++
#include <unordered_map>
// LOVE
#include "common/math.h"
#include "common/Matrix.h"
#include "Drawable.h"
#include "Color.h"
#include "Mesh.h"
namespace love
{
namespace graphics
{
// Forward declarations.
class Graphics;
class Texture;
class Quad;
class Buffer;
class SpriteBatch : public Drawable
{
public:
static love::Type type;
SpriteBatch(Graphics *gfx, Texture *texture, int size, vertex::Usage usage);
virtual ~SpriteBatch();
int add(const Matrix4 &m, int index = -1);
int addq(Quad *quad, const Matrix4 &m, int index = -1);
void clear();
void flush();
void setTexture(Texture *newtexture);
Texture *getTexture() const;
/**
* 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 sprites.
*/
void setColor(const Color &color);
/**
* Disable per-sprite colors for this SpriteBatch. The next call to
* draw will use the global color for all sprites.
*/
void setColor();
/**
* Get the current color for this SpriteBatch. Returns NULL if no color is
* set.
**/
const Color *getColor() const;
/**
* Get the number of sprites currently in this SpriteBatch.
**/
int getCount() const;
/**
* Get the total number of sprites this SpriteBatch can currently hold.
**/
int getBufferSize() const;
/**
* Attaches a specific vertex attribute from a Mesh to this SpriteBatch.
* The vertex attribute will be used when drawing the SpriteBatch.
**/
void attachAttribute(const std::string &name, Mesh *mesh);
void setDrawRange(int start, int count);
void setDrawRange();
bool getDrawRange(int &start, int &count) const;
protected:
struct AttachedAttribute
{
StrongRef<Mesh> mesh;
int index;
};
/**
* Sets the total number of sprites this SpriteBatch can hold.
* Leaves existing sprite data intact when possible.
**/
void setBufferSize(int newsize);
void addv(const Vertex *v, const Matrix4 &m, int index);
StrongRef<Texture> texture;
// Max number of sprites in the batch.
int size;
// The next free element.
int next;
// Current color. This color, if present, will be applied to the next
// added sprite.
Color *color;
love::graphics::Buffer *array_buf;
QuadIndices quad_indices;
std::unordered_map<std::string, AttachedAttribute> attached_attributes;
int range_start;
int range_count;
}; // SpriteBatch
} // graphics
} // love
+6 -11
View File
@@ -118,12 +118,12 @@ graphics::Font *Graphics::newFont(love::font::Rasterizer *r, const Texture::Filt
return new Font(r, filter);
}
SpriteBatch *Graphics::newSpriteBatch(Texture *texture, int size, vertex::Usage usage)
love::graphics::SpriteBatch *Graphics::newSpriteBatch(Texture *texture, int size, vertex::Usage usage)
{
return new SpriteBatch(this, texture, size, usage);
}
ParticleSystem *Graphics::newParticleSystem(Texture *texture, int size)
love::graphics::ParticleSystem *Graphics::newParticleSystem(Texture *texture, int size)
{
return new ParticleSystem(this, texture, size);
}
@@ -167,22 +167,22 @@ love::graphics::Buffer *Graphics::newBuffer(size_t size, const void *data, Buffe
return new Buffer(size, data, type, usage, mapflags);
}
Mesh *Graphics::newMesh(const std::vector<Vertex> &vertices, Mesh::DrawMode drawmode, vertex::Usage usage)
love::graphics::Mesh *Graphics::newMesh(const std::vector<Vertex> &vertices, Mesh::DrawMode drawmode, vertex::Usage usage)
{
return new Mesh(this, vertices, drawmode, usage);
}
Mesh *Graphics::newMesh(int vertexcount, Mesh::DrawMode drawmode, vertex::Usage usage)
love::graphics::Mesh *Graphics::newMesh(int vertexcount, Mesh::DrawMode drawmode, vertex::Usage usage)
{
return new Mesh(this, vertexcount, drawmode, usage);
}
Mesh *Graphics::newMesh(const std::vector<Mesh::AttribFormat> &vertexformat, int vertexcount, Mesh::DrawMode drawmode, vertex::Usage usage)
love::graphics::Mesh *Graphics::newMesh(const std::vector<Mesh::AttribFormat> &vertexformat, int vertexcount, Mesh::DrawMode drawmode, vertex::Usage usage)
{
return new Mesh(this, vertexformat, vertexcount, drawmode, usage);
}
Mesh *Graphics::newMesh(const std::vector<Mesh::AttribFormat> &vertexformat, const void *data, size_t datasize, Mesh::DrawMode drawmode, vertex::Usage usage)
love::graphics::Mesh *Graphics::newMesh(const std::vector<Mesh::AttribFormat> &vertexformat, const void *data, size_t datasize, Mesh::DrawMode drawmode, vertex::Usage usage)
{
return new Mesh(this, vertexformat, data, datasize, drawmode, usage);
}
@@ -498,11 +498,6 @@ void Graphics::flushStreamDraws()
streamBufferState.indexCount = 0;
}
void Graphics::drawInstanced(Mesh *mesh, const love::Matrix4 &m, int instancecount)
{
mesh->drawInstanced(this, m, instancecount);
}
static void APIENTRY debugCB(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei /*len*/, const GLchar *msg, const GLvoid* /*usr*/)
{
// Human-readable strings for the debug info.
+6 -8
View File
@@ -66,9 +66,9 @@ public:
love::graphics::Font *newFont(love::font::Rasterizer *data, const Texture::Filter &filter = Texture::defaultFilter) override;
SpriteBatch *newSpriteBatch(Texture *texture, int size, vertex::Usage usage);
love::graphics::SpriteBatch *newSpriteBatch(Texture *texture, int size, vertex::Usage usage) override;
ParticleSystem *newParticleSystem(Texture *texture, int size);
love::graphics::ParticleSystem *newParticleSystem(Texture *texture, int size) override;
love::graphics::Canvas *newCanvas(int width, int height, const Canvas::Settings &settings) override;
@@ -76,11 +76,11 @@ public:
love::graphics::Buffer *newBuffer(size_t size, const void *data, BufferType type, vertex::Usage usage, uint32 mapflags) override;
Mesh *newMesh(const std::vector<Vertex> &vertices, Mesh::DrawMode drawmode, vertex::Usage usage);
Mesh *newMesh(int vertexcount, Mesh::DrawMode drawmode, vertex::Usage usage);
love::graphics::Mesh *newMesh(const std::vector<Vertex> &vertices, Mesh::DrawMode drawmode, vertex::Usage usage) override;
love::graphics::Mesh *newMesh(int vertexcount, Mesh::DrawMode drawmode, vertex::Usage usage) override;
Mesh *newMesh(const std::vector<Mesh::AttribFormat> &vertexformat, int vertexcount, Mesh::DrawMode drawmode, vertex::Usage usage);
Mesh *newMesh(const std::vector<Mesh::AttribFormat> &vertexformat, const void *data, size_t datasize, Mesh::DrawMode drawmode, vertex::Usage usage);
love::graphics::Mesh *newMesh(const std::vector<Mesh::AttribFormat> &vertexformat, int vertexcount, Mesh::DrawMode drawmode, vertex::Usage usage) override;
love::graphics::Mesh *newMesh(const std::vector<Mesh::AttribFormat> &vertexformat, const void *data, size_t datasize, Mesh::DrawMode drawmode, vertex::Usage usage) override;
love::graphics::Text *newText(love::graphics::Font *font, const std::vector<Font::ColoredString> &text = {}) override;
@@ -94,8 +94,6 @@ public:
void flushStreamDraws() override;
void drawInstanced(Mesh *mesh, const Matrix4 &m, int instancecount);
void clear(Colorf color) override;
void clear(const std::vector<OptionalColorf> &colors) override;
+3 -593
View File
@@ -20,7 +20,6 @@
// LOVE
#include "Mesh.h"
#include "common/Matrix.h"
#include "common/Exception.h"
#include "Shader.h"
#include "graphics/Graphics.h"
@@ -36,87 +35,14 @@ namespace graphics
namespace opengl
{
static const char *getBuiltinAttribName(VertexAttribID attribid)
{
const char *name = "";
vertex::getConstant(attribid, name);
return name;
}
static_assert(offsetof(Vertex, x) == sizeof(float) * 0, "Incorrect position offset in Vertex struct");
static_assert(offsetof(Vertex, s) == sizeof(float) * 2, "Incorrect texture coordinate offset in Vertex struct");
static_assert(offsetof(Vertex, color.r) == sizeof(float) * 4, "Incorrect color offset in Vertex struct");
static std::vector<Mesh::AttribFormat> getDefaultVertexFormat()
{
// Corresponds to the love::Vertex struct.
std::vector<Mesh::AttribFormat> vertexformat = {
{getBuiltinAttribName(ATTRIB_POS), Mesh::DATA_FLOAT, 2},
{getBuiltinAttribName(ATTRIB_TEXCOORD), Mesh::DATA_FLOAT, 2},
{getBuiltinAttribName(ATTRIB_COLOR), Mesh::DATA_BYTE, 4},
};
return vertexformat;
}
love::Type Mesh::type("Mesh", &Drawable::type);
Mesh::Mesh(graphics::Graphics *gfx, const std::vector<AttribFormat> &vertexformat, const void *data, size_t datasize, DrawMode drawmode, vertex::Usage usage)
: vertexFormat(vertexformat)
, vbo(nullptr)
, vertexCount(0)
, vertexStride(0)
, ibo(nullptr)
, useIndexBuffer(false)
, elementCount(0)
, elementDataType(INDEX_UINT16)
, drawMode(drawmode)
, rangeStart(-1)
, rangeCount(-1)
: love::graphics::Mesh(gfx, vertexformat, data, datasize, drawmode, usage)
{
setupAttachedAttributes();
calculateAttributeSizes();
vertexCount = datasize / vertexStride;
elementDataType = vertex::getIndexDataTypeFromMax(vertexCount);
if (vertexCount == 0)
throw love::Exception("Data size is too small for specified vertex attribute formats.");
vbo = gfx->newBuffer(datasize, data, BUFFER_VERTEX, usage, Buffer::MAP_EXPLICIT_RANGE_MODIFY | Buffer::MAP_READ);
vertexScratchBuffer = new char[vertexStride];
}
Mesh::Mesh(graphics::Graphics *gfx, const std::vector<AttribFormat> &vertexformat, int vertexcount, DrawMode drawmode, vertex::Usage usage)
: vertexFormat(vertexformat)
, vbo(nullptr)
, vertexCount((size_t) vertexcount)
, vertexStride(0)
, ibo(nullptr)
, useIndexBuffer(false)
, elementCount(0)
, elementDataType(vertex::getIndexDataTypeFromMax(vertexcount))
, drawMode(drawmode)
, rangeStart(-1)
, rangeCount(-1)
: love::graphics::Mesh(gfx, vertexformat, vertexcount, drawmode, usage)
{
if (vertexcount <= 0)
throw love::Exception("Invalid number of vertices (%d).", vertexcount);
setupAttachedAttributes();
calculateAttributeSizes();
size_t buffersize = vertexCount * vertexStride;
vbo = gfx->newBuffer(buffersize, nullptr, BUFFER_VERTEX, usage, Buffer::MAP_EXPLICIT_RANGE_MODIFY | Buffer::MAP_READ);
// Initialize the buffer's contents to 0.
memset(vbo->map(), 0, buffersize);
vbo->setMappedRangeModified(0, vbo->getSize());
vbo->unmap();
vertexScratchBuffer = new char[vertexStride];
}
Mesh::Mesh(graphics::Graphics *gfx, const std::vector<Vertex> &vertices, DrawMode drawmode, vertex::Usage usage)
@@ -131,448 +57,6 @@ Mesh::Mesh(graphics::Graphics *gfx, int vertexcount, DrawMode drawmode, vertex::
Mesh::~Mesh()
{
delete vbo;
delete ibo;
delete vertexScratchBuffer;
for (const auto &attrib : attachedAttributes)
{
if (attrib.second.mesh != this)
attrib.second.mesh->release();
}
}
void Mesh::setupAttachedAttributes()
{
for (size_t i = 0; i < vertexFormat.size(); i++)
{
const std::string &name = vertexFormat[i].name;
if (attachedAttributes.find(name) != attachedAttributes.end())
throw love::Exception("Duplicate vertex attribute name: %s", name.c_str());
attachedAttributes[name] = {this, (int) i, STEP_PER_VERTEX, true};
}
}
void Mesh::calculateAttributeSizes()
{
size_t stride = 0;
for (const AttribFormat &format : vertexFormat)
{
// Hardware really doesn't like attributes that aren't 32 bit-aligned.
if (format.type == DATA_BYTE && format.components != 4)
throw love::Exception("byte vertex attributes must have 4 components.");
if (format.components <= 0 || format.components > 4)
throw love::Exception("Vertex attributes must have between 1 and 4 components.");
// Total size in bytes of each attribute in a single vertex.
attributeSizes.push_back(getAttribFormatSize(format));
stride += attributeSizes.back();
}
vertexStride = stride;
}
size_t Mesh::getAttributeOffset(size_t attribindex) const
{
size_t offset = 0;
for (size_t i = 0; i < attribindex; i++)
offset += attributeSizes[i];
return offset;
}
void Mesh::setVertex(size_t vertindex, const void *data, size_t datasize)
{
if (vertindex >= vertexCount)
throw love::Exception("Invalid vertex index: %ld", vertindex + 1);
size_t offset = vertindex * vertexStride;
size_t size = std::min(datasize, vertexStride);
uint8 *bufferdata = (uint8 *) vbo->map();
memcpy(bufferdata + offset, data, size);
vbo->setMappedRangeModified(offset, size);
}
size_t Mesh::getVertex(size_t vertindex, void *data, size_t datasize)
{
if (vertindex >= vertexCount)
throw love::Exception("Invalid vertex index: %ld", vertindex + 1);
size_t offset = vertindex * vertexStride;
size_t size = std::min(datasize, vertexStride);
// We're relying on vbo->map() returning read/write data... ew.
const uint8 *bufferdata = (const uint8 *) vbo->map();
memcpy(data, bufferdata + offset, size);
return size;
}
void *Mesh::getVertexScratchBuffer()
{
return vertexScratchBuffer;
}
void Mesh::setVertexAttribute(size_t vertindex, int attribindex, const void *data, size_t datasize)
{
if (vertindex >= vertexCount)
throw love::Exception("Invalid vertex index: %ld", vertindex + 1);
if (attribindex >= (int) vertexFormat.size())
throw love::Exception("Invalid vertex attribute index: %d", attribindex + 1);
size_t offset = vertindex * vertexStride + getAttributeOffset(attribindex);
size_t size = std::min(datasize, attributeSizes[attribindex]);
uint8 *bufferdata = (uint8 *) vbo->map();
memcpy(bufferdata + offset, data, size);
vbo->setMappedRangeModified(offset, size);
}
size_t Mesh::getVertexAttribute(size_t vertindex, int attribindex, void *data, size_t datasize)
{
if (vertindex >= vertexCount)
throw love::Exception("Invalid vertex index: %ld", vertindex + 1);
if (attribindex >= (int) vertexFormat.size())
throw love::Exception("Invalid vertex attribute index: %d", attribindex + 1);
size_t offset = vertindex * vertexStride + getAttributeOffset(attribindex);
size_t size = std::min(datasize, attributeSizes[attribindex]);
// We're relying on vbo->map() returning read/write data... ew.
const uint8 *bufferdata = (const uint8 *) vbo->map();
memcpy(data, bufferdata + offset, size);
return size;
}
size_t Mesh::getVertexCount() const
{
return vertexCount;
}
size_t Mesh::getVertexStride() const
{
return vertexStride;
}
const std::vector<Mesh::AttribFormat> &Mesh::getVertexFormat() const
{
return vertexFormat;
}
Mesh::DataType Mesh::getAttributeInfo(int attribindex, int &components) const
{
if (attribindex < 0 || attribindex >= (int) vertexFormat.size())
throw love::Exception("Invalid vertex attribute index: %d", attribindex + 1);
DataType type = vertexFormat[attribindex].type;
components = vertexFormat[attribindex].components;
return type;
}
int Mesh::getAttributeIndex(const std::string &name) const
{
for (int i = 0; i < (int) vertexFormat.size(); i++)
{
if (vertexFormat[i].name == name)
return i;
}
return -1;
}
void Mesh::setAttributeEnabled(const std::string &name, bool enable)
{
auto it = attachedAttributes.find(name);
if (it == attachedAttributes.end())
throw love::Exception("Mesh does not have an attached vertex attribute named '%s'", name.c_str());
it->second.enabled = enable;
}
bool Mesh::isAttributeEnabled(const std::string &name) const
{
const auto it = attachedAttributes.find(name);
if (it == attachedAttributes.end())
throw love::Exception("Mesh does not have an attached vertex attribute named '%s'", name.c_str());
return it->second.enabled;
}
void Mesh::attachAttribute(const std::string &name, Mesh *mesh, const std::string &attachname, AttributeStep step)
{
if (step == STEP_PER_INSTANCE && !gl.isInstancingSupported())
throw love::Exception("Vertex attribute instancing is not supported on this system.");
if (mesh != this)
{
for (const auto &it : mesh->attachedAttributes)
{
// If the supplied Mesh has attached attributes of its own, then we
// prevent it from being attached to avoid reference cycles.
if (it.second.mesh != mesh)
throw love::Exception("Cannot attach a Mesh which has attached Meshes of its own.");
}
}
AttachedAttribute oldattrib = {};
AttachedAttribute newattrib = {};
auto it = attachedAttributes.find(name);
if (it != attachedAttributes.end())
oldattrib = it->second;
newattrib.mesh = mesh;
newattrib.enabled = oldattrib.mesh ? oldattrib.enabled : true;
newattrib.index = mesh->getAttributeIndex(attachname);
newattrib.step = step;
if (newattrib.index < 0)
throw love::Exception("The specified mesh does not have a vertex attribute named '%s'", attachname.c_str());
if (newattrib.mesh != this)
newattrib.mesh->retain();
attachedAttributes[name] = newattrib;
if (oldattrib.mesh && oldattrib.mesh != this)
oldattrib.mesh->release();
}
bool Mesh::detachAttribute(const std::string &name)
{
auto it = attachedAttributes.find(name);
if (it != attachedAttributes.end() && it->second.mesh != this)
{
it->second.mesh->release();
attachedAttributes.erase(it);
if (getAttributeIndex(name) != -1)
attachAttribute(name, this, name);
return true;
}
return false;
}
void *Mesh::mapVertexData()
{
return vbo->map();
}
void Mesh::unmapVertexData(size_t modifiedoffset, size_t modifiedsize)
{
vbo->setMappedRangeModified(modifiedoffset, modifiedsize);
vbo->unmap();
}
void Mesh::flush()
{
vbo->unmap();
if (ibo != nullptr)
ibo->unmap();
}
/**
* Copies index data from a vector to a mapped index buffer.
**/
template <typename T>
static void copyToIndexBuffer(const std::vector<uint32> &indices, Buffer::Mapper &buffermap, size_t maxval)
{
T *elems = (T *) buffermap.get();
for (size_t i = 0; i < indices.size(); i++)
{
if (indices[i] >= maxval)
throw love::Exception("Invalid vertex map value: %d", indices[i] + 1);
elems[i] = (T) indices[i];
}
}
void Mesh::setVertexMap(const std::vector<uint32> &map)
{
size_t maxval = getVertexCount();
IndexDataType datatype = vertex::getIndexDataTypeFromMax(maxval);
// Calculate the size in bytes of the index buffer data.
size_t size = map.size() * vertex::getIndexDataSize(datatype);
if (ibo && size > ibo->getSize())
{
delete ibo;
ibo = nullptr;
}
if (!ibo && size > 0)
{
auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
ibo = gfx->newBuffer(size, nullptr, BUFFER_INDEX, vbo->getUsage(), Buffer::MAP_READ);
}
useIndexBuffer = true;
elementCount = map.size();
if (!ibo || elementCount == 0)
return;
Buffer::Mapper ibomap(*ibo);
// Fill the buffer with the index values from the vector.
switch (datatype)
{
case INDEX_UINT16:
copyToIndexBuffer<uint16>(map, ibomap, maxval);
break;
case INDEX_UINT32:
default:
copyToIndexBuffer<uint32>(map, ibomap, maxval);
break;
}
elementDataType = datatype;
}
void Mesh::setVertexMap(IndexDataType datatype, const void *data, size_t datasize)
{
if (ibo && datasize > ibo->getSize())
{
delete ibo;
ibo = nullptr;
}
if (!ibo && datasize > 0)
{
auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
ibo = gfx->newBuffer(datasize, nullptr, BUFFER_INDEX, vbo->getUsage(), Buffer::MAP_READ);
}
elementCount = datasize / vertex::getIndexDataSize(datatype);
if (!ibo || elementCount == 0)
return;
Buffer::Mapper ibomap(*ibo);
memcpy(ibomap.get(), data, datasize);
useIndexBuffer = true;
elementDataType = datatype;
}
void Mesh::setVertexMap()
{
useIndexBuffer = false;
}
/**
* Copies index data from a mapped buffer to a vector.
**/
template <typename T>
static void copyFromIndexBuffer(void *buffer, size_t count, std::vector<uint32> &indices)
{
T *elems = (T *) buffer;
for (size_t i = 0; i < count; i++)
indices.push_back((uint32) elems[i]);
}
bool Mesh::getVertexMap(std::vector<uint32> &map) const
{
if (!useIndexBuffer)
return false;
map.clear();
map.reserve(elementCount);
if (!ibo || elementCount == 0)
return true;
// We unmap the buffer in Mesh::draw, Mesh::setVertexMap, and Mesh::flush.
void *buffer = ibo->map();
// Fill the vector from the buffer.
switch (elementDataType)
{
case INDEX_UINT16:
copyFromIndexBuffer<uint16>(buffer, elementCount, map);
break;
case INDEX_UINT32:
default:
copyFromIndexBuffer<uint32>(buffer, elementCount, map);
break;
}
return true;
}
size_t Mesh::getVertexMapCount() const
{
return elementCount;
}
void Mesh::setTexture(Texture *tex)
{
texture.set(tex);
}
void Mesh::setTexture()
{
texture.set(nullptr);
}
Texture *Mesh::getTexture() const
{
return texture.get();
}
void Mesh::setDrawMode(DrawMode mode)
{
drawMode = mode;
}
Mesh::DrawMode Mesh::getDrawMode() const
{
return drawMode;
}
void Mesh::setDrawRange(int start, int count)
{
if (start < 0 || count <= 0)
throw love::Exception("Invalid draw range.");
rangeStart = start;
rangeCount = count;
}
void Mesh::setDrawRange()
{
rangeStart = rangeCount = -1;
}
bool Mesh::getDrawRange(int &start, int &count) const
{
if (rangeStart < 0 || rangeCount <= 0)
return false;
start = rangeStart;
count = rangeCount;
return true;
}
int Mesh::bindAttributeToShaderInput(int attributeindex, const std::string &inputname)
@@ -627,7 +111,7 @@ void Mesh::drawInstanced(love::graphics::Graphics *gfx, const love::Matrix4 &m,
if (!attrib.second.enabled)
continue;
Mesh *mesh = attrib.second.mesh;
love::graphics::Mesh *mesh = attrib.second.mesh;
int location = mesh->bindAttributeToShaderInput(attrib.second.index, attrib.first);
if (location >= 0)
@@ -692,24 +176,6 @@ void Mesh::drawInstanced(love::graphics::Graphics *gfx, const love::Matrix4 &m,
}
}
void Mesh::draw(love::graphics::Graphics *gfx, const love::Matrix4 &m)
{
drawInstanced(gfx, m, 1);
}
size_t Mesh::getAttribFormatSize(const AttribFormat &format)
{
switch (format.type)
{
case DATA_BYTE:
return format.components * sizeof(uint8);
case DATA_FLOAT:
return format.components * sizeof(float);
default:
return 0;
}
}
GLenum Mesh::getGLDrawMode(DrawMode mode)
{
switch (mode)
@@ -739,62 +205,6 @@ GLenum Mesh::getGLDataType(DataType type)
}
}
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);
}
bool Mesh::getConstant(const char *in, DataType &out)
{
return dataTypes.find(in, out);
}
bool Mesh::getConstant(DataType in, const char *&out)
{
return dataTypes.find(in, out);
}
bool Mesh::getConstant(const char *in, AttributeStep &out)
{
return attributeSteps.find(in, out);
}
bool Mesh::getConstant(AttributeStep in, const char *&out)
{
return attributeSteps.find(in, out);
}
StringMap<Mesh::DrawMode, Mesh::DRAWMODE_MAX_ENUM>::Entry Mesh::drawModeEntries[] =
{
{ "fan", DRAWMODE_FAN },
{ "strip", DRAWMODE_STRIP },
{ "triangles", DRAWMODE_TRIANGLES },
{ "points", DRAWMODE_POINTS },
};
StringMap<Mesh::DrawMode, Mesh::DRAWMODE_MAX_ENUM> Mesh::drawModes(Mesh::drawModeEntries, sizeof(Mesh::drawModeEntries));
StringMap<Mesh::DataType, Mesh::DATA_MAX_ENUM>::Entry Mesh::dataTypeEntries[] =
{
{ "byte", DATA_BYTE },
{ "float", DATA_FLOAT },
};
StringMap<Mesh::DataType, Mesh::DATA_MAX_ENUM> Mesh::dataTypes(Mesh::dataTypeEntries, sizeof(Mesh::dataTypeEntries));
StringMap<Mesh::AttributeStep, Mesh::STEP_MAX_ENUM>::Entry Mesh::attributeStepEntries[] =
{
{ "pervertex", STEP_PER_VERTEX },
{ "perinstance", STEP_PER_INSTANCE },
};
StringMap<Mesh::AttributeStep, Mesh::STEP_MAX_ENUM> Mesh::attributeSteps(Mesh::attributeStepEntries, sizeof(Mesh::attributeStepEntries));
} // opengl
} // graphics
} // love
+5 -228
View File
@@ -18,78 +18,23 @@
* 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
#pragma once
// LOVE
#include "common/config.h"
#include "common/int.h"
#include "common/math.h"
#include "common/StringMap.h"
#include "graphics/Drawable.h"
#include "graphics/Texture.h"
#include "graphics/vertex.h"
#include "graphics/Buffer.h"
#include "graphics/Mesh.h"
#include "OpenGL.h"
// C++
#include <vector>
#include <unordered_map>
namespace love
{
namespace graphics
{
class Graphics;
namespace opengl
{
/**
* Holds and draws arbitrary vertex geometry.
* Each vertex in the Mesh has a collection of vertex attributes specified on
* creation.
**/
class Mesh : public Drawable
class Mesh : public love::graphics::Mesh
{
public:
static love::Type type;
// How the Mesh's vertices are used when drawing.
// http://escience.anu.edu.au/lecture/cg/surfaceModeling/image/surfaceModeling015.png
enum DrawMode
{
DRAWMODE_FAN,
DRAWMODE_STRIP,
DRAWMODE_TRIANGLES,
DRAWMODE_POINTS,
DRAWMODE_MAX_ENUM
};
// The type of data a vertex attribute can store.
enum DataType
{
DATA_BYTE,
DATA_FLOAT,
DATA_MAX_ENUM
};
enum AttributeStep
{
STEP_PER_VERTEX,
STEP_PER_INSTANCE,
STEP_MAX_ENUM
};
struct AttribFormat
{
std::string name;
DataType type;
int components; // max 4
};
Mesh(graphics::Graphics *gfx, const std::vector<AttribFormat> &vertexformat, const void *data, size_t datasize, DrawMode drawmode, vertex::Usage usage);
Mesh(graphics::Graphics *gfx, const std::vector<AttribFormat> &vertexformat, int vertexcount, DrawMode drawmode, vertex::Usage usage);
@@ -98,184 +43,16 @@ public:
virtual ~Mesh();
/**
* Sets the values of all attributes at a specific vertex index in the Mesh.
* The size of the data must be less than or equal to the total size of all
* vertex attributes.
**/
void setVertex(size_t vertindex, const void *data, size_t datasize);
size_t getVertex(size_t vertindex, void *data, size_t datasize);
void *getVertexScratchBuffer();
/**
* Sets the values for a single attribute at a specific vertex index in the
* Mesh. The size of the data must be less than or equal to the size of the
* attribute.
**/
void setVertexAttribute(size_t vertindex, int attribindex, const void *data, size_t datasize);
size_t getVertexAttribute(size_t vertindex, int attribindex, void *data, size_t datasize);
/**
* Gets the total number of vertices that can be used when drawing the Mesh.
**/
size_t getVertexCount() const;
/**
* Gets the size in bytes of the start of one vertex to the start of the
* next, in the buffer.
**/
size_t getVertexStride() const;
/**
* Gets the format of each vertex attribute stored in the Mesh.
**/
const std::vector<AttribFormat> &getVertexFormat() const;
DataType getAttributeInfo(int attribindex, int &components) const;
int getAttributeIndex(const std::string &name) const;
/**
* Sets whether a specific vertex attribute is used when drawing the Mesh.
**/
void setAttributeEnabled(const std::string &name, bool enable);
bool isAttributeEnabled(const std::string &name) const;
/**
* Attaches a vertex attribute from another Mesh to this one. The attribute
* will be used when drawing this Mesh.
**/
void attachAttribute(const std::string &name, Mesh *mesh, const std::string &attachname, AttributeStep step = STEP_PER_VERTEX);
bool detachAttribute(const std::string &name);
void *mapVertexData();
void unmapVertexData(size_t modifiedoffset = 0, size_t modifiedsize = -1);
/**
* Flushes all modified data to the GPU.
**/
void flush();
/**
* 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);
void setVertexMap(IndexDataType datatype, const void *data, size_t datasize);
void setVertexMap();
/**
* Fills the uint32 vector passed into the method with the previously set
* vertex map (index buffer) values.
**/
bool getVertexMap(std::vector<uint32> &map) const;
/**
* Gets the total number of elements in the vertex map array.
**/
size_t getVertexMapCount() const;
/**
* Sets the texture used when drawing the Mesh.
**/
void setTexture(Texture *texture);
/**
* Disables any texture from being used when drawing the Mesh.
**/
void setTexture();
/**
* Gets the texture used when drawing the Mesh. May return null if no
* texture is set.
**/
Texture *getTexture() const;
/**
* Sets the draw mode used when drawing the Mesh.
**/
void setDrawMode(DrawMode mode);
DrawMode getDrawMode() const;
void setDrawRange(int start, int count);
void setDrawRange();
bool getDrawRange(int &start, int &count) const;
int bindAttributeToShaderInput(int attributeindex, const std::string &inputname);
void drawInstanced(Graphics *gfx, const Matrix4 &m, int instancecount);
// Implements Drawable.
void draw(Graphics *gfx, const Matrix4 &m) override;
static bool getConstant(const char *in, DrawMode &out);
static bool getConstant(DrawMode in, const char *&out);
static bool getConstant(const char *in, DataType &out);
static bool getConstant(DataType in, const char *&out);
static bool getConstant(const char *in, AttributeStep &out);
static bool getConstant(AttributeStep in, const char *&out);
int bindAttributeToShaderInput(int attributeindex, const std::string &inputname) override;
void drawInstanced(Graphics *gfx, const Matrix4 &m, int instancecount) override;
private:
struct AttachedAttribute
{
Mesh *mesh;
int index;
AttributeStep step;
bool enabled;
};
void setupAttachedAttributes();
void calculateAttributeSizes();
size_t getAttributeOffset(size_t attribindex) const;
static size_t getAttribFormatSize(const AttribFormat &format);
static GLenum getGLDrawMode(DrawMode mode);
static GLenum getGLDataType(DataType type);
std::vector<AttribFormat> vertexFormat;
std::vector<size_t> attributeSizes;
std::unordered_map<std::string, AttachedAttribute> attachedAttributes;
// Vertex buffer, for the vertex data.
Buffer *vbo;
size_t vertexCount;
size_t vertexStride;
// Block of memory whose size is at least as large as a single vertex. Helps
// avoid memory allocations when using Mesh::setVertex etc.
char *vertexScratchBuffer;
// Element (vertex index) buffer, for the vertex map.
Buffer *ibo;
bool useIndexBuffer;
size_t elementCount;
IndexDataType elementDataType;
DrawMode drawMode;
int rangeStart;
int rangeCount;
StrongRef<Texture> texture;
static StringMap<DrawMode, DRAWMODE_MAX_ENUM>::Entry drawModeEntries[];
static StringMap<DrawMode, DRAWMODE_MAX_ENUM> drawModes;
static StringMap<DataType, DATA_MAX_ENUM>::Entry dataTypeEntries[];
static StringMap<DataType, DATA_MAX_ENUM> dataTypes;
static StringMap<AttributeStep, STEP_MAX_ENUM>::Entry attributeStepEntries[];
static StringMap<AttributeStep, STEP_MAX_ENUM> attributeSteps;
}; // Mesh
} // opengl
} // graphics
} // love
#endif // LOVE_GRAPHICS_OPENGL_MESH_H
+2 -208
View File
@@ -25,6 +25,7 @@
#include "OpenGL.h"
// LOVE
#include "graphics/Buffer.h"
#include "graphics/Texture.h"
#include "graphics/Graphics.h"
@@ -41,199 +42,13 @@ namespace graphics
namespace opengl
{
love::Type SpriteBatch::type("SpriteBatch", &Drawable::type);
SpriteBatch::SpriteBatch(Graphics *gfx, Texture *texture, int size, vertex::Usage usage)
: texture(texture)
, size(size)
, next(0)
, color(0)
, array_buf(nullptr)
, quad_indices(gfx, size)
, range_start(-1)
, range_count(-1)
: love::graphics::SpriteBatch(gfx, texture, size, usage)
{
if (size <= 0)
throw love::Exception("Invalid SpriteBatch size.");
size_t vertex_size = sizeof(Vertex) * 4 * size;
array_buf = gfx->newBuffer(vertex_size, nullptr, BUFFER_VERTEX, usage, Buffer::MAP_EXPLICIT_RANGE_MODIFY);
}
SpriteBatch::~SpriteBatch()
{
delete color;
delete array_buf;
}
int SpriteBatch::add(const Matrix4 &m, int index /*= -1*/)
{
if (index < -1 || index >= size)
throw love::Exception("Invalid sprite index: %d", index + 1);
if (index == -1 && next >= size)
setBufferSize(size * 2);
addv(texture->getVertices(), m, (index == -1) ? next : index);
// Increment counter.
if (index == -1)
return next++;
return index;
}
int SpriteBatch::addq(Quad *quad, const Matrix4 &m, int index /*= -1*/)
{
if (index < -1 || index >= size)
throw love::Exception("Invalid sprite index: %d", index + 1);
if (index == -1 && next >= size)
setBufferSize(size * 2);
addv(quad->getVertices(), m, (index == -1) ? next : index);
// Increment counter.
if (index == -1)
return next++;
return index;
}
void SpriteBatch::clear()
{
// Reset the position of the next index.
next = 0;
}
void SpriteBatch::flush()
{
array_buf->unmap();
}
void SpriteBatch::setTexture(Texture *newtexture)
{
texture.set(newtexture);
}
Texture *SpriteBatch::getTexture() const
{
return texture.get();
}
void SpriteBatch::setColor(const Color &color)
{
if (!this->color)
this->color = new Color(color);
else
*(this->color) = color;
}
void SpriteBatch::setColor()
{
delete color;
color = nullptr;
}
const Color *SpriteBatch::getColor() const
{
return color;
}
int SpriteBatch::getCount() const
{
return next;
}
void SpriteBatch::setBufferSize(int newsize)
{
if (newsize <= 0)
throw love::Exception("Invalid SpriteBatch size.");
if (newsize == size)
return;
size_t vertex_size = sizeof(Vertex) * 4 * newsize;
love::graphics::Buffer *new_array_buf = nullptr;
int new_next = std::min(next, newsize);
try
{
auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
new_array_buf = gfx->newBuffer(vertex_size, nullptr, array_buf->getType(), array_buf->getUsage(), array_buf->getMapFlags());
// Copy as much of the old data into the new GLBuffer as can fit.
size_t copy_size = sizeof(Vertex) * 4 * new_next;
array_buf->copyTo(0, copy_size, new_array_buf, 0);
quad_indices = QuadIndices(gfx, newsize);
}
catch (love::Exception &)
{
delete new_array_buf;
throw;
}
// We don't need to unmap the old GLBuffer since we're deleting it.
delete array_buf;
array_buf = new_array_buf;
size = newsize;
next = new_next;
}
int SpriteBatch::getBufferSize() const
{
return size;
}
void SpriteBatch::attachAttribute(const std::string &name, Mesh *mesh)
{
AttachedAttribute oldattrib = {};
AttachedAttribute newattrib = {};
if (mesh->getVertexCount() < (size_t) next * 4)
throw love::Exception("Mesh has too few vertices to be attached to this SpriteBatch (at least %d vertices are required)", next*4);
auto it = attached_attributes.find(name);
if (it != attached_attributes.end())
oldattrib = it->second;
newattrib.index = mesh->getAttributeIndex(name);
if (newattrib.index < 0)
throw love::Exception("The specified mesh does not have a vertex attribute named '%s'", name.c_str());
newattrib.mesh = mesh;
attached_attributes[name] = newattrib;
}
void SpriteBatch::setDrawRange(int start, int count)
{
if (start < 0 || count <= 0)
throw love::Exception("Invalid draw range.");
range_start = start;
range_count = count;
}
void SpriteBatch::setDrawRange()
{
range_start = range_count = -1;
}
bool SpriteBatch::getDrawRange(int &start, int &count) const
{
if (range_start < 0 || range_count <= 0)
return false;
start = range_start;
count = range_count;
return true;
}
void SpriteBatch::draw(Graphics *gfx, const Matrix4 &m)
@@ -308,27 +123,6 @@ void SpriteBatch::draw(Graphics *gfx, const Matrix4 &m)
}
}
void SpriteBatch::addv(const Vertex *v, const Matrix4 &m, int index)
{
// Needed for colors.
Vertex sprite[4] = {v[0], v[1], v[2], v[3]};
const size_t sprite_size = 4 * sizeof(Vertex); // bytecount
m.transform(sprite, sprite, 4);
if (color != nullptr)
{
for (int i = 0; i < 4; i++)
sprite[i].color = *color;
}
// Always keep the VBO mapped when adding data for now (it'll be unmapped
// on draw.)
array_buf->map();
array_buf->fill(index * sprite_size, sprite_size, sprite);
}
} // opengl
} // graphics
} // love
+3 -112
View File
@@ -18,139 +18,30 @@
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_GRAPHICS_OPENGL_SPRITE_BATCH_H
#define LOVE_GRAPHICS_OPENGL_SPRITE_BATCH_H
// C
#include <cstring>
// C++
#include <unordered_map>
#pragma once
// LOVE
#include "common/math.h"
#include "common/Matrix.h"
#include "graphics/Drawable.h"
#include "graphics/Volatile.h"
#include "graphics/Color.h"
#include "graphics/Quad.h"
#include "graphics/Buffer.h"
#include "Mesh.h"
#include "graphics/SpriteBatch.h"
namespace love
{
namespace graphics
{
// Forward declarations.
class Texture;
class Graphics;
namespace opengl
{
class SpriteBatch : public Drawable
class SpriteBatch : public love::graphics::SpriteBatch
{
public:
static love::Type type;
SpriteBatch(Graphics *gfx, Texture *texture, int size, vertex::Usage usage);
virtual ~SpriteBatch();
int add(const Matrix4 &m, int index = -1);
int addq(Quad *quad, const Matrix4 &m, int index = -1);
void clear();
void flush();
void setTexture(Texture *newtexture);
Texture *getTexture() const;
/**
* 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 sprites.
*/
void setColor(const Color &color);
/**
* Disable per-sprite colors for this SpriteBatch. The next call to
* draw will use the global color for all sprites.
*/
void setColor();
/**
* Get the current color for this SpriteBatch. Returns NULL if no color is
* set.
**/
const Color *getColor() const;
/**
* Get the number of sprites currently in this SpriteBatch.
**/
int getCount() const;
/**
* Get the total number of sprites this SpriteBatch can currently hold.
**/
int getBufferSize() const;
/**
* Attaches a specific vertex attribute from a Mesh to this SpriteBatch.
* The vertex attribute will be used when drawing the SpriteBatch.
**/
void attachAttribute(const std::string &name, Mesh *mesh);
void setDrawRange(int start, int count);
void setDrawRange();
bool getDrawRange(int &start, int &count) const;
// Implements Drawable.
void draw(Graphics *gfx, const Matrix4 &m) override;
private:
struct AttachedAttribute
{
StrongRef<Mesh> mesh;
int index;
};
/**
* Sets the total number of sprites this SpriteBatch can hold.
* Leaves existing sprite data intact when possible.
**/
void setBufferSize(int newsize);
void addv(const Vertex *v, const Matrix4 &m, int index);
StrongRef<Texture> texture;
// Max number of sprites in the batch.
int size;
// The next free element.
int next;
// Current color. This color, if present, will be applied to the next
// added sprite.
Color *color;
love::graphics::Buffer *array_buf;
QuadIndices quad_indices;
std::unordered_map<std::string, AttachedAttribute> attached_attributes;
int range_start;
int range_count;
}; // SpriteBatch
} // opengl
} // graphics
} // love
#endif // LOVE_GRAPHICS_OPENGL_SPRITE_BATCH_H
@@ -651,7 +651,7 @@ int w_newSpriteBatch(lua_State *L)
return luaL_error(L, "Invalid usage hint: %s", usagestr);
}
SpriteBatch *t = nullptr;
love::graphics::SpriteBatch *t = nullptr;
luax_catchexcept(L,
[&](){ t = instance()->newSpriteBatch(texture, size, usage); }
);
@@ -667,7 +667,7 @@ int w_newParticleSystem(lua_State *L)
Texture *texture = luax_checktexture(L, 1);
lua_Number size = luaL_optnumber(L, 2, 1000);
ParticleSystem *t = 0;
love::graphics::ParticleSystem *t = nullptr;
if (size < 1.0 || size > ParticleSystem::MAX_PARTICLES)
return luaL_error(L, "Invalid ParticleSystem size");
@@ -882,9 +882,9 @@ static Mesh::DrawMode luax_optmeshdrawmode(lua_State *L, int idx, Mesh::DrawMode
return def;
}
static Mesh *newStandardMesh(lua_State *L)
static love::graphics::Mesh *newStandardMesh(lua_State *L)
{
Mesh *t = nullptr;
love::graphics::Mesh *t = nullptr;
Mesh::DrawMode drawmode = luax_optmeshdrawmode(L, 2, Mesh::DRAWMODE_FAN);
vertex::Usage usage = luax_optmeshusage(L, 3, vertex::USAGE_DYNAMIC);
@@ -938,9 +938,9 @@ static Mesh *newStandardMesh(lua_State *L)
return t;
}
static Mesh *newCustomMesh(lua_State *L)
static love::graphics::Mesh *newCustomMesh(lua_State *L)
{
Mesh *t = nullptr;
love::graphics::Mesh *t = nullptr;
// First argument is the vertex format, second is a table of vertices or
// the number of vertices.
@@ -1067,7 +1067,7 @@ int w_newMesh(lua_State *L)
if (arg1type != LUA_TTABLE && arg1type != LUA_TNUMBER)
luaL_argerror(L, 1, "table or number expected");
Mesh *t = nullptr;
love::graphics::Mesh *t = nullptr;
int arg2type = lua_type(L, 2);
if (arg1type == LUA_TTABLE && (arg2type == LUA_TTABLE || arg2type == LUA_TNUMBER || arg2type == LUA_TUSERDATA))
@@ -1671,7 +1671,7 @@ int w_draw(lua_State *L)
int w_drawInstanced(lua_State *L)
{
Mesh *t = luax_checkmesh(L, 1);
love::graphics::Mesh *t = luax_checkmesh(L, 1);
int instancecount = (int) luaL_checkinteger(L, 2);
if (luax_istype(L, 3, math::Transform::type))
+3 -3
View File
@@ -26,11 +26,11 @@
#include "graphics/wrap_Font.h"
#include "graphics/wrap_Image.h"
#include "graphics/wrap_Quad.h"
#include "wrap_SpriteBatch.h"
#include "wrap_ParticleSystem.h"
#include "graphics/wrap_SpriteBatch.h"
#include "graphics/wrap_ParticleSystem.h"
#include "graphics/wrap_Canvas.h"
#include "graphics/wrap_Shader.h"
#include "wrap_Mesh.h"
#include "graphics/wrap_Mesh.h"
#include "graphics/wrap_Text.h"
#include "graphics/wrap_Video.h"
#include "Graphics.h"
@@ -22,18 +22,15 @@
#include "wrap_Mesh.h"
#include "Image.h"
#include "Canvas.h"
#include "graphics/wrap_Texture.h"
#include "wrap_Texture.h"
// C++
#include <typeinfo>
#include <algorithm>
namespace love
{
namespace graphics
{
namespace opengl
{
Mesh *luax_checkmesh(lua_State *L, int idx)
{
@@ -570,6 +567,5 @@ extern "C" int luaopen_mesh(lua_State *L)
return luax_register_type(L, &Mesh::type, w_Mesh_functions, nullptr);
}
} // opengl
} // graphics
} // love
@@ -18,8 +18,7 @@
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_GRAPHICS_OPENGL_WRAP_MESH_H
#define LOVE_GRAPHICS_OPENGL_WRAP_MESH_H
#pragma once
// LOVE
#include "common/config.h"
@@ -30,8 +29,6 @@ namespace love
{
namespace graphics
{
namespace opengl
{
char *luax_writeAttributeData(lua_State *L, int startidx, Mesh::DataType type, int components, char *data);
const char *luax_readAttributeData(lua_State *L, Mesh::DataType type, int components, const char *data);
@@ -39,8 +36,5 @@ const char *luax_readAttributeData(lua_State *L, Mesh::DataType type, int compon
Mesh *luax_checkmesh(lua_State *L, int idx);
extern "C" int luaopen_mesh(lua_State *L);
} // opengl
} // graphics
} // love
#endif // LOVE_GRAPHICS_OPENGL_WRAP_MESH_H
@@ -24,7 +24,7 @@
#include "Image.h"
#include "Canvas.h"
#include "graphics/wrap_Texture.h"
#include "wrap_Texture.h"
// C
#include <cstring>
@@ -33,8 +33,6 @@ namespace love
{
namespace graphics
{
namespace opengl
{
ParticleSystem *luax_checkparticlesystem(lua_State *L, int idx)
{
@@ -772,6 +770,5 @@ extern "C" int luaopen_particlesystem(lua_State *L)
return luax_register_type(L, &ParticleSystem::type, w_ParticleSystem_functions, nullptr);
}
} // opengl
} // graphics
} // love
@@ -18,8 +18,7 @@
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_GRAPHICS_OPENGL_WRAP_PARTICLE_SYSTEM_H
#define LOVE_GRAPHICS_OPENGL_WRAP_PARTICLE_SYSTEM_H
#pragma once
// LOVE
#include "common/runtime.h"
@@ -29,14 +28,9 @@ namespace love
{
namespace graphics
{
namespace opengl
{
ParticleSystem *luax_checkparticlesystem(lua_State *L, int idx);
extern "C" int luaopen_particlesystem(lua_State *L);
} // opengl
} // graphics
} // love
#endif // LOVE_GRAPHICS_OPENGL_WRAP_PARTICLE_SYSTEM_H
@@ -22,18 +22,13 @@
#include "wrap_SpriteBatch.h"
#include "Image.h"
#include "Canvas.h"
#include "graphics/wrap_Texture.h"
#include "wrap_Texture.h"
#include "math/wrap_Transform.h"
// C++
#include <typeinfo>
namespace love
{
namespace graphics
{
namespace opengl
{
SpriteBatch *luax_checkspritebatch(lua_State *L, int idx)
{
@@ -274,6 +269,5 @@ extern "C" int luaopen_spritebatch(lua_State *L)
return luax_register_type(L, &SpriteBatch::type, w_SpriteBatch_functions, nullptr);
}
} // opengl
} // graphics
} // love
@@ -18,8 +18,7 @@
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_GRAPHICS_OPENGL_WRAP_SPRITE_BATCH_H
#define LOVE_GRAPHICS_OPENGL_WRAP_SPRITE_BATCH_H
#pragma once
#include "common/runtime.h"
#include "SpriteBatch.h"
@@ -28,14 +27,9 @@ namespace love
{
namespace graphics
{
namespace opengl
{
SpriteBatch *luax_checkspritebatch(lua_State *L, int idx);
extern "C" int luaopen_spritebatch(lua_State *L);
} // opengl
} // graphics
} // love
#endif // LOVE_GRAPHICS_OPENGL_WRAP_SPRITE_BATCH_H