2
0
Ivan Safrin 9 жил өмнө
parent
commit
61f350d3bb
67 өөрчлөгдсөн 2295 нэмэгдсэн , 2389 устгасан
  1. BIN
      assets/default/default.pak
  2. 1 1
      assets/default/default/default.mat
  3. 1 1
      bindings/javascript/Polycode.js
  4. 0 11
      bindings/javascript/Polycode/GPUDrawCall.js
  5. 20 185
      bindings/javascript/Polycode/Mesh.js
  6. 10 1
      bindings/javascript/Polycode/ProgramAttribute.js
  7. 1 10
      bindings/javascript/Polycode/RenderDataArray.js
  8. 4 0
      bindings/javascript/Polycode/RenderThread.js
  9. 2 16
      bindings/javascript/Polycode/Renderer.js
  10. 0 4
      bindings/javascript/Polycode/SceneMesh.js
  11. 0 8
      bindings/javascript/Polycode/ShaderPass.js
  12. BIN
      bindings/javascript/js_Polycode.pak
  13. 1 1
      bindings/lua/Polycode.lua
  14. 14 0
      bindings/lua/Polycode/CoreMutex.lua
  15. 2 11
      bindings/lua/Polycode/GPUDrawCall.lua
  16. 25 225
      bindings/lua/Polycode/Mesh.lua
  17. 5 0
      bindings/lua/Polycode/ProgramAttribute.lua
  18. 5 5
      bindings/lua/Polycode/RenderDataArray.lua
  19. 5 4
      bindings/lua/Polycode/RenderThread.lua
  20. 2 18
      bindings/lua/Polycode/Renderer.lua
  21. 0 12
      bindings/lua/Polycode/SceneMesh.lua
  22. 0 13
      bindings/lua/Polycode/ShaderPass.lua
  23. BIN
      bindings/lua/lua_Polycode.pak
  24. 2 2
      build/osx/TemplateApp/TemplateApp/PolycodeTemplateApp.h
  25. 63 17
      build/osx/TemplateApp/TemplateApp/PolycodeTemplateApp.mm
  26. 1 1
      build/osx/TemplateApp/TemplateApp/rotate.js
  27. 5 4
      build/osx/polybuild/polybuild.xcodeproj/project.pbxproj
  28. 221 209
      include/polycode/bindings/javascript/PolycodeJSWrappers.h
  29. 268 263
      include/polycode/bindings/lua/PolycodeLuaWrappers.h
  30. 1 0
      include/polycode/core/PolyCore.h
  31. 2 1
      include/polycode/core/PolyGPUDrawBuffer.h
  32. 1 8
      include/polycode/core/PolyMaterial.h
  33. 93 54
      include/polycode/core/PolyMesh.h
  34. 8 9
      include/polycode/core/PolyOpenGLGraphicsInterface.h
  35. 39 8
      include/polycode/core/PolyRenderDataArray.h
  36. 7 19
      include/polycode/core/PolyRenderer.h
  37. 2 14
      include/polycode/core/PolySceneMesh.h
  38. 1 0
      include/polycode/core/PolyShader.h
  39. 2 0
      include/polycode/modules/ui/PolyUIElement.h
  40. 1 1
      scripts/create_bindings/bindings.conf
  41. 64 63
      src/bindings/javascript/PolycodeJS.cpp
  42. 72 72
      src/bindings/lua/PolycodeLua.cpp
  43. 11 9
      src/core/PolyCamera.cpp
  44. 0 73
      src/core/PolyMaterial.cpp
  45. 554 359
      src/core/PolyMesh.cpp
  46. 165 81
      src/core/PolyOpenGLGraphicsInterface.cpp
  47. 44 42
      src/core/PolyParticleEmitter.cpp
  48. 39 8
      src/core/PolyRenderDataArray.cpp
  49. 38 119
      src/core/PolyRenderer.cpp
  50. 1 1
      src/core/PolyResourceManager.cpp
  51. 16 17
      src/core/PolySceneImage.cpp
  52. 24 14
      src/core/PolySceneLine.cpp
  53. 62 70
      src/core/PolySceneMesh.cpp
  54. 18 13
      src/core/PolyScenePrimitive.cpp
  55. 13 10
      src/core/PolySceneSprite.cpp
  56. 9 9
      src/ide/EditorGrid.cpp
  57. 80 57
      src/ide/PolycodeEntityEditor.cpp
  58. 10 6
      src/ide/PolycodeFrame.cpp
  59. 3 8
      src/ide/PolycodeMaterialEditor.cpp
  60. 1 1
      src/ide/PolycodeProps.cpp
  61. 103 88
      src/ide/PolycodeSpriteEditor.cpp
  62. 22 15
      src/ide/TransformGizmo.cpp
  63. 4 1
      src/modules/physics3D/PolyCollisionSceneEntity.cpp
  64. 48 45
      src/modules/ui/PolyUIBox.cpp
  65. 19 19
      src/modules/ui/PolyUIColorBox.cpp
  66. 40 32
      src/modules/ui/PolyUIElement.cpp
  67. 20 21
      src/tools/polyimport.cpp

BIN
assets/default/default.pak


+ 1 - 1
assets/default/default/default.mat

@@ -140,7 +140,7 @@
 		<material name="UnlitWireframe">
 			<shader name="UnlitWireframe" wireframe="true">
 				<params>
-					<param name="entityColor" value="1.0 1.0 1.0 1.0" />
+					<param name="wireframeColor" value="1.0 1.0 1.0 1.0" />
 				</params>					
 			</shader>
 		</material>				

+ 1 - 1
bindings/javascript/Polycode.js

@@ -10,7 +10,6 @@ require('Polycode/VideoModeChangeInfo')
 require('Polycode/PolycodeViewBase')
 require('Polycode/DummyCore')
 require('Polycode/TimeInfo')
-require('Polycode/CoreMutex')
 require('Polycode/CoreMotionEvent')
 require('Polycode/CoreFileExtension')
 require('Polycode/OSFileEntry')
@@ -42,6 +41,7 @@ require('Polycode/ShaderPass')
 require('Polycode/MaterialManager')
 require('Polycode/Matrix4')
 require('Polycode/Mesh')
+require('Polycode/MeshGeometry')
 require('Polycode/ObjectEntry')
 require('Polycode/BinaryObjectReader')
 require('Polycode/BinaryObjectWriter')

+ 0 - 11
bindings/javascript/Polycode/GPUDrawCall.js

@@ -1,21 +1,10 @@
 function GPUDrawCall() {
 	Object.defineProperties(this, {
-		'mesh': { enumerable: true, configurable: true, get: GPUDrawCall.prototype.__get_mesh, set: GPUDrawCall.prototype.__set_mesh},
 		'options': { enumerable: true, configurable: true, get: GPUDrawCall.prototype.__get_options, set: GPUDrawCall.prototype.__set_options},
 		'modelMatrix': { enumerable: true, configurable: true, get: GPUDrawCall.prototype.__get_modelMatrix, set: GPUDrawCall.prototype.__set_modelMatrix},
 		'material': { enumerable: true, configurable: true, get: GPUDrawCall.prototype.__get_material, set: GPUDrawCall.prototype.__set_material}
 	})
 }
-GPUDrawCall.prototype.__get_mesh = function() {
-	var retVal = new Mesh()
-	retVal.__ptr = 	Polycode.GPUDrawCall__get_mesh(this.__ptr)
-	return retVal
-}
-
-GPUDrawCall.prototype.__set_mesh = function(val) {
-	Polycode.GPUDrawCall__set_mesh(this.__ptr, val.__ptr)
-}
-
 GPUDrawCall.prototype.__get_options = function() {
 	var retVal = new GPUDrawOptions()
 	retVal.__ptr = 	Polycode.GPUDrawCall__get_options(this.__ptr)

+ 20 - 185
bindings/javascript/Polycode/Mesh.js

@@ -1,25 +1,16 @@
 function Mesh() {
-	Object.defineProperties(this, {
-		'indexedMesh': { enumerable: true, configurable: true, get: Mesh.prototype.__get_indexedMesh, set: Mesh.prototype.__set_indexedMesh}
-	})
-}
-Mesh.prototype.__get_indexedMesh = function() {
-	return Polycode.Mesh__get_indexedMesh(this.__ptr)
 }
 
-Mesh.prototype.__set_indexedMesh = function(val) {
-	Polycode.Mesh__set_indexedMesh(this.__ptr, val)
+Mesh.prototype.Copy = function() {
+	var retVal = new Mesh()
+	retVal.__ptr = Polycode.Mesh_Copy(this.__ptr)
+	return retVal
 }
 
-
 Mesh.prototype.loadMesh = function(fileName) {
 	Polycode.Mesh_loadMesh(this.__ptr, fileName)
 }
 
-Mesh.prototype.clearMesh = function() {
-	Polycode.Mesh_clearMesh(this.__ptr)
-}
-
 Mesh.prototype.saveToFile = function(fileName,writeNormals,writeTangents,writeColors,writeBoneWeights,writeUVs,writeSecondaryUVs) {
 	Polycode.Mesh_saveToFile(this.__ptr, fileName,writeNormals,writeTangents,writeColors,writeBoneWeights,writeUVs,writeSecondaryUVs)
 }
@@ -28,152 +19,32 @@ Mesh.prototype.loadFromFile = function(inFile) {
 	Polycode.Mesh_loadFromFile(this.__ptr, inFile)
 }
 
-Mesh.prototype.getVertexCount = function() {
-	return Polycode.Mesh_getVertexCount(this.__ptr)
-}
-
-Mesh.prototype.createPlane = function(w,h,tilingValue) {
-	Polycode.Mesh_createPlane(this.__ptr, w,h,tilingValue)
-}
-
-Mesh.prototype.createVPlane = function(w,h,tilingValue) {
-	Polycode.Mesh_createVPlane(this.__ptr, w,h,tilingValue)
-}
-
-Mesh.prototype.createCircle = function(w,h,numSegments,tilingValue) {
-	Polycode.Mesh_createCircle(this.__ptr, w,h,numSegments,tilingValue)
-}
-
-Mesh.prototype.createLineCircle = function(w,h,numSegments,tilingValue) {
-	Polycode.Mesh_createLineCircle(this.__ptr, w,h,numSegments,tilingValue)
-}
-
-Mesh.prototype.createTorus = function(radius,tubeRadius,segmentsW,segmentsH,tilingValue) {
-	Polycode.Mesh_createTorus(this.__ptr, radius,tubeRadius,segmentsW,segmentsH,tilingValue)
-}
-
-Mesh.prototype.createBox = function(w,d,h,tilingValue) {
-	Polycode.Mesh_createBox(this.__ptr, w,d,h,tilingValue)
-}
-
-Mesh.prototype.createSphere = function(radius,numRings,numSegments,tilingValue) {
-	Polycode.Mesh_createSphere(this.__ptr, radius,numRings,numSegments,tilingValue)
-}
-
-Mesh.prototype.createIcosphere = function(radius,subdivisions) {
-	Polycode.Mesh_createIcosphere(this.__ptr, radius,subdivisions)
-}
-
-Mesh.prototype.createOctosphere = function(radius,subdivisions) {
-	Polycode.Mesh_createOctosphere(this.__ptr, radius,subdivisions)
-}
-
-Mesh.prototype.createCylinder = function(height,radius,numSegments,capped,tilingValue) {
-	Polycode.Mesh_createCylinder(this.__ptr, height,radius,numSegments,capped,tilingValue)
-}
-
-Mesh.prototype.createCone = function(height,radius,numSegments,tilingValue) {
-	Polycode.Mesh_createCone(this.__ptr, height,radius,numSegments,tilingValue)
-}
-
-Mesh.prototype.recenterMesh = function() {
-	var retVal = new Vector3()
-	retVal.__ptr = Polycode.Mesh_recenterMesh(this.__ptr)
-	return retVal
-}
-
-Mesh.prototype.setVertexAtOffset = function(offset,x,y,z) {
-	Polycode.Mesh_setVertexAtOffset(this.__ptr, offset,x,y,z)
-}
-
-Mesh.prototype.addVertexWithUVAndNormal = function(x,y,z,u,v,nx,ny,nz) {
-	Polycode.Mesh_addVertexWithUVAndNormal(this.__ptr, x,y,z,u,v,nx,ny,nz)
-}
-
-Mesh.prototype.addTexCoord = function(u,v) {
-	Polycode.Mesh_addTexCoord(this.__ptr, u,v)
-}
-
-Mesh.prototype.addTexCoord2 = function(u,v) {
-	Polycode.Mesh_addTexCoord2(this.__ptr, u,v)
-}
-
-Mesh.prototype.addTangent = function(x,y,z) {
-	Polycode.Mesh_addTangent(this.__ptr, x,y,z)
-}
-
-Mesh.prototype.addVertexWithUV = function(x,y,z,u,v) {
-	Polycode.Mesh_addVertexWithUV(this.__ptr, x,y,z,u,v)
-}
-
-Mesh.prototype.addVertex = function(x,y,z) {
-	Polycode.Mesh_addVertex(this.__ptr, x,y,z)
+Mesh.prototype.addSubmesh = function(newSubmesh) {
+	Polycode.Mesh_addSubmesh(this.__ptr, newSubmesh)
 }
 
-Mesh.prototype.addNormal = function(nx,ny,nz) {
-	Polycode.Mesh_addNormal(this.__ptr, nx,ny,nz)
+Mesh.prototype.removeSubmeshAtIndex = function(index) {
+	Polycode.Mesh_removeSubmeshAtIndex(this.__ptr, index)
 }
 
-Mesh.prototype.addBoneAssignments = function(b1Weight,b1Index,b2Weight,b2Index,b3Weight,b3Index,b4Weight,b4Index) {
-	Polycode.Mesh_addBoneAssignments(this.__ptr, b1Weight,b1Index,b2Weight,b2Index,b3Weight,b3Index,b4Weight,b4Index)
+Mesh.prototype.getNumSubmeshes = function() {
+	return Polycode.Mesh_getNumSubmeshes(this.__ptr)
 }
 
-Mesh.prototype.addColor = function(r,g,b,a) {
-	Polycode.Mesh_addColor(this.__ptr, r,g,b,a)
-}
-
-Mesh.prototype.getVertexPosition = function(vertexOffset) {
-	var retVal = new Vector3()
-	retVal.__ptr = Polycode.Mesh_getVertexPosition(this.__ptr, vertexOffset)
-	return retVal
-}
-
-Mesh.prototype.getVertexPositionAtIndex = function(index) {
-	var retVal = new Vector3()
-	retVal.__ptr = Polycode.Mesh_getVertexPositionAtIndex(this.__ptr, index)
+Mesh.prototype.getSubmeshAtIndex = function(index) {
+	var retVal = new MeshGeometry()
+	retVal.__ptr = Polycode.Mesh_getSubmeshAtIndex(this.__ptr, index)
 	return retVal
 }
 
-Mesh.prototype.getVertexTexCoord = function(vertexOffset) {
-	var retVal = new Vector2()
-	retVal.__ptr = Polycode.Mesh_getVertexTexCoord(this.__ptr, vertexOffset)
+Mesh.prototype.getSubmeshPointer = function(index) {
+	var retVal = new shared_ptr<MeshGeometry>()
+	retVal.__ptr = Polycode.Mesh_getSubmeshPointer(this.__ptr, index)
 	return retVal
 }
 
-Mesh.prototype.getVertexTexCoordAtIndex = function(index) {
-	var retVal = new Vector2()
-	retVal.__ptr = Polycode.Mesh_getVertexTexCoordAtIndex(this.__ptr, index)
-	return retVal
-}
-
-Mesh.prototype.Copy = function() {
-	var retVal = new Mesh()
-	retVal.__ptr = Polycode.Mesh_Copy(this.__ptr)
-	return retVal
-}
-
-Mesh.prototype.getRadius = function() {
-	return Polycode.Mesh_getRadius(this.__ptr)
-}
-
-Mesh.prototype.calculateNormals = function() {
-	Polycode.Mesh_calculateNormals(this.__ptr)
-}
-
-Mesh.prototype.calculateTangents = function() {
-	Polycode.Mesh_calculateTangents(this.__ptr)
-}
-
-Mesh.prototype.getMeshType = function() {
-	return Polycode.Mesh_getMeshType(this.__ptr)
-}
-
-Mesh.prototype.setMeshType = function(newType) {
-	Polycode.Mesh_setMeshType(this.__ptr, newType)
-}
-
-Mesh.prototype.getIndexGroupSize = function() {
-	return Polycode.Mesh_getIndexGroupSize(this.__ptr)
+Mesh.prototype.clearMesh = function() {
+	Polycode.Mesh_clearMesh(this.__ptr)
 }
 
 Mesh.prototype.calculateBBox = function() {
@@ -182,42 +53,6 @@ Mesh.prototype.calculateBBox = function() {
 	return retVal
 }
 
-Mesh.prototype.hasVertexBuffer = function() {
-	return Polycode.Mesh_hasVertexBuffer(this.__ptr)
-}
-
-Mesh.prototype.addIndexedFace = function(i1,i2) {
-	Polycode.Mesh_addIndexedFace(this.__ptr, i1,i2)
-}
-
-Mesh.prototype.addIndex = function(index) {
-	Polycode.Mesh_addIndex(this.__ptr, index)
-}
-
-Mesh.prototype.removeVertexRange = function(beginRemoveVertex,vertexRemovalCount) {
-	Polycode.Mesh_removeVertexRange(this.__ptr, beginRemoveVertex,vertexRemovalCount)
-}
-
-Mesh.prototype.removeFace = function(faceIndex) {
-	Polycode.Mesh_removeFace(this.__ptr, faceIndex)
-}
-
-Mesh.prototype.removeUnusedVertices = function() {
-	return Polycode.Mesh_removeUnusedVertices(this.__ptr)
-}
-
-Mesh.prototype.getIndexCount = function() {
-	return Polycode.Mesh_getIndexCount(this.__ptr)
-}
-
-Mesh.prototype.subdivideToRadius = function(radius,subdivisions) {
-	Polycode.Mesh_subdivideToRadius(this.__ptr, radius,subdivisions)
-}
-
-Mesh.prototype.saveAsOBJ = function(fileName) {
-	Polycode.Mesh_saveAsOBJ(this.__ptr, fileName)
-}
-
-Mesh.prototype.normalizeBoneWeights = function() {
-	Polycode.Mesh_normalizeBoneWeights(this.__ptr)
+Mesh.prototype.getRadius = function() {
+	return Polycode.Mesh_getRadius(this.__ptr)
 }

+ 10 - 1
bindings/javascript/Polycode/ProgramAttribute.js

@@ -1,7 +1,8 @@
 function ProgramAttribute() {
 	Object.defineProperties(this, {
 		'size': { enumerable: true, configurable: true, get: ProgramAttribute.prototype.__get_size, set: ProgramAttribute.prototype.__set_size},
-		'name': { enumerable: true, configurable: true, get: ProgramAttribute.prototype.__get_name, set: ProgramAttribute.prototype.__set_name}
+		'name': { enumerable: true, configurable: true, get: ProgramAttribute.prototype.__get_name, set: ProgramAttribute.prototype.__set_name},
+		'arrayType': { enumerable: true, configurable: true, get: ProgramAttribute.prototype.__get_arrayType, set: ProgramAttribute.prototype.__set_arrayType}
 	})
 }
 ProgramAttribute.prototype.__get_size = function() {
@@ -20,6 +21,14 @@ ProgramAttribute.prototype.__set_name = function(val) {
 	Polycode.ProgramAttribute__set_name(this.__ptr, val)
 }
 
+ProgramAttribute.prototype.__get_arrayType = function() {
+	return Polycode.ProgramAttribute__get_arrayType(this.__ptr)
+}
+
+ProgramAttribute.prototype.__set_arrayType = function(val) {
+	Polycode.ProgramAttribute__set_arrayType(this.__ptr, val)
+}
+
 Duktape.fin(ProgramAttribute.prototype, function (x) {
 	if (x === ProgramAttribute.prototype) {
 		return;

+ 1 - 10
bindings/javascript/Polycode/RenderDataArray.js

@@ -1,8 +1,7 @@
 function RenderDataArray() {
 	Object.defineProperties(this, {
 		'type': { enumerable: true, configurable: true, get: RenderDataArray.prototype.__get_type, set: RenderDataArray.prototype.__set_type},
-		'customArrayName': { enumerable: true, configurable: true, get: RenderDataArray.prototype.__get_customArrayName, set: RenderDataArray.prototype.__set_customArrayName},
-		'hasVBO': { enumerable: true, configurable: true, get: RenderDataArray.prototype.__get_hasVBO, set: RenderDataArray.prototype.__set_hasVBO}
+		'customArrayName': { enumerable: true, configurable: true, get: RenderDataArray.prototype.__get_customArrayName, set: RenderDataArray.prototype.__set_customArrayName}
 	})
 }
 RenderDataArray.prototype.__get_type = function() {
@@ -21,14 +20,6 @@ RenderDataArray.prototype.__set_customArrayName = function(val) {
 	Polycode.RenderDataArray__set_customArrayName(this.__ptr, val)
 }
 
-RenderDataArray.prototype.__get_hasVBO = function() {
-	return Polycode.RenderDataArray__get_hasVBO(this.__ptr)
-}
-
-RenderDataArray.prototype.__set_hasVBO = function(val) {
-	Polycode.RenderDataArray__set_hasVBO(this.__ptr, val)
-}
-
 Duktape.fin(RenderDataArray.prototype, function (x) {
 	if (x === RenderDataArray.prototype) {
 		return;

+ 4 - 0
bindings/javascript/Polycode/RenderThread.js

@@ -33,6 +33,10 @@ RenderThread.prototype.getShaderBinding = function() {
 	return retVal
 }
 
+RenderThread.prototype.processDrawBufferLights = function(buffer) {
+	Polycode.RenderThread_processDrawBufferLights(this.__ptr, buffer)
+}
+
 RenderThread.prototype.processDrawBuffer = function(buffer) {
 	Polycode.RenderThread_processDrawBuffer(this.__ptr, buffer)
 }

+ 2 - 16
bindings/javascript/Polycode/Renderer.js

@@ -71,10 +71,6 @@ Renderer.prototype.createShader = function(vertexProgram,fragmentProgram) {
 	return retVal
 }
 
-Renderer.prototype.createVertexBuffers = function(mesh) {
-	Polycode.Renderer_createVertexBuffers(this.__ptr, mesh)
-}
-
 Renderer.prototype.enqueueFrameJob = function(jobType,data) {
 	Polycode.Renderer_enqueueFrameJob(this.__ptr, jobType,data)
 }
@@ -87,8 +83,8 @@ Renderer.prototype.destroyShader = function(shader) {
 	Polycode.Renderer_destroyShader(this.__ptr, shader)
 }
 
-Renderer.prototype.destroyBuffer = function(array) {
-	Polycode.Renderer_destroyBuffer(this.__ptr, array)
+Renderer.prototype.destroySubmeshPlatformData = function(platformData) {
+	Polycode.Renderer_destroySubmeshPlatformData(this.__ptr, platformData)
 }
 
 Renderer.prototype.destroyShaderBinding = function(binding) {
@@ -111,16 +107,6 @@ Renderer.prototype.getAnisotropyAmount = function() {
 	return Polycode.Renderer_getAnisotropyAmount(this.__ptr)
 }
 
-Renderer.prototype.createMesh = function(fileName) {
-	var retVal = new Mesh()
-	retVal.__ptr = Polycode.Renderer_createMesh(this.__ptr, fileName)
-	return retVal
-}
-
-Renderer.prototype.destroyMesh = function(mesh) {
-	Polycode.Renderer_destroyMesh(this.__ptr, mesh)
-}
-
 Renderer.prototype.beginFrame = function() {
 	Polycode.Renderer_beginFrame(this.__ptr)
 }

+ 0 - 4
bindings/javascript/Polycode/SceneMesh.js

@@ -132,10 +132,6 @@ SceneMesh.prototype.setMaterial = function(material) {
 	Polycode.SceneMesh_setMaterial(this.__ptr, material)
 }
 
-SceneMesh.prototype.rebuildAttributes = function() {
-	Polycode.SceneMesh_rebuildAttributes(this.__ptr)
-}
-
 SceneMesh.prototype.setMaterialByName = function(materialName,resourcePool) {
 	Polycode.SceneMesh_setMaterialByName(this.__ptr, materialName,resourcePool)
 }

+ 0 - 8
bindings/javascript/Polycode/ShaderPass.js

@@ -59,11 +59,3 @@ Duktape.fin(ShaderPass.prototype, function (x) {
 	}
 	Polycode.ShaderPass__delete(x.__ptr)
 })
-
-ShaderPass.prototype.setAttributeArraysFromMesh = function(mesh) {
-	Polycode.ShaderPass_setAttributeArraysFromMesh(this.__ptr, mesh)
-}
-
-ShaderPass.prototype.setExpectedAttributes = function() {
-	Polycode.ShaderPass_setExpectedAttributes(this.__ptr)
-}

BIN
bindings/javascript/js_Polycode.pak


+ 1 - 1
bindings/lua/Polycode.lua

@@ -10,7 +10,6 @@ require "Polycode/VideoModeChangeInfo"
 require "Polycode/PolycodeViewBase"
 require "Polycode/DummyCore"
 require "Polycode/TimeInfo"
-require "Polycode/CoreMutex"
 require "Polycode/CoreMotionEvent"
 require "Polycode/CoreFileExtension"
 require "Polycode/OSFileEntry"
@@ -42,6 +41,7 @@ require "Polycode/ShaderPass"
 require "Polycode/MaterialManager"
 require "Polycode/Matrix4"
 require "Polycode/Mesh"
+require "Polycode/MeshGeometry"
 require "Polycode/ObjectEntry"
 require "Polycode/BinaryObjectReader"
 require "Polycode/BinaryObjectWriter"

+ 14 - 0
bindings/lua/Polycode/CoreMutex.lua

@@ -14,6 +14,20 @@ function CoreMutex:__setvar(name,value)
 	end
 	return false
 end
+function CoreMutex:CoreMutex(...)
+	local arg = {...}
+	for k,v in pairs(arg) do
+		if type(v) == "table" then
+			if v.__ptr ~= nil then
+				arg[k] = v.__ptr
+			end
+		end
+	end
+	if self.__ptr == nil and arg[1] ~= "__skip_ptr__" then
+		self.__ptr = Polycode.CoreMutex(unpack(arg))
+	end
+end
+
 function CoreMutex:lock()
 	local retVal =  Polycode.CoreMutex_lock(self.__ptr)
 end

+ 2 - 11
bindings/lua/Polycode/GPUDrawCall.lua

@@ -2,13 +2,7 @@ class "GPUDrawCall"
 
 
 function GPUDrawCall:__getvar(name)
-	if name == "mesh" then
-		local retVal = Polycode.GPUDrawCall_get_mesh(self.__ptr)
-		if retVal == nil then return nil end
-		local __c = _G["Mesh"]("__skip_ptr__")
-		__c.__ptr = retVal
-		return __c
-	elseif name == "options" then
+	if name == "options" then
 		local retVal = Polycode.GPUDrawCall_get_options(self.__ptr)
 		if retVal == nil then return nil end
 		local __c = _G["GPUDrawOptions"]("__skip_ptr__")
@@ -30,10 +24,7 @@ function GPUDrawCall:__getvar(name)
 end
 
 function GPUDrawCall:__setvar(name,value)
-	if name == "mesh" then
-		Polycode.GPUDrawCall_set_mesh(self.__ptr, value.__ptr)
-		return true
-	elseif name == "options" then
+	if name == "options" then
 		Polycode.GPUDrawCall_set_options(self.__ptr, value.__ptr)
 		return true
 	elseif name == "modelMatrix" then

+ 25 - 225
bindings/lua/Polycode/Mesh.lua

@@ -2,34 +2,7 @@ require "Polycode/Resource"
 
 class "Mesh" (Resource)
 
-Mesh.TRISTRIP_MESH = 0
-Mesh.TRI_MESH = 1
-Mesh.TRIFAN_MESH = 2
-Mesh.LINE_MESH = 4
-Mesh.POINT_MESH = 5
-Mesh.LINE_STRIP_MESH = 6
-Mesh.LINE_LOOP_MESH = 7
 
-function Mesh:__getvar(name)
-	if name == "indexedMesh" then
-		return Polycode.Mesh_get_indexedMesh(self.__ptr)
-	end
-	if Resource["__getvar"] ~= nil then
-		return Resource.__getvar(self, name)
-	end
-end
-
-function Mesh:__setvar(name,value)
-	if name == "indexedMesh" then
-		Polycode.Mesh_set_indexedMesh(self.__ptr, value)
-		return true
-	end
-	if Resource["__setvar"] ~= nil then
-		return Resource.__setvar(self, name, value)
-	else
-		return false
-	end
-end
 function Mesh:Mesh(...)
 	local arg = {...}
 	if type(arg[1]) == "table" and count(arg) == 1 then
@@ -58,12 +31,16 @@ function Mesh:MeshFromFileName(fileName)
 	return __c
 end
 
-function Mesh:loadMesh(fileName)
-	local retVal = Polycode.Mesh_loadMesh(self.__ptr, fileName)
+function Mesh:Copy()
+	local retVal =  Polycode.Mesh_Copy(self.__ptr)
+	if retVal == nil then return nil end
+	local __c = _G["Mesh"]("__skip_ptr__")
+	__c.__ptr = retVal
+	return __c
 end
 
-function Mesh:clearMesh()
-	local retVal =  Polycode.Mesh_clearMesh(self.__ptr)
+function Mesh:loadMesh(fileName)
+	local retVal = Polycode.Mesh_loadMesh(self.__ptr, fileName)
 end
 
 function Mesh:saveToFile(fileName, writeNormals, writeTangents, writeColors, writeBoneWeights, writeUVs, writeSecondaryUVs)
@@ -74,168 +51,37 @@ function Mesh:loadFromFile(inFile)
 	local retVal = Polycode.Mesh_loadFromFile(self.__ptr, inFile.__ptr)
 end
 
-function Mesh:getVertexCount()
-	local retVal =  Polycode.Mesh_getVertexCount(self.__ptr)
-	return retVal
-end
-
-function Mesh:createPlane(w, h, tilingValue)
-	local retVal = Polycode.Mesh_createPlane(self.__ptr, w, h, tilingValue)
-end
-
-function Mesh:createVPlane(w, h, tilingValue)
-	local retVal = Polycode.Mesh_createVPlane(self.__ptr, w, h, tilingValue)
-end
-
-function Mesh:createCircle(w, h, numSegments, tilingValue)
-	local retVal = Polycode.Mesh_createCircle(self.__ptr, w, h, numSegments, tilingValue)
-end
-
-function Mesh:createLineCircle(w, h, numSegments, tilingValue)
-	local retVal = Polycode.Mesh_createLineCircle(self.__ptr, w, h, numSegments, tilingValue)
-end
-
-function Mesh:createTorus(radius, tubeRadius, segmentsW, segmentsH, tilingValue)
-	local retVal = Polycode.Mesh_createTorus(self.__ptr, radius, tubeRadius, segmentsW, segmentsH, tilingValue)
-end
-
-function Mesh:createBox(w, d, h, tilingValue)
-	local retVal = Polycode.Mesh_createBox(self.__ptr, w, d, h, tilingValue)
-end
-
-function Mesh:createSphere(radius, numRings, numSegments, tilingValue)
-	local retVal = Polycode.Mesh_createSphere(self.__ptr, radius, numRings, numSegments, tilingValue)
-end
-
-function Mesh:createIcosphere(radius, subdivisions)
-	local retVal = Polycode.Mesh_createIcosphere(self.__ptr, radius, subdivisions)
-end
-
-function Mesh:createOctosphere(radius, subdivisions)
-	local retVal = Polycode.Mesh_createOctosphere(self.__ptr, radius, subdivisions)
-end
-
-function Mesh:createCylinder(height, radius, numSegments, capped, tilingValue)
-	local retVal = Polycode.Mesh_createCylinder(self.__ptr, height, radius, numSegments, capped, tilingValue)
-end
-
-function Mesh:createCone(height, radius, numSegments, tilingValue)
-	local retVal = Polycode.Mesh_createCone(self.__ptr, height, radius, numSegments, tilingValue)
-end
-
-function Mesh:recenterMesh()
-	local retVal =  Polycode.Mesh_recenterMesh(self.__ptr)
-	if retVal == nil then return nil end
-	local __c = _G["Vector3"]("__skip_ptr__")
-	__c.__ptr = retVal
-	return __c
-end
-
-function Mesh:setVertexAtOffset(offset, x, y, z)
-	local retVal = Polycode.Mesh_setVertexAtOffset(self.__ptr, offset, x, y, z)
-end
-
-function Mesh:addVertexWithUVAndNormal(x, y, z, u, v, nx, ny, nz)
-	local retVal = Polycode.Mesh_addVertexWithUVAndNormal(self.__ptr, x, y, z, u, v, nx, ny, nz)
-end
-
-function Mesh:addTexCoord(u, v)
-	local retVal = Polycode.Mesh_addTexCoord(self.__ptr, u, v)
-end
-
-function Mesh:addTexCoord2(u, v)
-	local retVal = Polycode.Mesh_addTexCoord2(self.__ptr, u, v)
-end
-
-function Mesh:addTangent(x, y, z)
-	local retVal = Polycode.Mesh_addTangent(self.__ptr, x, y, z)
-end
-
-function Mesh:addVertexWithUV(x, y, z, u, v)
-	local retVal = Polycode.Mesh_addVertexWithUV(self.__ptr, x, y, z, u, v)
-end
-
-function Mesh:addVertex(x, y, z)
-	local retVal = Polycode.Mesh_addVertex(self.__ptr, x, y, z)
-end
-
-function Mesh:addNormal(nx, ny, nz)
-	local retVal = Polycode.Mesh_addNormal(self.__ptr, nx, ny, nz)
-end
-
-function Mesh:addBoneAssignments(b1Weight, b1Index, b2Weight, b2Index, b3Weight, b3Index, b4Weight, b4Index)
-	local retVal = Polycode.Mesh_addBoneAssignments(self.__ptr, b1Weight, b1Index, b2Weight, b2Index, b3Weight, b3Index, b4Weight, b4Index)
+function Mesh:addSubmesh(newSubmesh)
+	local retVal = Polycode.Mesh_addSubmesh(self.__ptr, newSubmesh.__ptr)
 end
 
-function Mesh:addColor(r, g, b, a)
-	local retVal = Polycode.Mesh_addColor(self.__ptr, r, g, b, a)
+function Mesh:removeSubmeshAtIndex(index)
+	local retVal = Polycode.Mesh_removeSubmeshAtIndex(self.__ptr, index)
 end
 
-function Mesh:getVertexPosition(vertexOffset)
-	local retVal = Polycode.Mesh_getVertexPosition(self.__ptr, vertexOffset)
-	if retVal == nil then return nil end
-	local __c = _G["Vector3"]("__skip_ptr__")
-	__c.__ptr = retVal
-	return __c
-end
-
-function Mesh:getVertexPositionAtIndex(index)
-	local retVal = Polycode.Mesh_getVertexPositionAtIndex(self.__ptr, index)
-	if retVal == nil then return nil end
-	local __c = _G["Vector3"]("__skip_ptr__")
-	__c.__ptr = retVal
-	return __c
+function Mesh:getNumSubmeshes()
+	local retVal =  Polycode.Mesh_getNumSubmeshes(self.__ptr)
+	return retVal
 end
 
-function Mesh:getVertexTexCoord(vertexOffset)
-	local retVal = Polycode.Mesh_getVertexTexCoord(self.__ptr, vertexOffset)
+function Mesh:getSubmeshAtIndex(index)
+	local retVal = Polycode.Mesh_getSubmeshAtIndex(self.__ptr, index)
 	if retVal == nil then return nil end
-	local __c = _G["Vector2"]("__skip_ptr__")
+	local __c = _G["MeshGeometry"]("__skip_ptr__")
 	__c.__ptr = retVal
 	return __c
 end
 
-function Mesh:getVertexTexCoordAtIndex(index)
-	local retVal = Polycode.Mesh_getVertexTexCoordAtIndex(self.__ptr, index)
+function Mesh:getSubmeshPointer(index)
+	local retVal = Polycode.Mesh_getSubmeshPointer(self.__ptr, index)
 	if retVal == nil then return nil end
-	local __c = _G["Vector2"]("__skip_ptr__")
+	local __c = _G["shared_ptr<MeshGeometry>"]("__skip_ptr__")
 	__c.__ptr = retVal
 	return __c
 end
 
-function Mesh:Copy()
-	local retVal =  Polycode.Mesh_Copy(self.__ptr)
-	if retVal == nil then return nil end
-	local __c = _G["Mesh"]("__skip_ptr__")
-	__c.__ptr = retVal
-	return __c
-end
-
-function Mesh:getRadius()
-	local retVal =  Polycode.Mesh_getRadius(self.__ptr)
-	return retVal
-end
-
-function Mesh:calculateNormals()
-	local retVal =  Polycode.Mesh_calculateNormals(self.__ptr)
-end
-
-function Mesh:calculateTangents()
-	local retVal =  Polycode.Mesh_calculateTangents(self.__ptr)
-end
-
-function Mesh:getMeshType()
-	local retVal =  Polycode.Mesh_getMeshType(self.__ptr)
-	return retVal
-end
-
-function Mesh:setMeshType(newType)
-	local retVal = Polycode.Mesh_setMeshType(self.__ptr, newType)
-end
-
-function Mesh:getIndexGroupSize()
-	local retVal =  Polycode.Mesh_getIndexGroupSize(self.__ptr)
-	return retVal
+function Mesh:clearMesh()
+	local retVal =  Polycode.Mesh_clearMesh(self.__ptr)
 end
 
 function Mesh:calculateBBox()
@@ -246,57 +92,11 @@ function Mesh:calculateBBox()
 	return __c
 end
 
-function Mesh:hasVertexBuffer()
-	local retVal =  Polycode.Mesh_hasVertexBuffer(self.__ptr)
-	return retVal
-end
-
-function Mesh:addIndexedFace(i1, i2)
-	local retVal = Polycode.Mesh_addIndexedFace(self.__ptr, i1, i2)
-end
-
-function Mesh:addIndex(index)
-	local retVal = Polycode.Mesh_addIndex(self.__ptr, index)
-end
-
-function Mesh:removeVertexRange(beginRemoveVertex, vertexRemovalCount)
-	local retVal = Polycode.Mesh_removeVertexRange(self.__ptr, beginRemoveVertex, vertexRemovalCount)
-end
-
-function Mesh:removeFace(faceIndex)
-	local retVal = Polycode.Mesh_removeFace(self.__ptr, faceIndex)
-end
-
-function Mesh:removeUnusedVertices()
-	local retVal =  Polycode.Mesh_removeUnusedVertices(self.__ptr)
-	return retVal
-end
-
-function Mesh:getIndexCount()
-	local retVal =  Polycode.Mesh_getIndexCount(self.__ptr)
+function Mesh:getRadius()
+	local retVal =  Polycode.Mesh_getRadius(self.__ptr)
 	return retVal
 end
 
-function Mesh:subdivideToRadius(radius, subdivisions)
-	local retVal = Polycode.Mesh_subdivideToRadius(self.__ptr, radius, subdivisions)
-end
-
-function Mesh:calculateFaceTangent(v1, v2, v3, texCoord1, texCoord2, texCoord3)
-	local retVal = Polycode.Mesh_calculateFaceTangent(self.__ptr, v1.__ptr, v2.__ptr, v3.__ptr, texCoord1.__ptr, texCoord2.__ptr, texCoord3.__ptr)
-	if retVal == nil then return nil end
-	local __c = _G["Vector3"]("__skip_ptr__")
-	__c.__ptr = retVal
-	return __c
-end
-
-function Mesh:saveAsOBJ(fileName)
-	local retVal = Polycode.Mesh_saveAsOBJ(self.__ptr, fileName)
-end
-
-function Mesh:normalizeBoneWeights()
-	local retVal =  Polycode.Mesh_normalizeBoneWeights(self.__ptr)
-end
-
 function Mesh:__delete()
 	if self then Polycode.delete_Mesh(self.__ptr) end
 end

+ 5 - 0
bindings/lua/Polycode/ProgramAttribute.lua

@@ -6,6 +6,8 @@ function ProgramAttribute:__getvar(name)
 		return Polycode.ProgramAttribute_get_size(self.__ptr)
 	elseif name == "name" then
 		return Polycode.ProgramAttribute_get_name(self.__ptr)
+	elseif name == "arrayType" then
+		return Polycode.ProgramAttribute_get_arrayType(self.__ptr)
 	end
 end
 
@@ -16,6 +18,9 @@ function ProgramAttribute:__setvar(name,value)
 	elseif name == "name" then
 		Polycode.ProgramAttribute_set_name(self.__ptr, value)
 		return true
+	elseif name == "arrayType" then
+		Polycode.ProgramAttribute_set_arrayType(self.__ptr, value)
+		return true
 	end
 	return false
 end

+ 5 - 5
bindings/lua/Polycode/RenderDataArray.lua

@@ -9,14 +9,17 @@ RenderDataArray.BONE_WEIGHT_DATA_ARRAY = 5
 RenderDataArray.BONE_INDEX_DATA_ARRAY = 6
 RenderDataArray.INDEX_DATA_ARRAY = 7
 RenderDataArray.TEXCOORD2_DATA_ARRAY = 8
+RenderDataArray.CUSTOM_DATA_ARRAY1 = 9
+RenderDataArray.CUSTOM_DATA_ARRAY2 = 10
+RenderDataArray.CUSTOM_DATA_ARRAY3 = 11
+RenderDataArray.CUSTOM_DATA_ARRAY4 = 12
+RenderDataArray.UNKNOWN_DATA_ARRAY = 13
 
 function RenderDataArray:__getvar(name)
 	if name == "type" then
 		return Polycode.RenderDataArray_get_type(self.__ptr)
 	elseif name == "customArrayName" then
 		return Polycode.RenderDataArray_get_customArrayName(self.__ptr)
-	elseif name == "hasVBO" then
-		return Polycode.RenderDataArray_get_hasVBO(self.__ptr)
 	end
 end
 
@@ -27,9 +30,6 @@ function RenderDataArray:__setvar(name,value)
 	elseif name == "customArrayName" then
 		Polycode.RenderDataArray_set_customArrayName(self.__ptr, value)
 		return true
-	elseif name == "hasVBO" then
-		Polycode.RenderDataArray_set_hasVBO(self.__ptr, value)
-		return true
 	end
 	return false
 end

+ 5 - 4
bindings/lua/Polycode/RenderThread.lua

@@ -7,18 +7,15 @@ RenderThread.JOB_END_FRAME = 3
 RenderThread.JOB_CREATE_PROGRAM = 4
 RenderThread.JOB_CREATE_SHADER = 5
 RenderThread.JOB_BEGIN_FRAME = 6
-RenderThread.JOB_CREATE_VERTEX_BUFFERS = 7
 RenderThread.JOB_DESTROY_TEXTURE = 8
 RenderThread.JOB_DESTROY_SHADER = 9
 RenderThread.JOB_DESTROY_PROGRAM = 10
-RenderThread.JOB_DESTROY_BUFFER = 11
+RenderThread.JOB_DESTROY_SUBMESH_BUFFER = 11
 RenderThread.JOB_CREATE_RENDER_BUFFER = 12
 RenderThread.JOB_DESTROY_RENDER_BUFFER = 13
 RenderThread.JOB_SET_TEXTURE_PARAM = 14
 RenderThread.JOB_DESTROY_SHADER_BINDING = 16
 RenderThread.JOB_DESTROY_SHADER_PARAM = 17
-RenderThread.JOB_CREATE_MESH = 18
-RenderThread.JOB_DESTROY_MESH = 19
 
 function RenderThread:RenderThread(...)
 	local arg = {...}
@@ -62,6 +59,10 @@ function RenderThread:getShaderBinding()
 	return __c
 end
 
+function RenderThread:processDrawBufferLights(buffer)
+	local retVal = Polycode.RenderThread_processDrawBufferLights(self.__ptr, buffer.__ptr)
+end
+
 function RenderThread:processDrawBuffer(buffer)
 	local retVal = Polycode.RenderThread_processDrawBuffer(self.__ptr, buffer.__ptr)
 end

+ 2 - 18
bindings/lua/Polycode/Renderer.lua

@@ -88,10 +88,6 @@ function Renderer:createShader(vertexProgram, fragmentProgram)
 	return __c
 end
 
-function Renderer:createVertexBuffers(mesh)
-	local retVal = Polycode.Renderer_createVertexBuffers(self.__ptr, mesh.__ptr)
-end
-
 function Renderer:enqueueFrameJob(jobType, data)
 	local retVal = Polycode.Renderer_enqueueFrameJob(self.__ptr, jobType, data.__ptr)
 end
@@ -104,8 +100,8 @@ function Renderer:destroyShader(shader)
 	local retVal = Polycode.Renderer_destroyShader(self.__ptr, shader.__ptr)
 end
 
-function Renderer:destroyBuffer(array)
-	local retVal = Polycode.Renderer_destroyBuffer(self.__ptr, array.__ptr)
+function Renderer:destroySubmeshPlatformData(platformData)
+	local retVal = Polycode.Renderer_destroySubmeshPlatformData(self.__ptr, platformData.__ptr)
 end
 
 function Renderer:destroyShaderBinding(binding)
@@ -129,18 +125,6 @@ function Renderer:getAnisotropyAmount()
 	return retVal
 end
 
-function Renderer:createMesh(fileName)
-	local retVal = Polycode.Renderer_createMesh(self.__ptr, fileName)
-	if retVal == nil then return nil end
-	local __c = _G["Mesh"]("__skip_ptr__")
-	__c.__ptr = retVal
-	return __c
-end
-
-function Renderer:destroyMesh(mesh)
-	local retVal = Polycode.Renderer_destroyMesh(self.__ptr, mesh.__ptr)
-end
-
 function Renderer:unProject(position, modelMatrix, projectionMatrix, viewport)
 	local retVal = Polycode.Renderer_unProject(self.__ptr, position.__ptr, modelMatrix.__ptr, projectionMatrix.__ptr, viewport.__ptr)
 	if retVal == nil then return nil end

+ 0 - 12
bindings/lua/Polycode/SceneMesh.lua

@@ -91,14 +91,6 @@ function SceneMesh:SceneMeshFromMesh(mesh)
 	return __c
 end
 
-function SceneMesh:SceneMeshWithType(meshType)
-	local retVal = Polycode.SceneMesh_SceneMeshWithType(self.__ptr, meshType)
-	if retVal == nil then return nil end
-	local __c = _G["SceneMesh"]("__skip_ptr__")
-	__c.__ptr = retVal
-	return __c
-end
-
 function SceneMesh:Render(buffer)
 	local retVal = Polycode.SceneMesh_Render(self.__ptr, buffer.__ptr)
 end
@@ -156,10 +148,6 @@ function SceneMesh:setMaterial(material)
 	local retVal = Polycode.SceneMesh_setMaterial(self.__ptr, material.__ptr)
 end
 
-function SceneMesh:rebuildAttributes()
-	local retVal =  Polycode.SceneMesh_rebuildAttributes(self.__ptr)
-end
-
 function SceneMesh:setMaterialByName(materialName, resourcePool)
 	local retVal = Polycode.SceneMesh_setMaterialByName(self.__ptr, materialName, resourcePool.__ptr)
 end

+ 0 - 13
bindings/lua/Polycode/ShaderPass.lua

@@ -60,19 +60,6 @@ function ShaderPass:ShaderPass(...)
 	end
 end
 
-function ShaderPass:setAttributeArraysFromMesh(mesh)
-	local retVal = Polycode.ShaderPass_setAttributeArraysFromMesh(self.__ptr, mesh.__ptr)
-end
-
-function ShaderPass:setExpectedAttributes()
-	local retVal =  Polycode.ShaderPass_setExpectedAttributes(self.__ptr)
-end
-
-function ShaderPass:arrayToAttributeName(array)
-	local retVal = Polycode.ShaderPass_arrayToAttributeName(self.__ptr, array.__ptr)
-	return retVal
-end
-
 function ShaderPass:__delete()
 	if self then Polycode.delete_ShaderPass(self.__ptr) end
 end

BIN
bindings/lua/lua_Polycode.pak


+ 2 - 2
build/osx/TemplateApp/TemplateApp/PolycodeTemplateApp.h

@@ -17,10 +17,10 @@ public:
     bool Update();
     
 private:
-    ScenePrimitive *test ;
     Core *core;
-    std::vector<ScenePrimitive*> tests;
+    std::vector<SceneMesh*> tests;
     SceneLabel *fpsLabel;
+    Scene *scene;
     Number counter;
     Entity *sourceEntity;
     Number positionValue;

+ 63 - 17
build/osx/TemplateApp/TemplateApp/PolycodeTemplateApp.mm

@@ -18,23 +18,41 @@ PolycodeTemplateApp::PolycodeTemplateApp(PolycodeView *view) {
     core->addFileSource("archive", "hdr.pak");
     globalPool->loadResourcesFromFolder("hdr", true);
     
+    Polycode:Script *rotateScript = (Script*) globalPool->loadResource("rotate.js");
     
-    Scene *scene = new Scene(Scene::SCENE_3D);
-    scene->useClearColor = true;
-    sourceEntity = new Entity();
-    
-    SceneSound *testSound = new SceneSound("test.wav", 20, 50);
-    testSound->getSound()->Play(true);
-    sourceEntity->addChild(testSound);
+	// Write your code here!
     
-    ScenePrimitive *soundShape = new ScenePrimitive(ScenePrimitive::TYPE_BOX, 1,1,1);
-    sourceEntity->addChild(soundShape);
-    scene->addEntity(sourceEntity);
+    scene = new Scene(Scene::SCENE_2D);
+    scene->useClearColor = true;
+    scene->clearColor.setColor(0.2, 0.2, 0.2, 1.0);
     
-    SceneSoundListener *soundListener = new SceneSoundListener();
-    scene->addEntity(soundListener);
+   // scene->setOverrideMaterial((Material*)globalPool->getResource(Resource::RESOURCE_MATERIAL, "Unlit"));
     
-    positionValue = 0;
+    for(int i=0; i  < 3000; i++) {
+        
+        MeshGeometry geom;
+        geom.createVPlane(0.5, 0.5);
+        SceneMesh *test = new SceneMesh();
+        test->setMaterialByName("Unlit");
+        test->getMesh()->addSubmesh(geom);
+        
+        //test->attachScript(rotateScript);
+        /*
+         ScriptInstance *scriptInstance = test->attachScript(rotateScript);
+         scriptInstance->setPropNumber("speed", 1.0);
+         */
+        test->getShaderPass(0).shaderBinding->loadTextureForParam("diffuse", "main_icon.png");
+        test->setPosition(RANDOM_NUMBER * 0.5, RANDOM_NUMBER * 0.4);
+        test->setBlendingMode(Renderer::BLEND_MODE_NONE);
+        test->setScale(0.3, 0.3);
+        scene->addChild(test);
+        tests.push_back(test);
+    }
+    Camera *camera = scene->getDefaultCamera();
+
+    fpsLabel = new SceneLabel("FPS:", 32, "mono", Label::ANTIALIAS_FULL, 0.1);
+    scene->addChild(fpsLabel);
+    fpsLabel->setPositionY(-0.4);
     
     Services()->getInput()->addEventListener(this, InputEvent::EVENT_KEYDOWN);
 }
@@ -50,10 +68,38 @@ PolycodeTemplateApp::~PolycodeTemplateApp() {
 bool PolycodeTemplateApp::Update() {
     Number elapsed = core->getElapsed();
     
-    positionValue += elapsed;
-    sourceEntity->setPosition((sin(positionValue) * 20), 0, cos(positionValue) * 50);
-    sourceEntity->Roll(core->getElapsed() * 120);
-    sourceEntity->Pitch(core->getElapsed()* 120);
+    for(int i=0; i < tests.size(); i++) {
+        tests[i]->Roll(elapsed * 30.0);
+    }
+    
+    if(tests.size() > 0) {
+        SceneMesh *removing = tests[0];
+        tests.erase(tests.begin());
+        scene->removeEntity(removing);
+        delete removing;
+        
+        MeshGeometry geom;
+        geom.createVPlane(0.5, 0.5);
+        SceneMesh *test = new SceneMesh();
+        test->setMaterialByName("Unlit");
+        test->getMesh()->addSubmesh(geom);
+        test->getShaderPass(0).shaderBinding->loadTextureForParam("diffuse", "main_icon.png");
+        test->setPosition(RANDOM_NUMBER * 0.5, RANDOM_NUMBER * 0.4);
+        test->setBlendingMode(Renderer::BLEND_MODE_NONE);
+        test->setScale(0.1, 0.1);
+        scene->addChild(test);
+        tests.push_back(test);
+        
+        
+    }
+    
+    ++numFrames;
+    counter += elapsed;
+    if(counter >= 1.0) {
+        counter = 0.0;
+        fpsLabel->setText("FPS:"+String::IntToString(numFrames)+" FRAME MS:"+String::IntToString(Services()->getRenderer()->getRenderThread()->getFrameInfo().timeTaken));
+        numFrames = 0;
+    }
     
     return core->updateAndRender();
 }

+ 1 - 1
build/osx/TemplateApp/TemplateApp/rotate.js

@@ -8,7 +8,7 @@ Rotator.prototype.init = function(entity) {
 
 Rotator.prototype.update = function(elapsed) {
     this.entity.Roll(elapsed * 30.0)
-    print(this.entity.getPosition().x)
+   // print(this.entity.getPosition().x)
 }
 
 Rotator

+ 5 - 4
build/osx/polybuild/polybuild.xcodeproj/project.pbxproj

@@ -7,13 +7,13 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
+		8A1DD6B31CF7840400008E9C /* liblua.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8A1DD6B21CF7840400008E9C /* liblua.a */; };
 		8AC7B36C1CB8623A00624970 /* polybuild.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8AC7B36B1CB8623A00624970 /* polybuild.cpp */; };
 		8AC7B3781CB866CC00624970 /* libarchive.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8AC7B36E1CB866CC00624970 /* libarchive.a */; };
 		8AC7B3791CB866CC00624970 /* libfreetype.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8AC7B36F1CB866CC00624970 /* libfreetype.a */; };
 		8AC7B37A1CB866CC00624970 /* liblibogg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8AC7B3701CB866CC00624970 /* liblibogg.a */; };
 		8AC7B37B1CB866CC00624970 /* liblibvorbis.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8AC7B3711CB866CC00624970 /* liblibvorbis.a */; };
 		8AC7B37C1CB866CC00624970 /* liblibvorbisfile.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8AC7B3721CB866CC00624970 /* liblibvorbisfile.a */; };
-		8AC7B37D1CB866CC00624970 /* liblua5.1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8AC7B3731CB866CC00624970 /* liblua5.1.a */; };
 		8AC7B37E1CB866CC00624970 /* libphysfs.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8AC7B3741CB866CC00624970 /* libphysfs.a */; };
 		8AC7B37F1CB866CC00624970 /* libPolycore.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8AC7B3751CB866CC00624970 /* libPolycore.a */; };
 		8AC7B3801CB866CC00624970 /* libportaudio.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8AC7B3761CB866CC00624970 /* libportaudio.a */; };
@@ -39,6 +39,7 @@
 /* End PBXCopyFilesBuildPhase section */
 
 /* Begin PBXFileReference section */
+		8A1DD6B21CF7840400008E9C /* liblua.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = liblua.a; path = ../../../lib/osx/liblua.a; sourceTree = "<group>"; };
 		8AC7B35F1CB861F200624970 /* polybuild */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = polybuild; sourceTree = BUILT_PRODUCTS_DIR; };
 		8AC7B36B1CB8623A00624970 /* polybuild.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = polybuild.cpp; path = ../../../../src/tools/polybuild.cpp; sourceTree = "<group>"; };
 		8AC7B36D1CB8626300624970 /* polybuild.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = polybuild.h; path = ../../../../include/polycode/tools/polybuild.h; sourceTree = "<group>"; };
@@ -47,7 +48,6 @@
 		8AC7B3701CB866CC00624970 /* liblibogg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = liblibogg.a; path = ../../../lib/osx/liblibogg.a; sourceTree = "<group>"; };
 		8AC7B3711CB866CC00624970 /* liblibvorbis.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = liblibvorbis.a; path = ../../../lib/osx/liblibvorbis.a; sourceTree = "<group>"; };
 		8AC7B3721CB866CC00624970 /* liblibvorbisfile.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = liblibvorbisfile.a; path = ../../../lib/osx/liblibvorbisfile.a; sourceTree = "<group>"; };
-		8AC7B3731CB866CC00624970 /* liblua5.1.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = liblua5.1.a; path = ../../../lib/osx/liblua5.1.a; sourceTree = "<group>"; };
 		8AC7B3741CB866CC00624970 /* libphysfs.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libphysfs.a; path = ../../../lib/osx/libphysfs.a; sourceTree = "<group>"; };
 		8AC7B3751CB866CC00624970 /* libPolycore.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libPolycore.a; path = ../../../lib/osx/libPolycore.a; sourceTree = "<group>"; };
 		8AC7B3761CB866CC00624970 /* libportaudio.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libportaudio.a; path = ../../../lib/osx/libportaudio.a; sourceTree = "<group>"; };
@@ -65,6 +65,7 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				8A1DD6B31CF7840400008E9C /* liblua.a in Frameworks */,
 				8AC7B38D1CB8671500624970 /* Cocoa.framework in Frameworks */,
 				8AC7B38B1CB8670E00624970 /* OpenGL.framework in Frameworks */,
 				8AC7B3891CB8670800624970 /* IOKit.framework in Frameworks */,
@@ -75,7 +76,6 @@
 				8AC7B3801CB866CC00624970 /* libportaudio.a in Frameworks */,
 				8AC7B37F1CB866CC00624970 /* libPolycore.a in Frameworks */,
 				8AC7B37B1CB866CC00624970 /* liblibvorbis.a in Frameworks */,
-				8AC7B37D1CB866CC00624970 /* liblua5.1.a in Frameworks */,
 				8AC7B3781CB866CC00624970 /* libarchive.a in Frameworks */,
 				8AC7B3791CB866CC00624970 /* libfreetype.a in Frameworks */,
 				8AC7B37C1CB866CC00624970 /* liblibvorbisfile.a in Frameworks */,
@@ -99,9 +99,9 @@
 				8AC7B36E1CB866CC00624970 /* libarchive.a */,
 				8AC7B36F1CB866CC00624970 /* libfreetype.a */,
 				8AC7B3701CB866CC00624970 /* liblibogg.a */,
+				8A1DD6B21CF7840400008E9C /* liblua.a */,
 				8AC7B3711CB866CC00624970 /* liblibvorbis.a */,
 				8AC7B3721CB866CC00624970 /* liblibvorbisfile.a */,
-				8AC7B3731CB866CC00624970 /* liblua5.1.a */,
 				8AC7B3741CB866CC00624970 /* libphysfs.a */,
 				8AC7B3751CB866CC00624970 /* libPolycore.a */,
 				8AC7B3761CB866CC00624970 /* libportaudio.a */,
@@ -332,6 +332,7 @@
 				8AC7B3681CB861F200624970 /* Release */,
 			);
 			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
 		};
 /* End XCConfigurationList section */
 	};

+ 221 - 209
include/polycode/bindings/javascript/PolycodeJSWrappers.h

@@ -2060,36 +2060,6 @@ namespace Polycode {
 		return 0;
 	}
 
-	duk_ret_t Polycode_CoreMutex__get_mutexID(duk_context *context) {
-		CoreMutex *inst = (CoreMutex*)duk_to_pointer(context, 0);
-		duk_push_int(context, inst->mutexID);
-		return 1;
-	}
-
-	duk_ret_t Polycode_CoreMutex__set_mutexID(duk_context *context) {
-		CoreMutex *inst = (CoreMutex*)duk_to_pointer(context, 0);
-		inst->mutexID = duk_to_int(context, 1);
-		return 0;
-	}
-
-	duk_ret_t Polycode_CoreMutex__delete(duk_context *context) {
-		CoreMutex *inst = (CoreMutex*)duk_to_pointer(context, 0);
-		delete inst;
-		return 0;
-	}
-
-	duk_ret_t Polycode_CoreMutex_lock(duk_context *context) {
-		CoreMutex *inst = (CoreMutex*)duk_to_pointer(context, 0);
-		inst->lock();
-		return 0;
-	}
-
-	duk_ret_t Polycode_CoreMutex_unlock(duk_context *context) {
-		CoreMutex *inst = (CoreMutex*)duk_to_pointer(context, 0);
-		inst->unlock();
-		return 0;
-	}
-
 	duk_ret_t Polycode_CoreMotionEvent__get_amount(duk_context *context) {
 		CoreMotionEvent *inst = (CoreMotionEvent*)duk_to_pointer(context, 0);
 		Vector3 *retInst = new Vector3();
@@ -4379,19 +4349,6 @@ namespace Polycode {
 		return 0;
 	}
 
-	duk_ret_t Polycode_GPUDrawCall__get_mesh(duk_context *context) {
-		GPUDrawCall *inst = (GPUDrawCall*)duk_to_pointer(context, 0);
-		PolyBase *ptrRetVal = (PolyBase*)inst->mesh;
-		duk_push_pointer(context, (void*)ptrRetVal);
-		return 1;
-	}
-
-	duk_ret_t Polycode_GPUDrawCall__set_mesh(duk_context *context) {
-		GPUDrawCall *inst = (GPUDrawCall*)duk_to_pointer(context, 0);
-		inst->mesh = (Mesh*)duk_to_pointer(context, 1);
-		return 0;
-	}
-
 	duk_ret_t Polycode_GPUDrawCall__get_options(duk_context *context) {
 		GPUDrawCall *inst = (GPUDrawCall*)duk_to_pointer(context, 0);
 		GPUDrawOptions *retInst = new GPUDrawOptions();
@@ -5730,19 +5687,6 @@ namespace Polycode {
 		return 0;
 	}
 
-	duk_ret_t Polycode_ShaderPass_setAttributeArraysFromMesh(duk_context *context) {
-		ShaderPass *inst = (ShaderPass*)duk_to_pointer(context, 0);
-		Mesh* mesh = (Mesh*)duk_to_pointer(context, 1);
-		inst->setAttributeArraysFromMesh(mesh);
-		return 0;
-	}
-
-	duk_ret_t Polycode_ShaderPass_setExpectedAttributes(duk_context *context) {
-		ShaderPass *inst = (ShaderPass*)duk_to_pointer(context, 0);
-		inst->setExpectedAttributes();
-		return 0;
-	}
-
 	duk_ret_t Polycode_MaterialManager__get_premultiplyAlphaOnLoad(duk_context *context) {
 		MaterialManager *inst = (MaterialManager*)duk_to_pointer(context, 0);
 		duk_push_boolean(context, inst->premultiplyAlphaOnLoad);
@@ -6179,22 +6123,17 @@ namespace Polycode {
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh__get_indexedMesh(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
-		duk_push_boolean(context, inst->indexedMesh);
-		return 1;
-	}
-
-	duk_ret_t Polycode_Mesh__set_indexedMesh(duk_context *context) {
+	duk_ret_t Polycode_Mesh__delete(duk_context *context) {
 		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
-		inst->indexedMesh = duk_to_boolean(context, 1);
+		delete inst;
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh__delete(duk_context *context) {
+	duk_ret_t Polycode_Mesh_Copy(duk_context *context) {
 		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
-		delete inst;
-		return 0;
+		PolyBase *ptrRetVal = (PolyBase*)inst->Copy();
+		duk_push_pointer(context, (void*)ptrRetVal);
+		return 1;
 	}
 
 	duk_ret_t Polycode_Mesh_loadMesh(duk_context *context) {
@@ -6204,12 +6143,6 @@ namespace Polycode {
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_clearMesh(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
-		inst->clearMesh();
-		return 0;
-	}
-
 	duk_ret_t Polycode_Mesh_saveToFile(duk_context *context) {
 		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
 		String fileName = duk_to_string(context, 1);
@@ -6230,14 +6163,120 @@ namespace Polycode {
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_getVertexCount(duk_context *context) {
+	duk_ret_t Polycode_Mesh_addSubmesh(duk_context *context) {
 		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
-		duk_push_int(context, inst->getVertexCount());
+		MeshGeometry newSubmesh = *(MeshGeometry*)duk_to_pointer(context, 1);
+		inst->addSubmesh(newSubmesh);
+		return 0;
+	}
+
+	duk_ret_t Polycode_Mesh_removeSubmeshAtIndex(duk_context *context) {
+		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+		int index = duk_to_int(context, 1);
+		inst->removeSubmeshAtIndex(index);
+		return 0;
+	}
+
+	duk_ret_t Polycode_Mesh_getNumSubmeshes(duk_context *context) {
+		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+		duk_push_int(context, inst->getNumSubmeshes());
+		return 1;
+	}
+
+	duk_ret_t Polycode_Mesh_getSubmeshAtIndex(duk_context *context) {
+		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+		int index = duk_to_int(context, 1);
+		MeshGeometry *retInst = new MeshGeometry();
+		*retInst = inst->getSubmeshAtIndex(index);
+		duk_push_pointer(context, (void*)retInst);
+		return 1;
+	}
+
+	duk_ret_t Polycode_Mesh_getSubmeshPointer(duk_context *context) {
+		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+		int index = duk_to_int(context, 1);
+		shared_ptr<MeshGeometry> *retInst = new shared_ptr<MeshGeometry>();
+		*retInst = inst->getSubmeshPointer(index);
+		duk_push_pointer(context, (void*)retInst);
+		return 1;
+	}
+
+	duk_ret_t Polycode_Mesh_clearMesh(duk_context *context) {
+		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+		inst->clearMesh();
+		return 0;
+	}
+
+	duk_ret_t Polycode_Mesh_calculateBBox(duk_context *context) {
+		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+		Vector3 *retInst = new Vector3();
+		*retInst = inst->calculateBBox();
+		duk_push_pointer(context, (void*)retInst);
 		return 1;
 	}
 
-	duk_ret_t Polycode_Mesh_createPlane(duk_context *context) {
+	duk_ret_t Polycode_Mesh_getRadius(duk_context *context) {
 		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+		duk_push_number(context, inst->getRadius());
+		return 1;
+	}
+
+	duk_ret_t Polycode_MeshGeometry__get_meshType(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
+		duk_push_int(context, inst->meshType);
+		return 1;
+	}
+
+	duk_ret_t Polycode_MeshGeometry__set_meshType(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
+		inst->meshType = duk_to_int(context, 1);
+		return 0;
+	}
+
+	duk_ret_t Polycode_MeshGeometry__get_dataChanged(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
+		duk_push_boolean(context, inst->dataChanged);
+		return 1;
+	}
+
+	duk_ret_t Polycode_MeshGeometry__set_dataChanged(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
+		inst->dataChanged = duk_to_boolean(context, 1);
+		return 0;
+	}
+
+	duk_ret_t Polycode_MeshGeometry__get_indexedMesh(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
+		duk_push_boolean(context, inst->indexedMesh);
+		return 1;
+	}
+
+	duk_ret_t Polycode_MeshGeometry__set_indexedMesh(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
+		inst->indexedMesh = duk_to_boolean(context, 1);
+		return 0;
+	}
+
+	duk_ret_t Polycode_MeshGeometry__delete(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
+		delete inst;
+		return 0;
+	}
+
+	duk_ret_t Polycode_MeshGeometry_clearMesh(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
+		inst->clearMesh();
+		return 0;
+	}
+
+	duk_ret_t Polycode_MeshGeometry_getVertexCount(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
+		duk_push_int(context, inst->getVertexCount());
+		return 1;
+	}
+
+	duk_ret_t Polycode_MeshGeometry_createPlane(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		Number w = duk_to_number(context, 1);
 		Number h = duk_to_number(context, 2);
 		Number tilingValue = duk_to_number(context, 3);
@@ -6245,8 +6284,8 @@ namespace Polycode {
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_createVPlane(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_createVPlane(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		Number w = duk_to_number(context, 1);
 		Number h = duk_to_number(context, 2);
 		Number tilingValue = duk_to_number(context, 3);
@@ -6254,8 +6293,8 @@ namespace Polycode {
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_createCircle(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_createCircle(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		Number w = duk_to_number(context, 1);
 		Number h = duk_to_number(context, 2);
 		int numSegments = duk_to_int(context, 3);
@@ -6264,8 +6303,8 @@ namespace Polycode {
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_createLineCircle(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_createLineCircle(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		Number w = duk_to_number(context, 1);
 		Number h = duk_to_number(context, 2);
 		int numSegments = duk_to_int(context, 3);
@@ -6274,8 +6313,8 @@ namespace Polycode {
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_createTorus(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_createTorus(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		Number radius = duk_to_number(context, 1);
 		Number tubeRadius = duk_to_number(context, 2);
 		int segmentsW = duk_to_int(context, 3);
@@ -6285,8 +6324,8 @@ namespace Polycode {
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_createBox(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_createBox(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		Number w = duk_to_number(context, 1);
 		Number d = duk_to_number(context, 2);
 		Number h = duk_to_number(context, 3);
@@ -6295,8 +6334,8 @@ namespace Polycode {
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_createSphere(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_createSphere(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		Number radius = duk_to_number(context, 1);
 		int numRings = duk_to_int(context, 2);
 		int numSegments = duk_to_int(context, 3);
@@ -6305,24 +6344,24 @@ namespace Polycode {
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_createIcosphere(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_createIcosphere(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		Number radius = duk_to_number(context, 1);
 		int subdivisions = duk_to_int(context, 2);
 		inst->createIcosphere(radius,subdivisions);
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_createOctosphere(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_createOctosphere(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		Number radius = duk_to_number(context, 1);
 		int subdivisions = duk_to_int(context, 2);
 		inst->createOctosphere(radius,subdivisions);
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_createCylinder(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_createCylinder(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		Number height = duk_to_number(context, 1);
 		Number radius = duk_to_number(context, 2);
 		int numSegments = duk_to_int(context, 3);
@@ -6332,8 +6371,8 @@ namespace Polycode {
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_createCone(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_createCone(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		Number height = duk_to_number(context, 1);
 		Number radius = duk_to_number(context, 2);
 		int numSegments = duk_to_int(context, 3);
@@ -6342,16 +6381,16 @@ namespace Polycode {
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_recenterMesh(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_recenterMesh(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		Vector3 *retInst = new Vector3();
 		*retInst = inst->recenterMesh();
 		duk_push_pointer(context, (void*)retInst);
 		return 1;
 	}
 
-	duk_ret_t Polycode_Mesh_setVertexAtOffset(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_setVertexAtOffset(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		int offset = duk_to_int(context, 1);
 		Number x = duk_to_number(context, 2);
 		Number y = duk_to_number(context, 3);
@@ -6360,8 +6399,8 @@ namespace Polycode {
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_addVertexWithUVAndNormal(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_addVertexWithUVAndNormal(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		Number x = duk_to_number(context, 1);
 		Number y = duk_to_number(context, 2);
 		Number z = duk_to_number(context, 3);
@@ -6374,24 +6413,24 @@ namespace Polycode {
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_addTexCoord(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_addTexCoord(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		Number u = duk_to_number(context, 1);
 		Number v = duk_to_number(context, 2);
 		inst->addTexCoord(u,v);
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_addTexCoord2(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_addTexCoord2(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		Number u = duk_to_number(context, 1);
 		Number v = duk_to_number(context, 2);
 		inst->addTexCoord2(u,v);
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_addTangent(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_addTangent(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		Number x = duk_to_number(context, 1);
 		Number y = duk_to_number(context, 2);
 		Number z = duk_to_number(context, 3);
@@ -6399,8 +6438,8 @@ namespace Polycode {
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_addVertexWithUV(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_addVertexWithUV(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		Number x = duk_to_number(context, 1);
 		Number y = duk_to_number(context, 2);
 		Number z = duk_to_number(context, 3);
@@ -6410,8 +6449,8 @@ namespace Polycode {
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_addVertex(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_addVertex(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		Number x = duk_to_number(context, 1);
 		Number y = duk_to_number(context, 2);
 		Number z = duk_to_number(context, 3);
@@ -6419,8 +6458,8 @@ namespace Polycode {
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_addNormal(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_addNormal(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		Number nx = duk_to_number(context, 1);
 		Number ny = duk_to_number(context, 2);
 		Number nz = duk_to_number(context, 3);
@@ -6428,8 +6467,8 @@ namespace Polycode {
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_addBoneAssignments(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_addBoneAssignments(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		Number b1Weight = duk_to_number(context, 1);
 		int b1Index = duk_to_int(context, 2);
 		Number b2Weight = duk_to_number(context, 3);
@@ -6442,8 +6481,8 @@ namespace Polycode {
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_addColor(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_addColor(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		Number r = duk_to_number(context, 1);
 		Number g = duk_to_number(context, 2);
 		Number b = duk_to_number(context, 3);
@@ -6452,8 +6491,8 @@ namespace Polycode {
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_getVertexPosition(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_getVertexPosition(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		int vertexOffset = duk_to_int(context, 1);
 		Vector3 *retInst = new Vector3();
 		*retInst = inst->getVertexPosition(vertexOffset);
@@ -6461,8 +6500,8 @@ namespace Polycode {
 		return 1;
 	}
 
-	duk_ret_t Polycode_Mesh_getVertexPositionAtIndex(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_getVertexPositionAtIndex(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		int index = duk_to_int(context, 1);
 		Vector3 *retInst = new Vector3();
 		*retInst = inst->getVertexPositionAtIndex(index);
@@ -6470,8 +6509,8 @@ namespace Polycode {
 		return 1;
 	}
 
-	duk_ret_t Polycode_Mesh_getVertexTexCoord(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_getVertexTexCoord(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		int vertexOffset = duk_to_int(context, 1);
 		Vector2 *retInst = new Vector2();
 		*retInst = inst->getVertexTexCoord(vertexOffset);
@@ -6479,8 +6518,8 @@ namespace Polycode {
 		return 1;
 	}
 
-	duk_ret_t Polycode_Mesh_getVertexTexCoordAtIndex(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_getVertexTexCoordAtIndex(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		int index = duk_to_int(context, 1);
 		Vector2 *retInst = new Vector2();
 		*retInst = inst->getVertexTexCoordAtIndex(index);
@@ -6488,123 +6527,117 @@ namespace Polycode {
 		return 1;
 	}
 
-	duk_ret_t Polycode_Mesh_Copy(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_Copy(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		PolyBase *ptrRetVal = (PolyBase*)inst->Copy();
 		duk_push_pointer(context, (void*)ptrRetVal);
 		return 1;
 	}
 
-	duk_ret_t Polycode_Mesh_getRadius(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_getRadius(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		duk_push_number(context, inst->getRadius());
 		return 1;
 	}
 
-	duk_ret_t Polycode_Mesh_calculateNormals(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_calculateNormals(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		inst->calculateNormals();
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_calculateTangents(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_calculateTangents(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		inst->calculateTangents();
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_getMeshType(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_getMeshType(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		duk_push_int(context, inst->getMeshType());
 		return 1;
 	}
 
-	duk_ret_t Polycode_Mesh_setMeshType(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_setMeshType(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		int newType = duk_to_int(context, 1);
 		inst->setMeshType(newType);
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_getIndexGroupSize(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_getIndexGroupSize(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		duk_push_int(context, inst->getIndexGroupSize());
 		return 1;
 	}
 
-	duk_ret_t Polycode_Mesh_calculateBBox(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_calculateBBox(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		Vector3 *retInst = new Vector3();
 		*retInst = inst->calculateBBox();
 		duk_push_pointer(context, (void*)retInst);
 		return 1;
 	}
 
-	duk_ret_t Polycode_Mesh_hasVertexBuffer(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
-		duk_push_boolean(context, inst->hasVertexBuffer());
-		return 1;
-	}
-
-	duk_ret_t Polycode_Mesh_addIndexedFace(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_addIndexedFace(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		int i1 = duk_to_int(context, 1);
 		int i2 = duk_to_int(context, 2);
 		inst->addIndexedFace(i1,i2);
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_addIndex(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_addIndex(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		int index = duk_to_int(context, 1);
 		inst->addIndex(index);
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_removeVertexRange(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_removeVertexRange(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		int beginRemoveVertex = duk_to_int(context, 1);
 		int vertexRemovalCount = duk_to_int(context, 2);
 		inst->removeVertexRange(beginRemoveVertex,vertexRemovalCount);
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_removeFace(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_removeFace(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		int faceIndex = duk_to_int(context, 1);
 		inst->removeFace(faceIndex);
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_removeUnusedVertices(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_removeUnusedVertices(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		duk_push_int(context, inst->removeUnusedVertices());
 		return 1;
 	}
 
-	duk_ret_t Polycode_Mesh_getIndexCount(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_getIndexCount(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		duk_push_int(context, inst->getIndexCount());
 		return 1;
 	}
 
-	duk_ret_t Polycode_Mesh_subdivideToRadius(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_subdivideToRadius(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		Number radius = duk_to_number(context, 1);
 		int subdivisions = duk_to_int(context, 2);
 		inst->subdivideToRadius(radius,subdivisions);
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_saveAsOBJ(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_saveAsOBJ(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		String fileName = duk_to_string(context, 1);
 		inst->saveAsOBJ(fileName);
 		return 0;
 	}
 
-	duk_ret_t Polycode_Mesh_normalizeBoneWeights(duk_context *context) {
-		Mesh *inst = (Mesh*)duk_to_pointer(context, 0);
+	duk_ret_t Polycode_MeshGeometry_normalizeBoneWeights(duk_context *context) {
+		MeshGeometry *inst = (MeshGeometry*)duk_to_pointer(context, 0);
 		inst->normalizeBoneWeights();
 		return 0;
 	}
@@ -7902,18 +7935,6 @@ namespace Polycode {
 		return 0;
 	}
 
-	duk_ret_t Polycode_RenderDataArray__get_hasVBO(duk_context *context) {
-		RenderDataArray *inst = (RenderDataArray*)duk_to_pointer(context, 0);
-		duk_push_boolean(context, inst->hasVBO);
-		return 1;
-	}
-
-	duk_ret_t Polycode_RenderDataArray__set_hasVBO(duk_context *context) {
-		RenderDataArray *inst = (RenderDataArray*)duk_to_pointer(context, 0);
-		inst->hasVBO = duk_to_boolean(context, 1);
-		return 0;
-	}
-
 	duk_ret_t Polycode_RenderDataArray__delete(duk_context *context) {
 		RenderDataArray *inst = (RenderDataArray*)duk_to_pointer(context, 0);
 		delete inst;
@@ -8174,6 +8195,13 @@ namespace Polycode {
 		return 1;
 	}
 
+	duk_ret_t Polycode_RenderThread_processDrawBufferLights(duk_context *context) {
+		RenderThread *inst = (RenderThread*)duk_to_pointer(context, 0);
+		GPUDrawBuffer* buffer = (GPUDrawBuffer*)duk_to_pointer(context, 1);
+		inst->processDrawBufferLights(buffer);
+		return 0;
+	}
+
 	duk_ret_t Polycode_RenderThread_processDrawBuffer(duk_context *context) {
 		RenderThread *inst = (RenderThread*)duk_to_pointer(context, 0);
 		GPUDrawBuffer* buffer = (GPUDrawBuffer*)duk_to_pointer(context, 1);
@@ -8374,13 +8402,6 @@ namespace Polycode {
 		return 1;
 	}
 
-	duk_ret_t Polycode_Renderer_createVertexBuffers(duk_context *context) {
-		Renderer *inst = (Renderer*)duk_to_pointer(context, 0);
-		Mesh* mesh = (Mesh*)duk_to_pointer(context, 1);
-		inst->createVertexBuffers(mesh);
-		return 0;
-	}
-
 	duk_ret_t Polycode_Renderer_enqueueFrameJob(duk_context *context) {
 		Renderer *inst = (Renderer*)duk_to_pointer(context, 0);
 		int jobType = duk_to_int(context, 1);
@@ -8403,10 +8424,10 @@ namespace Polycode {
 		return 0;
 	}
 
-	duk_ret_t Polycode_Renderer_destroyBuffer(duk_context *context) {
+	duk_ret_t Polycode_Renderer_destroySubmeshPlatformData(duk_context *context) {
 		Renderer *inst = (Renderer*)duk_to_pointer(context, 0);
-		RenderDataArray* array = (RenderDataArray*)duk_to_pointer(context, 1);
-		inst->destroyBuffer(array);
+		void* platformData = (void*)duk_to_pointer(context, 1);
+		inst->destroySubmeshPlatformData(platformData);
 		return 0;
 	}
 
@@ -8445,21 +8466,6 @@ namespace Polycode {
 		return 1;
 	}
 
-	duk_ret_t Polycode_Renderer_createMesh(duk_context *context) {
-		Renderer *inst = (Renderer*)duk_to_pointer(context, 0);
-		String fileName = duk_to_string(context, 1);
-		PolyBase *ptrRetVal = (PolyBase*)inst->createMesh(fileName);
-		duk_push_pointer(context, (void*)ptrRetVal);
-		return 1;
-	}
-
-	duk_ret_t Polycode_Renderer_destroyMesh(duk_context *context) {
-		Renderer *inst = (Renderer*)duk_to_pointer(context, 0);
-		Mesh* mesh = (Mesh*)duk_to_pointer(context, 1);
-		inst->destroyMesh(mesh);
-		return 0;
-	}
-
 	duk_ret_t Polycode_Renderer_beginFrame(duk_context *context) {
 		Renderer *inst = (Renderer*)duk_to_pointer(context, 0);
 		inst->beginFrame();
@@ -10210,12 +10216,6 @@ namespace Polycode {
 		return 0;
 	}
 
-	duk_ret_t Polycode_SceneMesh_rebuildAttributes(duk_context *context) {
-		SceneMesh *inst = (SceneMesh*)duk_to_pointer(context, 0);
-		inst->rebuildAttributes();
-		return 0;
-	}
-
 	duk_ret_t Polycode_SceneMesh_setMaterialByName(duk_context *context) {
 		SceneMesh *inst = (SceneMesh*)duk_to_pointer(context, 0);
 		String materialName = duk_to_string(context, 1);
@@ -11183,6 +11183,18 @@ namespace Polycode {
 		return 0;
 	}
 
+	duk_ret_t Polycode_ProgramAttribute__get_arrayType(duk_context *context) {
+		ProgramAttribute *inst = (ProgramAttribute*)duk_to_pointer(context, 0);
+		duk_push_int(context, inst->arrayType);
+		return 1;
+	}
+
+	duk_ret_t Polycode_ProgramAttribute__set_arrayType(duk_context *context) {
+		ProgramAttribute *inst = (ProgramAttribute*)duk_to_pointer(context, 0);
+		inst->arrayType = duk_to_int(context, 1);
+		return 0;
+	}
+
 	duk_ret_t Polycode_ProgramAttribute__delete(duk_context *context) {
 		ProgramAttribute *inst = (ProgramAttribute*)duk_to_pointer(context, 0);
 		delete inst;

+ 268 - 263
include/polycode/bindings/lua/PolycodeLuaWrappers.h

@@ -2735,41 +2735,6 @@ static int Polycode_TimeInfo_set_yearDay(lua_State *L) {
 		return 0;
 	}
 
-static int Polycode_CoreMutex_get_mutexID(lua_State *L) {
-	luaL_checktype(L, 1, LUA_TUSERDATA);
-	CoreMutex *inst = (CoreMutex*) *((PolyBase**)lua_touserdata(L, 1));
-	lua_pushinteger(L, inst->mutexID);
-	return 1;
-}
-
-static int Polycode_CoreMutex_set_mutexID(lua_State *L) {
-	luaL_checktype(L, 1, LUA_TUSERDATA);
-	CoreMutex *inst = (CoreMutex*) *((PolyBase**)lua_touserdata(L, 1));
-	int param = lua_tointeger(L, 2);
-	inst->mutexID = param;
-	return 0;
-}
-
-	static int Polycode_CoreMutex_lock(lua_State *L) {
-		luaL_checktype(L, 1, LUA_TUSERDATA);
-		CoreMutex *inst = (CoreMutex*) *((PolyBase**)lua_touserdata(L, 1));
-		inst->lock();
-		return 0;
-	}
-	static int Polycode_CoreMutex_unlock(lua_State *L) {
-		luaL_checktype(L, 1, LUA_TUSERDATA);
-		CoreMutex *inst = (CoreMutex*) *((PolyBase**)lua_touserdata(L, 1));
-		inst->unlock();
-		return 0;
-	}
-	static int Polycode_delete_CoreMutex(lua_State *L) {
-		luaL_checktype(L, 1, LUA_TUSERDATA);
-		PolyBase **inst = (PolyBase**)lua_touserdata(L, 1);
-		delete ((CoreMutex*) *inst);
-		*inst = NULL;
-		return 0;
-	}
-
 static int Polycode_CoreMotionEvent_get_amount(lua_State *L) {
 	luaL_checktype(L, 1, LUA_TUSERDATA);
 	CoreMotionEvent *inst = (CoreMotionEvent*) *((PolyBase**)lua_touserdata(L, 1));
@@ -5838,18 +5803,6 @@ static int Polycode_LightInfo_set_lightViewMatrix(lua_State *L) {
 		return 0;
 	}
 
-static int Polycode_GPUDrawCall_get_mesh(lua_State *L) {
-	luaL_checktype(L, 1, LUA_TUSERDATA);
-	GPUDrawCall *inst = (GPUDrawCall*) *((PolyBase**)lua_touserdata(L, 1));
-	if(!inst->mesh) {
-		lua_pushnil(L);
-	} else {
-		PolyBase **userdataPtr = (PolyBase**)lua_newuserdata(L, sizeof(PolyBase*));
-		*userdataPtr = (PolyBase*)inst->mesh;
-	}
-	return 1;
-}
-
 static int Polycode_GPUDrawCall_get_options(lua_State *L) {
 	luaL_checktype(L, 1, LUA_TUSERDATA);
 	GPUDrawCall *inst = (GPUDrawCall*) *((PolyBase**)lua_touserdata(L, 1));
@@ -5878,15 +5831,6 @@ static int Polycode_GPUDrawCall_get_material(lua_State *L) {
 	return 1;
 }
 
-static int Polycode_GPUDrawCall_set_mesh(lua_State *L) {
-	luaL_checktype(L, 1, LUA_TUSERDATA);
-	GPUDrawCall *inst = (GPUDrawCall*) *((PolyBase**)lua_touserdata(L, 1));
-	luaL_checktype(L, 2, LUA_TUSERDATA);
-	Mesh* *argInst = (Mesh**) *((PolyBase**)lua_touserdata(L, 2));
-	inst->mesh = *argInst;
-	return 0;
-}
-
 static int Polycode_GPUDrawCall_set_options(lua_State *L) {
 	luaL_checktype(L, 1, LUA_TUSERDATA);
 	GPUDrawCall *inst = (GPUDrawCall*) *((PolyBase**)lua_touserdata(L, 1));
@@ -7683,26 +7627,6 @@ static int Polycode_ShaderPass_set_materialShaderBinding(lua_State *L) {
 		lua_setmetatable(L, -2);
 		return 1;
 	}
-	static int Polycode_ShaderPass_setAttributeArraysFromMesh(lua_State *L) {
-		luaL_checktype(L, 1, LUA_TUSERDATA);
-		ShaderPass *inst = (ShaderPass*) *((PolyBase**)lua_touserdata(L, 1));
-		luaL_checktype(L, 2, LUA_TUSERDATA);
-		Mesh* mesh = (Mesh*) *((PolyBase**)lua_touserdata(L, 2));
-		inst->setAttributeArraysFromMesh(mesh);
-		return 0;
-	}
-	static int Polycode_ShaderPass_setExpectedAttributes(lua_State *L) {
-		luaL_checktype(L, 1, LUA_TUSERDATA);
-		ShaderPass *inst = (ShaderPass*) *((PolyBase**)lua_touserdata(L, 1));
-		inst->setExpectedAttributes();
-		return 0;
-	}
-	static int Polycode_ShaderPass_arrayToAttributeName(lua_State *L) {
-		luaL_checktype(L, 1, LUA_TUSERDATA);
-		VertexDataArray* array = (VertexDataArray*) *((PolyBase**)lua_touserdata(L, 1));
-		lua_pushstring(L, ShaderPass::arrayToAttributeName(array).c_str());
-		return 1;
-	}
 	static int Polycode_delete_ShaderPass(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
 		PolyBase **inst = (PolyBase**)lua_touserdata(L, 1);
@@ -8421,25 +8345,8 @@ static int Polycode_MaterialManager_set_keepTextureData(lua_State *L) {
 		return 0;
 	}
 
-static int Polycode_Mesh_get_indexedMesh(lua_State *L) {
-	luaL_checktype(L, 1, LUA_TUSERDATA);
-	Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
-	lua_pushboolean(L, inst->indexedMesh);
-	return 1;
-}
-
-static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
-	luaL_checktype(L, 1, LUA_TUSERDATA);
-	Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
-	bool param = lua_toboolean(L, 2) != 0;
-	inst->indexedMesh = param;
-	return 0;
-}
-
 	static int Polycode_Mesh(lua_State *L) {
-		luaL_checktype(L, 1, LUA_TNUMBER);
-		int meshType = lua_tointeger(L, 1);
-		Mesh *inst = new Mesh(meshType);
+		Mesh *inst = new Mesh();
 		PolyBase **userdataPtr = (PolyBase**)lua_newuserdata(L, sizeof(PolyBase*));
 		*userdataPtr = (PolyBase*)inst;
 		luaL_getmetatable(L, "Polycode.Mesh");
@@ -8458,6 +8365,18 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		}
 		return 1;
 	}
+	static int Polycode_Mesh_Copy(lua_State *L) {
+		luaL_checktype(L, 1, LUA_TUSERDATA);
+		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		PolyBase *ptrRetVal = (PolyBase*)inst->Copy();
+		if(ptrRetVal == NULL) {
+			lua_pushnil(L);
+		} else {
+			PolyBase **userdataPtr = (PolyBase**)lua_newuserdata(L, sizeof(PolyBase*));
+			*userdataPtr = ptrRetVal;
+		}
+		return 1;
+	}
 	static int Polycode_Mesh_loadMesh(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
 		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
@@ -8466,12 +8385,6 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		inst->loadMesh(fileName);
 		return 0;
 	}
-	static int Polycode_Mesh_clearMesh(lua_State *L) {
-		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
-		inst->clearMesh();
-		return 0;
-	}
 	static int Polycode_Mesh_saveToFile(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
 		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
@@ -8524,16 +8437,154 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		inst->loadFromFile(inFile);
 		return 0;
 	}
-	static int Polycode_Mesh_getVertexCount(lua_State *L) {
+	static int Polycode_Mesh_addSubmesh(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
 		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
-		lua_pushinteger(L, inst->getVertexCount());
+		luaL_checktype(L, 2, LUA_TUSERDATA);
+		MeshGeometry newSubmesh = *(MeshGeometry*) *((PolyBase**)lua_touserdata(L, 2));
+		inst->addSubmesh(newSubmesh);
+		return 0;
+	}
+	static int Polycode_Mesh_removeSubmeshAtIndex(lua_State *L) {
+		luaL_checktype(L, 1, LUA_TUSERDATA);
+		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		luaL_checktype(L, 2, LUA_TNUMBER);
+		int index = lua_tointeger(L, 2);
+		inst->removeSubmeshAtIndex(index);
+		return 0;
+	}
+	static int Polycode_Mesh_getNumSubmeshes(lua_State *L) {
+		luaL_checktype(L, 1, LUA_TUSERDATA);
+		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		lua_pushinteger(L, inst->getNumSubmeshes());
 		return 1;
 	}
-	static int Polycode_Mesh_createPlane(lua_State *L) {
+	static int Polycode_Mesh_getSubmeshAtIndex(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
 		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
+		int index = lua_tointeger(L, 2);
+		MeshGeometry *retInst = new MeshGeometry();
+		*retInst = inst->getSubmeshAtIndex(index);
+		PolyBase **userdataPtr = (PolyBase**)lua_newuserdata(L, sizeof(PolyBase*));
+		luaL_getmetatable(L, "Polycode.MeshGeometry");
+		lua_setmetatable(L, -2);
+		*userdataPtr = (PolyBase*)retInst;
+		return 1;
+	}
+	static int Polycode_Mesh_getSubmeshPointer(lua_State *L) {
+		luaL_checktype(L, 1, LUA_TUSERDATA);
+		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		luaL_checktype(L, 2, LUA_TNUMBER);
+		int index = lua_tointeger(L, 2);
+		shared_ptr<MeshGeometry> *retInst = new shared_ptr<MeshGeometry>();
+		*retInst = inst->getSubmeshPointer(index);
+		PolyBase **userdataPtr = (PolyBase**)lua_newuserdata(L, sizeof(PolyBase*));
+		luaL_getmetatable(L, "Polycode.shared_ptr<MeshGeometry>");
+		lua_setmetatable(L, -2);
+		*userdataPtr = (PolyBase*)retInst;
+		return 1;
+	}
+	static int Polycode_Mesh_clearMesh(lua_State *L) {
+		luaL_checktype(L, 1, LUA_TUSERDATA);
+		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		inst->clearMesh();
+		return 0;
+	}
+	static int Polycode_Mesh_calculateBBox(lua_State *L) {
+		luaL_checktype(L, 1, LUA_TUSERDATA);
+		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		Vector3 *retInst = new Vector3();
+		*retInst = inst->calculateBBox();
+		PolyBase **userdataPtr = (PolyBase**)lua_newuserdata(L, sizeof(PolyBase*));
+		luaL_getmetatable(L, "Polycode.Vector3");
+		lua_setmetatable(L, -2);
+		*userdataPtr = (PolyBase*)retInst;
+		return 1;
+	}
+	static int Polycode_Mesh_getRadius(lua_State *L) {
+		luaL_checktype(L, 1, LUA_TUSERDATA);
+		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		lua_pushnumber(L, inst->getRadius());
+		return 1;
+	}
+	static int Polycode_delete_Mesh(lua_State *L) {
+		luaL_checktype(L, 1, LUA_TUSERDATA);
+		PolyBase **inst = (PolyBase**)lua_touserdata(L, 1);
+		delete ((Mesh*) *inst);
+		*inst = NULL;
+		return 0;
+	}
+
+static int Polycode_MeshGeometry_get_meshType(lua_State *L) {
+	luaL_checktype(L, 1, LUA_TUSERDATA);
+	MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
+	lua_pushinteger(L, inst->meshType);
+	return 1;
+}
+
+static int Polycode_MeshGeometry_get_dataChanged(lua_State *L) {
+	luaL_checktype(L, 1, LUA_TUSERDATA);
+	MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
+	lua_pushboolean(L, inst->dataChanged);
+	return 1;
+}
+
+static int Polycode_MeshGeometry_get_indexedMesh(lua_State *L) {
+	luaL_checktype(L, 1, LUA_TUSERDATA);
+	MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
+	lua_pushboolean(L, inst->indexedMesh);
+	return 1;
+}
+
+static int Polycode_MeshGeometry_set_meshType(lua_State *L) {
+	luaL_checktype(L, 1, LUA_TUSERDATA);
+	MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
+	int param = lua_tointeger(L, 2);
+	inst->meshType = param;
+	return 0;
+}
+
+static int Polycode_MeshGeometry_set_dataChanged(lua_State *L) {
+	luaL_checktype(L, 1, LUA_TUSERDATA);
+	MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
+	bool param = lua_toboolean(L, 2) != 0;
+	inst->dataChanged = param;
+	return 0;
+}
+
+static int Polycode_MeshGeometry_set_indexedMesh(lua_State *L) {
+	luaL_checktype(L, 1, LUA_TUSERDATA);
+	MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
+	bool param = lua_toboolean(L, 2) != 0;
+	inst->indexedMesh = param;
+	return 0;
+}
+
+	static int Polycode_MeshGeometry(lua_State *L) {
+		MeshGeometry *inst = new MeshGeometry();
+		PolyBase **userdataPtr = (PolyBase**)lua_newuserdata(L, sizeof(PolyBase*));
+		*userdataPtr = (PolyBase*)inst;
+		luaL_getmetatable(L, "Polycode.MeshGeometry");
+		lua_setmetatable(L, -2);
+		return 1;
+	}
+	static int Polycode_MeshGeometry_clearMesh(lua_State *L) {
+		luaL_checktype(L, 1, LUA_TUSERDATA);
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
+		inst->clearMesh();
+		return 0;
+	}
+	static int Polycode_MeshGeometry_getVertexCount(lua_State *L) {
+		luaL_checktype(L, 1, LUA_TUSERDATA);
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
+		lua_pushinteger(L, inst->getVertexCount());
+		return 1;
+	}
+	static int Polycode_MeshGeometry_createPlane(lua_State *L) {
+		luaL_checktype(L, 1, LUA_TUSERDATA);
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
+		luaL_checktype(L, 2, LUA_TNUMBER);
 		Number w = lua_tonumber(L, 2);
 		luaL_checktype(L, 3, LUA_TNUMBER);
 		Number h = lua_tonumber(L, 3);
@@ -8546,9 +8597,9 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		inst->createPlane(w, h, tilingValue);
 		return 0;
 	}
-	static int Polycode_Mesh_createVPlane(lua_State *L) {
+	static int Polycode_MeshGeometry_createVPlane(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		Number w = lua_tonumber(L, 2);
 		luaL_checktype(L, 3, LUA_TNUMBER);
@@ -8562,9 +8613,9 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		inst->createVPlane(w, h, tilingValue);
 		return 0;
 	}
-	static int Polycode_Mesh_createCircle(lua_State *L) {
+	static int Polycode_MeshGeometry_createCircle(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		Number w = lua_tonumber(L, 2);
 		luaL_checktype(L, 3, LUA_TNUMBER);
@@ -8580,9 +8631,9 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		inst->createCircle(w, h, numSegments, tilingValue);
 		return 0;
 	}
-	static int Polycode_Mesh_createLineCircle(lua_State *L) {
+	static int Polycode_MeshGeometry_createLineCircle(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		Number w = lua_tonumber(L, 2);
 		luaL_checktype(L, 3, LUA_TNUMBER);
@@ -8598,9 +8649,9 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		inst->createLineCircle(w, h, numSegments, tilingValue);
 		return 0;
 	}
-	static int Polycode_Mesh_createTorus(lua_State *L) {
+	static int Polycode_MeshGeometry_createTorus(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		Number radius = lua_tonumber(L, 2);
 		luaL_checktype(L, 3, LUA_TNUMBER);
@@ -8618,9 +8669,9 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		inst->createTorus(radius, tubeRadius, segmentsW, segmentsH, tilingValue);
 		return 0;
 	}
-	static int Polycode_Mesh_createBox(lua_State *L) {
+	static int Polycode_MeshGeometry_createBox(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		Number w = lua_tonumber(L, 2);
 		luaL_checktype(L, 3, LUA_TNUMBER);
@@ -8636,9 +8687,9 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		inst->createBox(w, d, h, tilingValue);
 		return 0;
 	}
-	static int Polycode_Mesh_createSphere(lua_State *L) {
+	static int Polycode_MeshGeometry_createSphere(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		Number radius = lua_tonumber(L, 2);
 		luaL_checktype(L, 3, LUA_TNUMBER);
@@ -8654,9 +8705,9 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		inst->createSphere(radius, numRings, numSegments, tilingValue);
 		return 0;
 	}
-	static int Polycode_Mesh_createIcosphere(lua_State *L) {
+	static int Polycode_MeshGeometry_createIcosphere(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		Number radius = lua_tonumber(L, 2);
 		luaL_checktype(L, 3, LUA_TNUMBER);
@@ -8664,9 +8715,9 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		inst->createIcosphere(radius, subdivisions);
 		return 0;
 	}
-	static int Polycode_Mesh_createOctosphere(lua_State *L) {
+	static int Polycode_MeshGeometry_createOctosphere(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		Number radius = lua_tonumber(L, 2);
 		luaL_checktype(L, 3, LUA_TNUMBER);
@@ -8674,9 +8725,9 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		inst->createOctosphere(radius, subdivisions);
 		return 0;
 	}
-	static int Polycode_Mesh_createCylinder(lua_State *L) {
+	static int Polycode_MeshGeometry_createCylinder(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		Number height = lua_tonumber(L, 2);
 		luaL_checktype(L, 3, LUA_TNUMBER);
@@ -8698,9 +8749,9 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		inst->createCylinder(height, radius, numSegments, capped, tilingValue);
 		return 0;
 	}
-	static int Polycode_Mesh_createCone(lua_State *L) {
+	static int Polycode_MeshGeometry_createCone(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		Number height = lua_tonumber(L, 2);
 		luaL_checktype(L, 3, LUA_TNUMBER);
@@ -8716,9 +8767,9 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		inst->createCone(height, radius, numSegments, tilingValue);
 		return 0;
 	}
-	static int Polycode_Mesh_recenterMesh(lua_State *L) {
+	static int Polycode_MeshGeometry_recenterMesh(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		Vector3 *retInst = new Vector3();
 		*retInst = inst->recenterMesh();
 		PolyBase **userdataPtr = (PolyBase**)lua_newuserdata(L, sizeof(PolyBase*));
@@ -8727,9 +8778,9 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		*userdataPtr = (PolyBase*)retInst;
 		return 1;
 	}
-	static int Polycode_Mesh_setVertexAtOffset(lua_State *L) {
+	static int Polycode_MeshGeometry_setVertexAtOffset(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		int offset = lua_tointeger(L, 2);
 		luaL_checktype(L, 3, LUA_TNUMBER);
@@ -8741,9 +8792,9 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		inst->setVertexAtOffset(offset, x, y, z);
 		return 0;
 	}
-	static int Polycode_Mesh_addVertexWithUVAndNormal(lua_State *L) {
+	static int Polycode_MeshGeometry_addVertexWithUVAndNormal(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		Number x = lua_tonumber(L, 2);
 		luaL_checktype(L, 3, LUA_TNUMBER);
@@ -8763,9 +8814,9 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		inst->addVertexWithUVAndNormal(x, y, z, u, v, nx, ny, nz);
 		return 0;
 	}
-	static int Polycode_Mesh_addTexCoord(lua_State *L) {
+	static int Polycode_MeshGeometry_addTexCoord(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		Number u = lua_tonumber(L, 2);
 		luaL_checktype(L, 3, LUA_TNUMBER);
@@ -8773,9 +8824,9 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		inst->addTexCoord(u, v);
 		return 0;
 	}
-	static int Polycode_Mesh_addTexCoord2(lua_State *L) {
+	static int Polycode_MeshGeometry_addTexCoord2(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		Number u = lua_tonumber(L, 2);
 		luaL_checktype(L, 3, LUA_TNUMBER);
@@ -8783,9 +8834,9 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		inst->addTexCoord2(u, v);
 		return 0;
 	}
-	static int Polycode_Mesh_addTangent(lua_State *L) {
+	static int Polycode_MeshGeometry_addTangent(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		Number x = lua_tonumber(L, 2);
 		luaL_checktype(L, 3, LUA_TNUMBER);
@@ -8795,9 +8846,9 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		inst->addTangent(x, y, z);
 		return 0;
 	}
-	static int Polycode_Mesh_addVertexWithUV(lua_State *L) {
+	static int Polycode_MeshGeometry_addVertexWithUV(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		Number x = lua_tonumber(L, 2);
 		luaL_checktype(L, 3, LUA_TNUMBER);
@@ -8811,9 +8862,9 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		inst->addVertexWithUV(x, y, z, u, v);
 		return 0;
 	}
-	static int Polycode_Mesh_addVertex(lua_State *L) {
+	static int Polycode_MeshGeometry_addVertex(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		Number x = lua_tonumber(L, 2);
 		luaL_checktype(L, 3, LUA_TNUMBER);
@@ -8823,9 +8874,9 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		inst->addVertex(x, y, z);
 		return 0;
 	}
-	static int Polycode_Mesh_addNormal(lua_State *L) {
+	static int Polycode_MeshGeometry_addNormal(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		Number nx = lua_tonumber(L, 2);
 		luaL_checktype(L, 3, LUA_TNUMBER);
@@ -8835,9 +8886,9 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		inst->addNormal(nx, ny, nz);
 		return 0;
 	}
-	static int Polycode_Mesh_addBoneAssignments(lua_State *L) {
+	static int Polycode_MeshGeometry_addBoneAssignments(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		Number b1Weight = lua_tonumber(L, 2);
 		luaL_checktype(L, 3, LUA_TNUMBER);
@@ -8857,9 +8908,9 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		inst->addBoneAssignments(b1Weight, b1Index, b2Weight, b2Index, b3Weight, b3Index, b4Weight, b4Index);
 		return 0;
 	}
-	static int Polycode_Mesh_addColor(lua_State *L) {
+	static int Polycode_MeshGeometry_addColor(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		Number r = lua_tonumber(L, 2);
 		luaL_checktype(L, 3, LUA_TNUMBER);
@@ -8871,9 +8922,9 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		inst->addColor(r, g, b, a);
 		return 0;
 	}
-	static int Polycode_Mesh_getVertexPosition(lua_State *L) {
+	static int Polycode_MeshGeometry_getVertexPosition(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		int vertexOffset = lua_tointeger(L, 2);
 		Vector3 *retInst = new Vector3();
@@ -8884,9 +8935,9 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		*userdataPtr = (PolyBase*)retInst;
 		return 1;
 	}
-	static int Polycode_Mesh_getVertexPositionAtIndex(lua_State *L) {
+	static int Polycode_MeshGeometry_getVertexPositionAtIndex(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		int index = lua_tointeger(L, 2);
 		Vector3 *retInst = new Vector3();
@@ -8897,9 +8948,9 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		*userdataPtr = (PolyBase*)retInst;
 		return 1;
 	}
-	static int Polycode_Mesh_getVertexTexCoord(lua_State *L) {
+	static int Polycode_MeshGeometry_getVertexTexCoord(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		int vertexOffset = lua_tointeger(L, 2);
 		Vector2 *retInst = new Vector2();
@@ -8910,9 +8961,9 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		*userdataPtr = (PolyBase*)retInst;
 		return 1;
 	}
-	static int Polycode_Mesh_getVertexTexCoordAtIndex(lua_State *L) {
+	static int Polycode_MeshGeometry_getVertexTexCoordAtIndex(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		int index = lua_tointeger(L, 2);
 		Vector2 *retInst = new Vector2();
@@ -8923,9 +8974,9 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		*userdataPtr = (PolyBase*)retInst;
 		return 1;
 	}
-	static int Polycode_Mesh_Copy(lua_State *L) {
+	static int Polycode_MeshGeometry_Copy(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		PolyBase *ptrRetVal = (PolyBase*)inst->Copy();
 		if(ptrRetVal == NULL) {
 			lua_pushnil(L);
@@ -8935,47 +8986,47 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		}
 		return 1;
 	}
-	static int Polycode_Mesh_getRadius(lua_State *L) {
+	static int Polycode_MeshGeometry_getRadius(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		lua_pushnumber(L, inst->getRadius());
 		return 1;
 	}
-	static int Polycode_Mesh_calculateNormals(lua_State *L) {
+	static int Polycode_MeshGeometry_calculateNormals(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		inst->calculateNormals();
 		return 0;
 	}
-	static int Polycode_Mesh_calculateTangents(lua_State *L) {
+	static int Polycode_MeshGeometry_calculateTangents(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		inst->calculateTangents();
 		return 0;
 	}
-	static int Polycode_Mesh_getMeshType(lua_State *L) {
+	static int Polycode_MeshGeometry_getMeshType(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		lua_pushinteger(L, inst->getMeshType());
 		return 1;
 	}
-	static int Polycode_Mesh_setMeshType(lua_State *L) {
+	static int Polycode_MeshGeometry_setMeshType(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		int newType = lua_tointeger(L, 2);
 		inst->setMeshType(newType);
 		return 0;
 	}
-	static int Polycode_Mesh_getIndexGroupSize(lua_State *L) {
+	static int Polycode_MeshGeometry_getIndexGroupSize(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		lua_pushinteger(L, inst->getIndexGroupSize());
 		return 1;
 	}
-	static int Polycode_Mesh_calculateBBox(lua_State *L) {
+	static int Polycode_MeshGeometry_calculateBBox(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		Vector3 *retInst = new Vector3();
 		*retInst = inst->calculateBBox();
 		PolyBase **userdataPtr = (PolyBase**)lua_newuserdata(L, sizeof(PolyBase*));
@@ -8984,15 +9035,9 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		*userdataPtr = (PolyBase*)retInst;
 		return 1;
 	}
-	static int Polycode_Mesh_hasVertexBuffer(lua_State *L) {
+	static int Polycode_MeshGeometry_addIndexedFace(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
-		lua_pushboolean(L, inst->hasVertexBuffer());
-		return 1;
-	}
-	static int Polycode_Mesh_addIndexedFace(lua_State *L) {
-		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		int i1 = lua_tointeger(L, 2);
 		luaL_checktype(L, 3, LUA_TNUMBER);
@@ -9000,17 +9045,17 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		inst->addIndexedFace(i1, i2);
 		return 0;
 	}
-	static int Polycode_Mesh_addIndex(lua_State *L) {
+	static int Polycode_MeshGeometry_addIndex(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		int index = lua_tointeger(L, 2);
 		inst->addIndex(index);
 		return 0;
 	}
-	static int Polycode_Mesh_removeVertexRange(lua_State *L) {
+	static int Polycode_MeshGeometry_removeVertexRange(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		int beginRemoveVertex = lua_tointeger(L, 2);
 		int vertexRemovalCount;
@@ -9022,29 +9067,29 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		inst->removeVertexRange(beginRemoveVertex, vertexRemovalCount);
 		return 0;
 	}
-	static int Polycode_Mesh_removeFace(lua_State *L) {
+	static int Polycode_MeshGeometry_removeFace(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		int faceIndex = lua_tointeger(L, 2);
 		inst->removeFace(faceIndex);
 		return 0;
 	}
-	static int Polycode_Mesh_removeUnusedVertices(lua_State *L) {
+	static int Polycode_MeshGeometry_removeUnusedVertices(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		lua_pushinteger(L, inst->removeUnusedVertices());
 		return 1;
 	}
-	static int Polycode_Mesh_getIndexCount(lua_State *L) {
+	static int Polycode_MeshGeometry_getIndexCount(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		lua_pushinteger(L, inst->getIndexCount());
 		return 1;
 	}
-	static int Polycode_Mesh_subdivideToRadius(lua_State *L) {
+	static int Polycode_MeshGeometry_subdivideToRadius(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TNUMBER);
 		Number radius = lua_tonumber(L, 2);
 		luaL_checktype(L, 3, LUA_TNUMBER);
@@ -9052,7 +9097,7 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		inst->subdivideToRadius(radius, subdivisions);
 		return 0;
 	}
-	static int Polycode_Mesh_calculateFaceTangent(lua_State *L) {
+	static int Polycode_MeshGeometry_calculateFaceTangent(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
 		Vector3 v1 = *(Vector3*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TUSERDATA);
@@ -9066,31 +9111,31 @@ static int Polycode_Mesh_set_indexedMesh(lua_State *L) {
 		luaL_checktype(L, 6, LUA_TUSERDATA);
 		Vector2 texCoord3 = *(Vector2*) *((PolyBase**)lua_touserdata(L, 6));
 		Vector3 *retInst = new Vector3();
-		*retInst = Mesh::calculateFaceTangent(v1, v2, v3, texCoord1, texCoord2, texCoord3);
+		*retInst = MeshGeometry::calculateFaceTangent(v1, v2, v3, texCoord1, texCoord2, texCoord3);
 		PolyBase **userdataPtr = (PolyBase**)lua_newuserdata(L, sizeof(PolyBase*));
 		luaL_getmetatable(L, "Polycode.Vector3");
 		lua_setmetatable(L, -2);
 		*userdataPtr = (PolyBase*)retInst;
 		return 1;
 	}
-	static int Polycode_Mesh_saveAsOBJ(lua_State *L) {
+	static int Polycode_MeshGeometry_saveAsOBJ(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TSTRING);
 		String fileName = String(lua_tostring(L, 2));
 		inst->saveAsOBJ(fileName);
 		return 0;
 	}
-	static int Polycode_Mesh_normalizeBoneWeights(lua_State *L) {
+	static int Polycode_MeshGeometry_normalizeBoneWeights(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Mesh *inst = (Mesh*) *((PolyBase**)lua_touserdata(L, 1));
+		MeshGeometry *inst = (MeshGeometry*) *((PolyBase**)lua_touserdata(L, 1));
 		inst->normalizeBoneWeights();
 		return 0;
 	}
-	static int Polycode_delete_Mesh(lua_State *L) {
+	static int Polycode_delete_MeshGeometry(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
 		PolyBase **inst = (PolyBase**)lua_touserdata(L, 1);
-		delete ((Mesh*) *inst);
+		delete ((MeshGeometry*) *inst);
 		*inst = NULL;
 		return 0;
 	}
@@ -10844,13 +10889,6 @@ static int Polycode_RenderDataArray_get_customArrayName(lua_State *L) {
 	return 1;
 }
 
-static int Polycode_RenderDataArray_get_hasVBO(lua_State *L) {
-	luaL_checktype(L, 1, LUA_TUSERDATA);
-	RenderDataArray *inst = (RenderDataArray*) *((PolyBase**)lua_touserdata(L, 1));
-	lua_pushboolean(L, inst->hasVBO);
-	return 1;
-}
-
 static int Polycode_RenderDataArray_set_type(lua_State *L) {
 	luaL_checktype(L, 1, LUA_TUSERDATA);
 	RenderDataArray *inst = (RenderDataArray*) *((PolyBase**)lua_touserdata(L, 1));
@@ -10867,14 +10905,6 @@ static int Polycode_RenderDataArray_set_customArrayName(lua_State *L) {
 	return 0;
 }
 
-static int Polycode_RenderDataArray_set_hasVBO(lua_State *L) {
-	luaL_checktype(L, 1, LUA_TUSERDATA);
-	RenderDataArray *inst = (RenderDataArray*) *((PolyBase**)lua_touserdata(L, 1));
-	bool param = lua_toboolean(L, 2) != 0;
-	inst->hasVBO = param;
-	return 0;
-}
-
 	static int Polycode_RenderDataArray(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TNUMBER);
 		int type = lua_tointeger(L, 1);
@@ -11278,6 +11308,14 @@ static int Polycode_RendererThreadJob_set_jobType(lua_State *L) {
 		}
 		return 1;
 	}
+	static int Polycode_RenderThread_processDrawBufferLights(lua_State *L) {
+		luaL_checktype(L, 1, LUA_TUSERDATA);
+		RenderThread *inst = (RenderThread*) *((PolyBase**)lua_touserdata(L, 1));
+		luaL_checktype(L, 2, LUA_TUSERDATA);
+		GPUDrawBuffer* buffer = (GPUDrawBuffer*) *((PolyBase**)lua_touserdata(L, 2));
+		inst->processDrawBufferLights(buffer);
+		return 0;
+	}
 	static int Polycode_RenderThread_processDrawBuffer(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
 		RenderThread *inst = (RenderThread*) *((PolyBase**)lua_touserdata(L, 1));
@@ -11554,14 +11592,6 @@ static int Polycode_RenderThreadDebugInfo_set_timeTaken(lua_State *L) {
 		}
 		return 1;
 	}
-	static int Polycode_Renderer_createVertexBuffers(lua_State *L) {
-		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Renderer *inst = (Renderer*) *((PolyBase**)lua_touserdata(L, 1));
-		luaL_checktype(L, 2, LUA_TUSERDATA);
-		Mesh* mesh = (Mesh*) *((PolyBase**)lua_touserdata(L, 2));
-		inst->createVertexBuffers(mesh);
-		return 0;
-	}
 	static int Polycode_Renderer_enqueueFrameJob(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
 		Renderer *inst = (Renderer*) *((PolyBase**)lua_touserdata(L, 1));
@@ -11588,12 +11618,12 @@ static int Polycode_RenderThreadDebugInfo_set_timeTaken(lua_State *L) {
 		inst->destroyShader(shader);
 		return 0;
 	}
-	static int Polycode_Renderer_destroyBuffer(lua_State *L) {
+	static int Polycode_Renderer_destroySubmeshPlatformData(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
 		Renderer *inst = (Renderer*) *((PolyBase**)lua_touserdata(L, 1));
 		luaL_checktype(L, 2, LUA_TUSERDATA);
-		RenderDataArray* array = (RenderDataArray*) *((PolyBase**)lua_touserdata(L, 2));
-		inst->destroyBuffer(array);
+		void* platformData = (void*) *((PolyBase**)lua_touserdata(L, 2));
+		inst->destroySubmeshPlatformData(platformData);
 		return 0;
 	}
 	static int Polycode_Renderer_destroyShaderBinding(lua_State *L) {
@@ -11636,28 +11666,6 @@ static int Polycode_RenderThreadDebugInfo_set_timeTaken(lua_State *L) {
 		lua_pushnumber(L, inst->getAnisotropyAmount());
 		return 1;
 	}
-	static int Polycode_Renderer_createMesh(lua_State *L) {
-		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Renderer *inst = (Renderer*) *((PolyBase**)lua_touserdata(L, 1));
-		luaL_checktype(L, 2, LUA_TSTRING);
-		String fileName = String(lua_tostring(L, 2));
-		PolyBase *ptrRetVal = (PolyBase*)inst->createMesh(fileName);
-		if(ptrRetVal == NULL) {
-			lua_pushnil(L);
-		} else {
-			PolyBase **userdataPtr = (PolyBase**)lua_newuserdata(L, sizeof(PolyBase*));
-			*userdataPtr = ptrRetVal;
-		}
-		return 1;
-	}
-	static int Polycode_Renderer_destroyMesh(lua_State *L) {
-		luaL_checktype(L, 1, LUA_TUSERDATA);
-		Renderer *inst = (Renderer*) *((PolyBase**)lua_touserdata(L, 1));
-		luaL_checktype(L, 2, LUA_TUSERDATA);
-		Mesh* mesh = (Mesh*) *((PolyBase**)lua_touserdata(L, 2));
-		inst->destroyMesh(mesh);
-		return 0;
-	}
 	static int Polycode_Renderer_unProject(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
 		Vector3 position = *(Vector3*) *((PolyBase**)lua_touserdata(L, 1));
@@ -14222,18 +14230,6 @@ static int Polycode_SceneMesh_set_sendBoneMatricesToMaterial(lua_State *L) {
 		}
 		return 1;
 	}
-	static int Polycode_SceneMesh_SceneMeshWithType(lua_State *L) {
-		luaL_checktype(L, 1, LUA_TNUMBER);
-		int meshType = lua_tointeger(L, 1);
-		PolyBase *ptrRetVal = (PolyBase*)SceneMesh::SceneMeshWithType(meshType);
-		if(ptrRetVal == NULL) {
-			lua_pushnil(L);
-		} else {
-			PolyBase **userdataPtr = (PolyBase**)lua_newuserdata(L, sizeof(PolyBase*));
-			*userdataPtr = ptrRetVal;
-		}
-		return 1;
-	}
 	static int Polycode_SceneMesh_Render(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
 		SceneMesh *inst = (SceneMesh*) *((PolyBase**)lua_touserdata(L, 1));
@@ -14329,12 +14325,6 @@ static int Polycode_SceneMesh_set_sendBoneMatricesToMaterial(lua_State *L) {
 		inst->setMaterial(material);
 		return 0;
 	}
-	static int Polycode_SceneMesh_rebuildAttributes(lua_State *L) {
-		luaL_checktype(L, 1, LUA_TUSERDATA);
-		SceneMesh *inst = (SceneMesh*) *((PolyBase**)lua_touserdata(L, 1));
-		inst->rebuildAttributes();
-		return 0;
-	}
 	static int Polycode_SceneMesh_setMaterialByName(lua_State *L) {
 		luaL_checktype(L, 1, LUA_TUSERDATA);
 		SceneMesh *inst = (SceneMesh*) *((PolyBase**)lua_touserdata(L, 1));
@@ -15760,6 +15750,13 @@ static int Polycode_ProgramAttribute_get_name(lua_State *L) {
 	return 1;
 }
 
+static int Polycode_ProgramAttribute_get_arrayType(lua_State *L) {
+	luaL_checktype(L, 1, LUA_TUSERDATA);
+	ProgramAttribute *inst = (ProgramAttribute*) *((PolyBase**)lua_touserdata(L, 1));
+	lua_pushinteger(L, inst->arrayType);
+	return 1;
+}
+
 static int Polycode_ProgramAttribute_set_size(lua_State *L) {
 	luaL_checktype(L, 1, LUA_TUSERDATA);
 	ProgramAttribute *inst = (ProgramAttribute*) *((PolyBase**)lua_touserdata(L, 1));
@@ -15776,6 +15773,14 @@ static int Polycode_ProgramAttribute_set_name(lua_State *L) {
 	return 0;
 }
 
+static int Polycode_ProgramAttribute_set_arrayType(lua_State *L) {
+	luaL_checktype(L, 1, LUA_TUSERDATA);
+	ProgramAttribute *inst = (ProgramAttribute*) *((PolyBase**)lua_touserdata(L, 1));
+	int param = lua_tointeger(L, 2);
+	inst->arrayType = param;
+	return 0;
+}
+
 	static int Polycode_ProgramAttribute(lua_State *L) {
 		ProgramAttribute *inst = new ProgramAttribute();
 		PolyBase **userdataPtr = (PolyBase**)lua_newuserdata(L, sizeof(PolyBase*));

+ 1 - 0
include/polycode/core/PolyCore.h

@@ -40,6 +40,7 @@ namespace Polycode {
           
 	class _PolyExport CoreMutex : public PolyBase {
 	public:
+        virtual ~CoreMutex(){}
 
 		virtual void lock() = 0;
 		virtual void unlock() = 0;

+ 2 - 1
include/polycode/core/PolyGPUDrawBuffer.h

@@ -28,6 +28,7 @@
 #include "polycode/core/PolyMaterial.h"
 #include "polycode/core/PolyColor.h"
 #include "polycode/core/PolyVector3.h"
+#include <memory>
 
 namespace Polycode {
     
@@ -70,7 +71,7 @@ namespace Polycode {
     
     class _PolyExport GPUDrawCall {
     public:
-        Mesh *mesh;
+        std::shared_ptr<MeshGeometry> submesh;
         GPUDrawOptions options;
         Matrix4 modelMatrix;
         Material *material;

+ 1 - 8
include/polycode/core/PolyMaterial.h

@@ -38,19 +38,12 @@ namespace Polycode {
     class _PolyExport ShaderPass {
         public:
             ShaderPass();
-            ShaderPass(Shader *shader);
-        
-            void setAttributeArraysFromMesh(Mesh *mesh);
-            void setExpectedAttributes();
-            static String arrayToAttributeName(VertexDataArray *array);
-        
+            ShaderPass(Shader *shader);        
             Shader *shader;
             bool wireframe;
             unsigned short blendingMode;
             ShaderBinding* shaderBinding;
             ShaderBinding* materialShaderBinding;
-        
-            std::vector<VertexDataArray*> attributeArrays;
     };
 
 	class _PolyExport Material : public Resource {

+ 93 - 54
include/polycode/core/PolyMesh.h

@@ -24,11 +24,12 @@ THE SOFTWARE.
 #include "polycode/core/PolyGlobals.h"
 #include "polycode/core/PolyRenderDataArray.h"
 #include "polycode/core/PolyColor.h"
+#include "polycode/core/PolyCore.h"
 #include "polycode/core/PolyVector3.h"
 #include "polycode/core/PolyVector2.h"
-#include "polycode/core/PolyCore.h"
 #include "polycode/core/PolyResource.h"
 #include <vector>
+#include <memory>
 
 class CoreFile;
 
@@ -54,57 +55,32 @@ namespace Polycode {
 		float x;
 		float y;
 	} Vector2_struct;
+
 	
 	/**
 	*  A mesh comprised of vertices. When data in the mesh changes, arrayDirtyMap must be set to true for the appropriate array types (color, position, normal, etc). Available types are defined in RenderDataArray.
 	*/
-	class _PolyExport Mesh : public Resource {
+	class _PolyExport MeshGeometry {
 		public:
-		
 			
+        
+            MeshGeometry();
 			/**
 			* Construct with an empty mesh of specified type.
 			* @param meshType Type of mesh. Possible values are: Mesh::TRISTRIP_MESH, Mesh::TRI_MESH, Mesh::TRIFAN_MESH, Mesh::TRISTRIP_MESH, Mesh::LINE_MESH, Mesh::POINT_MESH.
 			*/			
-			explicit Mesh(int meshType);
-					
-			/**
-			* Construct from a mesh loaded from a file.
-			* @param fileName Path to mesh file.
-			*/
-			explicit Mesh(const String& fileName);
-
-			/**
-			* Construct from a mesh loaded from a file.
-			* @param fileName Path to mesh file.
-			*/			
-			static Mesh *MeshFromFileName(String& fileName);
-
-			virtual ~Mesh();
-			
-			/**
-			* Loads a mesh from a file.
-			* @param fileName Path to mesh file.
-			*/			
-			void loadMesh(const String& fileName);
-			
+			explicit MeshGeometry(int meshType);
+			virtual ~MeshGeometry();
+        
+            MeshGeometry(const MeshGeometry &geom);
+            MeshGeometry &operator=(const MeshGeometry &geom);
+        
 			/**
 			* Clears mesh data.
 			*/
 			
 			void clearMesh();
 
-			/**
-			* Saves mesh to a file.
-			* @param fileName Path to file to save to.
-			*/			
-			void saveToFile(const String& fileName, bool writeNormals = true, bool writeTangents = true, bool writeColors = true, bool writeBoneWeights = true, bool writeUVs = true, bool writeSecondaryUVs = false);
-
-			void loadFromFile(CoreFile *inFile);
-
-        
-			void saveToFile(CoreFile *outFile, bool writeNormals = true, bool writeTangents = true, bool writeColors = true, bool writeBoneWeights = true, bool writeUVs = true, bool writeSecondaryUVs = false);
-			
 			
 			/**
 			* Returns the total vertex count in the mesh.
@@ -235,7 +211,7 @@ namespace Polycode {
         
             Vector2 getVertexTexCoordAtIndex(unsigned int index);
         
-            Mesh *Copy() const;
+            MeshGeometry *Copy() const;
 			
 			/**
 			* Returns the radius of the mesh (furthest vertex away from origin).
@@ -278,12 +254,6 @@ namespace Polycode {
 			* Calculates the mesh bounding box.
 			*/
 			Vector3 calculateBBox();
-
-			/**
-			* Checks if the mesh has a vertex buffer.
-			* @param True if the mesh has a vertex buffer, false if not.
-			*/		
-			bool hasVertexBuffer() { return meshHasVertexBuffer; }
 	
 			/**
 			* Quad based mesh.
@@ -321,8 +291,7 @@ namespace Polycode {
 			static const int LINE_LOOP_MESH = 7;
         
         
-            bool indexedMesh;
-
+        
             void addIndexedFace(unsigned int i1, unsigned int i2);
             void addIndexedFace(unsigned int i1, unsigned int i2, unsigned int i3);
             void addIndexedFace(unsigned int i1, unsigned int i2, unsigned int i3, unsigned int i4);
@@ -362,18 +331,88 @@ namespace Polycode {
             VertexDataArray vertexBoneWeightArray;
             VertexDataArray vertexBoneIndexArray;
         
+            VertexDataArray customVertexArray1;
+            VertexDataArray customVertexArray2;
+            VertexDataArray customVertexArray3;
+            VertexDataArray customVertexArray4;
+        
             IndexDataArray indexArray;
         
-        protected:
+            int meshType;
+            bool dataChanged;
+            bool indexedMesh;
+	};
+    
+    class _PolyExport Mesh : public Resource {
+        public:
+        
+        
+            Mesh();
+            /**
+             * Construct from a mesh loaded from a file.
+             * @param fileName Path to mesh file.
+             */
+            explicit Mesh(const String& fileName);
+        
+            ~Mesh();
+        
+            /**
+             * Construct from a mesh loaded from a file.
+             * @param fileName Path to mesh file.
+             */
+            static Mesh *MeshFromFileName(String& fileName);
+        
+        
+            Mesh *Copy() const;
+        
+            /**
+             * Loads a mesh from a file.
+             * @param fileName Path to mesh file.
+             */
+            void loadMesh(const String& fileName);
+            /**
+             * Saves mesh to a file.
+             * @param fileName Path to file to save to.
+             */
+            void saveToFile(const String& fileName, bool writeNormals = true, bool writeTangents = true, bool writeColors = true, bool writeBoneWeights = true, bool writeUVs = true, bool writeSecondaryUVs = false);
+            
+            void loadFromFile(CoreFile *inFile);
+        
+            void saveToFile(CoreFile *outFile, bool writeNormals = true, bool writeTangents = true, bool writeColors = true, bool writeBoneWeights = true, bool writeUVs = true, bool writeSecondaryUVs = false) const;
+        
+            void addSubmesh(const MeshGeometry &newSubmesh);
+            void removeSubmeshAtIndex(unsigned int index);
+        
+            unsigned int getNumSubmeshes() const;
+            MeshGeometry getSubmeshAtIndex(unsigned int index) const;
+        
+            /**
+             * Returns an unsafe pointer to submesh.
+             @param index Index of submesh to return pointer to.
+             **/
+            std::shared_ptr<MeshGeometry> getSubmeshPointer(unsigned int index);
+        
+            void clearMesh();
+        
+            /**
+             * Calculates the mesh bounding box.
+             */
+            Vector3 calculateBBox();
+        
+            /**
+             * Returns the radius of the mesh (furthest vertex away from origin).
+             * @return Mesh radius.
+             */
+            Number getRadius();
+        
+        private:
+        
+            std::vector<std::shared_ptr<MeshGeometry>> submeshes;
         
             void loadFromFileV2(Polycode::CoreFile *inFile);
             void loadFromFileLegacyV1(Polycode::CoreFile *inFile);
-
-            void writeVertexBlock(VertexDataArray *array, Polycode::CoreFile *outFile);
-            void writeIndexBlock(IndexDataArray *array, Polycode::CoreFile *outFile);
-
-            bool meshHasVertexBuffer;
-            int meshType;
-
-	};
+            
+            void writeVertexBlock(const VertexDataArray &array, Polycode::CoreFile *outFile) const ;
+            void writeIndexBlock(const IndexDataArray &array, Polycode::CoreFile *outFile) const ;
+    };
 }

+ 8 - 9
include/polycode/core/PolyOpenGLGraphicsInterface.h

@@ -90,11 +90,6 @@ namespace Polycode {
         void createProgram(ShaderProgram *program);
         void destroyProgram(ShaderProgram *program);
         
-        void createVBOForVertexArray(VertexDataArray *array);
-        
-        void createMesh(Mesh *mesh);
-        void destroyMesh(Mesh *mesh);
-        
         void createShader(Shader *shader);
         void destroyShader(Shader *shader);
         
@@ -106,9 +101,9 @@ namespace Polycode {
         void destroyRenderBuffer(RenderBuffer *renderBuffer);
         void bindRenderBuffer(RenderBuffer *renderBuffer);
         
-        void createVertexBuffer(VertexDataArray *dataArray);
-        void createIndexBuffer(IndexDataArray *dataArray);
-        void destroyBuffer(RenderDataArray *array);
+        void createSubmeshBuffers(MeshGeometry *submesh);
+        void destroySubmeshBufferData(void *platformData);
+        void drawSubmeshBuffers(MeshGeometry *submesh, Shader *shader);
         
         void drawIndices(int type, IndexDataArray *indexArray);
         void drawArrays(int type, unsigned int vertexCount);
@@ -129,11 +124,15 @@ namespace Polycode {
 		
         GLuint currentShaderID;
         int textureIndex;
+        
+        static int mapNameToArrayType(const String &name);
         static GLenum getGLDrawMode(int polycodeMode);
         static int getPolycodeParamType(int glType);
         static int getAttributeSize(int glType);
         void setUniformMatrix(GLint paramLocation, const Polycode::Matrix4& matrix);
-        
+        void createVertexBuffer(VertexDataArray *array);
+        void createIndexBuffer(IndexDataArray *array);
+        void destroyBuffer(RenderDataArray *array);
 	};
 }
 

+ 39 - 8
include/polycode/core/PolyRenderDataArray.h

@@ -31,12 +31,14 @@ namespace Polycode {
     public:
         
         RenderDataArray(unsigned int type);
+        RenderDataArray(const RenderDataArray &other);
+        virtual RenderDataArray &operator=(const RenderDataArray &other);
+        
         unsigned int type;
-        virtual void *getArrayData();
-        virtual unsigned int getDataSize();
+        virtual void *getArrayData() const;
+        virtual unsigned int getDataSize() const;
         
         String customArrayName;
-        bool hasVBO;
         void *platformData;
         
         /**
@@ -84,29 +86,58 @@ namespace Polycode {
          */
         static const int TEXCOORD2_DATA_ARRAY = 8;
         
+        /**
+         * Custom data array.
+         */
+        static const int CUSTOM_DATA_ARRAY1 = 9;
+        
+        /**
+         * Custom data array.
+         */
+        static const int CUSTOM_DATA_ARRAY2 = 10;
+
+        /**
+         * Custom data array.
+         */
+        static const int CUSTOM_DATA_ARRAY3 = 11;
+
+        /**
+         * Custom data array.
+         */
+        static const int CUSTOM_DATA_ARRAY4 = 12;        
         
+        /**
+         * Unknown data array.
+         */
+        static const int UNKNOWN_DATA_ARRAY = 13;
     };
 
     class VertexDataArray : public RenderDataArray {
     public:
         VertexDataArray(unsigned char countPerVertex, unsigned int type) : RenderDataArray(type), countPerVertex(countPerVertex) {
         }
+        VertexDataArray(const VertexDataArray &other);
+        VertexDataArray &operator=(const VertexDataArray &other);
+
         
-        unsigned char getCountPerVertex();
+        unsigned char getCountPerVertex() const;
         unsigned char countPerVertex;
         std::vector<PolyRendererVertexType> data;
-        virtual void *getArrayData();
-        virtual unsigned int getDataSize();
+        virtual void *getArrayData() const;
+        virtual unsigned int getDataSize() const;
     };
 
     class IndexDataArray : public RenderDataArray {
     public:
         IndexDataArray(unsigned int type) : RenderDataArray(type) {
         }
+        IndexDataArray(const IndexDataArray &other);
+        IndexDataArray &operator=(const IndexDataArray &other);
+
         
         std::vector<PolyRendererIndexType> data;
-        virtual void *getArrayData();
-        virtual unsigned int getDataSize();
+        virtual void *getArrayData() const;
+        virtual unsigned int getDataSize() const;
     };
 
 }

+ 7 - 19
include/polycode/core/PolyRenderer.h

@@ -54,9 +54,6 @@ namespace Polycode {
             virtual void createTexture(Texture *texture) = 0;
             virtual void destroyTexture(Texture *texture) = 0;
         
-            virtual void createMesh(Mesh *mesh) = 0;
-            virtual void destroyMesh(Mesh *mesh) = 0;
-        
             virtual void setViewport(unsigned int x,unsigned  int y,unsigned  int width, unsigned height) = 0;
             virtual void clearBuffers(const Color &clearColor, bool colorBuffer, bool depthBuffer, bool stencilBuffer) = 0;
             virtual void createProgram(ShaderProgram *program) = 0;
@@ -65,13 +62,10 @@ namespace Polycode {
             virtual void destroyShader(Shader *shader) = 0;
             virtual void createShader(Shader *shader) = 0;
             virtual void useShader(Shader *shader) = 0;
-        
-            virtual void createVertexBuffer(VertexDataArray *dataArray) = 0;
-            virtual void createIndexBuffer(IndexDataArray *dataArray) = 0;
-            virtual void destroyBuffer(RenderDataArray *array) = 0;
-        
-            virtual void drawIndices(int type, IndexDataArray *indexArray) = 0;
-            virtual void drawArrays(int type, unsigned int vertexCount) = 0;
+
+            virtual void createSubmeshBuffers(MeshGeometry *submesh) = 0;
+            virtual void destroySubmeshBufferData(void *platformData) = 0;
+            virtual void drawSubmeshBuffers(MeshGeometry *submesh, Shader *shader) = 0;
         
             virtual void enableDepthTest(bool val) = 0;
             virtual void enableDepthWrite(bool val) = 0;
@@ -144,6 +138,7 @@ namespace Polycode {
         
             ShaderBinding *getShaderBinding();
         
+            void processDrawBufferLights(GPUDrawBuffer *buffer);
             void processDrawBuffer(GPUDrawBuffer *buffer);
             RenderThreadDebugInfo getFrameInfo();
         
@@ -161,18 +156,15 @@ namespace Polycode {
             static const int JOB_CREATE_PROGRAM = 4;
             static const int JOB_CREATE_SHADER = 5;
             static const int JOB_BEGIN_FRAME = 6;
-            static const int JOB_CREATE_VERTEX_BUFFERS = 7;
             static const int JOB_DESTROY_TEXTURE = 8;
             static const int JOB_DESTROY_SHADER = 9;
             static const int JOB_DESTROY_PROGRAM = 10;
-            static const int JOB_DESTROY_BUFFER = 11;
+            static const int JOB_DESTROY_SUBMESH_BUFFER = 11;
             static const int JOB_CREATE_RENDER_BUFFER = 12;
             static const int JOB_DESTROY_RENDER_BUFFER = 13;
             static const int JOB_SET_TEXTURE_PARAM = 14;
             static const int JOB_DESTROY_SHADER_BINDING = 16;
             static const int JOB_DESTROY_SHADER_PARAM = 17;
-            static const int JOB_CREATE_MESH = 18;
-            static const int JOB_DESTROY_MESH = 19;
         
         protected:
         
@@ -221,13 +213,12 @@ namespace Polycode {
         Number getBackingResolutionScaleY();
         ShaderProgram *createProgram(const String &fileName);
         Shader *createShader(ShaderProgram *vertexProgram, ShaderProgram *fragmentProgram);
-        void createVertexBuffers(Mesh *mesh);
         
         void enqueueFrameJob(int jobType, void *data);
         
         void destroyProgram(ShaderProgram *program);
         void destroyShader(Shader *shader);
-        void destroyBuffer(RenderDataArray *array);
+        void destroySubmeshPlatformData(void *platformData);
         
         void destroyShaderBinding(ShaderBinding *binding);
         void destroyShaderParam(LocalShaderParam *param);
@@ -237,9 +228,6 @@ namespace Polycode {
         void setAnisotropyAmount(Number amount);
         Number getAnisotropyAmount();
         
-        Mesh *createMesh(const String &fileName);
-        void destroyMesh(Mesh *mesh);
-        
         static Vector3 unProject(const Vector3 &position, const Matrix4 &modelMatrix, const Matrix4 &projectionMatrix, const Polycode::Rectangle &viewport);
         static Vector3 project(const Vector3 &position, const Matrix4 &modelMatrix, const Matrix4 &projectionMatrix, const Polycode::Rectangle &viewport);
         

+ 2 - 14
include/polycode/core/PolySceneMesh.h

@@ -48,28 +48,18 @@ namespace Polycode {
 			*/
 			explicit SceneMesh(const String& fileName);
 			
-			/**
-			* Construct an empty scene mesh with the specified type.
-			* @param meshType Mesh type to create. See Mesh for possible values.
-			*/			
-			explicit SceneMesh(int meshType);
-			
 			/**
 			* Construct scene mesh from an existing Mesh instance.
 			*/
 			explicit SceneMesh(Mesh *mesh);
+        
+            SceneMesh();
 			
 			/**
 			* Construct scene mesh from an existing Mesh instance.
 			*/			
 			static SceneMesh *SceneMeshFromMesh(Mesh *mesh);
 			
-			/**
-			* Construct an empty scene mesh with the specified type.
-			* @param meshType Mesh type to create. See Mesh for possible values.
-			*/						
-			static SceneMesh *SceneMeshWithType(int meshType);
-						
 			virtual ~SceneMesh();
 			
 			void Render(GPUDrawBuffer *buffer);
@@ -107,8 +97,6 @@ namespace Polycode {
 			*/												
 			void setMaterial(Material *material);
 			
-            void rebuildAttributes();
-        
 			/**
 			* Set material by name. You can create materials in material files and name them there, then use this to set a material by name to a scene mesh.
 			* @param materialName Name of material to apply.

+ 1 - 0
include/polycode/core/PolyShader.h

@@ -68,6 +68,7 @@ namespace Polycode {
         
             int size;
             String name;
+            int arrayType;
             void *platformData;
     };
     

+ 2 - 0
include/polycode/modules/ui/PolyUIElement.h

@@ -112,6 +112,8 @@ namespace Polycode {
             std::vector<ShaderPass> shaderPasses;
 			
 			Mesh *rectMesh;
+            MeshGeometry rectMeshGeometry;
+
 			Texture *texture;
 			
 	};

+ 1 - 1
scripts/create_bindings/bindings.conf

@@ -11,7 +11,7 @@ IgnoreFiles = PolyTween, PolyTweenManager, PolyGLSLProgram, PolyGLSLShader, Poly
 #comma separated list of non-standard symbols to strip that might affect header parsing (i.e. __declspec(dllexport))
 StripSymbols = _PolyExport
 #comma separated list of classes to ignore when parsing (i.e. CFoo, CBar)
-IgnoreClasses = PAAudioInterface, AudioInterface, ResourceLoader, CoreFile, CoreFileProvider, GraphicsInterface, Script, LuaScript, JSScript, Object, Threaded, OpenGLCubemap, PolyBase, Matrix4::union, BasicFile, BasicFileProvider, Cubemap, OpenGLGraphicsInterface, PhysFSFile, PhysFSFileProvider, TimerManager, VertexDataArray, IndexDataArray
+IgnoreClasses = PAAudioInterface, AudioInterface, ResourceLoader, CoreFile, CoreFileProvider, GraphicsInterface, Script, LuaScript, JSScript, Object, Threaded, OpenGLCubemap, PolyBase, Matrix4::union, BasicFile, BasicFileProvider, Cubemap, OpenGLGraphicsInterface, PhysFSFile, PhysFSFileProvider, TimerManager, VertexDataArray, IndexDataArray, CoreMutex
 #comma separated list of class methods to ignore
 IgnoreMethods = readByte32, readByte16, getCustomEntitiesByType, Core, Renderer, Shader, Texture, handleEvent, secondaryHandler, getSTLString, readInt, CoreServices
 #main library name

+ 64 - 63
src/bindings/javascript/PolycodeJS.cpp

@@ -293,11 +293,6 @@ int jsopen_Polycode(duk_context *ctx) {
 			{"TimeInfo__get_yearDay", Polycode_TimeInfo__get_yearDay, 1},
 			{"TimeInfo__set_yearDay", Polycode_TimeInfo__set_yearDay, 2},
 			{"TimeInfo__delete", Polycode_TimeInfo__delete, 1},
-			{"CoreMutex__get_mutexID", Polycode_CoreMutex__get_mutexID, 1},
-			{"CoreMutex__set_mutexID", Polycode_CoreMutex__set_mutexID, 2},
-			{"CoreMutex__delete", Polycode_CoreMutex__delete, 1},
-			{"CoreMutex_lock", Polycode_CoreMutex_lock, 1},
-			{"CoreMutex_unlock", Polycode_CoreMutex_unlock, 1},
 			{"CoreMotionEvent__get_amount", Polycode_CoreMotionEvent__get_amount, 1},
 			{"CoreMotionEvent__set_amount", Polycode_CoreMotionEvent__set_amount, 2},
 			{"CoreMotionEvent__delete", Polycode_CoreMotionEvent__delete, 1},
@@ -632,8 +627,6 @@ int jsopen_Polycode(duk_context *ctx) {
 			{"LightInfo__get_lightViewMatrix", Polycode_LightInfo__get_lightViewMatrix, 1},
 			{"LightInfo__set_lightViewMatrix", Polycode_LightInfo__set_lightViewMatrix, 2},
 			{"LightInfo__delete", Polycode_LightInfo__delete, 1},
-			{"GPUDrawCall__get_mesh", Polycode_GPUDrawCall__get_mesh, 1},
-			{"GPUDrawCall__set_mesh", Polycode_GPUDrawCall__set_mesh, 2},
 			{"GPUDrawCall__get_options", Polycode_GPUDrawCall__get_options, 1},
 			{"GPUDrawCall__set_options", Polycode_GPUDrawCall__set_options, 2},
 			{"GPUDrawCall__get_modelMatrix", Polycode_GPUDrawCall__get_modelMatrix, 1},
@@ -833,8 +826,6 @@ int jsopen_Polycode(duk_context *ctx) {
 			{"ShaderPass__get_materialShaderBinding", Polycode_ShaderPass__get_materialShaderBinding, 1},
 			{"ShaderPass__set_materialShaderBinding", Polycode_ShaderPass__set_materialShaderBinding, 2},
 			{"ShaderPass__delete", Polycode_ShaderPass__delete, 1},
-			{"ShaderPass_setAttributeArraysFromMesh", Polycode_ShaderPass_setAttributeArraysFromMesh, 2},
-			{"ShaderPass_setExpectedAttributes", Polycode_ShaderPass_setExpectedAttributes, 1},
 			{"MaterialManager__get_premultiplyAlphaOnLoad", Polycode_MaterialManager__get_premultiplyAlphaOnLoad, 1},
 			{"MaterialManager__set_premultiplyAlphaOnLoad", Polycode_MaterialManager__set_premultiplyAlphaOnLoad, 2},
 			{"MaterialManager__get_clampDefault", Polycode_MaterialManager__get_clampDefault, 1},
@@ -890,58 +881,71 @@ int jsopen_Polycode(duk_context *ctx) {
 			{"Matrix4_setOrthoProjection", Polycode_Matrix4_setOrthoProjection, 7},
 			{"Matrix4_setProjectionFrustum", Polycode_Matrix4_setProjectionFrustum, 7},
 			{"Matrix4_setProjection", Polycode_Matrix4_setProjection, 5},
-			{"Mesh__get_indexedMesh", Polycode_Mesh__get_indexedMesh, 1},
-			{"Mesh__set_indexedMesh", Polycode_Mesh__set_indexedMesh, 2},
 			{"Mesh__delete", Polycode_Mesh__delete, 1},
+			{"Mesh_Copy", Polycode_Mesh_Copy, 1},
 			{"Mesh_loadMesh", Polycode_Mesh_loadMesh, 2},
-			{"Mesh_clearMesh", Polycode_Mesh_clearMesh, 1},
 			{"Mesh_saveToFile", Polycode_Mesh_saveToFile, 8},
 			{"Mesh_loadFromFile", Polycode_Mesh_loadFromFile, 2},
-			{"Mesh_getVertexCount", Polycode_Mesh_getVertexCount, 1},
-			{"Mesh_createPlane", Polycode_Mesh_createPlane, 4},
-			{"Mesh_createVPlane", Polycode_Mesh_createVPlane, 4},
-			{"Mesh_createCircle", Polycode_Mesh_createCircle, 5},
-			{"Mesh_createLineCircle", Polycode_Mesh_createLineCircle, 5},
-			{"Mesh_createTorus", Polycode_Mesh_createTorus, 6},
-			{"Mesh_createBox", Polycode_Mesh_createBox, 5},
-			{"Mesh_createSphere", Polycode_Mesh_createSphere, 5},
-			{"Mesh_createIcosphere", Polycode_Mesh_createIcosphere, 3},
-			{"Mesh_createOctosphere", Polycode_Mesh_createOctosphere, 3},
-			{"Mesh_createCylinder", Polycode_Mesh_createCylinder, 6},
-			{"Mesh_createCone", Polycode_Mesh_createCone, 5},
-			{"Mesh_recenterMesh", Polycode_Mesh_recenterMesh, 1},
-			{"Mesh_setVertexAtOffset", Polycode_Mesh_setVertexAtOffset, 5},
-			{"Mesh_addVertexWithUVAndNormal", Polycode_Mesh_addVertexWithUVAndNormal, 9},
-			{"Mesh_addTexCoord", Polycode_Mesh_addTexCoord, 3},
-			{"Mesh_addTexCoord2", Polycode_Mesh_addTexCoord2, 3},
-			{"Mesh_addTangent", Polycode_Mesh_addTangent, 4},
-			{"Mesh_addVertexWithUV", Polycode_Mesh_addVertexWithUV, 6},
-			{"Mesh_addVertex", Polycode_Mesh_addVertex, 4},
-			{"Mesh_addNormal", Polycode_Mesh_addNormal, 4},
-			{"Mesh_addBoneAssignments", Polycode_Mesh_addBoneAssignments, 9},
-			{"Mesh_addColor", Polycode_Mesh_addColor, 5},
-			{"Mesh_getVertexPosition", Polycode_Mesh_getVertexPosition, 2},
-			{"Mesh_getVertexPositionAtIndex", Polycode_Mesh_getVertexPositionAtIndex, 2},
-			{"Mesh_getVertexTexCoord", Polycode_Mesh_getVertexTexCoord, 2},
-			{"Mesh_getVertexTexCoordAtIndex", Polycode_Mesh_getVertexTexCoordAtIndex, 2},
-			{"Mesh_Copy", Polycode_Mesh_Copy, 1},
-			{"Mesh_getRadius", Polycode_Mesh_getRadius, 1},
-			{"Mesh_calculateNormals", Polycode_Mesh_calculateNormals, 1},
-			{"Mesh_calculateTangents", Polycode_Mesh_calculateTangents, 1},
-			{"Mesh_getMeshType", Polycode_Mesh_getMeshType, 1},
-			{"Mesh_setMeshType", Polycode_Mesh_setMeshType, 2},
-			{"Mesh_getIndexGroupSize", Polycode_Mesh_getIndexGroupSize, 1},
+			{"Mesh_addSubmesh", Polycode_Mesh_addSubmesh, 2},
+			{"Mesh_removeSubmeshAtIndex", Polycode_Mesh_removeSubmeshAtIndex, 2},
+			{"Mesh_getNumSubmeshes", Polycode_Mesh_getNumSubmeshes, 1},
+			{"Mesh_getSubmeshAtIndex", Polycode_Mesh_getSubmeshAtIndex, 2},
+			{"Mesh_getSubmeshPointer", Polycode_Mesh_getSubmeshPointer, 2},
+			{"Mesh_clearMesh", Polycode_Mesh_clearMesh, 1},
 			{"Mesh_calculateBBox", Polycode_Mesh_calculateBBox, 1},
-			{"Mesh_hasVertexBuffer", Polycode_Mesh_hasVertexBuffer, 1},
-			{"Mesh_addIndexedFace", Polycode_Mesh_addIndexedFace, 3},
-			{"Mesh_addIndex", Polycode_Mesh_addIndex, 2},
-			{"Mesh_removeVertexRange", Polycode_Mesh_removeVertexRange, 3},
-			{"Mesh_removeFace", Polycode_Mesh_removeFace, 2},
-			{"Mesh_removeUnusedVertices", Polycode_Mesh_removeUnusedVertices, 1},
-			{"Mesh_getIndexCount", Polycode_Mesh_getIndexCount, 1},
-			{"Mesh_subdivideToRadius", Polycode_Mesh_subdivideToRadius, 3},
-			{"Mesh_saveAsOBJ", Polycode_Mesh_saveAsOBJ, 2},
-			{"Mesh_normalizeBoneWeights", Polycode_Mesh_normalizeBoneWeights, 1},
+			{"Mesh_getRadius", Polycode_Mesh_getRadius, 1},
+			{"MeshGeometry__get_meshType", Polycode_MeshGeometry__get_meshType, 1},
+			{"MeshGeometry__set_meshType", Polycode_MeshGeometry__set_meshType, 2},
+			{"MeshGeometry__get_dataChanged", Polycode_MeshGeometry__get_dataChanged, 1},
+			{"MeshGeometry__set_dataChanged", Polycode_MeshGeometry__set_dataChanged, 2},
+			{"MeshGeometry__get_indexedMesh", Polycode_MeshGeometry__get_indexedMesh, 1},
+			{"MeshGeometry__set_indexedMesh", Polycode_MeshGeometry__set_indexedMesh, 2},
+			{"MeshGeometry__delete", Polycode_MeshGeometry__delete, 1},
+			{"MeshGeometry_clearMesh", Polycode_MeshGeometry_clearMesh, 1},
+			{"MeshGeometry_getVertexCount", Polycode_MeshGeometry_getVertexCount, 1},
+			{"MeshGeometry_createPlane", Polycode_MeshGeometry_createPlane, 4},
+			{"MeshGeometry_createVPlane", Polycode_MeshGeometry_createVPlane, 4},
+			{"MeshGeometry_createCircle", Polycode_MeshGeometry_createCircle, 5},
+			{"MeshGeometry_createLineCircle", Polycode_MeshGeometry_createLineCircle, 5},
+			{"MeshGeometry_createTorus", Polycode_MeshGeometry_createTorus, 6},
+			{"MeshGeometry_createBox", Polycode_MeshGeometry_createBox, 5},
+			{"MeshGeometry_createSphere", Polycode_MeshGeometry_createSphere, 5},
+			{"MeshGeometry_createIcosphere", Polycode_MeshGeometry_createIcosphere, 3},
+			{"MeshGeometry_createOctosphere", Polycode_MeshGeometry_createOctosphere, 3},
+			{"MeshGeometry_createCylinder", Polycode_MeshGeometry_createCylinder, 6},
+			{"MeshGeometry_createCone", Polycode_MeshGeometry_createCone, 5},
+			{"MeshGeometry_recenterMesh", Polycode_MeshGeometry_recenterMesh, 1},
+			{"MeshGeometry_setVertexAtOffset", Polycode_MeshGeometry_setVertexAtOffset, 5},
+			{"MeshGeometry_addVertexWithUVAndNormal", Polycode_MeshGeometry_addVertexWithUVAndNormal, 9},
+			{"MeshGeometry_addTexCoord", Polycode_MeshGeometry_addTexCoord, 3},
+			{"MeshGeometry_addTexCoord2", Polycode_MeshGeometry_addTexCoord2, 3},
+			{"MeshGeometry_addTangent", Polycode_MeshGeometry_addTangent, 4},
+			{"MeshGeometry_addVertexWithUV", Polycode_MeshGeometry_addVertexWithUV, 6},
+			{"MeshGeometry_addVertex", Polycode_MeshGeometry_addVertex, 4},
+			{"MeshGeometry_addNormal", Polycode_MeshGeometry_addNormal, 4},
+			{"MeshGeometry_addBoneAssignments", Polycode_MeshGeometry_addBoneAssignments, 9},
+			{"MeshGeometry_addColor", Polycode_MeshGeometry_addColor, 5},
+			{"MeshGeometry_getVertexPosition", Polycode_MeshGeometry_getVertexPosition, 2},
+			{"MeshGeometry_getVertexPositionAtIndex", Polycode_MeshGeometry_getVertexPositionAtIndex, 2},
+			{"MeshGeometry_getVertexTexCoord", Polycode_MeshGeometry_getVertexTexCoord, 2},
+			{"MeshGeometry_getVertexTexCoordAtIndex", Polycode_MeshGeometry_getVertexTexCoordAtIndex, 2},
+			{"MeshGeometry_Copy", Polycode_MeshGeometry_Copy, 1},
+			{"MeshGeometry_getRadius", Polycode_MeshGeometry_getRadius, 1},
+			{"MeshGeometry_calculateNormals", Polycode_MeshGeometry_calculateNormals, 1},
+			{"MeshGeometry_calculateTangents", Polycode_MeshGeometry_calculateTangents, 1},
+			{"MeshGeometry_getMeshType", Polycode_MeshGeometry_getMeshType, 1},
+			{"MeshGeometry_setMeshType", Polycode_MeshGeometry_setMeshType, 2},
+			{"MeshGeometry_getIndexGroupSize", Polycode_MeshGeometry_getIndexGroupSize, 1},
+			{"MeshGeometry_calculateBBox", Polycode_MeshGeometry_calculateBBox, 1},
+			{"MeshGeometry_addIndexedFace", Polycode_MeshGeometry_addIndexedFace, 3},
+			{"MeshGeometry_addIndex", Polycode_MeshGeometry_addIndex, 2},
+			{"MeshGeometry_removeVertexRange", Polycode_MeshGeometry_removeVertexRange, 3},
+			{"MeshGeometry_removeFace", Polycode_MeshGeometry_removeFace, 2},
+			{"MeshGeometry_removeUnusedVertices", Polycode_MeshGeometry_removeUnusedVertices, 1},
+			{"MeshGeometry_getIndexCount", Polycode_MeshGeometry_getIndexCount, 1},
+			{"MeshGeometry_subdivideToRadius", Polycode_MeshGeometry_subdivideToRadius, 3},
+			{"MeshGeometry_saveAsOBJ", Polycode_MeshGeometry_saveAsOBJ, 2},
+			{"MeshGeometry_normalizeBoneWeights", Polycode_MeshGeometry_normalizeBoneWeights, 1},
 			{"ObjectEntry__get_type", Polycode_ObjectEntry__get_type, 1},
 			{"ObjectEntry__set_type", Polycode_ObjectEntry__set_type, 2},
 			{"ObjectEntry__get_name", Polycode_ObjectEntry__get_name, 1},
@@ -1129,8 +1133,6 @@ int jsopen_Polycode(duk_context *ctx) {
 			{"RenderDataArray__set_type", Polycode_RenderDataArray__set_type, 2},
 			{"RenderDataArray__get_customArrayName", Polycode_RenderDataArray__get_customArrayName, 1},
 			{"RenderDataArray__set_customArrayName", Polycode_RenderDataArray__set_customArrayName, 2},
-			{"RenderDataArray__get_hasVBO", Polycode_RenderDataArray__get_hasVBO, 1},
-			{"RenderDataArray__set_hasVBO", Polycode_RenderDataArray__set_hasVBO, 2},
 			{"RenderDataArray__delete", Polycode_RenderDataArray__delete, 1},
 			{"RenderDataArray_getArrayData", Polycode_RenderDataArray_getArrayData, 1},
 			{"RenderDataArray_getDataSize", Polycode_RenderDataArray_getDataSize, 1},
@@ -1171,6 +1173,7 @@ int jsopen_Polycode(duk_context *ctx) {
 			{"RenderThread_enqueueJob", Polycode_RenderThread_enqueueJob, 4},
 			{"RenderThread_processJob", Polycode_RenderThread_processJob, 2},
 			{"RenderThread_getShaderBinding", Polycode_RenderThread_getShaderBinding, 1},
+			{"RenderThread_processDrawBufferLights", Polycode_RenderThread_processDrawBufferLights, 2},
 			{"RenderThread_processDrawBuffer", Polycode_RenderThread_processDrawBuffer, 2},
 			{"RenderThread_getFrameInfo", Polycode_RenderThread_getFrameInfo, 1},
 			{"RenderThread_clearFrameQueue", Polycode_RenderThread_clearFrameQueue, 1},
@@ -1198,18 +1201,15 @@ int jsopen_Polycode(duk_context *ctx) {
 			{"Renderer_getBackingResolutionScaleY", Polycode_Renderer_getBackingResolutionScaleY, 1},
 			{"Renderer_createProgram", Polycode_Renderer_createProgram, 2},
 			{"Renderer_createShader", Polycode_Renderer_createShader, 3},
-			{"Renderer_createVertexBuffers", Polycode_Renderer_createVertexBuffers, 2},
 			{"Renderer_enqueueFrameJob", Polycode_Renderer_enqueueFrameJob, 3},
 			{"Renderer_destroyProgram", Polycode_Renderer_destroyProgram, 2},
 			{"Renderer_destroyShader", Polycode_Renderer_destroyShader, 2},
-			{"Renderer_destroyBuffer", Polycode_Renderer_destroyBuffer, 2},
+			{"Renderer_destroySubmeshPlatformData", Polycode_Renderer_destroySubmeshPlatformData, 2},
 			{"Renderer_destroyShaderBinding", Polycode_Renderer_destroyShaderBinding, 2},
 			{"Renderer_destroyShaderParam", Polycode_Renderer_destroyShaderParam, 2},
 			{"Renderer_setTextureParam", Polycode_Renderer_setTextureParam, 3},
 			{"Renderer_setAnisotropyAmount", Polycode_Renderer_setAnisotropyAmount, 2},
 			{"Renderer_getAnisotropyAmount", Polycode_Renderer_getAnisotropyAmount, 1},
-			{"Renderer_createMesh", Polycode_Renderer_createMesh, 2},
-			{"Renderer_destroyMesh", Polycode_Renderer_destroyMesh, 2},
 			{"Renderer_beginFrame", Polycode_Renderer_beginFrame, 1},
 			{"Renderer_endFrame", Polycode_Renderer_endFrame, 1},
 			{"Resource__get_reloadOnFileModify", Polycode_Resource__get_reloadOnFileModify, 1},
@@ -1466,7 +1466,6 @@ int jsopen_Polycode(duk_context *ctx) {
 			{"SceneMesh_loadSkeleton", Polycode_SceneMesh_loadSkeleton, 2},
 			{"SceneMesh_clearMaterial", Polycode_SceneMesh_clearMaterial, 1},
 			{"SceneMesh_setMaterial", Polycode_SceneMesh_setMaterial, 2},
-			{"SceneMesh_rebuildAttributes", Polycode_SceneMesh_rebuildAttributes, 1},
 			{"SceneMesh_setMaterialByName", Polycode_SceneMesh_setMaterialByName, 3},
 			{"SceneMesh_setMesh", Polycode_SceneMesh_setMesh, 2},
 			{"SceneMesh_setSkeleton", Polycode_SceneMesh_setSkeleton, 2},
@@ -1607,6 +1606,8 @@ int jsopen_Polycode(duk_context *ctx) {
 			{"ProgramAttribute__set_size", Polycode_ProgramAttribute__set_size, 2},
 			{"ProgramAttribute__get_name", Polycode_ProgramAttribute__get_name, 1},
 			{"ProgramAttribute__set_name", Polycode_ProgramAttribute__set_name, 2},
+			{"ProgramAttribute__get_arrayType", Polycode_ProgramAttribute__get_arrayType, 1},
+			{"ProgramAttribute__set_arrayType", Polycode_ProgramAttribute__set_arrayType, 2},
 			{"ProgramAttribute__delete", Polycode_ProgramAttribute__delete, 1},
 			{"ShaderRenderTarget__get_id", Polycode_ShaderRenderTarget__get_id, 1},
 			{"ShaderRenderTarget__set_id", Polycode_ShaderRenderTarget__set_id, 2},

+ 72 - 72
src/bindings/lua/PolycodeLua.cpp

@@ -306,11 +306,6 @@ int luaopen_Polycode(lua_State *L) {
 		{"TimeInfo_set_yearDay", Polycode_TimeInfo_set_yearDay},
 		{"TimeInfo", Polycode_TimeInfo},
 		{"delete_TimeInfo", Polycode_delete_TimeInfo},
-		{"CoreMutex_get_mutexID", Polycode_CoreMutex_get_mutexID},
-		{"CoreMutex_set_mutexID", Polycode_CoreMutex_set_mutexID},
-		{"CoreMutex_lock", Polycode_CoreMutex_lock},
-		{"CoreMutex_unlock", Polycode_CoreMutex_unlock},
-		{"delete_CoreMutex", Polycode_delete_CoreMutex},
 		{"CoreMotionEvent_get_amount", Polycode_CoreMotionEvent_get_amount},
 		{"CoreMotionEvent_set_amount", Polycode_CoreMotionEvent_set_amount},
 		{"delete_CoreMotionEvent", Polycode_delete_CoreMotionEvent},
@@ -661,11 +656,9 @@ int luaopen_Polycode(lua_State *L) {
 		{"LightInfo_set_shadowMapTexture", Polycode_LightInfo_set_shadowMapTexture},
 		{"LightInfo_set_lightViewMatrix", Polycode_LightInfo_set_lightViewMatrix},
 		{"delete_LightInfo", Polycode_delete_LightInfo},
-		{"GPUDrawCall_get_mesh", Polycode_GPUDrawCall_get_mesh},
 		{"GPUDrawCall_get_options", Polycode_GPUDrawCall_get_options},
 		{"GPUDrawCall_get_modelMatrix", Polycode_GPUDrawCall_get_modelMatrix},
 		{"GPUDrawCall_get_material", Polycode_GPUDrawCall_get_material},
-		{"GPUDrawCall_set_mesh", Polycode_GPUDrawCall_set_mesh},
 		{"GPUDrawCall_set_options", Polycode_GPUDrawCall_set_options},
 		{"GPUDrawCall_set_modelMatrix", Polycode_GPUDrawCall_set_modelMatrix},
 		{"GPUDrawCall_set_material", Polycode_GPUDrawCall_set_material},
@@ -871,9 +864,6 @@ int luaopen_Polycode(lua_State *L) {
 		{"ShaderPass_set_shaderBinding", Polycode_ShaderPass_set_shaderBinding},
 		{"ShaderPass_set_materialShaderBinding", Polycode_ShaderPass_set_materialShaderBinding},
 		{"ShaderPass", Polycode_ShaderPass},
-		{"ShaderPass_setAttributeArraysFromMesh", Polycode_ShaderPass_setAttributeArraysFromMesh},
-		{"ShaderPass_setExpectedAttributes", Polycode_ShaderPass_setExpectedAttributes},
-		{"ShaderPass_arrayToAttributeName", Polycode_ShaderPass_arrayToAttributeName},
 		{"delete_ShaderPass", Polycode_delete_ShaderPass},
 		{"MaterialManager_get_premultiplyAlphaOnLoad", Polycode_MaterialManager_get_premultiplyAlphaOnLoad},
 		{"MaterialManager_get_clampDefault", Polycode_MaterialManager_get_clampDefault},
@@ -933,61 +923,75 @@ int luaopen_Polycode(lua_State *L) {
 		{"Matrix4_setProjectionFrustum", Polycode_Matrix4_setProjectionFrustum},
 		{"Matrix4_setProjection", Polycode_Matrix4_setProjection},
 		{"delete_Matrix4", Polycode_delete_Matrix4},
-		{"Mesh_get_indexedMesh", Polycode_Mesh_get_indexedMesh},
-		{"Mesh_set_indexedMesh", Polycode_Mesh_set_indexedMesh},
 		{"Mesh", Polycode_Mesh},
 		{"Mesh_MeshFromFileName", Polycode_Mesh_MeshFromFileName},
+		{"Mesh_Copy", Polycode_Mesh_Copy},
 		{"Mesh_loadMesh", Polycode_Mesh_loadMesh},
-		{"Mesh_clearMesh", Polycode_Mesh_clearMesh},
 		{"Mesh_saveToFile", Polycode_Mesh_saveToFile},
 		{"Mesh_loadFromFile", Polycode_Mesh_loadFromFile},
-		{"Mesh_getVertexCount", Polycode_Mesh_getVertexCount},
-		{"Mesh_createPlane", Polycode_Mesh_createPlane},
-		{"Mesh_createVPlane", Polycode_Mesh_createVPlane},
-		{"Mesh_createCircle", Polycode_Mesh_createCircle},
-		{"Mesh_createLineCircle", Polycode_Mesh_createLineCircle},
-		{"Mesh_createTorus", Polycode_Mesh_createTorus},
-		{"Mesh_createBox", Polycode_Mesh_createBox},
-		{"Mesh_createSphere", Polycode_Mesh_createSphere},
-		{"Mesh_createIcosphere", Polycode_Mesh_createIcosphere},
-		{"Mesh_createOctosphere", Polycode_Mesh_createOctosphere},
-		{"Mesh_createCylinder", Polycode_Mesh_createCylinder},
-		{"Mesh_createCone", Polycode_Mesh_createCone},
-		{"Mesh_recenterMesh", Polycode_Mesh_recenterMesh},
-		{"Mesh_setVertexAtOffset", Polycode_Mesh_setVertexAtOffset},
-		{"Mesh_addVertexWithUVAndNormal", Polycode_Mesh_addVertexWithUVAndNormal},
-		{"Mesh_addTexCoord", Polycode_Mesh_addTexCoord},
-		{"Mesh_addTexCoord2", Polycode_Mesh_addTexCoord2},
-		{"Mesh_addTangent", Polycode_Mesh_addTangent},
-		{"Mesh_addVertexWithUV", Polycode_Mesh_addVertexWithUV},
-		{"Mesh_addVertex", Polycode_Mesh_addVertex},
-		{"Mesh_addNormal", Polycode_Mesh_addNormal},
-		{"Mesh_addBoneAssignments", Polycode_Mesh_addBoneAssignments},
-		{"Mesh_addColor", Polycode_Mesh_addColor},
-		{"Mesh_getVertexPosition", Polycode_Mesh_getVertexPosition},
-		{"Mesh_getVertexPositionAtIndex", Polycode_Mesh_getVertexPositionAtIndex},
-		{"Mesh_getVertexTexCoord", Polycode_Mesh_getVertexTexCoord},
-		{"Mesh_getVertexTexCoordAtIndex", Polycode_Mesh_getVertexTexCoordAtIndex},
-		{"Mesh_Copy", Polycode_Mesh_Copy},
-		{"Mesh_getRadius", Polycode_Mesh_getRadius},
-		{"Mesh_calculateNormals", Polycode_Mesh_calculateNormals},
-		{"Mesh_calculateTangents", Polycode_Mesh_calculateTangents},
-		{"Mesh_getMeshType", Polycode_Mesh_getMeshType},
-		{"Mesh_setMeshType", Polycode_Mesh_setMeshType},
-		{"Mesh_getIndexGroupSize", Polycode_Mesh_getIndexGroupSize},
+		{"Mesh_addSubmesh", Polycode_Mesh_addSubmesh},
+		{"Mesh_removeSubmeshAtIndex", Polycode_Mesh_removeSubmeshAtIndex},
+		{"Mesh_getNumSubmeshes", Polycode_Mesh_getNumSubmeshes},
+		{"Mesh_getSubmeshAtIndex", Polycode_Mesh_getSubmeshAtIndex},
+		{"Mesh_getSubmeshPointer", Polycode_Mesh_getSubmeshPointer},
+		{"Mesh_clearMesh", Polycode_Mesh_clearMesh},
 		{"Mesh_calculateBBox", Polycode_Mesh_calculateBBox},
-		{"Mesh_hasVertexBuffer", Polycode_Mesh_hasVertexBuffer},
-		{"Mesh_addIndexedFace", Polycode_Mesh_addIndexedFace},
-		{"Mesh_addIndex", Polycode_Mesh_addIndex},
-		{"Mesh_removeVertexRange", Polycode_Mesh_removeVertexRange},
-		{"Mesh_removeFace", Polycode_Mesh_removeFace},
-		{"Mesh_removeUnusedVertices", Polycode_Mesh_removeUnusedVertices},
-		{"Mesh_getIndexCount", Polycode_Mesh_getIndexCount},
-		{"Mesh_subdivideToRadius", Polycode_Mesh_subdivideToRadius},
-		{"Mesh_calculateFaceTangent", Polycode_Mesh_calculateFaceTangent},
-		{"Mesh_saveAsOBJ", Polycode_Mesh_saveAsOBJ},
-		{"Mesh_normalizeBoneWeights", Polycode_Mesh_normalizeBoneWeights},
+		{"Mesh_getRadius", Polycode_Mesh_getRadius},
 		{"delete_Mesh", Polycode_delete_Mesh},
+		{"MeshGeometry_get_meshType", Polycode_MeshGeometry_get_meshType},
+		{"MeshGeometry_get_dataChanged", Polycode_MeshGeometry_get_dataChanged},
+		{"MeshGeometry_get_indexedMesh", Polycode_MeshGeometry_get_indexedMesh},
+		{"MeshGeometry_set_meshType", Polycode_MeshGeometry_set_meshType},
+		{"MeshGeometry_set_dataChanged", Polycode_MeshGeometry_set_dataChanged},
+		{"MeshGeometry_set_indexedMesh", Polycode_MeshGeometry_set_indexedMesh},
+		{"MeshGeometry", Polycode_MeshGeometry},
+		{"MeshGeometry_clearMesh", Polycode_MeshGeometry_clearMesh},
+		{"MeshGeometry_getVertexCount", Polycode_MeshGeometry_getVertexCount},
+		{"MeshGeometry_createPlane", Polycode_MeshGeometry_createPlane},
+		{"MeshGeometry_createVPlane", Polycode_MeshGeometry_createVPlane},
+		{"MeshGeometry_createCircle", Polycode_MeshGeometry_createCircle},
+		{"MeshGeometry_createLineCircle", Polycode_MeshGeometry_createLineCircle},
+		{"MeshGeometry_createTorus", Polycode_MeshGeometry_createTorus},
+		{"MeshGeometry_createBox", Polycode_MeshGeometry_createBox},
+		{"MeshGeometry_createSphere", Polycode_MeshGeometry_createSphere},
+		{"MeshGeometry_createIcosphere", Polycode_MeshGeometry_createIcosphere},
+		{"MeshGeometry_createOctosphere", Polycode_MeshGeometry_createOctosphere},
+		{"MeshGeometry_createCylinder", Polycode_MeshGeometry_createCylinder},
+		{"MeshGeometry_createCone", Polycode_MeshGeometry_createCone},
+		{"MeshGeometry_recenterMesh", Polycode_MeshGeometry_recenterMesh},
+		{"MeshGeometry_setVertexAtOffset", Polycode_MeshGeometry_setVertexAtOffset},
+		{"MeshGeometry_addVertexWithUVAndNormal", Polycode_MeshGeometry_addVertexWithUVAndNormal},
+		{"MeshGeometry_addTexCoord", Polycode_MeshGeometry_addTexCoord},
+		{"MeshGeometry_addTexCoord2", Polycode_MeshGeometry_addTexCoord2},
+		{"MeshGeometry_addTangent", Polycode_MeshGeometry_addTangent},
+		{"MeshGeometry_addVertexWithUV", Polycode_MeshGeometry_addVertexWithUV},
+		{"MeshGeometry_addVertex", Polycode_MeshGeometry_addVertex},
+		{"MeshGeometry_addNormal", Polycode_MeshGeometry_addNormal},
+		{"MeshGeometry_addBoneAssignments", Polycode_MeshGeometry_addBoneAssignments},
+		{"MeshGeometry_addColor", Polycode_MeshGeometry_addColor},
+		{"MeshGeometry_getVertexPosition", Polycode_MeshGeometry_getVertexPosition},
+		{"MeshGeometry_getVertexPositionAtIndex", Polycode_MeshGeometry_getVertexPositionAtIndex},
+		{"MeshGeometry_getVertexTexCoord", Polycode_MeshGeometry_getVertexTexCoord},
+		{"MeshGeometry_getVertexTexCoordAtIndex", Polycode_MeshGeometry_getVertexTexCoordAtIndex},
+		{"MeshGeometry_Copy", Polycode_MeshGeometry_Copy},
+		{"MeshGeometry_getRadius", Polycode_MeshGeometry_getRadius},
+		{"MeshGeometry_calculateNormals", Polycode_MeshGeometry_calculateNormals},
+		{"MeshGeometry_calculateTangents", Polycode_MeshGeometry_calculateTangents},
+		{"MeshGeometry_getMeshType", Polycode_MeshGeometry_getMeshType},
+		{"MeshGeometry_setMeshType", Polycode_MeshGeometry_setMeshType},
+		{"MeshGeometry_getIndexGroupSize", Polycode_MeshGeometry_getIndexGroupSize},
+		{"MeshGeometry_calculateBBox", Polycode_MeshGeometry_calculateBBox},
+		{"MeshGeometry_addIndexedFace", Polycode_MeshGeometry_addIndexedFace},
+		{"MeshGeometry_addIndex", Polycode_MeshGeometry_addIndex},
+		{"MeshGeometry_removeVertexRange", Polycode_MeshGeometry_removeVertexRange},
+		{"MeshGeometry_removeFace", Polycode_MeshGeometry_removeFace},
+		{"MeshGeometry_removeUnusedVertices", Polycode_MeshGeometry_removeUnusedVertices},
+		{"MeshGeometry_getIndexCount", Polycode_MeshGeometry_getIndexCount},
+		{"MeshGeometry_subdivideToRadius", Polycode_MeshGeometry_subdivideToRadius},
+		{"MeshGeometry_calculateFaceTangent", Polycode_MeshGeometry_calculateFaceTangent},
+		{"MeshGeometry_saveAsOBJ", Polycode_MeshGeometry_saveAsOBJ},
+		{"MeshGeometry_normalizeBoneWeights", Polycode_MeshGeometry_normalizeBoneWeights},
+		{"delete_MeshGeometry", Polycode_delete_MeshGeometry},
 		{"ObjectEntry_get_type", Polycode_ObjectEntry_get_type},
 		{"ObjectEntry_get_name", Polycode_ObjectEntry_get_name},
 		{"ObjectEntry_get_NumberVal", Polycode_ObjectEntry_get_NumberVal},
@@ -1184,10 +1188,8 @@ int luaopen_Polycode(lua_State *L) {
 		{"delete_Rectangle", Polycode_delete_Rectangle},
 		{"RenderDataArray_get_type", Polycode_RenderDataArray_get_type},
 		{"RenderDataArray_get_customArrayName", Polycode_RenderDataArray_get_customArrayName},
-		{"RenderDataArray_get_hasVBO", Polycode_RenderDataArray_get_hasVBO},
 		{"RenderDataArray_set_type", Polycode_RenderDataArray_set_type},
 		{"RenderDataArray_set_customArrayName", Polycode_RenderDataArray_set_customArrayName},
-		{"RenderDataArray_set_hasVBO", Polycode_RenderDataArray_set_hasVBO},
 		{"RenderDataArray", Polycode_RenderDataArray},
 		{"RenderDataArray_getArrayData", Polycode_RenderDataArray_getArrayData},
 		{"RenderDataArray_getDataSize", Polycode_RenderDataArray_getDataSize},
@@ -1229,6 +1231,7 @@ int luaopen_Polycode(lua_State *L) {
 		{"RenderThread_enqueueJob", Polycode_RenderThread_enqueueJob},
 		{"RenderThread_processJob", Polycode_RenderThread_processJob},
 		{"RenderThread_getShaderBinding", Polycode_RenderThread_getShaderBinding},
+		{"RenderThread_processDrawBufferLights", Polycode_RenderThread_processDrawBufferLights},
 		{"RenderThread_processDrawBuffer", Polycode_RenderThread_processDrawBuffer},
 		{"RenderThread_getFrameInfo", Polycode_RenderThread_getFrameInfo},
 		{"RenderThread_clearFrameQueue", Polycode_RenderThread_clearFrameQueue},
@@ -1256,18 +1259,15 @@ int luaopen_Polycode(lua_State *L) {
 		{"Renderer_getBackingResolutionScaleY", Polycode_Renderer_getBackingResolutionScaleY},
 		{"Renderer_createProgram", Polycode_Renderer_createProgram},
 		{"Renderer_createShader", Polycode_Renderer_createShader},
-		{"Renderer_createVertexBuffers", Polycode_Renderer_createVertexBuffers},
 		{"Renderer_enqueueFrameJob", Polycode_Renderer_enqueueFrameJob},
 		{"Renderer_destroyProgram", Polycode_Renderer_destroyProgram},
 		{"Renderer_destroyShader", Polycode_Renderer_destroyShader},
-		{"Renderer_destroyBuffer", Polycode_Renderer_destroyBuffer},
+		{"Renderer_destroySubmeshPlatformData", Polycode_Renderer_destroySubmeshPlatformData},
 		{"Renderer_destroyShaderBinding", Polycode_Renderer_destroyShaderBinding},
 		{"Renderer_destroyShaderParam", Polycode_Renderer_destroyShaderParam},
 		{"Renderer_setTextureParam", Polycode_Renderer_setTextureParam},
 		{"Renderer_setAnisotropyAmount", Polycode_Renderer_setAnisotropyAmount},
 		{"Renderer_getAnisotropyAmount", Polycode_Renderer_getAnisotropyAmount},
-		{"Renderer_createMesh", Polycode_Renderer_createMesh},
-		{"Renderer_destroyMesh", Polycode_Renderer_destroyMesh},
 		{"Renderer_unProject", Polycode_Renderer_unProject},
 		{"Renderer_project", Polycode_Renderer_project},
 		{"Renderer_beginFrame", Polycode_Renderer_beginFrame},
@@ -1542,7 +1542,6 @@ int luaopen_Polycode(lua_State *L) {
 		{"SceneMesh_set_sendBoneMatricesToMaterial", Polycode_SceneMesh_set_sendBoneMatricesToMaterial},
 		{"SceneMesh", Polycode_SceneMesh},
 		{"SceneMesh_SceneMeshFromMesh", Polycode_SceneMesh_SceneMeshFromMesh},
-		{"SceneMesh_SceneMeshWithType", Polycode_SceneMesh_SceneMeshWithType},
 		{"SceneMesh_Render", Polycode_SceneMesh_Render},
 		{"SceneMesh_getShaderPass", Polycode_SceneMesh_getShaderPass},
 		{"SceneMesh_getNumShaderPasses", Polycode_SceneMesh_getNumShaderPasses},
@@ -1553,7 +1552,6 @@ int luaopen_Polycode(lua_State *L) {
 		{"SceneMesh_loadSkeleton", Polycode_SceneMesh_loadSkeleton},
 		{"SceneMesh_clearMaterial", Polycode_SceneMesh_clearMaterial},
 		{"SceneMesh_setMaterial", Polycode_SceneMesh_setMaterial},
-		{"SceneMesh_rebuildAttributes", Polycode_SceneMesh_rebuildAttributes},
 		{"SceneMesh_setMaterialByName", Polycode_SceneMesh_setMaterialByName},
 		{"SceneMesh_setMesh", Polycode_SceneMesh_setMesh},
 		{"SceneMesh_setSkeleton", Polycode_SceneMesh_setSkeleton},
@@ -1703,8 +1701,10 @@ int luaopen_Polycode(lua_State *L) {
 		{"delete_ProgramParam", Polycode_delete_ProgramParam},
 		{"ProgramAttribute_get_size", Polycode_ProgramAttribute_get_size},
 		{"ProgramAttribute_get_name", Polycode_ProgramAttribute_get_name},
+		{"ProgramAttribute_get_arrayType", Polycode_ProgramAttribute_get_arrayType},
 		{"ProgramAttribute_set_size", Polycode_ProgramAttribute_set_size},
 		{"ProgramAttribute_set_name", Polycode_ProgramAttribute_set_name},
+		{"ProgramAttribute_set_arrayType", Polycode_ProgramAttribute_set_arrayType},
 		{"ProgramAttribute", Polycode_ProgramAttribute},
 		{"delete_ProgramAttribute", Polycode_delete_ProgramAttribute},
 		{"ShaderRenderTarget_get_id", Polycode_ShaderRenderTarget_get_id},
@@ -2149,12 +2149,6 @@ int luaopen_Polycode(lua_State *L) {
 	lua_settable(L, -3);
 	lua_pop(L, 1);
 
-	luaL_newmetatable(L, "Polycode.CoreMutex");
-	lua_pushstring(L, "__gc");
-	lua_pushcfunction(L, Polycode_delete_CoreMutex);
-	lua_settable(L, -3);
-	lua_pop(L, 1);
-
 	luaL_newmetatable(L, "Polycode.CoreMotionEvent");
 	lua_pushstring(L, "__gc");
 	lua_pushcfunction(L, Polycode_delete_CoreMotionEvent);
@@ -2329,6 +2323,12 @@ int luaopen_Polycode(lua_State *L) {
 	luaL_newmetatable(L, "Polycode.Mesh");
 	lua_pop(L, 1);
 
+	luaL_newmetatable(L, "Polycode.MeshGeometry");
+	lua_pushstring(L, "__gc");
+	lua_pushcfunction(L, Polycode_delete_MeshGeometry);
+	lua_settable(L, -3);
+	lua_pop(L, 1);
+
 	luaL_newmetatable(L, "Polycode.ObjectEntry");
 	lua_pushstring(L, "__gc");
 	lua_pushcfunction(L, Polycode_delete_ObjectEntry);

+ 11 - 9
src/core/PolyCamera.cpp

@@ -337,15 +337,18 @@ void Camera::setPostFilter(Material *material) {
     }
     
     if(!screenQuadMesh) {
-        screenQuadMesh = new Mesh(Mesh::TRI_MESH);
+        screenQuadMesh = new Mesh();
         
-        screenQuadMesh->addVertexWithUV(1.0, 1.0, 0.0, 1.0, 1.0);
-        screenQuadMesh->addVertexWithUV(1.0, -1.0, 0.0, 1.0, 0.0);
-        screenQuadMesh->addVertexWithUV(-1.0, -1.0, 0.0, 0.0, 0.0);
+        MeshGeometry geometry;
+        geometry.addVertexWithUV(1.0, 1.0, 0.0, 1.0, 1.0);
+        geometry.addVertexWithUV(1.0, -1.0, 0.0, 1.0, 0.0);
+        geometry.addVertexWithUV(-1.0, -1.0, 0.0, 0.0, 0.0);
         
-        screenQuadMesh->addVertexWithUV(-1.0, -1.0, 0.0, 0.0, 0.0);
-        screenQuadMesh->addVertexWithUV(-1.0, 1.0, 0.0, 0.0, 1.0);
-        screenQuadMesh->addVertexWithUV(1.0, 1.0, 0.0, 1.0, 1.0);
+        geometry.addVertexWithUV(-1.0, -1.0, 0.0, 0.0, 0.0);
+        geometry.addVertexWithUV(-1.0, 1.0, 0.0, 0.0, 1.0);
+        geometry.addVertexWithUV(1.0, 1.0, 0.0, 1.0, 1.0);
+        
+        screenQuadMesh->addSubmesh(geometry);
         
     }
     
@@ -362,7 +365,6 @@ void Camera::setPostFilter(Material *material) {
         shaderPass.materialShaderBinding = shaderPass.shaderBinding;
         shaderPass.shaderBinding = new ShaderBinding();
         shaderPass.shaderBinding->targetShader = shaderPass.shader;
-        shaderPass.setAttributeArraysFromMesh(screenQuadMesh);
         shaderPass.shaderBinding->resetAttributes = true;
         
         for(int j=0; j < materialBinding->getNumColorTargetBindings(); j++) {
@@ -415,7 +417,7 @@ void Camera::renderFullScreenQuad(GPUDrawBuffer *drawBuffer, int shaderPass) {
     drawCall.options.backfaceCull = false;
     drawCall.options.depthTest = false;
     drawCall.options.depthWrite = false;
-    drawCall.mesh = screenQuadMesh;
+    drawCall.submesh = screenQuadMesh->getSubmeshPointer(0);
     drawCall.material = filterShaderMaterial;
     drawCall.shaderPasses.push_back(shaderPasses[shaderPass]);
     drawBuffer->drawCalls.push_back(drawCall);

+ 0 - 73
src/core/PolyMaterial.cpp

@@ -49,79 +49,6 @@ ShaderPass::ShaderPass(Shader *shader) :
     blendingMode(Renderer::BLEND_MODE_NONE)
 {
     
-}
-
- String ShaderPass::arrayToAttributeName(VertexDataArray *array) {
-    switch(array->type) {
-        case RenderDataArray::VERTEX_DATA_ARRAY:
-            return "position";
-        break;
-        case RenderDataArray::NORMAL_DATA_ARRAY:
-            return "normal";
-        break;
-        case RenderDataArray::TEXCOORD_DATA_ARRAY:
-            return "texCoord";
-        break;
-        case RenderDataArray::COLOR_DATA_ARRAY:
-            return "color";
-        break;
-        case RenderDataArray::TANGENT_DATA_ARRAY:
-            return "tangent";
-        break;
-        case RenderDataArray::TEXCOORD2_DATA_ARRAY:
-            return "texCoord2";
-        break;
-        case RenderDataArray::BONE_WEIGHT_DATA_ARRAY:
-            return "boneWeights";
-        break;
-        case RenderDataArray::BONE_INDEX_DATA_ARRAY:
-            return "boneIndices";
-        break;
-        default:
-            return array->customArrayName;
-        break;
-    }
-}
-
-void ShaderPass::setAttributeArraysFromMesh(Mesh *mesh) {
-    attributeArrays.clear();
-    attributeArrays.push_back(&mesh->vertexPositionArray);
-    attributeArrays.push_back(&mesh->vertexNormalArray);
-    attributeArrays.push_back(&mesh->vertexTexCoordArray);
-    attributeArrays.push_back(&mesh->vertexColorArray);
-    attributeArrays.push_back(&mesh->vertexBoneIndexArray);
-    attributeArrays.push_back(&mesh->vertexBoneWeightArray);
-    attributeArrays.push_back(&mesh->vertexTangentArray);
-    attributeArrays.push_back(&mesh->vertexTexCoord2Array);
-}
-
-void ShaderPass::setExpectedAttributes() {
-    if(!shader || !shaderBinding) {
-        return;
-    }
-    for(int i=0; i < shaderBinding->attributes.size(); i++) {
-        delete shaderBinding->attributes[i];
-    }
-    shaderBinding->attributes.clear();
-    
-    for(int i=0; i < shader->expectedAttributes.size(); i++) {
-        VertexDataArray *targetArray = NULL;
-        
-        for(int j=0; j < attributeArrays.size(); j++)  {
-            if(shader->expectedAttributes[i].name == arrayToAttributeName(attributeArrays[j])) {
-                targetArray = attributeArrays[j];
-            }
-        }
-        
-        if(targetArray) {
-            AttributeBinding *attributeBinding = shaderBinding->getAttributeBindingByName(shader->expectedAttributes[i].name);
-            if(attributeBinding) {
-                attributeBinding->vertexData = targetArray;
-            } else {
-                shaderBinding->addAttributeBinding(shader->expectedAttributes[i].name, targetArray);
-            }
-        }
-    }
 }
 
 Material::Material(const String& name) : Resource(Resource::RESOURCE_MATERIAL) {

+ 554 - 359
src/core/PolyMesh.cpp

@@ -25,6 +25,7 @@ THE SOFTWARE.
 #include "polycode/core/PolyMesh.h"
 #include "polycode/core/PolyLogger.h"
 #include "polycode/core/PolyCore.h"
+#include "polycode/core/PolyRenderer.h"
 #include "polycode/core/PolyCoreFileProvider.h"
 
 using std::min;
@@ -33,7 +34,7 @@ using std::vector;
 
 using namespace Polycode;
 
-Mesh::Mesh(const String& fileName) : Resource(Resource::RESOURCE_MESH),
+MeshGeometry::MeshGeometry() :
 vertexPositionArray(3, RenderDataArray::VERTEX_DATA_ARRAY),
 vertexColorArray(4, RenderDataArray::COLOR_DATA_ARRAY),
 vertexNormalArray(3, RenderDataArray::NORMAL_DATA_ARRAY),
@@ -42,17 +43,19 @@ vertexTexCoord2Array(2, RenderDataArray::TEXCOORD2_DATA_ARRAY),
 vertexTangentArray(3, RenderDataArray::TANGENT_DATA_ARRAY),
 vertexBoneWeightArray(4, RenderDataArray::BONE_WEIGHT_DATA_ARRAY),
 vertexBoneIndexArray(4, RenderDataArray::BONE_INDEX_DATA_ARRAY),
+customVertexArray1(0, RenderDataArray::CUSTOM_DATA_ARRAY1),
+customVertexArray2(0, RenderDataArray::CUSTOM_DATA_ARRAY2),
+customVertexArray3(0, RenderDataArray::CUSTOM_DATA_ARRAY3),
+customVertexArray4(0, RenderDataArray::CUSTOM_DATA_ARRAY4),
 indexArray(RenderDataArray::INDEX_DATA_ARRAY)
 {
-
+    
+    this->meshType = MeshGeometry::TRI_MESH;
     indexedMesh = false;
-    meshType = TRI_MESH;
-    meshHasVertexBuffer = false;
-    loadMesh(fileName);
-    setResourcePath(fileName);
+    dataChanged = false;
 }
 
-Mesh::Mesh(int meshType) : Resource(Resource::RESOURCE_MESH),
+MeshGeometry::MeshGeometry(int meshType) :
 vertexPositionArray(3, RenderDataArray::VERTEX_DATA_ARRAY),
 vertexColorArray(4, RenderDataArray::COLOR_DATA_ARRAY),
 vertexNormalArray(3, RenderDataArray::NORMAL_DATA_ARRAY),
@@ -61,24 +64,62 @@ vertexTexCoord2Array(2, RenderDataArray::TEXCOORD2_DATA_ARRAY),
 vertexTangentArray(3, RenderDataArray::TANGENT_DATA_ARRAY),
 vertexBoneWeightArray(4, RenderDataArray::BONE_WEIGHT_DATA_ARRAY),
 vertexBoneIndexArray(4, RenderDataArray::BONE_INDEX_DATA_ARRAY),
+customVertexArray1(0, RenderDataArray::CUSTOM_DATA_ARRAY1),
+customVertexArray2(0, RenderDataArray::CUSTOM_DATA_ARRAY2),
+customVertexArray3(0, RenderDataArray::CUSTOM_DATA_ARRAY3),
+customVertexArray4(0, RenderDataArray::CUSTOM_DATA_ARRAY4),
 indexArray(RenderDataArray::INDEX_DATA_ARRAY)
 {
 
     this->meshType = meshType;
-    meshHasVertexBuffer = false;
     indexedMesh = false;
+    dataChanged = false;
 }
 
-Mesh *Mesh::MeshFromFileName(String& fileName) {
-    return new Mesh(fileName);
-}
-
-Mesh::~Mesh() {
-    clearMesh();
+MeshGeometry::~MeshGeometry() {
+    if(vertexPositionArray.platformData) {
+        Services()->getRenderer()->destroySubmeshPlatformData(vertexPositionArray.platformData);
+    }
+    if(vertexColorArray.platformData) {
+        Services()->getRenderer()->destroySubmeshPlatformData(vertexColorArray.platformData);
+    }
+    if(vertexNormalArray.platformData) {
+        Services()->getRenderer()->destroySubmeshPlatformData(vertexNormalArray.platformData);
+    }
+    if(vertexTexCoordArray.platformData) {
+        Services()->getRenderer()->destroySubmeshPlatformData(vertexTexCoordArray.platformData);
+    }
+    if(vertexTexCoord2Array.platformData) {
+        Services()->getRenderer()->destroySubmeshPlatformData(vertexTexCoord2Array.platformData);
+    }
+    if(vertexTangentArray.platformData) {
+        Services()->getRenderer()->destroySubmeshPlatformData(vertexTangentArray.platformData);
+    }
+    if(indexArray.platformData) {
+        Services()->getRenderer()->destroySubmeshPlatformData(indexArray.platformData);
+    }
+    if(vertexBoneWeightArray.platformData) {
+        Services()->getRenderer()->destroySubmeshPlatformData(vertexBoneWeightArray.platformData);
+    }
+    if(vertexBoneIndexArray.platformData) {
+        Services()->getRenderer()->destroySubmeshPlatformData(vertexBoneIndexArray.platformData);
+    }
+    if(customVertexArray1.platformData) {
+        Services()->getRenderer()->destroySubmeshPlatformData(customVertexArray1.platformData);
+    }
+    if(customVertexArray2.platformData) {
+        Services()->getRenderer()->destroySubmeshPlatformData(customVertexArray2.platformData);
+    }
+    if(customVertexArray3.platformData) {
+        Services()->getRenderer()->destroySubmeshPlatformData(customVertexArray3.platformData);
+    }
+    if(customVertexArray4.platformData) {
+        Services()->getRenderer()->destroySubmeshPlatformData(customVertexArray4.platformData);
+    }
+    
 }
 
-void Mesh::clearMesh() {
-    
+void MeshGeometry::clearMesh() {
     vertexPositionArray.data.clear();
     vertexColorArray.data.clear();
     vertexNormalArray.data.clear();
@@ -88,11 +129,13 @@ void Mesh::clearMesh() {
     indexArray.data.clear();
     vertexBoneWeightArray.data.clear();
     vertexBoneIndexArray.data.clear();
-    
-    meshHasVertexBuffer = false;
+    customVertexArray1.data.clear();
+    customVertexArray2.data.clear();
+    customVertexArray3.data.clear();
+    customVertexArray4.data.clear();
 }
 
-Number Mesh::getRadius() {
+Number MeshGeometry::getRadius() {
     Number hRad = 0;
     Number len;
     for(int i=0; i < getVertexCount(); i ++) {
@@ -105,152 +148,8 @@ Number Mesh::getRadius() {
     return hRad;
 }
 
-void Mesh::writeVertexBlock(VertexDataArray *array, Polycode::CoreFile *outFile) {
-    
-    if(array->getDataSize() == 0) {
-        return;
-    }
-    
-    unsigned char blockType = array->type;
-    unsigned int blockCount = array->getDataSize();
-
-    outFile->write(&blockType, sizeof(unsigned char), 1);
-    outFile->write(&blockCount, sizeof(unsigned int), 1);
-    
-    outFile->write(array->getArrayData(), sizeof(PolyRendererVertexType), array->getDataSize());
-}
-
-void Mesh::writeIndexBlock(IndexDataArray *array, Polycode::CoreFile *outFile) {
-    
-    if(array->getDataSize() == 0) {
-        return;
-    }
-    
-    unsigned char blockType = array->type;
-    unsigned int blockCount = array->getDataSize();
-    
-    outFile->write(&blockType, sizeof(unsigned char), 1);
-    outFile->write(&blockCount, sizeof(unsigned int), 1);
-    
-    outFile->write(array->getArrayData(), sizeof(PolyRendererIndexType), array->getDataSize());
-}
-
-void Mesh::saveToFile(Polycode::CoreFile *outFile, bool writeNormals, bool writeTangents, bool writeColors, bool writeBoneWeights, bool writeUVs, bool writeSecondaryUVs) {
 
-    // new mesh format
-    // IMPORTANT: PolyRendererVertexType type defines mesh format internal type. Consider making floats always. Don't want to cast for now.
-    
-    const char headerTag[] = "MSH2";
-    outFile->write(headerTag, 1, 4);
-    
-    unsigned char meshFlags = 0;
-    
-    if(indexedMesh) {
-        meshFlags |= 1 << 0;
-    }
-    
-    outFile->write(&meshFlags, sizeof(unsigned char), 1);
-    
-    writeVertexBlock(&vertexPositionArray, outFile);
-    
-    if(indexedMesh) {
-        writeIndexBlock(&indexArray, outFile);
-    }
-    
-    if(writeColors) {
-        writeVertexBlock(&vertexColorArray, outFile);
-    }
-
-    if(writeNormals) {
-        writeVertexBlock(&vertexNormalArray, outFile);
-    }
-    
-    if(writeUVs) {
-        writeVertexBlock(&vertexTexCoordArray, outFile);
-    }
-
-    if(writeSecondaryUVs) {
-        writeVertexBlock(&vertexTexCoord2Array, outFile);
-    }
-    
-    if(writeTangents) {
-        writeVertexBlock(&vertexTangentArray, outFile);
-    }
-    
-    if(writeBoneWeights) {
-        writeVertexBlock(&vertexBoneWeightArray, outFile);
-        writeVertexBlock(&vertexBoneIndexArray, outFile);
-    }
-}
-
-void Mesh::loadFromFile(Polycode::CoreFile *inFile) {
-    clearMesh();
-    
-    char tag[4];
-    inFile->read(tag, 1, 4);
-    
-    if(tag[0] == 'M' && tag[1] == 'S' && tag[2] == 'H' && tag[3] == '2') {
-        loadFromFileV2(inFile);
-    } else {
-        inFile->seek(0, SEEK_SET);
-        loadFromFileLegacyV1(inFile);
-    }
-}
-
-void Mesh::loadFromFileV2(Polycode::CoreFile *inFile) {
-    
-    unsigned char meshFlags;
-    inFile->read(&meshFlags, sizeof(unsigned char), 1);
-    
-    indexedMesh = meshFlags & (1 << 0);
-    
-    char blockType;
-    unsigned int blockSize;
-    while(inFile->read(&blockType, sizeof(unsigned char), 1)) {
-        inFile->read(&blockSize, sizeof(unsigned int), 1);
-        
-        switch(blockType) {
-            case RenderDataArray::VERTEX_DATA_ARRAY:
-                vertexPositionArray.data.resize(blockSize);
-                inFile->read(&vertexPositionArray.data[0], sizeof(PolyRendererVertexType), blockSize);
-            break;
-            case RenderDataArray::TEXCOORD_DATA_ARRAY:
-                vertexTexCoordArray.data.resize(blockSize);
-                inFile->read(&vertexTexCoordArray.data[0], sizeof(PolyRendererVertexType), blockSize);
-            break;
-            case RenderDataArray::NORMAL_DATA_ARRAY:
-                vertexNormalArray.data.resize(blockSize);
-                inFile->read(&vertexNormalArray.data[0], sizeof(PolyRendererVertexType), blockSize);
-            break;
-            case RenderDataArray::COLOR_DATA_ARRAY:
-                vertexColorArray.data.resize(blockSize);
-                inFile->read(&vertexColorArray.data[0], sizeof(PolyRendererVertexType), blockSize);
-            break;
-            case RenderDataArray::TANGENT_DATA_ARRAY:
-                vertexTangentArray.data.resize(blockSize);
-                inFile->read(&vertexTangentArray.data[0], sizeof(PolyRendererVertexType), blockSize);
-            break;
-            case RenderDataArray::BONE_WEIGHT_DATA_ARRAY:
-                vertexBoneWeightArray.data.resize(blockSize);
-                inFile->read(&vertexBoneWeightArray.data[0], sizeof(PolyRendererVertexType), blockSize);
-            break;
-            case RenderDataArray::INDEX_DATA_ARRAY:
-                indexArray.data.resize(blockSize);
-                inFile->read(&indexArray.data[0], sizeof(PolyRendererIndexType), blockSize);
-            break;
-            case RenderDataArray::BONE_INDEX_DATA_ARRAY:
-                vertexBoneIndexArray.data.resize(blockSize);
-                inFile->read(&vertexBoneIndexArray.data[0], sizeof(PolyRendererVertexType), blockSize);
-            break;
-        }
-    }
-    
-    if(vertexBoneIndexArray.getDataSize() > 0) {
-        normalizeBoneWeights();
-    }
-}
-
-void Mesh::normalizeBoneWeights() {
+void MeshGeometry::normalizeBoneWeights() {
     
     for(int i=0; i < vertexBoneWeightArray.getDataSize()-3; i += 4) {
         Number totalWeight = vertexBoneWeightArray.data[i] + vertexBoneWeightArray.data[i+1] + vertexBoneWeightArray.data[i+2] + vertexBoneWeightArray.data[i+3];
@@ -264,180 +163,63 @@ void Mesh::normalizeBoneWeights() {
     }
 }
 
-void Mesh::loadFromFileLegacyV1(Polycode::CoreFile *inFile) {
-    
-    unsigned char meshFlags;
-    inFile->read(&meshFlags, sizeof(unsigned char), 1);
-    
-    indexedMesh = meshFlags & (1 << 0);
-    bool hasNormals = meshFlags & (1 << 1);
-    bool hasTangents = meshFlags & (1 << 2);
-    bool hasColors = meshFlags & (1 << 3);
-    bool hasUV = meshFlags & (1 << 4);
-    bool hasSecondaryUVs = meshFlags & (1 << 5);
-    bool hasBoneWeights = meshFlags & (1 << 6);
-    
-    unsigned int meshType;		
-    inFile->read(&meshType, sizeof(unsigned int), 1);
-    setMeshType(meshType);
-    
-    unsigned int numVertices;
-    inFile->read(&numVertices, sizeof(unsigned int), 1);
-    
-    Vector3_struct pos;
-    Vector3_struct nor;
-    Vector3_struct tan;
-    Vector4_struct col;			
-    Vector2_struct tex;
-    
-    for(int i=0; i < numVertices; i++) {
-        inFile->read(&pos, sizeof(Vector3_struct), 1);
-
-        vertexPositionArray.data.push_back(pos.x);
-        vertexPositionArray.data.push_back(pos.y);
-        vertexPositionArray.data.push_back(pos.z);
-        
-        if(hasNormals) {
-            inFile->read(&nor, sizeof(Vector3_struct), 1);
-
-            vertexNormalArray.data.push_back(nor.x);
-            vertexNormalArray.data.push_back(nor.y);
-            vertexNormalArray.data.push_back(nor.z);
-            
-            
-        }
-        if(hasTangents) {
-            inFile->read(&tan, sizeof(Vector3_struct), 1);
-            
-            vertexTangentArray.data.push_back(tan.x);
-            vertexTangentArray.data.push_back(tan.y);
-            vertexTangentArray.data.push_back(tan.z);
-            
-        }
-        
-        if(hasColors) {
-            inFile->read(&col, sizeof(Vector4_struct), 1);
-            
-            vertexColorArray.data.push_back(col.x);
-            vertexColorArray.data.push_back(col.y);
-            vertexColorArray.data.push_back(col.z);
-            vertexColorArray.data.push_back(col.w);
-        }
-        
-        if(hasUV) {
-            inFile->read(&tex, sizeof(Vector2_struct), 1);
-            vertexTexCoordArray.data.push_back(tex.x);
-            vertexTexCoordArray.data.push_back(tex.y);
-        }
-        
-        if(hasSecondaryUVs) {
-            inFile->read(&tex, sizeof(Vector2_struct), 1);
-            vertexTexCoord2Array.data.push_back(tex.x);
-            vertexTexCoord2Array.data.push_back(tex.x);
-        }
-        
-        if(hasBoneWeights) {
-            unsigned int numBoneWeights;
-            inFile->read(&numBoneWeights, sizeof(unsigned int), 1);
-            
-            Number totalWeight = 0;
-            int numPushed = 0;
-            
-            for(int b=0; b < numBoneWeights; b++) {
-                float weight;
-                unsigned int boneID;
-                inFile->read(&boneID, sizeof(unsigned int), 1);
-                inFile->read(&weight, sizeof(float), 1);
-                
-                if(b < 4) {
-                    vertexBoneWeightArray.data.push_back(weight);
-                    vertexBoneIndexArray.data.push_back(boneID);
-                    numPushed++;
-                }
-                totalWeight += weight;
-            }
-            
-            if(numPushed < 4) {
-                for(int b=numPushed; b < 4; b++) {
-                    vertexBoneWeightArray.data.push_back(0.0);
-                    vertexBoneIndexArray.data.push_back(0.0);
-                }
-            }
-            
-            for(int m=0; m < 4; m++) {
-                vertexBoneWeightArray.data[vertexBoneWeightArray.data.size()-1-m] = vertexBoneWeightArray.data[vertexBoneWeightArray.data.size()-1-m] / totalWeight;
-            }				
-        }
-    }
-    
-    if(indexedMesh) {
-        unsigned int numIndices;
-        inFile->read(&numIndices, sizeof(unsigned int), 1);
-        unsigned int val;
-        for(int i=0; i < numIndices; i++) {
-            inFile->read(&val, sizeof(unsigned int), 1);
-            indexArray.data.push_back(val);
-        }
-    }
-}
-
-Vector2 Mesh::getVertexTexCoord(unsigned int vertexOffset) {
+Vector2 MeshGeometry::getVertexTexCoord(unsigned int vertexOffset) {
     return Vector2(vertexTexCoordArray.data[(vertexOffset*2)], vertexTexCoordArray.data[(vertexOffset*2)+1]);
 }
 
-Vector2 Mesh::getVertexTexCoordAtIndex(unsigned int index) {
+Vector2 MeshGeometry::getVertexTexCoordAtIndex(unsigned int index) {
     unsigned int vertexOffset = indexArray.data[index]*2;
     return Vector2(vertexTexCoordArray.data[vertexOffset], vertexTexCoordArray.data[vertexOffset+1]);
 }
 
 
-Vector3 Mesh::getVertexPosition(unsigned int vertexOffset) {
+Vector3 MeshGeometry::getVertexPosition(unsigned int vertexOffset) {
     return Vector3(vertexPositionArray.data[(vertexOffset*3)], vertexPositionArray.data[(vertexOffset*3)+1], vertexPositionArray.data[(vertexOffset*3)+2]);
 }
 
-Vector3 Mesh::getVertexPositionAtIndex(unsigned int index) {
+Vector3 MeshGeometry::getVertexPositionAtIndex(unsigned int index) {
     unsigned int vertexOffset = indexArray.data[index]*3;
     return Vector3(vertexPositionArray.data[vertexOffset], vertexPositionArray.data[vertexOffset+1], vertexPositionArray.data[vertexOffset+2]);
 }
 
 
-void Mesh::addColor(const Color &color) {
+void MeshGeometry::addColor(const Color &color) {
     vertexColorArray.data.push_back(color.r);
     vertexColorArray.data.push_back(color.g);
     vertexColorArray.data.push_back(color.b);
     vertexColorArray.data.push_back(color.a);
 }
 
-void Mesh::addColor(Number r, Number g, Number b, Number a) {
+void MeshGeometry::addColor(Number r, Number g, Number b, Number a) {
     vertexColorArray.data.push_back(r);
     vertexColorArray.data.push_back(g);
     vertexColorArray.data.push_back(b);
     vertexColorArray.data.push_back(a);
 }
 
-void Mesh::addVertex(Number x, Number y, Number z) {
+void MeshGeometry::addVertex(Number x, Number y, Number z) {
     vertexPositionArray.data.push_back(x);
     vertexPositionArray.data.push_back(y);
     vertexPositionArray.data.push_back(z);
 }
 
-void Mesh::addTangent(Number x, Number y, Number z) {
+void MeshGeometry::addTangent(Number x, Number y, Number z) {
     vertexTangentArray.data.push_back(x);
     vertexTangentArray.data.push_back(y);
     vertexTangentArray.data.push_back(z);
 }
 
-void Mesh::addTexCoord(Number u, Number v) {
+void MeshGeometry::addTexCoord(Number u, Number v) {
     vertexTexCoordArray.data.push_back(u);
     vertexTexCoordArray.data.push_back(v);
 }
 
-void Mesh::addTexCoord2(Number u, Number v) {
+void MeshGeometry::addTexCoord2(Number u, Number v) {
     vertexTexCoord2Array.data.push_back(u);
     vertexTexCoord2Array.data.push_back(v);
 }
 
-void Mesh::addBoneAssignments(Number b1Weight, unsigned int b1Index, Number b2Weight, unsigned int b2Index, Number b3Weight, unsigned int b3Index, Number b4Weight, unsigned int b4Index) {
+void MeshGeometry::addBoneAssignments(Number b1Weight, unsigned int b1Index, Number b2Weight, unsigned int b2Index, Number b3Weight, unsigned int b3Index, Number b4Weight, unsigned int b4Index) {
  
     vertexBoneWeightArray.data.push_back(b1Weight);
     vertexBoneWeightArray.data.push_back(b2Weight);
@@ -450,7 +232,7 @@ void Mesh::addBoneAssignments(Number b1Weight, unsigned int b1Index, Number b2We
     vertexBoneIndexArray.data.push_back(b4Index);
 }
 
-void Mesh::setVertexAtOffset(unsigned int offset, Number x, Number y, Number z) {
+void MeshGeometry::setVertexAtOffset(unsigned int offset, Number x, Number y, Number z) {
     if((offset*3)+2 < vertexPositionArray.data.size()) {
         vertexPositionArray.data[(offset*3)] = x;
         vertexPositionArray.data[(offset*3)+1] = y;
@@ -458,51 +240,31 @@ void Mesh::setVertexAtOffset(unsigned int offset, Number x, Number y, Number z)
     }
 }
 
-void Mesh::addVertexWithUV(Number x, Number y, Number z, Number u, Number v) {
+void MeshGeometry::addVertexWithUV(Number x, Number y, Number z, Number u, Number v) {
     addVertex(x,y,z);
     addTexCoord(u,v);
 }
 
-void Mesh::addVertexWithUVAndNormal(Number x, Number y, Number z, Number u, Number v, Number nx, Number ny, Number nz) {
+void MeshGeometry::addVertexWithUVAndNormal(Number x, Number y, Number z, Number u, Number v, Number nx, Number ny, Number nz) {
     addVertexWithUV(x,y,z, u, v);
     addNormal(nx, ny, nz);
 }
 
-void Mesh::addNormal(Number nx, Number ny, Number nz) {
+void MeshGeometry::addNormal(Number nx, Number ny, Number nz) {
     vertexNormalArray.data.push_back(nx);
     vertexNormalArray.data.push_back(ny);
     vertexNormalArray.data.push_back(nz);
 }
 
-void Mesh::addNormal(const Vector3 &n) {
+void MeshGeometry::addNormal(const Vector3 &n) {
     vertexNormalArray.data.push_back(n.x);
     vertexNormalArray.data.push_back(n.y);
     vertexNormalArray.data.push_back(n.z);
 }
 
-void Mesh::saveToFile(const String& fileName, bool writeNormals, bool writeTangents, bool writeColors, bool writeBoneWeights, bool writeUVs, bool writeSecondaryUVs) {
-    CoreFile *outFile = Services()->getCore()->openFile(fileName, "wb");
-    if(!outFile) {
-        Logger::log("Error opening mesh file for saving: %s\n", fileName.c_str());
-        return;
-    }
-    saveToFile(outFile, writeNormals, writeTangents, writeColors, writeBoneWeights, writeUVs, writeSecondaryUVs);
-    Services()->getCore()->closeFile(outFile);
 
-}
-
-void Mesh::loadMesh(const String& fileName) {
-    CoreFile *inFile = Services()->getCore()->openFile(fileName, "rb");
-    if(!inFile) {
-        Logger::log("Error opening mesh file %s\n", fileName.c_str());
-        return;
-    }
-    loadFromFile(inFile);
-    Services()->getCore()->closeFile(inFile);
-}
-
-void Mesh::createCircle(Number w, Number h, unsigned int numSegments, Number tilingValue) {
-    setMeshType(Mesh::TRI_MESH);
+void MeshGeometry::createCircle(Number w, Number h, unsigned int numSegments, Number tilingValue) {
+    setMeshType(MeshGeometry::TRI_MESH);
     indexedMesh = false;
 
     Number lastx = 0;
@@ -526,15 +288,67 @@ void Mesh::createCircle(Number w, Number h, unsigned int numSegments, Number til
     }
 }
 
-Mesh *Mesh::Copy() const {
-    Mesh *newMesh = new Mesh(meshType);
+MeshGeometry::MeshGeometry(const MeshGeometry &geom) :
+vertexPositionArray(3, RenderDataArray::VERTEX_DATA_ARRAY),
+vertexColorArray(4, RenderDataArray::COLOR_DATA_ARRAY),
+vertexNormalArray(3, RenderDataArray::NORMAL_DATA_ARRAY),
+vertexTexCoordArray(2, RenderDataArray::TEXCOORD_DATA_ARRAY),
+vertexTexCoord2Array(2, RenderDataArray::TEXCOORD2_DATA_ARRAY),
+vertexTangentArray(3, RenderDataArray::TANGENT_DATA_ARRAY),
+vertexBoneWeightArray(4, RenderDataArray::BONE_WEIGHT_DATA_ARRAY),
+vertexBoneIndexArray(4, RenderDataArray::BONE_INDEX_DATA_ARRAY),
+customVertexArray1(0, RenderDataArray::CUSTOM_DATA_ARRAY1),
+customVertexArray2(0, RenderDataArray::CUSTOM_DATA_ARRAY2),
+customVertexArray3(0, RenderDataArray::CUSTOM_DATA_ARRAY3),
+customVertexArray4(0, RenderDataArray::CUSTOM_DATA_ARRAY4),
+indexArray(RenderDataArray::INDEX_DATA_ARRAY) {
+    vertexPositionArray = geom.vertexPositionArray;
+    vertexColorArray = geom.vertexColorArray;
+    vertexNormalArray = geom.vertexNormalArray;
+    vertexTexCoordArray = geom.vertexTexCoordArray;
+    vertexTexCoord2Array = geom.vertexTexCoord2Array;
+    vertexTangentArray = geom.vertexTangentArray;
+    vertexBoneWeightArray = geom.vertexBoneWeightArray;
+    vertexBoneIndexArray = geom.vertexBoneIndexArray;
+    customVertexArray1 = geom.customVertexArray1;
+    customVertexArray2 = geom.customVertexArray2;
+    customVertexArray3 = geom.customVertexArray3;
+    customVertexArray4 = geom.customVertexArray4;
+    indexArray = geom.indexArray;
+    indexedMesh = geom.indexedMesh;
+    meshType = geom.meshType;
+    dataChanged = true;
+}
+
+MeshGeometry &MeshGeometry::operator=(const MeshGeometry &geom) {
+    vertexPositionArray = geom.vertexPositionArray;
+    vertexColorArray = geom.vertexColorArray;
+    vertexNormalArray = geom.vertexNormalArray;
+    vertexTexCoordArray = geom.vertexTexCoordArray;
+    vertexTexCoord2Array = geom.vertexTexCoord2Array;
+    vertexTangentArray = geom.vertexTangentArray;
+    vertexBoneWeightArray = geom.vertexBoneWeightArray;
+    vertexBoneIndexArray = geom.vertexBoneIndexArray;
+    customVertexArray1 = geom.customVertexArray1;
+    customVertexArray2 = geom.customVertexArray2;
+    customVertexArray3 = geom.customVertexArray3;
+    customVertexArray4 = geom.customVertexArray4;
+    indexArray = geom.indexArray;
+    indexedMesh = geom.indexedMesh;
+    meshType = geom.meshType;
+    dataChanged = true;
+    return *this;
+}
+
+MeshGeometry *MeshGeometry::Copy() const {
+    MeshGeometry *newMesh = new MeshGeometry(meshType);
     newMesh->indexedMesh = indexedMesh;
     (*newMesh) = (*this);
     return newMesh;
 }
 
-void Mesh::createLineCircle(Number w, Number h, unsigned int numSegments, Number tilingValue) {
-    setMeshType(Mesh::TRIFAN_MESH);
+void MeshGeometry::createLineCircle(Number w, Number h, unsigned int numSegments, Number tilingValue) {
+    setMeshType(MeshGeometry::TRIFAN_MESH);
     indexedMesh = false;
     
     int step;
@@ -561,8 +375,8 @@ void Mesh::createLineCircle(Number w, Number h, unsigned int numSegments, Number
     }
 }
 
-void Mesh::createVPlane(Number w, Number h, Number tilingValue) {
-    setMeshType(Mesh::TRI_MESH);
+void MeshGeometry::createVPlane(Number w, Number h, Number tilingValue) {
+    setMeshType(MeshGeometry::TRI_MESH);
     indexedMesh = false;
     
     addVertexWithUVAndNormal(0 - (w/2.0f),0 - (h/2.0f), 0,0,0, 0.0, 0.0, 1.0);
@@ -577,8 +391,8 @@ void Mesh::createVPlane(Number w, Number h, Number tilingValue) {
     calculateTangents();
 }	
 
-void Mesh::createPlane(Number w, Number h, Number tilingValue) {
-    setMeshType(Mesh::TRI_MESH);
+void MeshGeometry::createPlane(Number w, Number h, Number tilingValue) {
+    setMeshType(MeshGeometry::TRI_MESH);
     indexedMesh = false;
     
 	addVertexWithUV(0 - (w / 2.0f), 0, h - (h / 2.0f), 0, 0);
@@ -593,7 +407,7 @@ void Mesh::createPlane(Number w, Number h, Number tilingValue) {
     calculateTangents();
 }
 
-Vector3 Mesh::recenterMesh() {
+Vector3 MeshGeometry::recenterMesh() {
     
     // TODO: implement
     
@@ -630,7 +444,7 @@ Vector3 Mesh::recenterMesh() {
     return finalOffset;		
 }	
 
-Vector3 Mesh::calculateBBox() {
+Vector3 MeshGeometry::calculateBBox() {
     Vector3 retVec;
     
     if(vertexPositionArray.data.size() == 0) {
@@ -656,12 +470,12 @@ Vector3 Mesh::calculateBBox() {
     return retVec*2;
 }
 
-void Mesh::createSphere(Number radius, int segmentsH, int segmentsW, Number tilingValue) {
+void MeshGeometry::createSphere(Number radius, int segmentsH, int segmentsW, Number tilingValue) {
 
     segmentsH++;
     segmentsW++;
     
-    setMeshType(Mesh::TRI_MESH);
+    setMeshType(MeshGeometry::TRI_MESH);
     indexedMesh = true;
 
     Number tdelta = 360.f/(segmentsW-1);
@@ -696,7 +510,7 @@ void Mesh::createSphere(Number radius, int segmentsH, int segmentsW, Number tili
     calculateTangents();
 }
 
-void Mesh::subdivideToRadius(Number radius, int subdivisions)
+void MeshGeometry::subdivideToRadius(Number radius, int subdivisions)
 {
 	typedef std::map<std::pair<int,int>, int> EdgeSet;
 	for (int s = 0; s < subdivisions; s++) {
@@ -773,9 +587,9 @@ void Mesh::subdivideToRadius(Number radius, int subdivisions)
 	}
 }
 
-void Mesh::createOctosphere(Number radius, int subdivisions) {
+void MeshGeometry::createOctosphere(Number radius, int subdivisions) {
 
-    setMeshType(Mesh::TRI_MESH);
+    setMeshType(MeshGeometry::TRI_MESH);
     
 	indexedMesh = true;
 
@@ -811,9 +625,9 @@ void Mesh::createOctosphere(Number radius, int subdivisions) {
 	calculateTangents();
 }
 
-void Mesh::createIcosphere(Number radius, int subdivisions) {
+void MeshGeometry::createIcosphere(Number radius, int subdivisions) {
 
-    setMeshType(Mesh::TRI_MESH);
+    setMeshType(MeshGeometry::TRI_MESH);
     
 	const float a = 0.5257311121191336;
 	const float b = 0.85065080835204;
@@ -870,21 +684,21 @@ void Mesh::createIcosphere(Number radius, int subdivisions) {
 	calculateTangents();
 }
 
-unsigned int Mesh::getVertexCount() {
+unsigned int MeshGeometry::getVertexCount() {
     return vertexPositionArray.data.size()/3;
 }
 
-unsigned int Mesh::getIndexCount() {
+unsigned int MeshGeometry::getIndexCount() {
     return indexArray.data.size();
 }
 
 
-void Mesh::createTorus(Number radius, Number tubeRadius, int segmentsW, int segmentsH, Number tilingValue) {
+void MeshGeometry::createTorus(Number radius, Number tubeRadius, int segmentsW, int segmentsH, Number tilingValue) {
 
     segmentsH++;
     segmentsW++;
     
-    setMeshType(Mesh::TRI_MESH);
+    setMeshType(MeshGeometry::TRI_MESH);
     indexedMesh = true;
     
     Number tdelta = 360.f/(segmentsW-1);
@@ -920,9 +734,9 @@ void Mesh::createTorus(Number radius, Number tubeRadius, int segmentsW, int segm
     calculateTangents();
 }
 
-void Mesh::createCylinder(Number height, Number radius, int numSegments, bool capped, Number tilingValue) {
+void MeshGeometry::createCylinder(Number height, Number radius, int numSegments, bool capped, Number tilingValue) {
 
-    setMeshType(Mesh::TRI_MESH);
+    setMeshType(MeshGeometry::TRI_MESH);
     indexedMesh = true;
     
     Number lastx = 0;
@@ -979,9 +793,9 @@ void Mesh::createCylinder(Number height, Number radius, int numSegments, bool ca
     calculateTangents();
 }
 
-void Mesh::createCone(Number height, Number radius, int numSegments, Number tilingValue) {
+void MeshGeometry::createCone(Number height, Number radius, int numSegments, Number tilingValue) {
     
-    setMeshType(Mesh::TRI_MESH);
+    setMeshType(MeshGeometry::TRI_MESH);
     indexedMesh = true;
     
     Number lastx = 0;
@@ -1025,29 +839,29 @@ void Mesh::createCone(Number height, Number radius, int numSegments, Number tili
     calculateTangents();
 }
 
-void Mesh::addIndex(unsigned int index) {
+void MeshGeometry::addIndex(unsigned int index) {
     indexArray.data.push_back(index);
 }
 
-void Mesh::addIndexedFace(unsigned int i1, unsigned int i2, unsigned int i3) {
+void MeshGeometry::addIndexedFace(unsigned int i1, unsigned int i2, unsigned int i3) {
     indexArray.data.push_back(i1);
     indexArray.data.push_back(i2);
     indexArray.data.push_back(i3);
 }
 
-void Mesh::addIndexedFace(unsigned int i1, unsigned int i2) {
+void MeshGeometry::addIndexedFace(unsigned int i1, unsigned int i2) {
     indexArray.data.push_back(i1);
     indexArray.data.push_back(i2);
 }
 
-void Mesh::addIndexedFace(unsigned int i1, unsigned int i2, unsigned int i3, unsigned int i4) {
+void MeshGeometry::addIndexedFace(unsigned int i1, unsigned int i2, unsigned int i3, unsigned int i4) {
     indexArray.data.push_back(i1);
     indexArray.data.push_back(i2);
     indexArray.data.push_back(i3);
     indexArray.data.push_back(i4);
 }
 
-void Mesh::removeFace(unsigned int faceIndex) {
+void MeshGeometry::removeFace(unsigned int faceIndex) {
 	unsigned int groupSize = getIndexGroupSize();
 	unsigned int startOffset = faceIndex * groupSize;
 	if (indexedMesh) {
@@ -1059,7 +873,7 @@ void Mesh::removeFace(unsigned int faceIndex) {
 	}
 }
 
-void Mesh::removeVertexRange(unsigned int beginRemoveVertex, int vertexRemovalCount) {
+void MeshGeometry::removeVertexRange(unsigned int beginRemoveVertex, int vertexRemovalCount) {
     // TODO: fix
     /*
 	if (!vertices.size()) return;
@@ -1087,7 +901,7 @@ void Mesh::removeVertexRange(unsigned int beginRemoveVertex, int vertexRemovalCo
      */
 }
 
-int Mesh::removeUnusedVertices() {
+int MeshGeometry::removeUnusedVertices() {
 	int removals = 0;
         // TODO: fix
     /*
@@ -1117,8 +931,8 @@ int Mesh::removeUnusedVertices() {
 	return removals;
 }
 
-void Mesh::createBox(Number w, Number d, Number h, Number tilingValue) {
-    setMeshType(Mesh::TRI_MESH);
+void MeshGeometry::createBox(Number w, Number d, Number h, Number tilingValue) {
+    setMeshType(MeshGeometry::TRI_MESH);
     indexedMesh = false;
     
     addVertexWithUV(w,0,h, tilingValue, tilingValue);
@@ -1179,7 +993,7 @@ void Mesh::createBox(Number w, Number d, Number h, Number tilingValue) {
     calculateTangents();
 }
 
-Vector3 Mesh::calculateFaceTangent(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, const Vector2 &texCoord1, const Vector2 &texCoord2, const Vector2 &texCoord3) {
+Vector3 MeshGeometry::calculateFaceTangent(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, const Vector2 &texCoord1, const Vector2 &texCoord2, const Vector2 &texCoord3) {
     Vector3 tangent;
     Vector3 side0 = v1 - v2;
     Vector3 side1 = v3 - v1;
@@ -1205,7 +1019,7 @@ Vector3 Mesh::calculateFaceTangent(const Vector3 &v1, const Vector3 &v2, const V
 }
 
 
-void Mesh::calculateTangents() {
+void MeshGeometry::calculateTangents() {
 
     vertexTangentArray.data.clear();
     
@@ -1250,7 +1064,7 @@ void Mesh::calculateTangents() {
 
 }
 
-void Mesh::calculateNormals() {
+void MeshGeometry::calculateNormals() {
 
     int polySize = 3;
     
@@ -1297,7 +1111,7 @@ void Mesh::calculateNormals() {
     }
 }
 
-void Mesh::saveAsOBJ(const String fileName) {
+void MeshGeometry::saveAsOBJ(const String fileName) {
 	FILE *f = fopen(fileName.c_str(), "w");
     
 	if (!f) {
@@ -1337,10 +1151,391 @@ void Mesh::saveAsOBJ(const String fileName) {
 	fclose(f);
 }
 
-int Mesh::getMeshType() {
+
+int MeshGeometry::getMeshType() {
     return meshType;
 }
 
-void Mesh::setMeshType(int newType) {
+void MeshGeometry::setMeshType(int newType) {
     meshType = newType;
 }
+
+Mesh::Mesh() : Resource(Resource::RESOURCE_MESH) {
+}
+
+Mesh::Mesh(const String& fileName) : Resource(Resource::RESOURCE_MESH) {
+    loadMesh(fileName);
+    setResourcePath(fileName);
+}
+
+Mesh::~Mesh() {
+    clearMesh();
+}
+
+Mesh *Mesh::MeshFromFileName(String& fileName) {
+    return new Mesh(fileName);
+}
+
+unsigned int Mesh::getNumSubmeshes() const {
+    return submeshes.size();
+}
+
+void Mesh::writeVertexBlock(const VertexDataArray &array, Polycode::CoreFile *outFile) const  {
+    
+    if(array.getDataSize() == 0) {
+        return;
+    }
+    
+    unsigned char blockType = array.type;
+    unsigned int blockCount = array.getDataSize();
+    
+    outFile->write(&blockType, sizeof(unsigned char), 1);
+    outFile->write(&blockCount, sizeof(unsigned int), 1);
+    
+    outFile->write(array.getArrayData(), sizeof(PolyRendererVertexType), array.getDataSize());
+}
+
+void Mesh::writeIndexBlock(const IndexDataArray &array, Polycode::CoreFile *outFile) const  {
+    
+    if(array.getDataSize() == 0) {
+        return;
+    }
+    
+    unsigned char blockType = array.type;
+    unsigned int blockCount = array.getDataSize();
+    
+    outFile->write(&blockType, sizeof(unsigned char), 1);
+    outFile->write(&blockCount, sizeof(unsigned int), 1);
+    
+    outFile->write(array.getArrayData(), sizeof(PolyRendererIndexType), array.getDataSize());
+}
+
+Vector3 Mesh::calculateBBox() {
+    Vector3 retBox;
+    for(int i = 0; i < submeshes.size(); i++) {
+        Vector3 bBox = submeshes[i]->calculateBBox();
+        if(bBox.length() > retBox.length()) {
+            retBox = bBox;
+        }
+    }
+    return retBox;
+}
+
+Mesh *Mesh::Copy() const {
+    Mesh *newMesh = new Mesh();
+    for(int i=0; i  < submeshes.size(); i++) {
+        newMesh->addSubmesh(*submeshes[i]);
+    }
+    newMesh->setResourceName(getResourceName());
+    newMesh->setResourcePath(getResourcePath());
+    return newMesh;
+}
+
+void Mesh::saveToFile(Polycode::CoreFile *outFile, bool writeNormals, bool writeTangents, bool writeColors, bool writeBoneWeights, bool writeUVs, bool writeSecondaryUVs) const {
+    
+    if(submeshes.size() == 0) {
+        return;
+    }
+    
+    // new mesh format
+    // IMPORTANT: PolyRendererVertexType type defines mesh format internal type. Consider making floats always. Don't want to cast for now.
+    
+    const char headerTag[] = "MSH2";
+    outFile->write(headerTag, 1, 4);
+    
+    unsigned char meshFlags = 0;
+    
+    if(submeshes[0]->indexedMesh) {
+        meshFlags |= 1 << 0;
+    }
+    
+    outFile->write(&meshFlags, sizeof(unsigned char), 1);
+    
+    writeVertexBlock(submeshes[0]->vertexPositionArray, outFile);
+    
+    if(submeshes[0]->indexedMesh) {
+        writeIndexBlock(submeshes[0]->indexArray, outFile);
+    }
+    
+    if(writeColors) {
+        writeVertexBlock(submeshes[0]->vertexColorArray, outFile);
+    }
+    
+    if(writeNormals) {
+        writeVertexBlock(submeshes[0]->vertexNormalArray, outFile);
+    }
+    
+    if(writeUVs) {
+        writeVertexBlock(submeshes[0]->vertexTexCoordArray, outFile);
+    }
+    
+    if(writeSecondaryUVs) {
+        writeVertexBlock(submeshes[0]->vertexTexCoord2Array, outFile);
+    }
+    
+    if(writeTangents) {
+        writeVertexBlock(submeshes[0]->vertexTangentArray, outFile);
+    }
+    
+    if(writeBoneWeights) {
+        writeVertexBlock(submeshes[0]->vertexBoneWeightArray, outFile);
+        writeVertexBlock(submeshes[0]->vertexBoneIndexArray, outFile);
+    }
+}
+
+void Mesh::loadFromFile(Polycode::CoreFile *inFile) {
+    clearMesh();
+    
+    char tag[4];
+    inFile->read(tag, 1, 4);
+    
+    if(tag[0] == 'M' && tag[1] == 'S' && tag[2] == 'H' && tag[3] == '2') {
+        loadFromFileV2(inFile);
+    } else {
+        inFile->seek(0, SEEK_SET);
+        loadFromFileLegacyV1(inFile);
+    }
+}
+
+void Mesh::saveToFile(const String& fileName, bool writeNormals, bool writeTangents, bool writeColors, bool writeBoneWeights, bool writeUVs, bool writeSecondaryUVs) {
+    CoreFile *outFile = Services()->getCore()->openFile(fileName, "wb");
+    if(!outFile) {
+        Logger::log("Error opening mesh file for saving: %s\n", fileName.c_str());
+        return;
+    }
+    saveToFile(outFile, writeNormals, writeTangents, writeColors, writeBoneWeights, writeUVs, writeSecondaryUVs);
+    Services()->getCore()->closeFile(outFile);
+    
+}
+
+void Mesh::loadMesh(const String& fileName) {
+    CoreFile *inFile = Services()->getCore()->openFile(fileName, "rb");
+    if(!inFile) {
+        Logger::log("Error opening mesh file %s\n", fileName.c_str());
+        return;
+    }
+    loadFromFile(inFile);
+    Services()->getCore()->closeFile(inFile);
+}
+
+void Mesh::addSubmesh(const MeshGeometry &newSubmesh) {
+    std::shared_ptr<MeshGeometry> _newSubMesh  = std::make_shared<MeshGeometry>();
+    (*_newSubMesh) = newSubmesh;
+    submeshes.push_back(_newSubMesh);
+    submeshes[submeshes.size()-1]->dataChanged = true;
+}
+
+void Mesh::removeSubmeshAtIndex(unsigned int index) {
+    if(index < submeshes.size()) {
+        submeshes.erase(submeshes.begin()+index);
+    }
+}
+
+void Mesh::clearMesh() {
+    submeshes.clear();
+}
+
+std::shared_ptr<MeshGeometry> Mesh::getSubmeshPointer(unsigned int index) {
+    if(index < submeshes.size()) {
+        return submeshes[index];
+    } else {
+        return NULL;
+    }
+}
+
+MeshGeometry Mesh::getSubmeshAtIndex(unsigned int index) const {
+    MeshGeometry retGeom;
+    if(index < submeshes.size()) {
+        retGeom = *(submeshes[index]);
+    }
+    return retGeom;
+}
+
+Number Mesh::getRadius() {
+    Number radius = 0.0;
+    for(int i = 0; i < submeshes.size(); i++) {
+        Number newRadius = submeshes[i]->getRadius();
+        if(newRadius > radius) {
+            radius = newRadius;
+        }
+    }
+    return radius;
+}
+
+void Mesh::loadFromFileV2(Polycode::CoreFile *inFile) {
+    
+    MeshGeometry newSubmesh;
+    
+    unsigned char meshFlags;
+    inFile->read(&meshFlags, sizeof(unsigned char), 1);
+    
+    newSubmesh.indexedMesh = meshFlags & (1 << 0);
+    
+    char blockType;
+    unsigned int blockSize;
+    while(inFile->read(&blockType, sizeof(unsigned char), 1)) {
+        inFile->read(&blockSize, sizeof(unsigned int), 1);
+        
+        switch(blockType) {
+            case RenderDataArray::VERTEX_DATA_ARRAY:
+                newSubmesh.vertexPositionArray.data.resize(blockSize);
+                inFile->read(&newSubmesh.vertexPositionArray.data[0], sizeof(PolyRendererVertexType), blockSize);
+                break;
+            case RenderDataArray::TEXCOORD_DATA_ARRAY:
+                newSubmesh.vertexTexCoordArray.data.resize(blockSize);
+                inFile->read(&newSubmesh.vertexTexCoordArray.data[0], sizeof(PolyRendererVertexType), blockSize);
+                break;
+            case RenderDataArray::NORMAL_DATA_ARRAY:
+                newSubmesh.vertexNormalArray.data.resize(blockSize);
+                inFile->read(&newSubmesh.vertexNormalArray.data[0], sizeof(PolyRendererVertexType), blockSize);
+                break;
+            case RenderDataArray::COLOR_DATA_ARRAY:
+                newSubmesh.vertexColorArray.data.resize(blockSize);
+                inFile->read(&newSubmesh.vertexColorArray.data[0], sizeof(PolyRendererVertexType), blockSize);
+                break;
+            case RenderDataArray::TANGENT_DATA_ARRAY:
+                newSubmesh.vertexTangentArray.data.resize(blockSize);
+                inFile->read(&newSubmesh.vertexTangentArray.data[0], sizeof(PolyRendererVertexType), blockSize);
+                break;
+            case RenderDataArray::BONE_WEIGHT_DATA_ARRAY:
+                newSubmesh.vertexBoneWeightArray.data.resize(blockSize);
+                inFile->read(&newSubmesh.vertexBoneWeightArray.data[0], sizeof(PolyRendererVertexType), blockSize);
+                break;
+            case RenderDataArray::INDEX_DATA_ARRAY:
+                newSubmesh.indexArray.data.resize(blockSize);
+                inFile->read(&newSubmesh.indexArray.data[0], sizeof(PolyRendererIndexType), blockSize);
+                break;
+            case RenderDataArray::BONE_INDEX_DATA_ARRAY:
+                newSubmesh.vertexBoneIndexArray.data.resize(blockSize);
+                inFile->read(&newSubmesh.vertexBoneIndexArray.data[0], sizeof(PolyRendererVertexType), blockSize);
+                break;
+        }
+    }
+    
+    if(newSubmesh.vertexBoneIndexArray.getDataSize() > 0) {
+        newSubmesh.normalizeBoneWeights();
+    }
+    
+    addSubmesh(newSubmesh);
+}
+
+void Mesh::loadFromFileLegacyV1(Polycode::CoreFile *inFile) {
+    
+    MeshGeometry newSubmesh;
+    
+    unsigned char meshFlags;
+    inFile->read(&meshFlags, sizeof(unsigned char), 1);
+    
+    newSubmesh.indexedMesh = meshFlags & (1 << 0);
+    bool hasNormals = meshFlags & (1 << 1);
+    bool hasTangents = meshFlags & (1 << 2);
+    bool hasColors = meshFlags & (1 << 3);
+    bool hasUV = meshFlags & (1 << 4);
+    bool hasSecondaryUVs = meshFlags & (1 << 5);
+    bool hasBoneWeights = meshFlags & (1 << 6);
+    
+    unsigned int meshType;
+    inFile->read(&meshType, sizeof(unsigned int), 1);
+    newSubmesh.setMeshType(meshType);
+    
+    unsigned int numVertices;
+    inFile->read(&numVertices, sizeof(unsigned int), 1);
+    
+    Vector3_struct pos;
+    Vector3_struct nor;
+    Vector3_struct tan;
+    Vector4_struct col;
+    Vector2_struct tex;
+    
+    for(int i=0; i < numVertices; i++) {
+        inFile->read(&pos, sizeof(Vector3_struct), 1);
+        
+        newSubmesh.vertexPositionArray.data.push_back(pos.x);
+        newSubmesh.vertexPositionArray.data.push_back(pos.y);
+        newSubmesh.vertexPositionArray.data.push_back(pos.z);
+        
+        if(hasNormals) {
+            inFile->read(&nor, sizeof(Vector3_struct), 1);
+            
+            newSubmesh.vertexNormalArray.data.push_back(nor.x);
+            newSubmesh.vertexNormalArray.data.push_back(nor.y);
+            newSubmesh.vertexNormalArray.data.push_back(nor.z);
+            
+            
+        }
+        if(hasTangents) {
+            inFile->read(&tan, sizeof(Vector3_struct), 1);
+            
+            newSubmesh.vertexTangentArray.data.push_back(tan.x);
+            newSubmesh.vertexTangentArray.data.push_back(tan.y);
+            newSubmesh.vertexTangentArray.data.push_back(tan.z);
+            
+        }
+        
+        if(hasColors) {
+            inFile->read(&col, sizeof(Vector4_struct), 1);
+            
+            newSubmesh.vertexColorArray.data.push_back(col.x);
+            newSubmesh.vertexColorArray.data.push_back(col.y);
+            newSubmesh.vertexColorArray.data.push_back(col.z);
+            newSubmesh.vertexColorArray.data.push_back(col.w);
+        }
+        
+        if(hasUV) {
+            inFile->read(&tex, sizeof(Vector2_struct), 1);
+            newSubmesh.vertexTexCoordArray.data.push_back(tex.x);
+            newSubmesh.vertexTexCoordArray.data.push_back(tex.y);
+        }
+        
+        if(hasSecondaryUVs) {
+            inFile->read(&tex, sizeof(Vector2_struct), 1);
+            newSubmesh.vertexTexCoord2Array.data.push_back(tex.x);
+            newSubmesh.vertexTexCoord2Array.data.push_back(tex.x);
+        }
+        
+        if(hasBoneWeights) {
+            unsigned int numBoneWeights;
+            inFile->read(&numBoneWeights, sizeof(unsigned int), 1);
+            
+            Number totalWeight = 0;
+            int numPushed = 0;
+            
+            for(int b=0; b < numBoneWeights; b++) {
+                float weight;
+                unsigned int boneID;
+                inFile->read(&boneID, sizeof(unsigned int), 1);
+                inFile->read(&weight, sizeof(float), 1);
+                
+                if(b < 4) {
+                    newSubmesh.vertexBoneWeightArray.data.push_back(weight);
+                    newSubmesh.vertexBoneIndexArray.data.push_back(boneID);
+                    numPushed++;
+                }
+                totalWeight += weight;
+            }
+            
+            if(numPushed < 4) {
+                for(int b=numPushed; b < 4; b++) {
+                    newSubmesh.vertexBoneWeightArray.data.push_back(0.0);
+                    newSubmesh.vertexBoneIndexArray.data.push_back(0.0);
+                }
+            }
+            
+            for(int m=0; m < 4; m++) {
+                newSubmesh.vertexBoneWeightArray.data[newSubmesh.vertexBoneWeightArray.data.size()-1-m] = newSubmesh.vertexBoneWeightArray.data[newSubmesh.vertexBoneWeightArray.data.size()-1-m] / totalWeight;
+            }
+        }
+    }
+    
+    if(newSubmesh.indexedMesh) {
+        unsigned int numIndices;
+        inFile->read(&numIndices, sizeof(unsigned int), 1);
+        unsigned int val;
+        for(int i=0; i < numIndices; i++) {
+            inFile->read(&val, sizeof(unsigned int), 1);
+            newSubmesh.indexArray.data.push_back(val);
+        }
+    }
+    
+    addSubmesh(newSubmesh);
+}

+ 165 - 81
src/core/PolyOpenGLGraphicsInterface.cpp

@@ -191,7 +191,33 @@ void OpenGLGraphicsInterface::setParamInShader(Shader *shader, ProgramParam *par
     }
 }
 
-void OpenGLGraphicsInterface::createVBOForVertexArray(VertexDataArray *array) {
+void OpenGLGraphicsInterface::destroyBuffer(RenderDataArray *array) {
+    if(array->platformData) {
+        GLuint vboID = *((GLuint*)array->platformData);
+        glDeleteBuffers(1, &vboID);
+        delete ((GLuint*)array->platformData);
+        array->platformData = NULL;
+    }
+}
+
+void OpenGLGraphicsInterface::createIndexBuffer(IndexDataArray *dataArray) {
+    destroyBuffer(dataArray);
+    
+    if(dataArray->getDataSize() == 0) {
+        return;
+    }
+    
+    GLuint bufferID;
+    glGenBuffers(1, &bufferID);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferID);
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, dataArray->getDataSize() * sizeof(PolyRendererIndexType), dataArray->getArrayData(), GL_STATIC_DRAW);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+    dataArray->platformData = (void*)(new GLuint);
+    *((GLuint*)dataArray->platformData) = bufferID;
+}
+
+void OpenGLGraphicsInterface::createVertexBuffer(VertexDataArray *array) {
+    destroyBuffer(array);
     if(array->getDataSize() == 0) {
         return;
     }
@@ -199,25 +225,107 @@ void OpenGLGraphicsInterface::createVBOForVertexArray(VertexDataArray *array) {
     glGenBuffers(1, &bufferID);
     glBindBuffer(GL_ARRAY_BUFFER, bufferID);
     glBufferData(GL_ARRAY_BUFFER, array->getDataSize() * sizeof(PolyRendererVertexType), array->getArrayData(), GL_STATIC_DRAW);
-    array->hasVBO = true;
-    array->platformData = (void*) malloc(sizeof(GLuint));
+    array->platformData = (void*)(new GLuint);
     *((GLuint*)array->platformData) = bufferID;
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
 }
 
-void OpenGLGraphicsInterface::createMesh(Mesh *mesh) {
-    createVBOForVertexArray(&mesh->vertexPositionArray);
-    createVBOForVertexArray(&mesh->vertexTexCoordArray);
-    createVBOForVertexArray(&mesh->vertexNormalArray);
-    createVBOForVertexArray(&mesh->vertexColorArray);
-    createVBOForVertexArray(&mesh->vertexTangentArray);
-    createVBOForVertexArray(&mesh->vertexBoneIndexArray);
-    createVBOForVertexArray(&mesh->vertexBoneWeightArray);
-    createVBOForVertexArray(&mesh->vertexTexCoord2Array);
-    createVBOForVertexArray(&mesh->vertexBoneIndexArray);
+void OpenGLGraphicsInterface::createSubmeshBuffers(MeshGeometry *submesh) {
+    createVertexBuffer(&submesh->vertexPositionArray);
+    createVertexBuffer(&submesh->vertexTexCoordArray);
+    createVertexBuffer(&submesh->vertexNormalArray);
+    createVertexBuffer(&submesh->vertexColorArray);
+    createVertexBuffer(&submesh->vertexTangentArray);
+    createVertexBuffer(&submesh->vertexBoneIndexArray);
+    createVertexBuffer(&submesh->vertexBoneWeightArray);
+    createVertexBuffer(&submesh->vertexTexCoord2Array);
+    createVertexBuffer(&submesh->vertexBoneIndexArray);
+    createVertexBuffer(&submesh->customVertexArray1);
+    createVertexBuffer(&submesh->customVertexArray2);
+    createVertexBuffer(&submesh->customVertexArray3);
+    createVertexBuffer(&submesh->customVertexArray4);
+    createIndexBuffer(&submesh->indexArray);
 }
 
-void OpenGLGraphicsInterface::destroyMesh(Mesh *mesh) {
+void OpenGLGraphicsInterface::destroySubmeshBufferData(void *platformData) {
+    GLuint vboID = *((GLuint*)platformData);
+    glDeleteBuffers(1, &vboID);
+    delete ((GLuint*)platformData);
+}
+
+void OpenGLGraphicsInterface::drawSubmeshBuffers(MeshGeometry *submesh, Shader *shader) {
+    
+    static std::vector<int> enabledAttributes;
+    enabledAttributes.reserve(16);
     
+    for(int i=0; i < shader->expectedAttributes.size(); i++) {
+        VertexDataArray *targetArray = NULL;
+        switch(shader->expectedAttributes[i].arrayType) {
+            case RenderDataArray::VERTEX_DATA_ARRAY:
+                targetArray = &submesh->vertexPositionArray;
+            break;
+            case RenderDataArray::NORMAL_DATA_ARRAY:
+                targetArray = &submesh->vertexNormalArray;
+            break;
+            case RenderDataArray::TEXCOORD_DATA_ARRAY:
+                targetArray = &submesh->vertexTexCoordArray;
+            break;
+            case RenderDataArray::TEXCOORD2_DATA_ARRAY:
+                targetArray = &submesh->vertexTexCoord2Array;
+            break;
+            case RenderDataArray::BONE_INDEX_DATA_ARRAY:
+                targetArray = &submesh->vertexBoneIndexArray;
+            break;
+            case RenderDataArray::BONE_WEIGHT_DATA_ARRAY:
+                targetArray = &submesh->vertexBoneWeightArray;
+            break;
+            case RenderDataArray::TANGENT_DATA_ARRAY:
+                targetArray = &submesh->vertexTangentArray;
+            break;
+            case RenderDataArray::COLOR_DATA_ARRAY:
+                targetArray = &submesh->vertexColorArray;
+            break;
+            case RenderDataArray::CUSTOM_DATA_ARRAY1:
+                targetArray = &submesh->customVertexArray1;
+            break;
+            case RenderDataArray::CUSTOM_DATA_ARRAY2:
+                targetArray = &submesh->customVertexArray2;
+            break;
+            case RenderDataArray::CUSTOM_DATA_ARRAY3:
+                targetArray = &submesh->customVertexArray3;
+               break;
+            case RenderDataArray::CUSTOM_DATA_ARRAY4:
+                targetArray = &submesh->customVertexArray4;
+            break;
+        }
+        
+        if(targetArray) {
+            if(targetArray->platformData) {
+                int bufferIndex = *((GLuint*)targetArray->platformData);
+                int attributeLocation = *((GLuint*)shader->expectedAttributes[i].platformData);
+                glBindBuffer(GL_ARRAY_BUFFER, bufferIndex);
+                glVertexAttribPointer(attributeLocation, targetArray->getCountPerVertex(), GL_FLOAT, GL_FALSE, 0, NULL);
+                glEnableVertexAttribArray(attributeLocation);
+                enabledAttributes.push_back(attributeLocation);
+                glBindBuffer(GL_ARRAY_BUFFER, 0);
+            }
+        }
+    }
+    
+    if(submesh->indexedMesh) {
+        if(submesh->indexArray.platformData) {
+           glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, *((GLuint*)submesh->indexArray.platformData));
+           glDrawElements(getGLDrawMode(submesh->meshType), submesh->indexArray.getDataSize(), GL_UNSIGNED_INT, NULL);
+           glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0);
+        }
+    } else {
+        glDrawArrays(getGLDrawMode(submesh->meshType), 0, submesh->getVertexCount());
+    }
+    
+    for(int i=0; i < enabledAttributes.size(); i++) {
+        glDisableVertexAttribArray(enabledAttributes[i]);
+    }
+    enabledAttributes.clear();
 }
 
 void OpenGLGraphicsInterface::setBlendingMode(unsigned int blendingMode) {
@@ -277,7 +385,7 @@ void OpenGLGraphicsInterface::useShader(Shader *shader) {
 void OpenGLGraphicsInterface::setAttributeInShader(Shader *shader, ProgramAttribute *attribute, AttributeBinding *attributeBinding) {
     GLuint attribLocation = *((GLuint*) attribute->platformData);
     
-    if(attributeBinding->vertexData->hasVBO) {
+    if(attributeBinding->vertexData->platformData) {
         GLuint bufferID = *((GLuint*) attributeBinding->vertexData->platformData);
         glBindBuffer(GL_ARRAY_BUFFER, bufferID);
         glVertexAttribPointer(attribLocation, attributeBinding->vertexData->countPerVertex, GL_FLOAT, false, 0, NULL);
@@ -319,25 +427,25 @@ void OpenGLGraphicsInterface::setWireframeMode(bool val) {
 
 GLenum OpenGLGraphicsInterface::getGLDrawMode(int polycodeMode) {
     switch(polycodeMode) {
-        case Mesh::POINT_MESH:
+        case MeshGeometry::POINT_MESH:
             return GL_POINTS;
         break;
-        case Mesh::LINE_STRIP_MESH:
+        case MeshGeometry::LINE_STRIP_MESH:
             return GL_LINE_STRIP;
         break;
-        case Mesh::LINE_LOOP_MESH:
+        case MeshGeometry::LINE_LOOP_MESH:
             return GL_LINE_LOOP;
         break;
-        case Mesh::LINE_MESH:
+        case MeshGeometry::LINE_MESH:
             return GL_LINES;
         break;
-        case Mesh::TRISTRIP_MESH:
+        case MeshGeometry::TRISTRIP_MESH:
             return GL_TRIANGLE_STRIP;
         break;
-        case Mesh::TRIFAN_MESH:
+        case MeshGeometry::TRIFAN_MESH:
             return GL_TRIANGLE_FAN;
         break;
-        case Mesh::TRI_MESH:
+        case MeshGeometry::TRI_MESH:
             return GL_TRIANGLES;
         break;
     }
@@ -345,21 +453,6 @@ GLenum OpenGLGraphicsInterface::getGLDrawMode(int polycodeMode) {
     return GL_TRIANGLES;
 }
 
-void OpenGLGraphicsInterface::drawIndices(int type, IndexDataArray *indexArray) {
-    if(indexArray->hasVBO) {
-        GLuint bufferID = *((GLuint*) indexArray->platformData);
-        glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, bufferID);
-        glDrawElements(getGLDrawMode(type), indexArray->data.size(), GL_UNSIGNED_INT, NULL);
-        glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0);
-    } else {
-     glDrawElements(getGLDrawMode(type), indexArray->data.size(), GL_UNSIGNED_INT, indexArray->data.data());
-    }
-}
-
-void OpenGLGraphicsInterface::drawArrays(int type, unsigned int vertexCount) {
-    glDrawArrays(getGLDrawMode(type), 0, vertexCount);
-}
-
 void OpenGLGraphicsInterface::createRenderBuffer(RenderBuffer *renderBuffer) {
     if(!renderBuffer->platformData) {
         renderBuffer->platformData = (void*) new GLuint;
@@ -620,48 +713,6 @@ void OpenGLGraphicsInterface::createProgram(ShaderProgram *program) {
     *((GLuint*)program->platformData) = programID;
 }
 
-void OpenGLGraphicsInterface::destroyBuffer(RenderDataArray *array) {
-    if(array->hasVBO) {
-        GLuint vboID = *((GLuint*)array->platformData);
-        glDeleteBuffers(1, &vboID);
-        delete (GLuint*)array->platformData;
-    }
-}
-
-void OpenGLGraphicsInterface::createVertexBuffer(VertexDataArray *dataArray) {
-    if(dataArray->hasVBO) {
-        GLuint vboID = *((GLuint*)dataArray->platformData);
-        glDeleteBuffers(1, &vboID);
-    } else {
-        dataArray->platformData = (new GLuint);
-    }
-    
-    GLuint bufferID;
-    glGenBuffers(1, &bufferID);
-    glBindBuffer(GL_ARRAY_BUFFER, bufferID);
-    glBufferData(GL_ARRAY_BUFFER, dataArray->getDataSize() * sizeof(PolyRendererVertexType), dataArray->getArrayData(), GL_STATIC_DRAW);
-    glBindBuffer(GL_ARRAY_BUFFER, 0);
-    dataArray->hasVBO = true;
-    *((GLuint*)dataArray->platformData) = bufferID;
-}
-
-void OpenGLGraphicsInterface::createIndexBuffer(IndexDataArray *dataArray) {
-
-    if(dataArray->hasVBO) {
-        // delete vbo
-    } else {
-        dataArray->platformData = (new GLuint);
-    }
-    
-    GLuint bufferID;
-    glGenBuffers(1, &bufferID);
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferID);
-    glBufferData(GL_ELEMENT_ARRAY_BUFFER, dataArray->getDataSize() * sizeof(PolyRendererIndexType), dataArray->getArrayData(), GL_STATIC_DRAW);
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-    dataArray->hasVBO = true;
-    *((GLuint*)dataArray->platformData) = bufferID;
-}
-
 void OpenGLGraphicsInterface::destroyShader(Shader *shader) {
     if(shader->platformData) {
         GLuint shaderID = *((GLuint*)shader->platformData);
@@ -744,12 +795,45 @@ void OpenGLGraphicsInterface::createShader(Shader *shader) {
         attribute.platformData = (void*) new GLuint;
         *((GLuint*)attribute.platformData) = attribLocation;
         attribute.size = getAttributeSize(type);
+        attribute.arrayType = mapNameToArrayType(attribute.name);
+        
+        attribute.platformData = (void*) new GLuint;
+        *((GLuint*)attribute.platformData) = glGetAttribLocation(shaderID, attribute.name.c_str());
+        
+        
         shader->expectedAttributes.push_back(attribute);
     }
     
-    
      *((GLuint*)shader->platformData) = shaderID;
-    
+}
+
+int OpenGLGraphicsInterface::mapNameToArrayType(const String &name) {
+    if(name == "position") {
+        return RenderDataArray::VERTEX_DATA_ARRAY;
+    } else if(name == "normal") {
+        return RenderDataArray::NORMAL_DATA_ARRAY;
+    } else if(name == "texCoord") {
+        return RenderDataArray::TEXCOORD_DATA_ARRAY;
+    } else if(name == "color") {
+        return RenderDataArray::COLOR_DATA_ARRAY;
+    } else if(name == "tangent") {
+        return RenderDataArray::TANGENT_DATA_ARRAY;
+    } else if(name == "texCoord2") {
+        return RenderDataArray::TEXCOORD2_DATA_ARRAY;
+    } else if(name == "boneWeights") {
+        return RenderDataArray::BONE_WEIGHT_DATA_ARRAY;
+    } else if(name == "boneIndices") {
+        return RenderDataArray::BONE_INDEX_DATA_ARRAY;
+    } else if(name == "customData1") {
+        return RenderDataArray::CUSTOM_DATA_ARRAY1;
+    } else if(name == "customData2") {
+        return RenderDataArray::CUSTOM_DATA_ARRAY2;
+    } else if(name == "customData3") {
+        return RenderDataArray::CUSTOM_DATA_ARRAY3;
+    } else if(name == "customData4") {
+        return RenderDataArray::CUSTOM_DATA_ARRAY4;
+    }
+    return RenderDataArray::UNKNOWN_DATA_ARRAY;
 }
 
 void OpenGLGraphicsInterface::enableBackfaceCulling(bool val) {

+ 44 - 42
src/core/PolyParticleEmitter.cpp

@@ -28,7 +28,7 @@
 
 using namespace Polycode;
 
-SceneParticleEmitter::SceneParticleEmitter(unsigned int particleCount, Number lifetime, Number speed) : SceneMesh(Mesh::POINT_MESH), particleCount(particleCount), particleSpeed(speed), lifetime(lifetime), directionVector(0.0, 1.0, 0.0), useFloorPlane(false), floorPlaneOffset(-1.0), floorDamping(0.5), particlesInWorldSpace(false), perlinEnabled(false), perlinValue(1.0,1.0,1.0), particleType(SceneParticleEmitter::PARTICLE_TYPE_QUAD), particleSize(0.1), particleRotationSpeed(0.0, 0.0, 0.0), useColorCurves(false), useScaleCurve(false), loopParticles(true){
+SceneParticleEmitter::SceneParticleEmitter(unsigned int particleCount, Number lifetime, Number speed) : particleCount(particleCount), particleSpeed(speed), lifetime(lifetime), directionVector(0.0, 1.0, 0.0), useFloorPlane(false), floorPlaneOffset(-1.0), floorDamping(0.5), particlesInWorldSpace(false), perlinEnabled(false), perlinValue(1.0,1.0,1.0), particleType(SceneParticleEmitter::PARTICLE_TYPE_QUAD), particleSize(0.1), particleRotationSpeed(0.0, 0.0, 0.0), useColorCurves(false), useScaleCurve(false), loopParticles(true){
     
     core = CoreServices::getInstance()->getCore();
     motionPerlin = new Perlin(3,5,1.0,RANDOM_NUMBER);
@@ -202,13 +202,13 @@ void SceneParticleEmitter::enableParticleSystem(bool val) {
 }
 
 void SceneParticleEmitter::rebuildParticles(GPUDrawBuffer *buffer) {
-    mesh->clearMesh();
     Matrix4 inverseMatrix = systemTrasnformMatrix.Inverse();
     
+    MeshGeometry geometry;
     switch(particleType) {
         case PARTICLE_TYPE_POINT:
         {
-            mesh->setMeshType(Mesh::POINT_MESH);
+            geometry.setMeshType(MeshGeometry::POINT_MESH);
             for(int i=0; i < particles.size(); i++) {
                 if(particles[i].lifetime > lifetime || particles[i].lifetime < 0.0) {
                     continue;
@@ -217,9 +217,9 @@ void SceneParticleEmitter::rebuildParticles(GPUDrawBuffer *buffer) {
                 if(particlesInWorldSpace) {
                     vertexPosition = inverseMatrix * vertexPosition;
                 }
-                mesh->addVertexWithUV(vertexPosition.x, vertexPosition.y, vertexPosition.z, 0.5, 0.5);
-                mesh->addColor(particles[i].color);
-                mesh->indexedMesh = false;
+                geometry.addVertexWithUV(vertexPosition.x, vertexPosition.y, vertexPosition.z, 0.5, 0.5);
+                geometry.addColor(particles[i].color);
+                geometry.indexedMesh = false;
             }
         }
         break;
@@ -244,74 +244,74 @@ void SceneParticleEmitter::rebuildParticles(GPUDrawBuffer *buffer) {
                 }
                 
                 if(particleType == PARTICLE_TYPE_MESH) {
-                    mesh->setMeshType(Mesh::TRI_MESH);
+                    geometry.setMeshType(MeshGeometry::TRI_MESH);
                     
                     int indexOffset = 0;
 
-					mesh->indexedMesh = true;
+					geometry.indexedMesh = true;
                     
                     int meshIndex = particles[i].varianceIndex;
                     if(meshIndex < sourceMeshes.size()) {
                         
-						indexOffset = mesh->vertexPositionArray.data.size()/3;
-                        
-						Mesh *sourceMesh = sourceMeshes[meshIndex];
-
-						mesh->setMeshType(sourceMesh->getMeshType());
-
-                        for(int v=0; v <  sourceMesh->getVertexCount(); v++) {
-                           
-							Vector3 vpos = Vector3(sourceMesh->vertexPositionArray.data[(v * 3)], sourceMesh->vertexPositionArray.data[(v * 3)+1], sourceMesh->vertexPositionArray.data[(v * 3)+2]) * finalParticleSize;
-                            vpos = q.applyTo(vpos);
+						indexOffset = geometry.vertexPositionArray.data.size()/3;
+                        if(sourceMeshes[meshIndex]->getNumSubmeshes() > 0) {
+                            std::shared_ptr<MeshGeometry> sourceMesh = sourceMeshes[meshIndex]->getSubmeshPointer(0);
+                            geometry.setMeshType(sourceMesh->getMeshType());
+
+                            for(int v=0; v < sourceMesh->getVertexCount(); v++) {
+                               
+                                Vector3 vpos = Vector3(sourceMesh->vertexPositionArray.data[(v * 3)], sourceMesh->vertexPositionArray.data[(v * 3)+1], sourceMesh->vertexPositionArray.data[(v * 3)+2]) * finalParticleSize;
+                                vpos = q.applyTo(vpos);
+                                
+                                vpos += particlePosition;
+                                geometry.addVertex(vpos.x, vpos.y, vpos.z);
+                                geometry.addTexCoord(sourceMesh->vertexTexCoordArray.data[(v * 2)], sourceMesh->vertexTexCoordArray.data[(v * 2) + 1]);
+                                geometry.addColor(vertexColor);
+                                Vector3 svNormal = Vector3(sourceMesh->vertexNormalArray.data[(v * 3)], sourceMesh->vertexNormalArray.data[(v * 3) + 1], sourceMesh->vertexNormalArray.data[(v * 3) + 2]);
+                                svNormal = q.applyTo(svNormal);
+                                geometry.addNormal(svNormal.x, svNormal.y, svNormal.z);
+                            }
                             
-                            vpos += particlePosition;
-							mesh->addVertex(vpos.x, vpos.y, vpos.z);
-							mesh->addTexCoord(sourceMesh->vertexTexCoordArray.data[(v * 2)], sourceMesh->vertexTexCoordArray.data[(v * 2) + 1]);
-							mesh->addColor(vertexColor);
-							Vector3 svNormal = Vector3(sourceMesh->vertexNormalArray.data[(v * 3)], sourceMesh->vertexNormalArray.data[(v * 3) + 1], sourceMesh->vertexNormalArray.data[(v * 3) + 2]);
-							svNormal = q.applyTo(svNormal);
-							mesh->addNormal(svNormal.x, svNormal.y, svNormal.z);
+                            for (int v = 0; v < sourceMesh->indexArray.data.size(); v++) {
+                                geometry.addIndex(indexOffset + sourceMesh->indexArray.data[v]);
+                            }
                         }
                         
-						for (int v = 0; v < sourceMesh->indexArray.data.size(); v++) {
-							mesh->addIndex(indexOffset + sourceMesh->indexArray.data[v]);
-                        }
-                         
                     }
                     
                 } else {
-                    mesh->setMeshType(Mesh::TRI_MESH);
-                    mesh->indexedMesh = true;
+                    geometry.setMeshType(MeshGeometry::TRI_MESH);
+                    geometry.indexedMesh = true;
                     
-                    int vertexCount = mesh->getVertexCount();
+                    int vertexCount = geometry.getVertexCount();
                     
                     Vector3 vertexPosition = Vector3(-finalParticleSize, -finalParticleSize, 0.0);
                     vertexPosition = q.applyTo(vertexPosition);
                     vertexPosition = buffer->cameraMatrix.rotateVector(vertexPosition);
-                    mesh->addVertexWithUV(particlePosition.x+vertexPosition.x, particlePosition.y+vertexPosition.y, particlePosition.z+vertexPosition.z, 0.0, 0.0);
-                    mesh->addColor(vertexColor);
+                    geometry.addVertexWithUV(particlePosition.x+vertexPosition.x, particlePosition.y+vertexPosition.y, particlePosition.z+vertexPosition.z, 0.0, 0.0);
+                    geometry.addColor(vertexColor);
                     
                     vertexPosition = Vector3(finalParticleSize, -finalParticleSize, 0.0);
                     vertexPosition = q.applyTo(vertexPosition);
                     vertexPosition = buffer->cameraMatrix.rotateVector(vertexPosition);
-                    mesh->addVertexWithUV(particlePosition.x+vertexPosition.x, particlePosition.y+vertexPosition.y, particlePosition.z+vertexPosition.z, 1.0, 0.0);
-                    mesh->addColor(vertexColor);
+                    geometry.addVertexWithUV(particlePosition.x+vertexPosition.x, particlePosition.y+vertexPosition.y, particlePosition.z+vertexPosition.z, 1.0, 0.0);
+                    geometry.addColor(vertexColor);
 
                     vertexPosition = Vector3(finalParticleSize, finalParticleSize, 0.0);
                     vertexPosition = q.applyTo(vertexPosition);
                     vertexPosition = buffer->cameraMatrix.rotateVector(vertexPosition);
-                    mesh->addVertexWithUV(particlePosition.x+vertexPosition.x, particlePosition.y+vertexPosition.y, particlePosition.z+vertexPosition.z, 1.0, 1.0);
-                    mesh->addColor(vertexColor);
+                    geometry.addVertexWithUV(particlePosition.x+vertexPosition.x, particlePosition.y+vertexPosition.y, particlePosition.z+vertexPosition.z, 1.0, 1.0);
+                    geometry.addColor(vertexColor);
 
                     vertexPosition = Vector3(-finalParticleSize, finalParticleSize, 0.0);
                     vertexPosition = q.applyTo(vertexPosition);
                     vertexPosition = buffer->cameraMatrix.rotateVector(vertexPosition);
-                    mesh->addVertexWithUV(particlePosition.x+vertexPosition.x, particlePosition.y+vertexPosition.y, particlePosition.z+vertexPosition.z, 0.0, 1.0);
-                    mesh->addColor(vertexColor);
+                    geometry.addVertexWithUV(particlePosition.x+vertexPosition.x, particlePosition.y+vertexPosition.y, particlePosition.z+vertexPosition.z, 0.0, 1.0);
+                    geometry.addColor(vertexColor);
                     
 
-                    mesh->addIndexedFace(vertexCount, vertexCount+1, vertexCount+2);
-                    mesh->addIndexedFace(vertexCount, vertexCount+2, vertexCount+3);
+                    geometry.addIndexedFace(vertexCount, vertexCount+1, vertexCount+2);
+                    geometry.addIndexedFace(vertexCount, vertexCount+2, vertexCount+3);
                 }
 
             }
@@ -319,6 +319,8 @@ void SceneParticleEmitter::rebuildParticles(GPUDrawBuffer *buffer) {
             break;
             
     }
+    mesh->clearMesh();    
+    mesh->addSubmesh(geometry);
 }
 
 unsigned int SceneParticleEmitter::getParticleCount() const {

+ 39 - 8
src/core/PolyRenderDataArray.cpp

@@ -24,34 +24,65 @@
 
 using namespace Polycode;
 
-RenderDataArray::RenderDataArray(unsigned int type) : type(type), hasVBO(false), platformData(NULL) {
+RenderDataArray::RenderDataArray(unsigned int type) : type(type), platformData(NULL) {
 }
 
-void *RenderDataArray::getArrayData() {
+RenderDataArray::RenderDataArray(const RenderDataArray &other) : platformData(NULL) {
+    type = other.type;
+    customArrayName = other.customArrayName;
+}
+
+RenderDataArray &RenderDataArray::operator=(const RenderDataArray &other) {
+    type = other.type;
+    return *this;
+}
+
+void *RenderDataArray::getArrayData()  const{
     return NULL;
 }
 
-unsigned int RenderDataArray::getDataSize() {
+unsigned int RenderDataArray::getDataSize() const {
     return 0;
 }
 
-void *VertexDataArray::getArrayData() {
+VertexDataArray::VertexDataArray(const VertexDataArray &other) : RenderDataArray(other) {
+    countPerVertex = other.countPerVertex;
+    data = other.data;
+}
+
+VertexDataArray &VertexDataArray::operator=(const VertexDataArray &other) {
+    data = other.data;
+    countPerVertex = other.countPerVertex;
+    RenderDataArray::operator=(other);
+    return *this;
+}
+
+void *VertexDataArray::getArrayData() const {
     return (void*) data.data();
 }
 
-unsigned int VertexDataArray::getDataSize() {
+unsigned int VertexDataArray::getDataSize()  const{
     return data.size();
 }
 
+IndexDataArray &IndexDataArray::operator=(const IndexDataArray &other) {
+    data = other.data;
+    RenderDataArray::operator=(other);
+    return *this;
+}
+
+IndexDataArray::IndexDataArray(const IndexDataArray &other) : RenderDataArray(other) {
+    data = other.data;
+}
 
-void *IndexDataArray::getArrayData() {
+void *IndexDataArray::getArrayData() const {
     return (void*) data.data();
 }
 
-unsigned int IndexDataArray::getDataSize() {
+unsigned int IndexDataArray::getDataSize()  const {
     return data.size();
 }
 
-unsigned char VertexDataArray::getCountPerVertex() {
+unsigned char VertexDataArray::getCountPerVertex() const {
     return countPerVertex;
 }

+ 38 - 119
src/core/PolyRenderer.cpp

@@ -33,8 +33,7 @@ GraphicsInterface::GraphicsInterface() {
 }
 
 RenderThread::RenderThread() : graphicsInterface(NULL) {
-    
-    
+        
     jobQueueMutex = Services()->getCore()->createMutex();
     renderMutex = Services()->getCore()->createMutex();
 }
@@ -71,11 +70,11 @@ void RenderThread::initGlobals() {
 
 void RenderThread::runThread() {
     
-        initGlobals();
+    initGlobals();
     
-       while(threadRunning) {
+    while(threadRunning) {
         
-        Services()->getCore()->lockMutex(jobQueueMutex);
+        jobQueueMutex->lock();
         
         while(jobQueue.size() > 0) {
             RendererThreadJob nextJob = jobQueue.front();
@@ -89,7 +88,7 @@ void RenderThread::runThread() {
             frameQueue.pop();
         }
 
-        Services()->getCore()->unlockMutex(jobQueueMutex);
+        jobQueueMutex->unlock();
 
         if(nextFrame) {
             while(nextFrame->jobQueue.size() > 0) {
@@ -106,21 +105,7 @@ ShaderBinding *RenderThread::getShaderBinding() {
     return rendererShaderBinding;
 }
 
-void RenderThread::processDrawBuffer(GPUDrawBuffer *buffer) {
-    
-    ++currentDebugFrameInfo.buffersProcessed;
-    
-    if(buffer->targetFramebuffer) {
-        graphicsInterface->bindRenderBuffer(buffer->targetFramebuffer);
-    }
-    
-    graphicsInterface->setViewport(buffer->viewport.x, buffer->viewport.y, buffer->viewport.w, buffer->viewport.h);
-    graphicsInterface->clearBuffers(buffer->clearColor, buffer->clearColorBuffer, buffer->clearDepthBuffer, true);
-    
-    projectionMatrixParam->setMatrix4(buffer->projectionMatrix);
-    viewMatrixParam->setMatrix4(buffer->viewMatrix);
-
-    
+void RenderThread::processDrawBufferLights(GPUDrawBuffer *buffer) {
     int lightShadowIndex = 0;
     
     for(int i=0; i <RENDERER_MAX_LIGHTS; i++) {
@@ -162,12 +147,33 @@ void RenderThread::processDrawBuffer(GPUDrawBuffer *buffer) {
             lights[i].constantAttenuation->setNumber(1.0);
             lights[i].linearAttenuation->setNumber(1.0);
             lights[i].quadraticAttenuation->setNumber(1.0);
-
+            
         }
     }
+}
+
+void RenderThread::processDrawBuffer(GPUDrawBuffer *buffer) {
+    
+    ++currentDebugFrameInfo.buffersProcessed;
+    
+    if(buffer->targetFramebuffer) {
+        graphicsInterface->bindRenderBuffer(buffer->targetFramebuffer);
+    }
+    
+    graphicsInterface->setViewport(buffer->viewport.x, buffer->viewport.y, buffer->viewport.w, buffer->viewport.h);
+    graphicsInterface->clearBuffers(buffer->clearColor, buffer->clearColorBuffer, buffer->clearDepthBuffer, true);
+    
+    projectionMatrixParam->setMatrix4(buffer->projectionMatrix);
+    viewMatrixParam->setMatrix4(buffer->viewMatrix);
+
+    processDrawBufferLights(buffer);
     
     for(int i=0; i < buffer->drawCalls.size(); i++) {
         
+        if(!buffer->drawCalls[i].submesh) {
+            continue;
+        }
+        
         if(buffer->drawCalls[i].options.enableScissor) {
             graphicsInterface->enableScissor(true);
             Polycode::Rectangle scissorBox = buffer->drawCalls[i].options.scissorBox;
@@ -211,20 +217,18 @@ void RenderThread::processDrawBuffer(GPUDrawBuffer *buffer) {
                 ShaderPass shaderPass;
 
                 shaderPass = buffer->drawCalls[i].shaderPasses[s];
-                //graphicsInterface->setBlendingMode(shaderPass.blendingMode);
                 
                 ShaderBinding *localShaderBinding = buffer->drawCalls[i].shaderPasses[s].shaderBinding;
                 ShaderBinding *materialShaderBinding = shaderPass.materialShaderBinding;
                 
                 
-                if(buffer->globalMaterial) {
+                if(buffer->globalMaterial && !buffer->drawCalls[i].options.forceMaterial) {
                     if(s < buffer->globalMaterial->getNumShaderPasses()) {
                         shaderPass = buffer->globalMaterial->getShaderPass(s);
                         localShaderBinding = shaderPass.shaderBinding;
                     }
                 }
                 
-
                 if(!shaderPass.shader || !localShaderBinding) {
                     continue;
                 }
@@ -260,24 +264,11 @@ void RenderThread::processDrawBuffer(GPUDrawBuffer *buffer) {
                     materialShaderBinding->accessMutex->unlock();
                 }
                 
-                bool rebindAttributes = false;
-                
-                // TODO: this is a slow solution
-                
-                if(buffer->globalMaterial) {
-                    rebindAttributes = true;
-                }
-                
-                if(buffer->drawCalls[i].shaderPasses[s].shaderBinding->targetShader != shaderPass.shader) {
-                    buffer->drawCalls[i].shaderPasses[s].shaderBinding->targetShader = shaderPass.shader;
-                    rebindAttributes = true;
-                }
-                
                 localShaderBinding->accessMutex->lock();
                 for(int p=0; p < localShaderBinding->getNumLocalParams(); p++) {
                     LocalShaderParam *localParam = localShaderBinding->getLocalParam(p);
                     if(localParam) {
-                        if(!localParam->param || rebindAttributes) {
+                        if(!localParam->param) {
                             localParam->param = shaderPass.shader->getParamPointer(localParam->name);
                         }
                         if(localParam->param) {
@@ -286,52 +277,12 @@ void RenderThread::processDrawBuffer(GPUDrawBuffer *buffer) {
                     }
                 }
                 localShaderBinding->accessMutex->unlock();
-
-                if(rebindAttributes || localShaderBinding->resetAttributes ) {
-                    buffer->drawCalls[i].shaderPasses[s].setExpectedAttributes();
-                    localShaderBinding->resetAttributes = false;
-                }
-
-                for(int a=0; a < buffer->drawCalls[i].shaderPasses[s].shaderBinding->getNumAttributeBindings(); a++) {
-
-                    AttributeBinding *attributeBinding = buffer->drawCalls[i].shaderPasses[s].shaderBinding->getAttributeBinding(a);
-                    
-                    if(attributeBinding) {
-                        if(attributeBinding->enabled  || rebindAttributes) {
-                            
-                            if(rebindAttributes) {
-                                attributeBinding->attribute = NULL;
-                                attributeBinding->enabled = true;
-                            }
-                            
-                            if(!attributeBinding->attribute) {
-                                attributeBinding->attribute = shaderPass.shader->getAttribPointer(attributeBinding->name);
-                            }
-                            
-                            if(attributeBinding->attribute) {
-                                attributeBinding->enabled = true;
-                                if(attributeBinding->vertexData->data.size() / attributeBinding->vertexData->countPerVertex >= buffer->drawCalls[i].mesh->getVertexCount()) {
-                                    
-                                    graphicsInterface->setAttributeInShader(shaderPass.shader, attributeBinding->attribute, attributeBinding);
-                                }
-                            } else {
-                                attributeBinding->enabled = false;
-                            }
-                        }
-                    }
-                }
                 
-                if(buffer->drawCalls[i].mesh->indexedMesh) {
-                    graphicsInterface->drawIndices(buffer->drawCalls[i].mesh->getMeshType(), &buffer->drawCalls[i].mesh->indexArray);
-                } else {
-                    graphicsInterface->drawArrays(buffer->drawCalls[i].mesh->getMeshType(), buffer->drawCalls[i].mesh->getVertexCount());
-                }
-
-                for(int a=0; a < shaderPass.shader->expectedAttributes.size(); a++) {
-                    ProgramAttribute attribute = shaderPass.shader->expectedAttributes[a];
-                    graphicsInterface->disableAttribute(shaderPass.shader, attribute);
+                if(buffer->drawCalls[i].submesh->dataChanged) {
+                    graphicsInterface->createSubmeshBuffers(&*buffer->drawCalls[i].submesh);
+                    buffer->drawCalls[i].submesh->dataChanged = false;
                 }
-                
+                graphicsInterface->drawSubmeshBuffers(&*buffer->drawCalls[i].submesh, shaderPass.shader);
                 graphicsInterface->endDrawCall();
             }
         }
@@ -463,27 +414,9 @@ void RenderThread::processJob(const RendererThreadJob &job) {
             shader->reloadResource();
         }
         break;
-        case JOB_CREATE_VERTEX_BUFFERS:
-        {
-            Mesh *mesh = (Mesh*) job.data;
-            
-            graphicsInterface->createVertexBuffer(&mesh->vertexPositionArray);
-            graphicsInterface->createVertexBuffer(&mesh->vertexTexCoordArray);
-            if(mesh->indexedMesh) {
-                graphicsInterface->createIndexBuffer(&mesh->indexArray);
-            }
-        }
-        break;
-        case JOB_CREATE_MESH:
+        case JOB_DESTROY_SUBMESH_BUFFER:
         {
-            Mesh *mesh = (Mesh*) job.data;
-            graphicsInterface->createMesh(mesh);
-        }
-        break;
-        case JOB_DESTROY_MESH:
-        {
-            Mesh *mesh = (Mesh*) job.data;
-            graphicsInterface->destroyMesh(mesh);
+            graphicsInterface->destroySubmeshBufferData(job.data);
         }
         break;
             
@@ -637,10 +570,6 @@ ShaderProgram *Renderer::createProgram(const String &fileName) {
     return program;
 }
 
-void Renderer::createVertexBuffers(Mesh *mesh) {
-    renderThread->enqueueJob(RenderThread::JOB_CREATE_VERTEX_BUFFERS, (void*) mesh);
-}
-
 void Renderer::destroyTexture(Texture *texture) {
     renderThread->enqueueJob(RenderThread::JOB_DESTROY_TEXTURE, (void*)texture);
 }
@@ -665,8 +594,8 @@ void Renderer::destroyShader(Shader *shader) {
     renderThread->enqueueJob(RenderThread::JOB_DESTROY_SHADER, (void*)shader);
 }
 
-void Renderer::destroyBuffer(RenderDataArray *array) {
-     renderThread->enqueueJob(RenderThread::JOB_DESTROY_BUFFER, (void*)array);
+void Renderer::destroySubmeshPlatformData(void *platformData) {
+     renderThread->enqueueJob(RenderThread::JOB_DESTROY_SUBMESH_BUFFER, platformData);
 }
 
 Vector3 Renderer::project(const Vector3 &position, const Matrix4 &modelMatrix, const Matrix4 &projectionMatrix, const Polycode::Rectangle &viewport) {
@@ -691,16 +620,6 @@ Vector3 Renderer::project(const Vector3 &position, const Matrix4 &modelMatrix, c
     return Vector3(in.x, in.y, in.z);
 }
 
-Mesh *Renderer::createMesh(const String &fileName) {
-    Mesh *mesh = new Mesh(fileName);
-    renderThread->enqueueJob(RenderThread::JOB_CREATE_MESH, (void*)mesh);
-    return mesh;
-}
-
-void Renderer::destroyMesh(Mesh *mesh) {
-    renderThread->enqueueJob(RenderThread::JOB_DESTROY_MESH, (void*)mesh);
-}
-
 Vector3 Renderer::unProject(const Vector3 &position, const Matrix4 &modelMatrix, const Matrix4 &projectionMatrix, const Polycode::Rectangle &viewport) {
 
     Matrix4 finalMatrix = modelMatrix * projectionMatrix;

+ 1 - 1
src/core/PolyResourceManager.cpp

@@ -619,7 +619,7 @@ MeshResourceLoader::MeshResourceLoader() {
 }
 
 Resource *MeshResourceLoader::loadResource(const String &path, ResourcePool *targetPool) {
-    Mesh *mesh = Services()->getRenderer()->createMesh(path);
+    Mesh *mesh = new Mesh(path);
     return mesh;
 }
 

+ 16 - 17
src/core/PolySceneImage.cpp

@@ -109,29 +109,28 @@ void SceneImage::setImageCoordinates(Number x, Number y, Number width, Number he
 	Number wFloat = width * pixelSizeX;
 	Number hFloat = height * pixelSizeY;
 
-	mesh->vertexPositionArray.data.clear();
-	mesh->vertexTexCoordArray.data.clear();
-    mesh->indexArray.data.clear();
+    mesh->clearMesh();
+    MeshGeometry geometry;
     
-    mesh->indexedMesh = true;
+    geometry.indexedMesh = true;
 
-	mesh->setMeshType(Mesh::TRI_MESH);
+	geometry.setMeshType(MeshGeometry::TRI_MESH);
+	geometry.addVertex(0 - whalf, 0 - hhalf, 0);
+	geometry.addTexCoord(xFloat, (1.0 - yFloat) - hFloat);
 
-	mesh->addVertex(0 - whalf, 0 - hhalf, 0);
-	mesh->addTexCoord(xFloat, (1.0 - yFloat) - hFloat);
+	geometry.addVertex(realWidth - whalf, 0 - hhalf, 0);
+	geometry.addTexCoord(xFloat + wFloat, (1.0 - yFloat) - hFloat);
 
-	mesh->addVertex(realWidth - whalf, 0 - hhalf, 0);
-	mesh->addTexCoord(xFloat + wFloat, (1.0 - yFloat) - hFloat);
-
-	mesh->addVertex(realWidth - whalf, realHeight - hhalf, 0);
-	mesh->addTexCoord(xFloat + wFloat, 1.0 - yFloat);
-
-	mesh->addVertex(0 - whalf, realHeight - hhalf, 0);
-	mesh->addTexCoord(xFloat, 1.0 - yFloat);
+	geometry.addVertex(realWidth - whalf, realHeight - hhalf, 0);
+	geometry.addTexCoord(xFloat + wFloat, 1.0 - yFloat);
 
+	geometry.addVertex(0 - whalf, realHeight - hhalf, 0);
+	geometry.addTexCoord(xFloat, 1.0 - yFloat);
+    
+    geometry.addIndexedFace(0, 1, 2);
+    geometry.addIndexedFace(0, 2, 3);
     
-    mesh->addIndexedFace(0, 1, 2);
-    mesh->addIndexedFace(0, 2, 3);
+    mesh->addSubmesh(geometry);
     
 	rebuildTransformMatrix();
 	matrixDirty = true;

+ 24 - 14
src/core/PolySceneLine.cpp

@@ -28,13 +28,13 @@ using namespace Polycode;
 using std::min;
 using std::max;
 
-SceneCurve::SceneCurve() : SceneMesh(Mesh::LINE_STRIP_MESH) {
+SceneCurve::SceneCurve() : SceneMesh() {
     curveResolution = 256;
     renderCurve = true;
     curve = new BezierCurve();
 }
 
-SceneCurve::SceneCurve(BezierCurve *curve) : SceneMesh(Mesh::LINE_STRIP_MESH) {
+SceneCurve::SceneCurve(BezierCurve *curve) : SceneMesh() {
     curveResolution = 256;
     renderCurve = true;
     this->curve = curve;
@@ -83,13 +83,14 @@ void SceneCurve::Update() {
     mesh->clearMesh();
     Vector3 bBox;
     
+    MeshGeometry geometry;
+    geometry.meshType = MeshGeometry::LINE_STRIP_MESH;
     if(renderCurve) {
-
         Number step = (1.0 / ((Number)curveResolution));
         
         for(Number offset=0.0; offset <= 1.0; offset += step) {
             Vector3 pt = curve->getPointAt(offset);
-            mesh->addVertexWithUV(pt.x, pt.y, pt.z, offset, 0.0);
+            geometry.addVertexWithUV(pt.x, pt.y, pt.z, offset, 0.0);
             
             bBox.x = max(bBox.x,(Number)fabs(pt.x));
             bBox.y = max(bBox.y,(Number)fabs(pt.y));
@@ -98,10 +99,12 @@ void SceneCurve::Update() {
         }
     }
     
+    mesh->addSubmesh(geometry);
+    
     setLocalBoundingBox(bBox * 2.0);
 }
 
-SceneLine::SceneLine(Vector3 startp, Vector3 endp) : SceneMesh(Mesh::LINE_MESH) {
+SceneLine::SceneLine(Vector3 startp, Vector3 endp) : SceneMesh() {
 	this->ent1 = NULL;
 	this->ent2 = NULL;
 	this->start = start;
@@ -110,7 +113,7 @@ SceneLine::SceneLine(Vector3 startp, Vector3 endp) : SceneMesh(Mesh::LINE_MESH)
 	ignoreParentMatrix = false;
 }
 
-SceneLine::SceneLine(Entity *ent1, Entity *ent2) : SceneMesh(Mesh::LINE_MESH) {
+SceneLine::SceneLine(Entity *ent1, Entity *ent2) : SceneMesh() {
 	this->ent1 = ent1;
 	this->ent2 = ent2;	
 	initLine();
@@ -119,8 +122,12 @@ SceneLine::SceneLine(Entity *ent1, Entity *ent2) : SceneMesh(Mesh::LINE_MESH) {
 }
 
 void SceneLine::initLine() {
-	mesh->addVertexWithUV(0,0,0,0,0);
-	mesh->addVertexWithUV(0,0,0,1,0);
+    mesh->clearMesh();
+    MeshGeometry geometry;
+    geometry.meshType = MeshGeometry::LINE_MESH;
+	geometry.addVertexWithUV(0,0,0,0,0);
+	geometry.addVertexWithUV(0,0,0,1,0);
+    mesh->addSubmesh(geometry);
 }
 
 SceneLine *SceneLine::SceneLineWithPositions(Vector3 startp, Vector3 endp) {
@@ -143,19 +150,22 @@ void SceneLine::Update(){
 	Vector3 v1;
 	Vector3 v2;
 
-    mesh->vertexPositionArray.data.clear();
-	
+    mesh->clearMesh();
+    MeshGeometry geometry;
+	geometry.meshType = MeshGeometry::LINE_MESH;
+    
 	if(ent1 != NULL && ent2 != NULL) {
 		v1 = ent1->getConcatenatedMatrix().getPosition();
 		v2 = ent2->getConcatenatedMatrix().getPosition();
         
-        mesh->addVertex(v1.x,v1.y,v1.z);
-        mesh->addVertex(v2.x,v2.y,v2.z);
+        geometry.addVertex(v1.x,v1.y,v1.z);
+        geometry.addVertex(v2.x,v2.y,v2.z);
 	} else {
 		v1 = start;
 		v2 = end;
-        mesh->addVertex(v1.x,v1.y*yAdjust,v1.z);
-        mesh->addVertex(v2.x,v2.y*yAdjust,v2.z);
+        geometry.addVertex(v1.x,v1.y*yAdjust,v1.z);
+        geometry.addVertex(v2.x,v2.y*yAdjust,v2.z);
 
 	}
+    mesh->addSubmesh(geometry);
 }

+ 62 - 70
src/core/PolySceneMesh.cpp

@@ -39,11 +39,23 @@ SceneMesh *SceneMesh::SceneMeshFromMesh(Mesh *mesh) {
 	return new SceneMesh(mesh);
 }
 
-SceneMesh *SceneMesh::SceneMeshWithType(int meshType) {
-	return new SceneMesh(meshType);
+SceneMesh::SceneMesh() : material(NULL), skeleton(NULL), skeletalVertexPositions(3, RenderDataArray::VERTEX_DATA_ARRAY), skeletalVertexNormals(3, RenderDataArray::NORMAL_DATA_ARRAY) { 
+    mesh = new Mesh();
+    setLocalBoundingBox(mesh->calculateBBox());
+    useVertexBuffer = false;
+    lineSmooth = false;
+    ownsMesh = true;
+    ownsSkeleton = true;
+    lineWidth = 1.0;
+    useGeometryHitDetection = false;
+    backfaceCulled = true;
+    alphaTest = false;
+    sendBoneMatricesToMaterial = false;
+    setMaterialByName("UnlitUntextured");
 }
 
-SceneMesh::SceneMesh(const String& fileName) : Entity(), material(NULL), skeleton(NULL), mesh(NULL), skeletalVertexPositions(3, RenderDataArray::VERTEX_DATA_ARRAY), skeletalVertexNormals(3, RenderDataArray::NORMAL_DATA_ARRAY) {
+
+SceneMesh::SceneMesh(const String& fileName) : material(NULL), skeleton(NULL), mesh(NULL), skeletalVertexPositions(3, RenderDataArray::VERTEX_DATA_ARRAY), skeletalVertexNormals(3, RenderDataArray::NORMAL_DATA_ARRAY) {
     loadFromFile(fileName);
 	useVertexBuffer = false;
 	lineSmooth = false;
@@ -57,7 +69,7 @@ SceneMesh::SceneMesh(const String& fileName) : Entity(), material(NULL), skeleto
     setMaterialByName("UnlitUntextured");
 }
 
-SceneMesh::SceneMesh(Mesh *mesh) : Entity(), material(NULL), skeleton(NULL), skeletalVertexPositions(3, RenderDataArray::VERTEX_DATA_ARRAY), skeletalVertexNormals(3, RenderDataArray::NORMAL_DATA_ARRAY) {
+SceneMesh::SceneMesh(Mesh *mesh) : material(NULL), skeleton(NULL), skeletalVertexPositions(3, RenderDataArray::VERTEX_DATA_ARRAY), skeletalVertexNormals(3, RenderDataArray::NORMAL_DATA_ARRAY) {
 	this->mesh = mesh;
 	setLocalBoundingBox(mesh->calculateBBox());
 	useVertexBuffer = false;
@@ -73,49 +85,18 @@ SceneMesh::SceneMesh(Mesh *mesh) : Entity(), material(NULL), skeleton(NULL), ske
     setMaterialByName("UnlitUntextured");
 }
 
-SceneMesh::SceneMesh(int meshType) : material(NULL), skeleton(NULL), skeletalVertexPositions(3, RenderDataArray::VERTEX_DATA_ARRAY), skeletalVertexNormals(3, RenderDataArray::NORMAL_DATA_ARRAY) {
-	mesh = new Mesh(meshType);
-	setLocalBoundingBox(mesh->calculateBBox());
-	useVertexBuffer = false;	
-	lineSmooth = false;
-	ownsMesh = true;
-	ownsSkeleton = true;	
-	lineWidth = 1.0;
-	useGeometryHitDetection = false;
-    backfaceCulled = true;
-	alphaTest = false;
-    sendBoneMatricesToMaterial = false;
-    setMaterialByName("UnlitUntextured");
-}
-
 void SceneMesh::setMesh(Mesh *mesh) {
-    if(this->mesh == mesh) {
-        return;
-    }
-    
 	this->mesh = mesh;
 	setLocalBoundingBox(mesh->calculateBBox());
 	useVertexBuffer = false;
-
-    rebuildAttributes();
-}
-
-void SceneMesh::rebuildAttributes() {
-    for(int i=0; i < shaderPasses.size(); i++) {
-        shaderPasses[i].setAttributeArraysFromMesh(mesh);
-        if(skeleton) {
-          //  shaderPasses[i].attributeArrays.push_back(&skeletalVertexPositions);
-          //  shaderPasses[i].attributeArrays.push_back(&skeletalVertexNormals);
-        }
-        shaderPasses[i].shaderBinding->resetAttributes = true;
-    }
 }
 
 SceneMesh::~SceneMesh() {
 	if(ownsSkeleton)
 		delete skeleton;
-	if(ownsMesh)
-		delete mesh;
+    if(ownsMesh) {
+        delete mesh;
+    }
     
     for(int i=0; i < shaderPasses.size(); i++)  {
         Services()->getRenderer()->destroyShaderBinding(shaderPasses[i].shaderBinding);
@@ -123,7 +104,7 @@ SceneMesh::~SceneMesh() {
 }
 
 Entity *SceneMesh::Clone(bool deepClone, bool ignoreEditorOnly) const {
-    SceneMesh *newEntity = new SceneMesh(mesh->getMeshType());
+    SceneMesh *newEntity = new SceneMesh();
     applyClone(newEntity, deepClone, ignoreEditorOnly);
     return newEntity;
 }
@@ -213,10 +194,9 @@ void SceneMesh::setMaterial(Material *material) {
         shaderPass.shaderBinding->targetShader = shaderPass.shader;
         shaderPass.shaderBinding->addParamPointer(ProgramParam::PARAM_COLOR, "entityColor", &color);
         shaderPass.shaderBinding->resetAttributes = true;
-        shaderPass.setAttributeArraysFromMesh(mesh);
         if(skeleton) {
-            shaderPass.attributeArrays.push_back(&skeletalVertexPositions);
-            shaderPass.attributeArrays.push_back(&skeletalVertexNormals);
+         //   shaderPass.attributeArrays.push_back(&skeletalVertexPositions);
+         //   shaderPass.attributeArrays.push_back(&skeletalVertexNormals);
         }
         shaderPasses.push_back(shaderPass);
     }    
@@ -258,7 +238,6 @@ Skeleton *SceneMesh::loadSkeleton(const String& fileName) {
 
 void SceneMesh::setSkeleton(Skeleton *skeleton) {
 	this->skeleton = skeleton;
-    rebuildAttributes();
 }
 
 void SceneMesh::setLineWidth(Number newWidth) {
@@ -283,25 +262,31 @@ bool SceneMesh::customHitDetection(const Ray &ray) {
 	transformedRay.origin = adjustedMatrix * ray.origin;
 	transformedRay.direction = adjustedMatrix.rotateVector(ray.direction);
 	
-    if(mesh->indexedMesh) {
-        for(int i=0; i < mesh->getIndexCount(); i+=3) {
-            if(i+2 < mesh->getIndexCount()) {
-                if(transformedRay.polygonIntersect(mesh->getVertexPositionAtIndex(i), mesh->getVertexPositionAtIndex(i+1), mesh->getVertexPositionAtIndex(i+2))) {
-                    return true;
+    if(mesh->getNumSubmeshes() == 0) {
+        return false;
+    }
+    
+    for(int m=0; m < mesh->getNumSubmeshes(); m++) {
+        std::shared_ptr<MeshGeometry> subMesh = mesh->getSubmeshPointer(m);
+        if(subMesh->indexedMesh) {
+            for(int i=0; i < subMesh->getIndexCount(); i+=3) {
+                if(i+2 < subMesh->getIndexCount()) {
+                    if(transformedRay.polygonIntersect(subMesh->getVertexPositionAtIndex(i), subMesh->getVertexPositionAtIndex(i+1), subMesh->getVertexPositionAtIndex(i+2))) {
+                        return true;
+                    }
                 }
             }
-        }
-        
-    } else {
-        for(int i=0; i < mesh->getVertexCount(); i+=3) {
-            if(i+2 < mesh->getVertexCount()) {
-               if(transformedRay.polygonIntersect(mesh->getVertexPosition(i), mesh->getVertexPosition(i+1), mesh->getVertexPosition(i+2))) {
-                    return true;
+            
+        } else {
+            for(int i=0; i < subMesh->getVertexCount(); i+=3) {
+                if(i+2 < subMesh->getVertexCount()) {
+                   if(transformedRay.polygonIntersect(subMesh->getVertexPosition(i), subMesh->getVertexPosition(i+1), subMesh->getVertexPosition(i+2))) {
+                        return true;
+                    }
                 }
             }
         }
     }
-
 	return false;
 }
 
@@ -317,6 +302,8 @@ void SceneMesh::applySkeletonLocally() {
     skeletalVertexPositions.data.clear();
     skeletalVertexNormals.data.clear();
     
+    // REDNERER_TODO: appply to submeshes
+    /*
     for(int i=0; i < mesh->vertexPositionArray.data.size()/3; i++) {
         
         Vector3 norm;
@@ -348,25 +335,30 @@ void SceneMesh::applySkeletonLocally() {
         skeletalVertexNormals.data.push_back(norm.y);
         skeletalVertexNormals.data.push_back(norm.z);
     }
+     */
 }
 
 void SceneMesh::Render(GPUDrawBuffer *buffer) {
-    
-    drawCall.options.alphaTest = alphaTest;
-    drawCall.options.linePointSize = lineWidth;
-    drawCall.options.backfaceCull = backfaceCulled;
-    drawCall.options.depthTest = depthTest;
-    drawCall.options.depthWrite = depthWrite;
-    
-    drawCall.mesh = mesh;
-    drawCall.material = material;
-    drawCall.shaderPasses = shaderPasses;
-    
-    if(skeleton) {
-        applySkeletonLocally();
+
+    if(!mesh) {
+        return;
     }
     
-    buffer->drawCalls.push_back(drawCall);
+    for(int i=0; i < mesh->getNumSubmeshes(); i++) {
+        drawCall.options.alphaTest = alphaTest;
+        drawCall.options.linePointSize = lineWidth;
+        drawCall.options.backfaceCull = backfaceCulled;
+        drawCall.options.depthTest = depthTest;
+        drawCall.options.depthWrite = depthWrite;
+        drawCall.submesh = mesh->getSubmeshPointer(i);        
+        drawCall.material = material;
+        drawCall.shaderPasses = shaderPasses;
+        if(skeleton) {
+            applySkeletonLocally();
+        }
+        
+        buffer->drawCalls.push_back(drawCall);
+    }
     
     // RENDERERTODO: FIX GPU SKINNING
     /*

+ 18 - 13
src/core/PolyScenePrimitive.cpp

@@ -25,7 +25,7 @@
 
 using namespace Polycode;
 
-ScenePrimitive::ScenePrimitive(int type, Number v1, Number v2, Number v3,Number v4,Number v5) : SceneMesh(Mesh::TRI_MESH) {
+ScenePrimitive::ScenePrimitive(int type, Number v1, Number v2, Number v3,Number v4,Number v5) : SceneMesh() {
 
 	this->type = type;
 	this->v1 = v1;
@@ -63,56 +63,61 @@ Number ScenePrimitive::getPrimitiveParameter5() const {
 
 void ScenePrimitive::recreatePrimitive() {
 	mesh->clearMesh();
+    MeshGeometry geometry;
+
 	switch(type) {
 		case TYPE_PLANE:
-			mesh->createPlane(v1, v2, v3);
+			geometry.createPlane(v1, v2, v3);
             setLocalBoundingBox(v1, 0.001, v2);
 		break;
 		case TYPE_VPLANE:
-			mesh->createVPlane(v1, v2, v3);
+			geometry.createVPlane(v1, v2, v3);
             setLocalBoundingBox(v1, v2, 0.001);
 		break;
 		case TYPE_BOX:
-			mesh->createBox(v1, v2, v3, v4);
+			geometry.createBox(v1, v2, v3, v4);
             setLocalBoundingBox(v1, v2, v3);
 		break;
 		case TYPE_SPHERE:
-			mesh->createSphere(v1, v2, v3, v4);
+			geometry.createSphere(v1, v2, v3, v4);
             setLocalBoundingBox(v1*2, v1*2, v1*2);
 		break;
 		case TYPE_CYLINDER:
-			mesh->createCylinder(v1, v2, v3, true, v4);
+			geometry.createCylinder(v1, v2, v3, true, v4);
             setLocalBoundingBox(v2*2, v1, v2*2);
 		break;
 		case TYPE_UNCAPPED_CYLINDER:
-			mesh->createCylinder(v1, v2, v3, false, v5);
+			geometry.createCylinder(v1, v2, v3, false, v5);
             setLocalBoundingBox(v2*2, v1, v2*2);
 		break;
 		case TYPE_CONE:
-			mesh->createCone(v1, v2, v3, v4);
+			geometry.createCone(v1, v2, v3, v4);
             setLocalBoundingBox(v2*2, v1, v2*2);
 		break;
 		case TYPE_TORUS:
-			mesh->createTorus(v1, v2, v3, v4, v5);
+			geometry.createTorus(v1, v2, v3, v4, v5);
             setLocalBoundingBox((v1*2) + (v2*2), v2 * 2, (v1*2) + (v2*2));
 		break;
 		case TYPE_CIRCLE:
-			mesh->createCircle(v1, v2, v3, v4);
+			geometry.createCircle(v1, v2, v3, v4);
             setLocalBoundingBox(v1, v2, 0.001);
 		break;
 		case TYPE_LINE_CIRCLE:
-			mesh->createLineCircle(v1, v2, v3, v4);
+			geometry.createLineCircle(v1, v2, v3, v4);
+            geometry.meshType = MeshGeometry::LINE_LOOP_MESH;
             setLocalBoundingBox(v1, v2, 0.001);
         break;
 		case TYPE_ICOSPHERE:
-			mesh->createIcosphere(v1, v2);
+			geometry.createIcosphere(v1, v2);
             setLocalBoundingBox(v1*2, v1*2, v1*2);
         break;
 		case TYPE_OCTOSPHERE:
-			mesh->createOctosphere(v1, v2);
+			geometry.createOctosphere(v1, v2);
             setLocalBoundingBox(v1*2, v1*2, v1*2);
         break;
 	}
+    
+    mesh->addSubmesh(geometry);
 }
 
 Entity *ScenePrimitive::Clone(bool deepClone, bool ignoreEditorOnly) const {

+ 13 - 10
src/core/PolySceneSprite.cpp

@@ -31,7 +31,7 @@ using std::vector;
 using namespace Polycode;
 
 
-SceneSprite::SceneSprite(SpriteSet *spriteSet) : SceneMesh(Mesh::TRI_MESH) {
+SceneSprite::SceneSprite(SpriteSet *spriteSet) : SceneMesh() {
     setMaterialByName("Unlit");    
     currentSprite = NULL;
     currentSpriteState = NULL;
@@ -377,10 +377,11 @@ void SpriteState::rebuildStateMeshes() {
     largestFrameBoundingBox = Vector3();
     
     for(int i=0; i < frameIDs.size(); i++) {
-        Mesh *frameMesh = new Mesh(Mesh::TRI_MESH);
+        Mesh *frameMesh = new Mesh();
         SpriteFrame frame = spriteSet->getSpriteFrameByID(frameIDs[i]);
         
-        frameMesh->indexedMesh = true;
+        MeshGeometry geometry;
+        geometry.indexedMesh = true;
         
         Number aspectRatio = frame.coordinates.w / frame.coordinates.h;
         Number textureAspectRatio = ((Number)spriteSet->getTexture()->getWidth()) / ((Number)spriteSet->getTexture()->getHeight());
@@ -399,15 +400,15 @@ void SpriteState::rebuildStateMeshes() {
         meshOffset.x -= frameWidth * frame.anchorPoint.x;
         meshOffset.y += frameHeight * frame.anchorPoint.y;
         
-        frameMesh->addVertexWithUVAndNormal(meshOffset.x+-frameWidth*0.5, meshOffset.y+frameHeight*0.5, 0.0, frame.coordinates.x, 1.0-frame.coordinates.y, 0.0, 0.0, 1.0);
-        frameMesh->addVertexWithUVAndNormal(meshOffset.x+-frameWidth*0.5, meshOffset.y+frameHeight*0.5-frameHeight, 0.0, frame.coordinates.x, 1.0-frame.coordinates.y  - frame.coordinates.h, 0.0, 0.0, 1.0);
-        frameMesh->addVertexWithUVAndNormal(meshOffset.x+-frameWidth*0.5+frameWidth, meshOffset.y+frameHeight*0.5-frameHeight, 0.0, frame.coordinates.x+frame.coordinates.w, 1.0- frame.coordinates.y  - frame.coordinates.h, 0.0, 0.0, 1.0);
-        frameMesh->addVertexWithUVAndNormal(meshOffset.x+-frameWidth*0.5+frameWidth, meshOffset.y+frameHeight*0.5, 0.0, frame.coordinates.x+frame.coordinates.w, 1.0-frame.coordinates.y, 0.0, 0.0, 1.0);
+        geometry.addVertexWithUVAndNormal(meshOffset.x+-frameWidth*0.5, meshOffset.y+frameHeight*0.5, 0.0, frame.coordinates.x, 1.0-frame.coordinates.y, 0.0, 0.0, 1.0);
+        geometry.addVertexWithUVAndNormal(meshOffset.x+-frameWidth*0.5, meshOffset.y+frameHeight*0.5-frameHeight, 0.0, frame.coordinates.x, 1.0-frame.coordinates.y  - frame.coordinates.h, 0.0, 0.0, 1.0);
+        geometry.addVertexWithUVAndNormal(meshOffset.x+-frameWidth*0.5+frameWidth, meshOffset.y+frameHeight*0.5-frameHeight, 0.0, frame.coordinates.x+frame.coordinates.w, 1.0- frame.coordinates.y  - frame.coordinates.h, 0.0, 0.0, 1.0);
+        geometry.addVertexWithUVAndNormal(meshOffset.x+-frameWidth*0.5+frameWidth, meshOffset.y+frameHeight*0.5, 0.0, frame.coordinates.x+frame.coordinates.w, 1.0-frame.coordinates.y, 0.0, 0.0, 1.0);
         
         
         for(int j=0; j < 4; j++) {
 
-            Vector3 vertex(frameMesh->vertexPositionArray.data[j], frameMesh->vertexPositionArray.data[j+1], frameMesh->vertexPositionArray.data[j+2]);
+            Vector3 vertex(geometry.vertexPositionArray.data[j], geometry.vertexPositionArray.data[j+1], geometry.vertexPositionArray.data[j+2]);
             
             Number val = fabs(vertex.x);
             if(val > largestFrameBoundingBox.x) {
@@ -423,8 +424,10 @@ void SpriteState::rebuildStateMeshes() {
             }
         }
         
-        frameMesh->addIndexedFace(0, 1, 2);
-        frameMesh->addIndexedFace(0, 2, 3);
+        geometry.addIndexedFace(0, 1, 2);
+        geometry.addIndexedFace(0, 2, 3);
+        
+        frameMesh->addSubmesh(geometry);
         
         frameMeshes.push_back(frameMesh);
     }

+ 9 - 9
src/ide/EditorGrid.cpp

@@ -99,7 +99,7 @@ EditorGrid::EditorGrid() : Entity() {
 	grid = NULL;
     gridMode = GRID_MODE_3D;
     
-    Mesh *gridMesh = new Mesh(Mesh::LINE_MESH);
+    Mesh *gridMesh = new Mesh();
     
     grid = new SceneMesh(gridMesh);
     grid->setForceMaterial(true);
@@ -190,16 +190,19 @@ void EditorGrid::rebuildGrid() {
     }
     
     grid->getMesh()->clearMesh();
+    MeshGeometry geometry;
+    geometry.meshType = MeshGeometry::LINE_MESH;
 
     for(int x=0; x < gridLen+1; x++) {
-        grid->getMesh()->addVertex((-gridSize * gridLen * 0.5) + (x * gridSize), (-gridSize * gridLen * 0.5), 0);
-        grid->getMesh()->addVertex((-gridSize * gridLen * 0.5) + (x * gridSize) , (-gridSize * gridLen * 0.5) + (gridSize * gridLen), 0);
+        geometry.addVertex((-gridSize * gridLen * 0.5) + (x * gridSize), (-gridSize * gridLen * 0.5), 0);
+        geometry.addVertex((-gridSize * gridLen * 0.5) + (x * gridSize) , (-gridSize * gridLen * 0.5) + (gridSize * gridLen), 0);
     }
     
     for(int y=0; y < gridLen+1; y++) {
-        grid->getMesh()->addVertex((-gridSize * gridLen * 0.5), (-gridSize * gridLen * 0.5) + (y * gridSize), 0);
-        grid->getMesh()->addVertex((-gridSize * gridLen * 0.5) + (gridSize * gridLen), (-gridSize * gridLen * 0.5) + (y * gridSize), 0);
+        geometry.addVertex((-gridSize * gridLen * 0.5), (-gridSize * gridLen * 0.5) + (y * gridSize), 0);
+        geometry.addVertex((-gridSize * gridLen * 0.5) + (gridSize * gridLen), (-gridSize * gridLen * 0.5) + (y * gridSize), 0);
     }
+    grid->getMesh()->addSubmesh(geometry);
     
     yLine->setStart(Vector3(0.0, gridSize * gridLen * 0.5, 0.0));
     yLine->setEnd(Vector3(0.0, gridSize * gridLen * -0.5, 0.0));
@@ -210,10 +213,7 @@ void EditorGrid::rebuildGrid() {
     zLine->setStart(Vector3(0.0, 0.0, gridSize * gridLen * 0.5));
     zLine->setEnd(Vector3(0.0, 0.0, gridSize * gridLen * -0.5));
     
-    grid->setLocalBoundingBox(grid->getMesh()->calculateBBox());
-    
-    // RENDERER_TODO
-//    grid->cacheToVertexBuffer(true);
+    grid->setLocalBoundingBox(grid->getMesh()->calculateBBox());    
 }
 
 void EditorGrid::setGridMode(int mode) {

+ 80 - 57
src/ide/PolycodeEntityEditor.cpp

@@ -95,29 +95,27 @@ CurveDisplay::CurveDisplay(Scene *parentScene, SceneCurve *curve) : DummyTargetE
     propertyEntity = curve;
     colorAffectsChildren = false;
     
-    controlPointLines = new SceneMesh(Mesh::LINE_MESH);
+    controlPointLines = new SceneMesh();
     controlPointLines->setColor(1.0, 1.0, 0.4, 1.0);
     addChild(controlPointLines);
     controlPointLines->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
     controlPointLines->setForceMaterial(true);
    
-    mainPoints = new SceneMesh(Mesh::POINT_MESH);
+    mainPoints = new SceneMesh();
     mainPoints->setColor(0.0, 0.5, 1.0, 1.0);
     addChild(mainPoints);
     mainPoints->pointSmooth = true;
     mainPoints->setForceMaterial(true);
     mainPoints->setMaterialByName("UnlitPointUntextured");
     mainPoints->getShaderPass(0).shaderBinding->addParam(ProgramParam::PARAM_NUMBER, "pointSize")->setNumber(10.0);
-    mainPoints->getMesh()->indexedMesh = false;
     
-    controlPoints = new SceneMesh(Mesh::POINT_MESH);
+    controlPoints = new SceneMesh();
     controlPoints->setColor(1.0, 0.7, 0.0, 1.0);
     addChild(controlPoints);
     controlPoints->pointSmooth = true;
     controlPoints->setForceMaterial(true);
     controlPoints->setMaterialByName("UnlitPointUntextured");
     controlPoints->getShaderPass(0).shaderBinding->addParam(ProgramParam::PARAM_NUMBER, "pointSize")->setNumber(8.0);
-    controlPoints->getMesh()->indexedMesh = false;
     
     renderControlPoints = false;
     
@@ -256,27 +254,39 @@ void CurveDisplay::Update() {
     controlPoints->getMesh()->clearMesh();
     controlPointLines->getMesh()->clearMesh();
     
+    MeshGeometry mainPointsGeometry;
+    mainPointsGeometry.meshType = MeshGeometry::POINT_MESH;
+    
+    MeshGeometry controlPointsGeometry;
+    controlPointsGeometry.meshType = MeshGeometry::POINT_MESH;
+    
+    MeshGeometry controlPointLinesGeometry;
+    controlPointLinesGeometry.meshType = MeshGeometry::LINE_MESH;
+    
     for(int i=0; i < curve->getCurve()->getNumControlPoints(); i++) {
         
         Vector3 pt2 = curve->getCurve()->getControlPoint(i)->p2;
-        mainPoints->getMesh()->addVertex(pt2.x, pt2.y, pt2.z);
+        mainPointsGeometry.addVertex(pt2.x, pt2.y, pt2.z);
         
         if(renderControlPoints) {
             Vector3 pt1 = curve->getCurve()->getControlPoint(i)->p1;
-            controlPoints->getMesh()->addVertex(pt1.x, pt1.y, pt1.z);
+            controlPointsGeometry.addVertex(pt1.x, pt1.y, pt1.z);
             
             Vector3 pt3 = curve->getCurve()->getControlPoint(i)->p3;
-            controlPoints->getMesh()->addVertex(pt3.x, pt3.y, pt3.z);
-            
+            controlPointsGeometry.addVertex(pt3.x, pt3.y, pt3.z);
             
-            controlPointLines->getMesh()->addVertex(pt1.x, pt1.y, pt1.z);
-            controlPointLines->getMesh()->addVertex(pt2.x, pt2.y, pt2.z);
+            controlPointLinesGeometry.addVertex(pt1.x, pt1.y, pt1.z);
+            controlPointLinesGeometry.addVertex(pt2.x, pt2.y, pt2.z);
             
-            controlPointLines->getMesh()->addVertex(pt2.x, pt2.y, pt2.z);
-            controlPointLines->getMesh()->addVertex(pt3.x, pt3.y, pt3.z);
+            controlPointLinesGeometry.addVertex(pt2.x, pt2.y, pt2.z);
+            controlPointLinesGeometry.addVertex(pt3.x, pt3.y, pt3.z);
         }
     }
     
+    mainPoints->getMesh()->addSubmesh(mainPointsGeometry);
+    controlPoints->getMesh()->addSubmesh(controlPointsGeometry);
+    controlPointLines->getMesh()->addSubmesh(controlPointLinesGeometry);
+    
     mainPoints->setLocalBoundingBox(mainPoints->getMesh()->calculateBBox());
     controlPoints->setLocalBoundingBox(controlPoints->getMesh()->calculateBBox());
     controlPointLines->setLocalBoundingBox(controlPointLines->getMesh()->calculateBBox());
@@ -287,35 +297,36 @@ LightDisplay::LightDisplay(SceneLight *light) : Entity() {
     editorOnly = true;
     this->light = light;
     spotSpot = new ScenePrimitive(ScenePrimitive::TYPE_LINE_CIRCLE, 1.0, 1.0, 32);
-	spotSpot->getMesh()->setMeshType(Mesh::LINE_LOOP_MESH);
     addChild(spotSpot);
     spotSpot->setColor(1.0, 0.8, 0.0, 1.0);
     spotSpot->enabled = false;
     spotSpot->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
     spotSpot->setForceMaterial(true);
     
-    fovSceneMesh = new SceneMesh(Mesh::LINE_MESH);
+    fovSceneMesh = new SceneMesh();
     fovSceneMesh->setColor(1.0, 0.8, 0.0, 1.0);
     fovMesh = fovSceneMesh->getMesh();
-    fovMesh->indexedMesh = true;
     addChild(fovSceneMesh);
     fovSceneMesh->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
     fovSceneMesh->setForceMaterial(true);
     
-    fovMesh->addVertex(0.0, 0.0, 0.0);
+    MeshGeometry fovMeshGeometry;
+    fovMeshGeometry.setMeshType(MeshGeometry::LINE_MESH);
     
-    fovMesh->addVertex(-1.0, 1.0, -1.0);
-    fovMesh->addVertex(1.0, 1.0, -1.0);
-    fovMesh->addVertex(1.0, -1.0, -1.0);
-    fovMesh->addVertex(-1.0, -1.0, -1.0);
+    fovMeshGeometry.addVertex(0.0, 0.0, 0.0);
     
-    fovMesh->addIndexedFace(0, 1);
-    fovMesh->addIndexedFace(0, 2);
-    fovMesh->addIndexedFace(0, 3);
-    fovMesh->addIndexedFace(0, 4);
+    fovMeshGeometry.addVertex(-1.0, 1.0, -1.0);
+    fovMeshGeometry.addVertex(1.0, 1.0, -1.0);
+    fovMeshGeometry.addVertex(1.0, -1.0, -1.0);
+    fovMeshGeometry.addVertex(-1.0, -1.0, -1.0);
     
-    fovSceneMesh->setLocalBoundingBox(fovMesh->calculateBBox());
+    fovMeshGeometry.addIndexedFace(0, 1);
+    fovMeshGeometry.addIndexedFace(0, 2);
+    fovMeshGeometry.addIndexedFace(0, 3);
+    fovMeshGeometry.addIndexedFace(0, 4);
     
+    fovSceneMesh->getMesh()->addSubmesh(fovMeshGeometry);
+    fovSceneMesh->setLocalBoundingBox(fovMesh->calculateBBox());
     light->addChild(this);
 }
 
@@ -333,13 +344,17 @@ void LightDisplay::Update() {
         
         spotSpot->setPosition(0.0, 0.0, -distance);
         spotSpot->setPrimitiveOptions(ScenePrimitive::TYPE_LINE_CIRCLE, spotLightSize, spotLightSize, 32);
-       	spotSpot->getMesh()->setMeshType(Mesh::LINE_LOOP_MESH);
         
+        MeshGeometry geom = fovMesh->getSubmeshAtIndex(0);
         spotLightSize *= 0.5;
-        fovMesh->setVertexAtOffset(1, sin(PI/2.0)*spotLightSize, cos(PI/2.0)*spotLightSize, -distance);
-        fovMesh->setVertexAtOffset(2, sin(PI)*spotLightSize, cos(PI)*spotLightSize, -distance);
-        fovMesh->setVertexAtOffset(3, sin(PI + (PI/2.0))*spotLightSize, cos(PI + (PI/2.0))*spotLightSize, -distance);
-        fovMesh->setVertexAtOffset(4, sin(PI*2.0)*spotLightSize, cos(PI*2.0)*spotLightSize, -distance);
+        geom.setVertexAtOffset(1, sin(PI/2.0)*spotLightSize, cos(PI/2.0)*spotLightSize, -distance);
+        geom.setVertexAtOffset(2, sin(PI)*spotLightSize, cos(PI)*spotLightSize, -distance);
+        geom.setVertexAtOffset(3, sin(PI + (PI/2.0))*spotLightSize, cos(PI + (PI/2.0))*spotLightSize, -distance);
+        geom.setVertexAtOffset(4, sin(PI*2.0)*spotLightSize, cos(PI*2.0)*spotLightSize, -distance);
+        
+        fovMesh->clearMesh();
+        fovMesh->addSubmesh(geom);
+        
         fovSceneMesh->setLocalBoundingBox(fovMesh->calculateBBox());
     } else {
         spotSpot->enabled = false;
@@ -352,29 +367,34 @@ CameraDisplay::CameraDisplay(Camera *camera) : Entity() {
     
     editorOnly = true;
     
-    fovSceneMesh = new SceneMesh(Mesh::LINE_MESH);
+    fovSceneMesh = new SceneMesh();
     fovSceneMesh->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
     fovSceneMesh->setColor(1.0, 0.0, 1.0, 1.0);
     fovMesh = fovSceneMesh->getMesh();
-    fovMesh->indexedMesh = true;
     fovSceneMesh->setForceMaterial(true);
     
-    fovMesh->addVertex(0.0, 0.0, 0.0);
+    MeshGeometry geometry;
+    geometry.setMeshType(MeshGeometry::LINE_MESH);
+    
+    geometry.indexedMesh = true;
     
-    fovMesh->addVertex(-1.0, 1.0, -1.0);
-    fovMesh->addVertex(1.0, 1.0, -1.0);
-    fovMesh->addVertex(1.0, -1.0, -1.0);
-    fovMesh->addVertex(-1.0, -1.0, -1.0);
+    geometry.addVertex(0.0, 0.0, 0.0);
+    geometry.addVertex(-1.0, 1.0, -1.0);
+    geometry.addVertex(1.0, 1.0, -1.0);
+    geometry.addVertex(1.0, -1.0, -1.0);
+    geometry.addVertex(-1.0, -1.0, -1.0);
     
-    fovMesh->addIndexedFace(0, 1);
-    fovMesh->addIndexedFace(0, 2);
-    fovMesh->addIndexedFace(0, 3);
-    fovMesh->addIndexedFace(0, 4);
+    geometry.addIndexedFace(0, 1);
+    geometry.addIndexedFace(0, 2);
+    geometry.addIndexedFace(0, 3);
+    geometry.addIndexedFace(0, 4);
     
-    fovMesh->addIndexedFace(1, 2);
-    fovMesh->addIndexedFace(2, 3);
-    fovMesh->addIndexedFace(3, 4);
-    fovMesh->addIndexedFace(4, 1);
+    geometry.addIndexedFace(1, 2);
+    geometry.addIndexedFace(2, 3);
+    geometry.addIndexedFace(3, 4);
+    geometry.addIndexedFace(4, 1);
+    
+    fovMesh->addSubmesh(geometry);
     
     fovSceneMesh->setLocalBoundingBox(fovMesh->calculateBBox());
     
@@ -409,11 +429,13 @@ void CameraDisplay::Update() {
                 yPos = camera->getViewport().h * 0.5;
             break;
         }
-        
-        fovMesh->setVertexAtOffset(1, -xPos, yPos, zPos);
-        fovMesh->setVertexAtOffset(2, xPos, yPos, zPos);
-        fovMesh->setVertexAtOffset(3, xPos, -yPos, zPos);
-        fovMesh->setVertexAtOffset(4, -xPos, -yPos, zPos);
+        MeshGeometry geom = fovMesh->getSubmeshAtIndex(0);
+        geom.setVertexAtOffset(1, -xPos, yPos, zPos);
+        geom.setVertexAtOffset(2, xPos, yPos, zPos);
+        geom.setVertexAtOffset(3, xPos, -yPos, zPos);
+        geom.setVertexAtOffset(4, -xPos, -yPos, zPos);
+        fovMesh->clearMesh();
+        fovMesh->addSubmesh(geom);
     } else {
         Number fovRad = (90+camera->getFOV()/2.0) * TORADIANS;
         Number displayScale = 3.0;
@@ -421,10 +443,13 @@ void CameraDisplay::Update() {
         Number yPos = xPos * 0.5625;
         Number zPos = -sin(fovRad) * displayScale * 0.5;
         
-        fovMesh->setVertexAtOffset(1, -xPos, yPos, zPos);
-        fovMesh->setVertexAtOffset(2, xPos, yPos, zPos);
-        fovMesh->setVertexAtOffset(3, xPos, -yPos, zPos);
-        fovMesh->setVertexAtOffset(4, -xPos, -yPos, zPos);
+        MeshGeometry geom = fovMesh->getSubmeshAtIndex(0);
+        geom.setVertexAtOffset(1, -xPos, yPos, zPos);
+        geom.setVertexAtOffset(2, xPos, yPos, zPos);
+        geom.setVertexAtOffset(3, xPos, -yPos, zPos);
+        geom.setVertexAtOffset(4, -xPos, -yPos, zPos);
+        fovMesh->clearMesh();
+        fovMesh->addSubmesh(geom);
     }
 }
 
@@ -1571,7 +1596,6 @@ void EntityEditorMainView::handleEvent(Event *event) {
             {
                 Material *wireframeMaterial = (Material*)CoreServices::getInstance()->getResourceManager()->getGlobalPool()->getResource(Resource::RESOURCE_MATERIAL, "UnlitWireframe");
                 
-                
                 if(!wireframeMaterial->getShaderPass(0).shaderBinding->getLocalParamByName("wireframeColor")) {
                     wireframeMaterial->getShaderPass(0).shaderBinding->addParam(ProgramParam::PARAM_COLOR, "wireframeColor")->setColor(Color(1.0, 1.0, 1.0, 1.0));
                 }
@@ -1796,7 +1820,6 @@ void EntityEditorMainView::setOverlayWireframeRecursive(Entity *targetEntity, bo
                 wireframePass.shaderBinding = new ShaderBinding();
                 wireframePass.shaderBinding->targetShader = wireframePass.shader;
                 wireframePass.blendingMode = Renderer::BLEND_MODE_NORMAL;
-                wireframePass.setAttributeArraysFromMesh(sceneMesh->getMesh());
                 wireframePass.shaderBinding->resetAttributes = true;
                 wireframePass.shaderBinding->addParam(ProgramParam::PARAM_COLOR, "wireframeColor")->setColor(Color(0.5, 0.6, 1.0, 0.75));
                 

+ 10 - 6
src/ide/PolycodeFrame.cpp

@@ -217,11 +217,13 @@ EditCurve::EditCurve(BezierCurve *targetCurve, Color curveColor) : UIElement() {
 	
 	this->targetCurve = targetCurve;
 	
-	visMesh = new SceneMesh(Mesh::LINE_STRIP_MESH);
+	visMesh = new SceneMesh();
 	
+    MeshGeometry geometry;
 	for(int i=0; i < CURVE_SIZE; i++) {		
-		visMesh->getMesh()->addVertex(0.0, 0.0, 0.0);
+		geometry.addVertex(0.0, 0.0, 0.0);
 	}
+    visMesh->getMesh()->addSubmesh(geometry);
 	
 	visMesh->lineSmooth = true;
 	visMesh->lineWidth = 2.0;
@@ -320,12 +322,14 @@ void EditCurve::updateCurve() {
 	interval += interval/CURVE_SIZE;
 	normInterval += normInterval/CURVE_SIZE;
 
-    visMesh->getMesh()->vertexPositionArray.data.clear();
+    visMesh->getMesh()->clearMesh();
+    MeshGeometry geometry;
     
 	for(int i=0; i < CURVE_SIZE; i++) {        
-        visMesh->getMesh()->addVertex(targetCurve->getPointAt(normInterval * i).x * 300, targetCurve->getPointAt(normInterval * i).y * 100.0, 0.0);
+        geometry.addVertex(targetCurve->getPointAt(normInterval * i).x * 300, targetCurve->getPointAt(normInterval * i).y * 100.0, 0.0);
 	}
-	
+    visMesh->getMesh()->addSubmesh(geometry);
+    
     visMesh->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
 }
 
@@ -1380,7 +1384,7 @@ PolycodeFrame::PolycodeFrame(PolycodeEditorManager *editorManager) : UIElement()
 	
 	modalBlocker = new UIRect(10,10);
     modalBlocker->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
-	modalBlocker->setColor(0,0,0,0.4);
+	modalBlocker->setColor(0,0,0,0.1);
 	modalBlocker->setAnchorPoint(-1.0, -1.0, 0.0);
 	modalBlocker->enabled = false;	
 	modalBlocker->blockMouseInput = true;

+ 3 - 8
src/ide/PolycodeMaterialEditor.cpp

@@ -593,8 +593,7 @@ PostPreviewBox::PostPreviewBox() : UIElement() {
 	previewPrimitive->setColorInt(0, 255, 0, 255);
 	previewPrimitive->setPosition(-0.8, 1.0, 0.8);
 
-	previewPrimitive = new ScenePrimitive(ScenePrimitive::TYPE_BOX, 2,  2, 2);
-	previewPrimitive->getMesh()->calculateNormals();	
+	previewPrimitive = new ScenePrimitive(ScenePrimitive::TYPE_BOX, 2,  2, 2);	
 	previewScene->addChild(previewPrimitive);
 	previewPrimitive->setMaterialByName("DefaultHDR");
 	previewPrimitive->setColorInt(0, 0, 255, 255);
@@ -727,25 +726,21 @@ MaterialPreviewBox::MaterialPreviewBox() : UIElement() {
 	previewPrimitive = new ScenePrimitive(ScenePrimitive::TYPE_TORUS, 3.0, 1.2, 26, 16);
 	previewScene->addChild(previewPrimitive);
 	shapePrimitives.push_back(previewPrimitive);
-	previewPrimitive->getMesh()->calculateTangents();	
+    
 
 	previewPrimitive = new ScenePrimitive(ScenePrimitive::TYPE_SPHERE, 3.0, 16, 16);
 	previewScene->addChild(previewPrimitive);
 	shapePrimitives.push_back(previewPrimitive);
-	previewPrimitive->getMesh()->calculateTangents();	
 
 	previewPrimitive = new ScenePrimitive(ScenePrimitive::TYPE_BOX, 4.0, 4.0, 4.0);
 	previewPrimitive->Yaw(45.0);
-	previewPrimitive->getMesh()->calculateNormals();
-	previewPrimitive->getMesh()->calculateTangents();
 	previewScene->addChild(previewPrimitive);
 	shapePrimitives.push_back(previewPrimitive);
 
 	previewPrimitive = new ScenePrimitive(ScenePrimitive::TYPE_VPLANE, 6.0, 6.0);
 	previewPrimitive->billboardMode = true;
 	previewScene->addChild(previewPrimitive);
-	shapePrimitives.push_back(previewPrimitive);
-	previewPrimitive->getMesh()->calculateTangents();	
+	shapePrimitives.push_back(previewPrimitive);	
 
 	
 	mainLight = new SceneLight(SceneLight::POINT_LIGHT, previewScene, 290.0);

+ 1 - 1
src/ide/PolycodeProps.cpp

@@ -1256,7 +1256,7 @@ MaterialProp::MaterialProp(const String &caption) : PropProp(caption, "Material"
     
 	previewPrimitive = new ScenePrimitive(ScenePrimitive::TYPE_SPHERE, 3.0, 16, 16);
 	previewScene->addChild(previewPrimitive);
-	previewPrimitive->getMesh()->calculateTangents();
+
   	
 	mainLight = new SceneLight(SceneLight::POINT_LIGHT, previewScene, 290.0);
 	mainLight->setPosition(-10,10,10);

+ 103 - 88
src/ide/PolycodeSpriteEditor.cpp

@@ -52,14 +52,14 @@ SpriteSheetEditor::SpriteSheetEditor(SpriteSet *sprite) : UIElement() {
     previewImage->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
     addChild(previewImage);
     
-    frameVisualizerMesh = new SceneMesh(Mesh::LINE_MESH);
+    frameVisualizerMesh = new SceneMesh();
     frameVisualizerMesh->setColor(1.0, 1.0, 1.0, 1.0);
     addChild(frameVisualizerMesh);
     frameVisualizerMesh->setAnchorPoint(-1.0, -1.0, 0.0);
     frameVisualizerMesh->getShaderPass(0).shaderBinding->loadTextureForParam("diffuse", "main/stipple.png");
     frameVisualizerMesh->lineWidth = 1; //CoreServices::getInstance()->getRenderer()->getBackingResolutionScaleX();
 
-    frameVisualizerMeshSelected = new SceneMesh(Mesh::LINE_MESH);
+    frameVisualizerMeshSelected = new SceneMesh();
     frameVisualizerMeshSelected->setColor(1.0, 1.0, 0.0, 1.0);
     addChild(frameVisualizerMeshSelected);
     frameVisualizerMeshSelected->setAnchorPoint(-1.0, -1.0, 0.0);
@@ -229,8 +229,14 @@ void SpriteSheetEditor::Update() {
     mesh->clearMesh();
     meshSelected->clearMesh();
     
-    mesh->indexedMesh = true;
-    meshSelected->indexedMesh = true;
+    MeshGeometry geometry;
+    MeshGeometry geometrySelected;
+    
+    geometry.meshType = MeshGeometry::LINE_MESH;
+    geometrySelected.meshType = MeshGeometry::LINE_MESH;
+    
+    geometry.indexedMesh = true;
+    geometrySelected.indexedMesh = true;
     
     unsigned int offsetSelected = 0;
     unsigned int offset = 0;
@@ -238,25 +244,25 @@ void SpriteSheetEditor::Update() {
     for(int i=0; i < sprite->getNumFrames(); i++){
         SpriteFrame frame = sprite->getSpriteFrame(i);
         
-        mesh->addVertexWithUV(frame.coordinates.x, -frame.coordinates.y, 0.0, frame.coordinates.x, frame.coordinates.y);
-        mesh->addVertexWithUV(frame.coordinates.x+frame.coordinates.w, -frame.coordinates.y, 0.0, frame.coordinates.x+frame.coordinates.w, frame.coordinates.y);
-        mesh->addVertexWithUV(frame.coordinates.x+frame.coordinates.w, -frame.coordinates.y - frame.coordinates.h, 0.0, frame.coordinates.x+frame.coordinates.w, frame.coordinates.y + frame.coordinates.h);
-        mesh->addVertexWithUV(frame.coordinates.x, -frame.coordinates.y - frame.coordinates.h, 0.0, frame.coordinates.x, frame.coordinates.y + frame.coordinates.h);
-        mesh->addIndexedFace(offset+0,offset+1);
-        mesh->addIndexedFace(offset+1,offset+2);
-        mesh->addIndexedFace(offset+2,offset+3);
-        mesh->addIndexedFace(offset+3,offset+0);
+        geometry.addVertexWithUV(frame.coordinates.x, -frame.coordinates.y, 0.0, frame.coordinates.x, frame.coordinates.y);
+        geometry.addVertexWithUV(frame.coordinates.x+frame.coordinates.w, -frame.coordinates.y, 0.0, frame.coordinates.x+frame.coordinates.w, frame.coordinates.y);
+        geometry.addVertexWithUV(frame.coordinates.x+frame.coordinates.w, -frame.coordinates.y - frame.coordinates.h, 0.0, frame.coordinates.x+frame.coordinates.w, frame.coordinates.y + frame.coordinates.h);
+        geometry.addVertexWithUV(frame.coordinates.x, -frame.coordinates.y - frame.coordinates.h, 0.0, frame.coordinates.x, frame.coordinates.y + frame.coordinates.h);
+        geometry.addIndexedFace(offset+0,offset+1);
+        geometry.addIndexedFace(offset+1,offset+2);
+        geometry.addIndexedFace(offset+2,offset+3);
+        geometry.addIndexedFace(offset+3,offset+0);
         offset += 4;
         
         if(hasSelectedID(frame.frameID)) {
-            meshSelected->addVertexWithUV(frame.coordinates.x, -frame.coordinates.y, 0.0, frame.coordinates.x, frame.coordinates.y);
-            meshSelected->addVertexWithUV(frame.coordinates.x+frame.coordinates.w, -frame.coordinates.y, 0.0, frame.coordinates.x+frame.coordinates.w, frame.coordinates.y);
-            meshSelected->addVertexWithUV(frame.coordinates.x+frame.coordinates.w, -frame.coordinates.y - frame.coordinates.h, 0.0, frame.coordinates.x+frame.coordinates.w, frame.coordinates.y + frame.coordinates.h);
-            meshSelected->addVertexWithUV(frame.coordinates.x, -frame.coordinates.y - frame.coordinates.h, 0.0, frame.coordinates.x, frame.coordinates.y + frame.coordinates.h);
-            meshSelected->addIndexedFace(offsetSelected+0,offsetSelected+1);
-            meshSelected->addIndexedFace(offsetSelected+1,offsetSelected+2);
-            meshSelected->addIndexedFace(offsetSelected+2,offsetSelected+3);
-            meshSelected->addIndexedFace(offsetSelected+3,offsetSelected+0);
+            geometrySelected.addVertexWithUV(frame.coordinates.x, -frame.coordinates.y, 0.0, frame.coordinates.x, frame.coordinates.y);
+            geometrySelected.addVertexWithUV(frame.coordinates.x+frame.coordinates.w, -frame.coordinates.y, 0.0, frame.coordinates.x+frame.coordinates.w, frame.coordinates.y);
+            geometrySelected.addVertexWithUV(frame.coordinates.x+frame.coordinates.w, -frame.coordinates.y - frame.coordinates.h, 0.0, frame.coordinates.x+frame.coordinates.w, frame.coordinates.y + frame.coordinates.h);
+            geometrySelected.addVertexWithUV(frame.coordinates.x, -frame.coordinates.y - frame.coordinates.h, 0.0, frame.coordinates.x, frame.coordinates.y + frame.coordinates.h);
+            geometrySelected.addIndexedFace(offsetSelected+0,offsetSelected+1);
+            geometrySelected.addIndexedFace(offsetSelected+1,offsetSelected+2);
+            geometrySelected.addIndexedFace(offsetSelected+2,offsetSelected+3);
+            geometrySelected.addIndexedFace(offsetSelected+3,offsetSelected+0);
             offsetSelected += 4;
         }
         
@@ -266,18 +272,19 @@ void SpriteSheetEditor::Update() {
      
         SpriteFrame frame = frameToAdd;
         
-        mesh->addVertexWithUV(frame.coordinates.x, -frame.coordinates.y, 0.0, frame.coordinates.x, frame.coordinates.y);
-        mesh->addVertexWithUV(frame.coordinates.x+frame.coordinates.w, -frame.coordinates.y, 0.0, frame.coordinates.x+frame.coordinates.w, frame.coordinates.y);
-        mesh->addVertexWithUV(frame.coordinates.x+frame.coordinates.w, -frame.coordinates.y - frame.coordinates.h, 0.0, frame.coordinates.x+frame.coordinates.w, frame.coordinates.y + frame.coordinates.h);
-        mesh->addVertexWithUV(frame.coordinates.x, -frame.coordinates.y - frame.coordinates.h, 0.0, frame.coordinates.x, frame.coordinates.y + frame.coordinates.h);
-        mesh->addIndexedFace(offset+0,offset+1);
-        mesh->addIndexedFace(offset+1,offset+2);
-        mesh->addIndexedFace(offset+2,offset+3);
-        mesh->addIndexedFace(offset+3,offset+0);
+        geometry.addVertexWithUV(frame.coordinates.x, -frame.coordinates.y, 0.0, frame.coordinates.x, frame.coordinates.y);
+        geometry.addVertexWithUV(frame.coordinates.x+frame.coordinates.w, -frame.coordinates.y, 0.0, frame.coordinates.x+frame.coordinates.w, frame.coordinates.y);
+        geometry.addVertexWithUV(frame.coordinates.x+frame.coordinates.w, -frame.coordinates.y - frame.coordinates.h, 0.0, frame.coordinates.x+frame.coordinates.w, frame.coordinates.y + frame.coordinates.h);
+        geometry.addVertexWithUV(frame.coordinates.x, -frame.coordinates.y - frame.coordinates.h, 0.0, frame.coordinates.x, frame.coordinates.y + frame.coordinates.h);
+        geometry.addIndexedFace(offset+0,offset+1);
+        geometry.addIndexedFace(offset+1,offset+2);
+        geometry.addIndexedFace(offset+2,offset+3);
+        geometry.addIndexedFace(offset+3,offset+0);
         offset += 4;
-
     }
     
+    mesh->addSubmesh(geometry);
+    meshSelected->addSubmesh(geometrySelected);
 }
 
 void SpriteSheetEditor::handleEvent(Event *event) {
@@ -1135,19 +1142,19 @@ void SpriteStateEditBar::refreshBar() {
     
     Mesh *mesh = barMesh->getMesh();
     mesh->clearMesh();
-    mesh->indexedMesh = true;
+    MeshGeometry meshGeometry;
     
     Mesh *meshBg = barMeshBg->getMesh();
     meshBg->clearMesh();
-    meshBg->indexedMesh = true;
+    MeshGeometry meshBgGeometry;
     
     Mesh *meshTicks = frameTicksMesh->getMesh();
     meshTicks->clearMesh();
-    meshTicks->indexedMesh = true;
+    MeshGeometry meshTicksGeometry;
     
     Mesh *meshGrips = frameGripsMesh->getMesh();
     meshGrips->clearMesh();
-    meshGrips->indexedMesh = true;
+    MeshGeometry meshGripsGeometry;
     
     Number frameOffset = 0;
     Number frameSize = 0;
@@ -1204,23 +1211,23 @@ void SpriteStateEditBar::refreshBar() {
             vertexColor = Color(1.0, 0.8, 0.0, 1.0);
         }
         
-        meshTicks->addVertexWithUV(frameOffset, 0.0, 0.0, 0.0, 0.0);
-        meshTicks->addColor(vertexColor);
+        meshTicksGeometry.addVertexWithUV(frameOffset, 0.0, 0.0, 0.0, 0.0);
+        meshTicksGeometry.addColor(vertexColor);
         
-        meshTicks->addVertexWithUV(frameOffset, 0.0-frameTickHeight, 0.0, 0.0, 1.0);
-        meshTicks->addColor(vertexColor);
+        meshTicksGeometry.addVertexWithUV(frameOffset, 0.0-frameTickHeight, 0.0, 0.0, 1.0);
+        meshTicksGeometry.addColor(vertexColor);
         
-        meshTicks->addVertexWithUV(frameOffset+frameSize-frameGapSize, -frameTickHeight, 0.0, 1.0, 1.0);
-        meshTicks->addColor(vertexColor);
+        meshTicksGeometry.addVertexWithUV(frameOffset+frameSize-frameGapSize, -frameTickHeight, 0.0, 1.0, 1.0);
+        meshTicksGeometry.addColor(vertexColor);
         
-        meshTicks->addVertexWithUV(frameOffset+frameSize-frameGapSize, 0.0, 0.0, 1.0, 0.0);
-        meshTicks->addColor(vertexColor);
+        meshTicksGeometry.addVertexWithUV(frameOffset+frameSize-frameGapSize, 0.0, 0.0, 1.0, 0.0);
+        meshTicksGeometry.addColor(vertexColor);
         
         
-        meshTicks->addIndexedFace(offset+0,offset+1);
-        meshTicks->addIndexedFace(offset+1,offset+2);
-        meshTicks->addIndexedFace(offset+2,offset+3);
-        meshTicks->addIndexedFace(offset+3,offset+0);
+        meshTicksGeometry.addIndexedFace(offset+0,offset+1);
+        meshTicksGeometry.addIndexedFace(offset+1,offset+2);
+        meshTicksGeometry.addIndexedFace(offset+2,offset+3);
+        meshTicksGeometry.addIndexedFace(offset+3,offset+0);
         
         // draw icons
         
@@ -1238,16 +1245,15 @@ void SpriteStateEditBar::refreshBar() {
         Number iconOffset = 2.0;
         
         if(drawIcon) {
-        
-            mesh->addVertexWithUV(frameOffset+iconOffset, -frameTickHeight-frameTickGap-iconOffset, 0.0, frame.coordinates.x, 1.0-frame.coordinates.y);
-            mesh->addVertexWithUV(frameOffset+iconOffset, -frameTickHeight-frameTickGap-iconFrameHeight-iconOffset, 0.0, frame.coordinates.x, 1.0-frame.coordinates.y  - frame.coordinates.h);
-            mesh->addVertexWithUV(frameOffset+iconFrameWidth+iconOffset, -frameTickHeight-frameTickGap-iconFrameHeight-iconOffset, 0.0, frame.coordinates.x+frame.coordinates.w, 1.0- frame.coordinates.y  - frame.coordinates.h);
-            mesh->addVertexWithUV(frameOffset+iconFrameWidth+iconOffset, -frameTickHeight-frameTickGap-iconOffset, 0.0, frame.coordinates.x+frame.coordinates.w, 1.0-frame.coordinates.y);
+            meshGeometry.addVertexWithUV(frameOffset+iconOffset, -frameTickHeight-frameTickGap-iconOffset, 0.0, frame.coordinates.x, 1.0-frame.coordinates.y);
+            meshGeometry.addVertexWithUV(frameOffset+iconOffset, -frameTickHeight-frameTickGap-iconFrameHeight-iconOffset, 0.0, frame.coordinates.x, 1.0-frame.coordinates.y  - frame.coordinates.h);
+            meshGeometry.addVertexWithUV(frameOffset+iconFrameWidth+iconOffset, -frameTickHeight-frameTickGap-iconFrameHeight-iconOffset, 0.0, frame.coordinates.x+frame.coordinates.w, 1.0- frame.coordinates.y  - frame.coordinates.h);
+            meshGeometry.addVertexWithUV(frameOffset+iconFrameWidth+iconOffset, -frameTickHeight-frameTickGap-iconOffset, 0.0, frame.coordinates.x+frame.coordinates.w, 1.0-frame.coordinates.y);
             
-            mesh->addIndexedFace(offsetIcon+0,offsetIcon+1);
-            mesh->addIndexedFace(offsetIcon+1,offsetIcon+2);
-            mesh->addIndexedFace(offsetIcon+2,offsetIcon+3);
-            mesh->addIndexedFace(offsetIcon+3,offsetIcon+0);
+            meshGeometry.addIndexedFace(offsetIcon+0,offsetIcon+1);
+            meshGeometry.addIndexedFace(offsetIcon+1,offsetIcon+2);
+            meshGeometry.addIndexedFace(offsetIcon+2,offsetIcon+3);
+            meshGeometry.addIndexedFace(offsetIcon+3,offsetIcon+0);
             
             offsetIcon += 4;
         }
@@ -1260,23 +1266,23 @@ void SpriteStateEditBar::refreshBar() {
             bgFrameColor = Color(1.0, 0.5, 0.5, 1.0);
         }
         
-        meshBg->addVertexWithUV(frameOffset, -frameTickHeight-frameTickGap, 0.0, 0.0, 0.0);
-        meshBg->addColor(bgFrameColor);
+        meshBgGeometry.addVertexWithUV(frameOffset, -frameTickHeight-frameTickGap, 0.0, 0.0, 0.0);
+        meshBgGeometry.addColor(bgFrameColor);
         
-        meshBg->addVertexWithUV(frameOffset, -frameTickHeight-frameTickGap-frameHeight, 0.0, 0.0, 1.0);
-        meshBg->addColor(bgFrameColor);
+        meshBgGeometry.addVertexWithUV(frameOffset, -frameTickHeight-frameTickGap-frameHeight, 0.0, 0.0, 1.0);
+        meshBgGeometry.addColor(bgFrameColor);
         
-        meshBg->addVertexWithUV(frameOffset+frameSize-gapSize, -frameTickHeight-frameTickGap-frameHeight, 0.0, 1.0, 1.0);
-        meshBg->addColor(bgFrameColor);
+        meshBgGeometry.addVertexWithUV(frameOffset+frameSize-gapSize, -frameTickHeight-frameTickGap-frameHeight, 0.0, 1.0, 1.0);
+        meshBgGeometry.addColor(bgFrameColor);
         
-        meshBg->addVertexWithUV(frameOffset+frameSize-gapSize, -frameTickHeight-frameTickGap, 0.0, 1.0, 0.0);
-        meshBg->addColor(bgFrameColor);
+        meshBgGeometry.addVertexWithUV(frameOffset+frameSize-gapSize, -frameTickHeight-frameTickGap, 0.0, 1.0, 0.0);
+        meshBgGeometry.addColor(bgFrameColor);
 
         
-        meshBg->addIndexedFace(offset+0,offset+1);
-        meshBg->addIndexedFace(offset+1,offset+2);
-        meshBg->addIndexedFace(offset+2,offset+3);
-        meshBg->addIndexedFace(offset+3,offset+0);
+        meshBgGeometry.addIndexedFace(offset+0,offset+1);
+        meshBgGeometry.addIndexedFace(offset+1,offset+2);
+        meshBgGeometry.addIndexedFace(offset+2,offset+3);
+        meshBgGeometry.addIndexedFace(offset+3,offset+0);
         
         
         Number gripWidth = 8;
@@ -1285,15 +1291,15 @@ void SpriteStateEditBar::refreshBar() {
         Number gripOffset = (frameHeight-24.0) / 2.0;
         
         if(drawGrip) {
-            meshGrips->addVertexWithUV(frameOffset+frameSize-gapSize-gripWidth, -frameTickHeight-frameTickGap-gripOffset, 0.0, 0.0, 0.0);
-            meshGrips->addVertexWithUV(frameOffset+frameSize-gapSize-gripWidth, -frameTickHeight-frameTickGap-gripHeight-gripOffset, 0.0, 0.0, 1.0);
-            meshGrips->addVertexWithUV(frameOffset+frameSize-gapSize, -frameTickHeight-frameTickGap-gripHeight-gripOffset, 0.0, 1.0, 1.0);
-            meshGrips->addVertexWithUV(frameOffset+frameSize-gapSize, -frameTickHeight-frameTickGap-gripOffset, 0.0, 1.0, 0.0);
+            meshGripsGeometry.addVertexWithUV(frameOffset+frameSize-gapSize-gripWidth, -frameTickHeight-frameTickGap-gripOffset, 0.0, 0.0, 0.0);
+            meshGripsGeometry.addVertexWithUV(frameOffset+frameSize-gapSize-gripWidth, -frameTickHeight-frameTickGap-gripHeight-gripOffset, 0.0, 0.0, 1.0);
+            meshGripsGeometry.addVertexWithUV(frameOffset+frameSize-gapSize, -frameTickHeight-frameTickGap-gripHeight-gripOffset, 0.0, 1.0, 1.0);
+            meshGripsGeometry.addVertexWithUV(frameOffset+frameSize-gapSize, -frameTickHeight-frameTickGap-gripOffset, 0.0, 1.0, 0.0);
             
-            meshGrips->addIndexedFace(offsetGrip+0,offsetGrip+1);
-            meshGrips->addIndexedFace(offsetGrip+1,offsetGrip+2);
-            meshGrips->addIndexedFace(offsetGrip+2,offsetGrip+3);
-            meshGrips->addIndexedFace(offsetGrip+3,offsetGrip+0);
+            meshGripsGeometry.addIndexedFace(offsetGrip+0,offsetGrip+1);
+            meshGripsGeometry.addIndexedFace(offsetGrip+1,offsetGrip+2);
+            meshGripsGeometry.addIndexedFace(offsetGrip+2,offsetGrip+3);
+            meshGripsGeometry.addIndexedFace(offsetGrip+3,offsetGrip+0);
             
             offsetGrip += 4;
         }
@@ -1302,6 +1308,11 @@ void SpriteStateEditBar::refreshBar() {
         
     }
     
+    mesh->addSubmesh(meshGeometry);
+    meshBg->addSubmesh(meshBgGeometry);
+    meshGrips->addSubmesh(meshGripsGeometry);
+    meshTicks->addSubmesh(meshTicksGeometry);
+    
     scroller->setContentSize(frameOffset+frameSize, getHeight());
 }
 
@@ -1335,19 +1346,19 @@ SpriteStateEditBar::SpriteStateEditBar(SpriteSet *spriteSet) : UIElement() {
     
     barBase = new UIElement();
     
-    barMeshBg = new SceneMesh(Mesh::TRI_MESH);
+    barMeshBg = new SceneMesh();
     barBase->addChild(barMeshBg);
     barMeshBg->getShaderPass(0).shaderBinding->loadTextureForParam("diffuse", "spriteEditor/sprite_frame_bg.png");
     barMeshBg->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
     
-    barMesh = new SceneMesh(Mesh::TRI_MESH);
+    barMesh = new SceneMesh();
     barBase->addChild(barMesh);
     barMesh->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
     
-    frameTicksMesh = new SceneMesh(Mesh::TRI_MESH);
+    frameTicksMesh = new SceneMesh();
     barBase->addChild(frameTicksMesh);
     
-    frameGripsMesh = new SceneMesh(Mesh::TRI_MESH);
+    frameGripsMesh = new SceneMesh();
     barBase->addChild(frameGripsMesh);
     frameGripsMesh->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
     frameGripsMesh->getShaderPass(0).shaderBinding->loadTextureForParam("diffuse", "spriteEditor/frame_grip.png");
@@ -1932,7 +1943,7 @@ SpritePreview::SpritePreview(SpriteSet *spriteSet) : UIElement() {
 	addChild(label);
 	label->setPosition(10, 3);
     
-    boundingBoxPreview = new SceneMesh(Mesh::LINE_MESH);
+    boundingBoxPreview = new SceneMesh();
     addChild(boundingBoxPreview);
     boundingBoxPreview->getShaderPass(0).shaderBinding->loadTextureForParam("diffuse", "main/stipple_small.png");
     boundingBoxPreview->lineWidth = 1;
@@ -1982,7 +1993,9 @@ void SpritePreview::Update() {
     
     Mesh *bbBoxMesh = boundingBoxPreview->getMesh();
     bbBoxMesh->clearMesh();
-    bbBoxMesh->indexedMesh = true;
+    
+    MeshGeometry bBoxMeshGeometry;
+    bBoxMeshGeometry.indexedMesh = true;
     
     
     Number spriteScale =  (getWidth() - 80) / sprite->getSpriteBoundingBox().x;
@@ -2003,15 +2016,17 @@ void SpritePreview::Update() {
     frame.coordinates.w = bBoxNorm.x * spriteScale;
     frame.coordinates.h = bBoxNorm.y * spriteScale;
     
-    bbBoxMesh->addVertexWithUV(-bBox.x * 0.5, bBox.y * 0.5, 0.0, frame.coordinates.x, frame.coordinates.y);
-    bbBoxMesh->addVertexWithUV((-bBox.x * 0.5)+bBox.x, bBox.y * 0.5, 0.0, frame.coordinates.x+frame.coordinates.w, frame.coordinates.y);
-    bbBoxMesh->addVertexWithUV((-bBox.x * 0.5)+bBox.x, bBox.y * 0.5 - bBox.y, 0.0, frame.coordinates.x+frame.coordinates.w, frame.coordinates.y + frame.coordinates.h);
-    bbBoxMesh->addVertexWithUV(-bBox.x * 0.5, bBox.y * 0.5 - bBox.y, 0.0, frame.coordinates.x, frame.coordinates.y + frame.coordinates.h);
+    bBoxMeshGeometry.addVertexWithUV(-bBox.x * 0.5, bBox.y * 0.5, 0.0, frame.coordinates.x, frame.coordinates.y);
+    bBoxMeshGeometry.addVertexWithUV((-bBox.x * 0.5)+bBox.x, bBox.y * 0.5, 0.0, frame.coordinates.x+frame.coordinates.w, frame.coordinates.y);
+    bBoxMeshGeometry.addVertexWithUV((-bBox.x * 0.5)+bBox.x, bBox.y * 0.5 - bBox.y, 0.0, frame.coordinates.x+frame.coordinates.w, frame.coordinates.y + frame.coordinates.h);
+    bBoxMeshGeometry.addVertexWithUV(-bBox.x * 0.5, bBox.y * 0.5 - bBox.y, 0.0, frame.coordinates.x, frame.coordinates.y + frame.coordinates.h);
+    
+    bBoxMeshGeometry.addIndexedFace(0,1);
+    bBoxMeshGeometry.addIndexedFace(1,2);
+    bBoxMeshGeometry.addIndexedFace(2,3);
+    bBoxMeshGeometry.addIndexedFace(3,0);
     
-    bbBoxMesh->addIndexedFace(0,1);
-    bbBoxMesh->addIndexedFace(1,2);
-    bbBoxMesh->addIndexedFace(2,3);
-    bbBoxMesh->addIndexedFace(3,0);
+    bbBoxMesh->addSubmesh(bBoxMeshGeometry);
     
     sprite->setScale(spriteScale, spriteScale, 1.0);
 

+ 22 - 15
src/ide/TransformGizmo.cpp

@@ -254,7 +254,6 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
 	this->targetCamera = targetCamera;
 	
 	ScenePrimitive *centerCircle = new ScenePrimitive(ScenePrimitive::TYPE_LINE_CIRCLE, 0.3, 0.3, 16);
-	centerCircle->getMesh()->setMeshType(Mesh::LINE_LOOP_MESH);
 	centerCircle->setColor(0.7, 0.7, 0.7, 1.0);
 	centerCircle->depthTest = false;
 	centerCircle->billboardMode = true;
@@ -274,9 +273,14 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
 	rotateDectorators = new Entity();
 	addChild(rotateDectorators);
     
-	yLine = new SceneMesh(Mesh::LINE_MESH);
-	yLine->getMesh()->addVertex(0.0, 0.0, 0.0);
-	yLine->getMesh()->addVertex(0.0, 0.75, 0.0);
+	yLine = new SceneMesh();
+    
+    MeshGeometry yLineGeometry;
+    yLineGeometry.meshType = MeshGeometry::LINE_MESH;
+	yLineGeometry.addVertex(0.0, 0.0, 0.0);
+	yLineGeometry.addVertex(0.0, 0.75, 0.0);
+    yLine->getMesh()->addSubmesh(yLineGeometry);
+    
 	yLine->depthTest = false;
 	yLine->color.setColorHexFromString(TRANSGIZMO_Y_COLOR);
     yLine->setLocalBoundingBox(yLine->getMesh()->calculateBBox());
@@ -285,9 +289,13 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
     yLine->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
     yLine->setForceMaterial(true);
     
-	xLine = new SceneMesh(Mesh::LINE_MESH);
-	xLine->getMesh()->addVertex(0.0, 0.0, 0.0);
-	xLine->getMesh()->addVertex(0.75, 0.0, 0.0);
+	xLine = new SceneMesh();
+    MeshGeometry xLineGeometry;
+    xLineGeometry.meshType = MeshGeometry::LINE_MESH;
+    xLineGeometry.addVertex(0.0, 0.0, 0.0);
+    xLineGeometry.addVertex(0.75, 0.0, 0.0);
+    xLine->getMesh()->addSubmesh(xLineGeometry);
+    
 	xLine->depthTest = false;
 	xLine->color.setColorHexFromString(TRANSGIZMO_X_COLOR);
     xLine->setLocalBoundingBox(xLine->getMesh()->calculateBBox());
@@ -296,9 +304,13 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
     xLine->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
     xLine->setForceMaterial(true);
     
-	zLine = new SceneMesh(Mesh::LINE_MESH);
-	zLine->getMesh()->addVertex(0.0, 0.0, 0.0);
-	zLine->getMesh()->addVertex(0.0, 0.0, 0.75);
+	zLine = new SceneMesh();
+    MeshGeometry zLineGeometry;
+    zLineGeometry.meshType = MeshGeometry::LINE_MESH;
+    zLineGeometry.addVertex(0.0, 0.0, 0.0);
+    zLineGeometry.addVertex(0.00, 0.0, 0.75);
+    zLine->getMesh()->addSubmesh(zLineGeometry);
+    
 	zLine->depthTest = false;
 	zLine->color.setColorHexFromString(TRANSGIZMO_Z_COLOR);
     zLine->setLocalBoundingBox(zLine->getMesh()->calculateBBox());
@@ -360,7 +372,6 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
 	// ROTATE
 
 	bgCircle = new ScenePrimitive(ScenePrimitive::TYPE_LINE_CIRCLE, 2.6, 2.6, 32);
-	bgCircle->getMesh()->setMeshType(Mesh::LINE_LOOP_MESH);
 	bgCircle->setColor(0.0, 0.0, 0.0, 1.0);
 	bgCircle->depthTest = false;
 //	bgCircle->billboardMode = true;
@@ -370,7 +381,6 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
     bgCircle->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
     
 	outerCircle = new ScenePrimitive(ScenePrimitive::TYPE_LINE_CIRCLE, 3.0, 3.0, 32);
-	outerCircle->getMesh()->setMeshType(Mesh::LINE_LOOP_MESH);
 	outerCircle->setColor(1.0, 1.0, 1.0, 1.0);
 	outerCircle->depthTest = false;
 	outerCircle->billboardMode = true;
@@ -380,7 +390,6 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
     outerCircle->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
     
 	pitchCircle = new ScenePrimitive(ScenePrimitive::TYPE_LINE_CIRCLE, 1.55, 1.55, 64);
-	pitchCircle->getMesh()->setMeshType(Mesh::LINE_LOOP_MESH);
 	pitchCircle->color.setColorHexFromString(TRANSGIZMO_X_COLOR);
 	pitchCircle->depthTest = false;
 	pitchCircle->Yaw(90);	
@@ -391,7 +400,6 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
     pitchCircle->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
     
 	yawCircle = new ScenePrimitive(ScenePrimitive::TYPE_LINE_CIRCLE, 1.65, 1.65, 64);
-	yawCircle->getMesh()->setMeshType(Mesh::LINE_LOOP_MESH);
 	yawCircle->color.setColorHexFromString(TRANSGIZMO_Y_COLOR);
 	yawCircle->depthTest = false;
 	yawCircle->Pitch(90);
@@ -402,7 +410,6 @@ TransformGizmo::TransformGizmo(Scene *targetScene, Camera *targetCamera) : Entit
     yawCircle->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
     
 	rollCircle = new ScenePrimitive(ScenePrimitive::TYPE_LINE_CIRCLE, 1.6, 1.6, 64);
-	rollCircle->getMesh()->setMeshType(Mesh::LINE_LOOP_MESH);
 	rollCircle->color.setColorHexFromString(TRANSGIZMO_Z_COLOR);
 	rollCircle->depthTest = false;
 	rotateDectorators->addChild(rollCircle);

+ 4 - 1
src/modules/physics3D/PolyCollisionSceneEntity.cpp

@@ -131,10 +131,13 @@ btCollisionShape *CollisionEntity::createCollisionShape(Entity *entity, int type
 			if(sceneMesh != NULL) {
 				btConvexHullShape *hullShape = new btConvexHullShape();
                 Mesh *mesh = sceneMesh->getMesh();
+                // TODO: fix to work with new mesh system
+                /*
 				for(int i=0; i < mesh->vertexPositionArray.data.size()-2; i += 3) {
                     
                     hullShape->addPoint(btVector3((btScalar)mesh->vertexPositionArray.data[i], (btScalar)mesh->vertexPositionArray.data[i+1],mesh->vertexPositionArray.data[i+2]));
-				}				
+				}
+                 */
 				collisionShape = hullShape;
 				
 			} else {

+ 48 - 45
src/modules/ui/PolyUIBox.cpp

@@ -43,8 +43,7 @@ UIBox::UIBox(String imageFile, Number t, Number r, Number b, Number l, Number bo
     MaterialManager *materialManager = CoreServices::getInstance()->getMaterialManager();
     texture = materialManager->createTextureFromFile(imageFile, materialManager->clampDefault, false);
     
-    boxMesh = new Mesh(Mesh::TRI_MESH);
-    boxMesh->indexedMesh = true;
+    boxMesh = new Mesh();
     
     setMaterial((Material*)CoreServices::getInstance()->getResourceManager()->getGlobalPool()->getResource(Resource::RESOURCE_MATERIAL, "Unlit"));
     
@@ -69,61 +68,65 @@ UIBox::UIBox(String imageFile, Number t, Number r, Number b, Number l, Number bo
 void UIBox::redrawMesh() {
     
     boxMesh->clearMesh();
-
-    boxMesh->addVertexWithUV(0.0, 0.0, 0.0, 0.0, 0.0);
-    boxMesh->addVertexWithUV(l, 0.0, 0.0, l/imageWidth, 0.0);
-    boxMesh->addVertexWithUV(getWidth() - r, 0.0, 0.0, 1.0-r/imageWidth, 0.0);
-    boxMesh->addVertexWithUV(getWidth(), 0.0, 0.0, 1.0, 0.0);
     
-    boxMesh->addVertexWithUV(0.0, t, 0.0, 0.0, t/imageHeight);
-    boxMesh->addVertexWithUV(l, t, 0.0, l/imageWidth, t/imageHeight);
-    boxMesh->addVertexWithUV(getWidth() - r, t, 0.0, 1.0-r/imageWidth, t/imageHeight);
-    boxMesh->addVertexWithUV(getWidth(), t, 0.0, 1.0, t/imageHeight);
+    MeshGeometry newGeometry;
+    newGeometry.indexedMesh = true;
+    
+    newGeometry.addVertexWithUV(0.0, 0.0, 0.0, 0.0, 0.0);
+    newGeometry.addVertexWithUV(l, 0.0, 0.0, l/imageWidth, 0.0);
+    newGeometry.addVertexWithUV(getWidth() - r, 0.0, 0.0, 1.0-r/imageWidth, 0.0);
+    newGeometry.addVertexWithUV(getWidth(), 0.0, 0.0, 1.0, 0.0);
     
+    newGeometry.addVertexWithUV(0.0, t, 0.0, 0.0, t/imageHeight);
+    newGeometry.addVertexWithUV(l, t, 0.0, l/imageWidth, t/imageHeight);
+    newGeometry.addVertexWithUV(getWidth() - r, t, 0.0, 1.0-r/imageWidth, t/imageHeight);
+    newGeometry.addVertexWithUV(getWidth(), t, 0.0, 1.0, t/imageHeight);
     
-    boxMesh->addVertexWithUV(0.0, getHeight()-t, 0.0, 0.0, 1.0-b/imageHeight);
-    boxMesh->addVertexWithUV(l, getHeight()-t, 0.0, l/imageWidth, 1.0-b/imageHeight);
-    boxMesh->addVertexWithUV(getWidth() - r, getHeight()-t, 0.0, 1.0-r/imageWidth, 1.0-b/imageHeight);
-    boxMesh->addVertexWithUV(getWidth(), getHeight()-t, 0.0, 1.0, 1.0-b/imageHeight);
+    
+    newGeometry.addVertexWithUV(0.0, getHeight()-t, 0.0, 0.0, 1.0-b/imageHeight);
+    newGeometry.addVertexWithUV(l, getHeight()-t, 0.0, l/imageWidth, 1.0-b/imageHeight);
+    newGeometry.addVertexWithUV(getWidth() - r, getHeight()-t, 0.0, 1.0-r/imageWidth, 1.0-b/imageHeight);
+    newGeometry.addVertexWithUV(getWidth(), getHeight()-t, 0.0, 1.0, 1.0-b/imageHeight);
 
-    boxMesh->addVertexWithUV(0.0, getHeight(), 0.0, 0.0, 1.0);
-    boxMesh->addVertexWithUV(l, getHeight(), 0.0, l/imageWidth, 1.0);
-    boxMesh->addVertexWithUV(getWidth() - r, getHeight(), 0.0, 1.0-r/imageWidth, 1.0);
-    boxMesh->addVertexWithUV(getWidth(), getHeight(), 0.0, 1.0, 1.0);
+    newGeometry.addVertexWithUV(0.0, getHeight(), 0.0, 0.0, 1.0);
+    newGeometry.addVertexWithUV(l, getHeight(), 0.0, l/imageWidth, 1.0);
+    newGeometry.addVertexWithUV(getWidth() - r, getHeight(), 0.0, 1.0-r/imageWidth, 1.0);
+    newGeometry.addVertexWithUV(getWidth(), getHeight(), 0.0, 1.0, 1.0);
     
-    boxMesh->addIndexedFace(1, 0, 4);
-    boxMesh->addIndexedFace(1, 4, 5);
+    newGeometry.addIndexedFace(1, 0, 4);
+    newGeometry.addIndexedFace(1, 4, 5);
     
-    boxMesh->addIndexedFace(2, 1, 5);
-    boxMesh->addIndexedFace(5, 6, 2);
+    newGeometry.addIndexedFace(2, 1, 5);
+    newGeometry.addIndexedFace(5, 6, 2);
     
-    boxMesh->addIndexedFace(3, 2, 6);
-    boxMesh->addIndexedFace(3, 6, 7);
+    newGeometry.addIndexedFace(3, 2, 6);
+    newGeometry.addIndexedFace(3, 6, 7);
 
-    boxMesh->addIndexedFace(5, 4, 8);
-    boxMesh->addIndexedFace(5, 8, 9);
+    newGeometry.addIndexedFace(5, 4, 8);
+    newGeometry.addIndexedFace(5, 8, 9);
     
-    boxMesh->addIndexedFace(6, 5, 9);
-    boxMesh->addIndexedFace(6, 9, 10);
+    newGeometry.addIndexedFace(6, 5, 9);
+    newGeometry.addIndexedFace(6, 9, 10);
     
-    boxMesh->addIndexedFace(7, 6, 10);
-    boxMesh->addIndexedFace(7, 10, 11);
+    newGeometry.addIndexedFace(7, 6, 10);
+    newGeometry.addIndexedFace(7, 10, 11);
     
-    boxMesh->addIndexedFace(9, 8, 12);
-    boxMesh->addIndexedFace(9, 12, 13);
+    newGeometry.addIndexedFace(9, 8, 12);
+    newGeometry.addIndexedFace(9, 12, 13);
     
-    boxMesh->addIndexedFace(10, 9, 13);
-    boxMesh->addIndexedFace(10, 13, 14);
+    newGeometry.addIndexedFace(10, 9, 13);
+    newGeometry.addIndexedFace(10, 13, 14);
 
-    boxMesh->addIndexedFace(11, 10, 14);
-    boxMesh->addIndexedFace(11, 14, 15);
+    newGeometry.addIndexedFace(11, 10, 14);
+    newGeometry.addIndexedFace(11, 14, 15);
     
     
-    for(int i=0; i < boxMesh->getVertexCount(); i++) {
-        Vector3 v = boxMesh->getVertexPosition(i);
-        boxMesh->setVertexAtOffset(i, v.x-getWidth()/2.0, v.y-getHeight()/2.0, v.z);
+    for(int i=0; i < newGeometry.getVertexCount(); i++) {
+        Vector3 v = newGeometry.getVertexPosition(i);
+        newGeometry.setVertexAtOffset(i, v.x-getWidth()/2.0, v.y-getHeight()/2.0, v.z);
     }
-
+    
+    boxMesh->addSubmesh(newGeometry);
     shaderPasses[0].shaderBinding->resetAttributes = true;
 }
 
@@ -143,7 +146,6 @@ void UIBox::setMaterial(Material *material) {
     shaderPasses.push_back(pass);
     
     shaderPasses[0].shaderBinding->addParamPointer(ProgramParam::PARAM_COLOR, "entityColor", &color);
-    shaderPasses[0].setAttributeArraysFromMesh(boxMesh);
     shaderPasses[0].shaderBinding->resetAttributes = true;
 }
 
@@ -151,11 +153,12 @@ void UIBox::Render(GPUDrawBuffer *buffer) {
     drawCall.options.depthTest = false;
     drawCall.options.depthWrite = false;
     drawCall.options.backfaceCull = false;
-    
-    drawCall.mesh = boxMesh;
+    if(boxMesh->getNumSubmeshes() == 0) {
+        assert(false);
+    }
+    drawCall.submesh = boxMesh->getSubmeshPointer(0);
     drawCall.material = material;
     drawCall.shaderPasses = shaderPasses;
-    
     buffer->drawCalls.push_back(drawCall);
     
 }

+ 19 - 19
src/modules/ui/PolyUIColorBox.cpp

@@ -33,8 +33,7 @@ UIColorPicker::UIColorPicker() : UIWindow(L"", 300, 240) {
 	closeOnEscape = true;
 	
 	continuous = true;
-		
-//	topPadding
+
 	Config *conf = CoreServices::getInstance()->getConfig();	
     Number uiScale = conf->getNumericValue("Polycode", "uiScale");
 		
@@ -59,25 +58,25 @@ UIColorPicker::UIColorPicker() : UIWindow(L"", 300, 240) {
 	addChild(alphaSlider);
 	alphaSlider->addEventListener(this, UIEvent::CHANGE_EVENT);
 	
-	mainColorRect = new SceneMesh(Mesh::TRI_MESH);
+	mainColorRect = new SceneMesh();
     mainColorRect->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
 	mainColorRect->setWidth(mainFrame->getWidth());
 	mainColorRect->setHeight(mainFrame->getWidth());
 	mainColorRect->setDepth(0.001);
-		
-	mainColorRect->getMesh()->addVertexWithUV(-mainFrame->getWidth()/2,mainFrame->getHeight()/2.0,0,0,0);
-	mainColorRect->getMesh()->addVertexWithUV(mainFrame->getWidth()/2,mainFrame->getHeight()/2.0,0, 1, 0);
-	mainColorRect->getMesh()->addVertexWithUV(mainFrame->getWidth()/2,-mainFrame->getHeight()/2.0,0, 1, 1);
-	mainColorRect->getMesh()->addVertexWithUV(-mainFrame->getWidth()/2,-mainFrame->getHeight()/2.0,0,0,1);
     
-    mainColorRect->getMesh()->indexedMesh = true;
     
-//    mainColorRect->getMesh()->addIndexedFace(0, 1, 2);
-//    mainColorRect->getMesh()->addIndexedFace(0, 2, 3);
+    MeshGeometry geometry;
     
-    mainColorRect->getMesh()->addIndexedFace(3, 0, 1);
-    mainColorRect->getMesh()->addIndexedFace(3, 1, 2);
+	geometry.addVertexWithUV(-mainFrame->getWidth()/2,mainFrame->getHeight()/2.0,0,0,0);
+	geometry.addVertexWithUV(mainFrame->getWidth()/2,mainFrame->getHeight()/2.0,0, 1, 0);
+	geometry.addVertexWithUV(mainFrame->getWidth()/2,-mainFrame->getHeight()/2.0,0, 1, 1);
+	geometry.addVertexWithUV(-mainFrame->getWidth()/2,-mainFrame->getHeight()/2.0,0,0,1);
+    geometry.indexedMesh = true;
+        
+    geometry.addIndexedFace(3, 0, 1);
+    geometry.addIndexedFace(3, 1, 2);
     
+    mainColorRect->getMesh()->addSubmesh(geometry);
     
 	mainColorRect->backfaceCulled = false;	
 
@@ -275,13 +274,14 @@ void UIColorPicker::updateSelectedColor(bool updateTextFields, bool updateHue, b
 	hueCol.setColorHSV(currentH, 1.0, 1.0);
 	hueCol.a = colorAlpha;
 
+    mainColorRect->getMesh()->clearMesh();
     
-    mainColorRect->getMesh()->vertexColorArray.data.clear();
-    
-    mainColorRect->getMesh()->addColor(Color((Number)1,(Number)1,(Number)1,colorAlpha));
-    mainColorRect->getMesh()->addColor(hueCol);
-    mainColorRect->getMesh()->addColor(Color((Number)0,(Number)0,(Number)0,colorAlpha));
-    mainColorRect->getMesh()->addColor(Color((Number)0,(Number)0,(Number)0,colorAlpha));
+    MeshGeometry geometry;
+    geometry.addColor(Color((Number)1,(Number)1,(Number)1,colorAlpha));
+    geometry.addColor(hueCol);
+    geometry.addColor(Color((Number)0,(Number)0,(Number)0,colorAlpha));
+    geometry.addColor(Color((Number)0,(Number)0,(Number)0,colorAlpha));
+    mainColorRect->getMesh()->addSubmesh(geometry);    
     
 	if(updateHue) {
 		hueSelector->setPositionY(hueFrame->getPosition().y + hueFrame->getHeight() - ((currentH/360.0) * hueFrame->getHeight()));

+ 40 - 32
src/modules/ui/PolyUIElement.cpp

@@ -220,22 +220,26 @@ void UIRect::setImageCoordinates(Number x, Number y, Number width, Number height
 	Number hFloat = height * pixelSizeY * imageScale;
 
     rectMesh->clearMesh();
-    rectMesh->indexedMesh = true;
     
-	rectMesh->addVertex(-whalf,-hhalf,0);
-	rectMesh->addTexCoord(xFloat, (1.0-yFloat) - hFloat);
+    rectMeshGeometry.vertexPositionArray.data.clear();
+    rectMeshGeometry.vertexTexCoordArray.data.clear();
+    
+	rectMeshGeometry.addVertex(-whalf,-hhalf,0);
+	rectMeshGeometry.addTexCoord(xFloat, (1.0-yFloat) - hFloat);
 
-	rectMesh->addVertex(-whalf+width,-hhalf,0);
-	rectMesh->addTexCoord(xFloat + wFloat, (1.0-yFloat) - hFloat);
+	rectMeshGeometry.addVertex(-whalf+width,-hhalf,0);
+	rectMeshGeometry.addTexCoord(xFloat + wFloat, (1.0-yFloat) - hFloat);
 
-	rectMesh->addVertex(-whalf+width,-hhalf+height,0);
-	rectMesh->addTexCoord(xFloat + wFloat, 1.0-yFloat);
+	rectMeshGeometry.addVertex(-whalf+width,-hhalf+height,0);
+	rectMeshGeometry.addTexCoord(xFloat + wFloat, 1.0-yFloat);
 
-	rectMesh->addVertex(-whalf,-hhalf+height,0);
-	rectMesh->addTexCoord(xFloat, 1.0-yFloat);
+	rectMeshGeometry.addVertex(-whalf,-hhalf+height,0);
+	rectMeshGeometry.addTexCoord(xFloat, 1.0-yFloat);
 
-    rectMesh->addIndexedFace(0, 1, 2);
-    rectMesh->addIndexedFace(0, 2, 3);
+    rectMeshGeometry.addIndexedFace(0, 1, 2);
+    rectMeshGeometry.addIndexedFace(0, 2, 3);
+    
+    rectMesh->addSubmesh(rectMeshGeometry);
     
     
 	rebuildTransformMatrix();
@@ -251,7 +255,7 @@ Number UIRect::getImageHeight() const {
 }
 
 void UIRect::initRect(Number width, Number height) {
-	rectMesh = new Mesh(Mesh::TRI_MESH);
+	rectMesh = new Mesh();
 	processInputEvents = true;
 
 	setAnchorPoint(-1.0, -1.0, 0.0);
@@ -260,15 +264,17 @@ void UIRect::initRect(Number width, Number height) {
 	
 	Number whalf = width/2.0f;
 	Number hhalf = height/2.0f;
-				
-	rectMesh->addVertexWithUV(-whalf,-hhalf,0,0,0);
-	rectMesh->addVertexWithUV(-whalf+width,-hhalf,0, 1, 0);
-	rectMesh->addVertexWithUV(-whalf+width,-hhalf+height,0, 1, 1);
-	rectMesh->addVertexWithUV(-whalf,-hhalf+height,0,0,1);
+	
+	rectMeshGeometry.addVertexWithUV(-whalf,-hhalf,0,0,0);
+	rectMeshGeometry.addVertexWithUV(-whalf+width,-hhalf,0, 1, 0);
+	rectMeshGeometry.addVertexWithUV(-whalf+width,-hhalf+height,0, 1, 1);
+	rectMeshGeometry.addVertexWithUV(-whalf,-hhalf+height,0,0,1);
+    
+    rectMeshGeometry.indexedMesh = true;
+    rectMeshGeometry.addIndexedFace(0, 1, 2);
+    rectMeshGeometry.addIndexedFace(0, 2, 3);
     
-    rectMesh->indexedMesh = true;
-    rectMesh->addIndexedFace(0, 1, 2);
-    rectMesh->addIndexedFace(0, 2, 3);
+    rectMesh->addSubmesh(rectMeshGeometry);
     
     setMaterial((Material*)CoreServices::getInstance()->getResourceManager()->getGlobalPool()->getResource(Resource::RESOURCE_MATERIAL, "UnlitUntextured"));
     
@@ -331,7 +337,6 @@ void UIRect::setMaterial(Material *material) {
     shaderPasses.push_back(pass);
     
     shaderPasses[0].shaderBinding->addParamPointer(ProgramParam::PARAM_COLOR, "entityColor", &color);
-    shaderPasses[0].setAttributeArraysFromMesh(rectMesh);
     shaderPasses[0].shaderBinding->resetAttributes = true;
 }
 
@@ -344,7 +349,10 @@ void UIRect::Render(GPUDrawBuffer *buffer) {
     drawCall.options.depthTest = depthTest;
     drawCall.options.depthWrite = depthWrite;
     
-    drawCall.mesh = rectMesh;
+    if(rectMesh->getNumSubmeshes() == 0) {
+        assert(false);
+    }
+    drawCall.submesh = rectMesh->getSubmeshPointer(0);
     drawCall.material = material;
     drawCall.shaderPasses = shaderPasses;
     
@@ -359,18 +367,18 @@ void UIRect::Resize(Number width, Number height) {
 	Number whalf = width/2.0f;
 	Number hhalf = height/2.0f;
 
-    rectMesh->vertexPositionArray.data.clear();
-    rectMesh->indexArray.data.clear();
-    rectMesh->indexedMesh = true;
-
-    rectMesh->addVertex(-whalf,-hhalf,0);
-    rectMesh->addVertex(-whalf+width,-hhalf,0);
-    rectMesh->addVertex(-whalf+width,-hhalf+height,0);
-    rectMesh->addVertex(-whalf,-hhalf+height,0);
+    rectMesh->clearMesh();
+    
+    rectMeshGeometry.vertexPositionArray.data.clear();
+    rectMeshGeometry.addVertex(-whalf,-hhalf,0);
+    rectMeshGeometry.addVertex(-whalf+width,-hhalf,0);
+    rectMeshGeometry.addVertex(-whalf+width,-hhalf+height,0);
+    rectMeshGeometry.addVertex(-whalf,-hhalf+height,0);
     
-    rectMesh->addIndexedFace(0, 1, 2);
-    rectMesh->addIndexedFace(0, 2, 3);
+    rectMeshGeometry.addIndexedFace(0, 1, 2);
+    rectMeshGeometry.addIndexedFace(0, 2, 3);
     
+    rectMesh->addSubmesh(rectMeshGeometry);
 }
 
 UIImage::UIImage(String imagePath, int width, int height) : UIRect(imagePath, width, height) {

+ 20 - 21
src/tools/polyimport.cpp

@@ -71,12 +71,9 @@ void addToMesh(String prefix, Polycode::Mesh *tmesh, const struct aiScene *sc, c
 	// draw all meshes assigned to this node
 
 	for (; n < nd->mNumMeshes; ++n) {
-	
-		if(!addSubmeshes) {
-			tmesh = new Polycode::Mesh(Mesh::TRI_MESH);
-            tmesh->indexedMesh = true;
-		}
-	
+
+        MeshGeometry geometry;
+        
 		const struct aiMesh* mesh = scene->mMeshes[nd->mMeshes[n]];
         
         Vector3 bBox;
@@ -108,7 +105,7 @@ void addToMesh(String prefix, Polycode::Mesh *tmesh, const struct aiScene *sc, c
 		//apply_material(sc->mMaterials[mesh->mMaterialIndex]);
         
         
-        int baseVertexCount = tmesh->getVertexCount();
+        int baseVertexCount = 0;
         
 		for (t = 0; t < mesh->mNumVertices; ++t) {
 
@@ -116,33 +113,33 @@ void addToMesh(String prefix, Polycode::Mesh *tmesh, const struct aiScene *sc, c
             
             int index = t;
             if(mesh->mColors[0] != NULL) {
-                tmesh->addColor(mesh->mColors[0][index].r, mesh->mColors[0][index].g, mesh->mColors[0][index].b, mesh->mColors[0][index].a);
+                geometry.addColor(mesh->mColors[0][index].r, mesh->mColors[0][index].g, mesh->mColors[0][index].b, mesh->mColors[0][index].a);
             }
 
             if(mesh->mTangents != NULL)  {
                 if(swapZY) {
-                    tmesh->addTangent(mesh->mTangents[index].x, mesh->mTangents[index].z, -mesh->mTangents[index].y);
+                    geometry.addTangent(mesh->mTangents[index].x, mesh->mTangents[index].z, -mesh->mTangents[index].y);
                 } else {
-                    tmesh->addTangent(mesh->mTangents[index].x, mesh->mTangents[index].y, mesh->mTangents[index].z);
+                    geometry.addTangent(mesh->mTangents[index].x, mesh->mTangents[index].y, mesh->mTangents[index].z);
                 }
             }
 
             if(mesh->mNormals != NULL)  {
                 if(swapZY) {
-                    tmesh->addNormal(mesh->mNormals[index].x, mesh->mNormals[index].z, -mesh->mNormals[index].y);
+                    geometry.addNormal(mesh->mNormals[index].x, mesh->mNormals[index].z, -mesh->mNormals[index].y);
                 } else {
-                    tmesh->addNormal(mesh->mNormals[index].x, mesh->mNormals[index].y, mesh->mNormals[index].z);
+                    geometry.addNormal(mesh->mNormals[index].x, mesh->mNormals[index].y, mesh->mNormals[index].z);
                 }
             }
 
             if(mesh->HasTextureCoords(0))
             {
-                tmesh->addTexCoord(mesh->mTextureCoords[0][index].x, mesh->mTextureCoords[0][index].y);
+                geometry.addTexCoord(mesh->mTextureCoords[0][index].x, mesh->mTextureCoords[0][index].y);
             }
 
             if(mesh->HasTextureCoords(1))
             {
-                tmesh->addTexCoord2(mesh->mTextureCoords[1][index].x, mesh->mTextureCoords[1][index].y);
+                geometry.addTexCoord2(mesh->mTextureCoords[1][index].x, mesh->mTextureCoords[1][index].y);
             }
 
             int numAssignments = 0;
@@ -167,7 +164,7 @@ void addToMesh(String prefix, Polycode::Mesh *tmesh, const struct aiScene *sc, c
             }
             
             
-            tmesh->addBoneAssignments(weights[0], boneIds[0], weights[1], boneIds[1], weights[2], boneIds[2], weights[3], boneIds[3]);
+            geometry.addBoneAssignments(weights[0], boneIds[0], weights[1], boneIds[1], weights[2], boneIds[2], weights[3], boneIds[3]);
 
             if(swapZY) {
 					vPosition.set(mesh->mVertices[index].x, mesh->mVertices[index].z, -mesh->mVertices[index].y);
@@ -185,7 +182,7 @@ void addToMesh(String prefix, Polycode::Mesh *tmesh, const struct aiScene *sc, c
                 bBox.z = fabs(vPosition.z);
             }
             
-            tmesh->addVertex(vPosition.x, vPosition.y, vPosition.z);
+            geometry.addVertex(vPosition.x, vPosition.y, vPosition.z);
 		}
         
 
@@ -198,14 +195,17 @@ void addToMesh(String prefix, Polycode::Mesh *tmesh, const struct aiScene *sc, c
 
              for(i = 0; i < face->mNumIndices; i++) {
                  int index = face->mIndices[i];
-                 tmesh->addIndex(baseVertexCount+index);
+                 geometry.addIndex(baseVertexCount+index);
              }
          }
 		
 		if(!addSubmeshes && !listOnly) {
 			String fileNameMesh = prefix+meshFileName+".mesh";
-			tmesh->saveToFile(fileNameMesh, writeNormals, writeTangents, writeColors, writeBoneWeights, writeUVs, writeSecondaryUVs);
-			delete tmesh;
+            
+            Mesh *nmesh = new Polycode::Mesh();
+            nmesh->addSubmesh(geometry);
+			nmesh->saveToFile(fileNameMesh, writeNormals, writeTangents, writeColors, writeBoneWeights, writeUVs, writeSecondaryUVs);
+			delete nmesh;
             
             ObjectEntry *meshEntry = parentSceneObject->addChild("child");
             meshEntry->addChild("id", String(nd->mName.data));
@@ -386,8 +386,7 @@ int exportToFile(String prefix, bool swapZY, bool addSubmeshes, bool listOnly, b
     ObjectEntry *children = parentEntry->addChild("children");
 
 		
-	Polycode::Mesh *mesh = new Polycode::Mesh(Mesh::TRI_MESH);
-    mesh->indexedMesh = true;
+	Polycode::Mesh *mesh = new Polycode::Mesh();
 	addToMesh(prefix, mesh, scene, scene->mRootNode, swapZY, addSubmeshes, listOnly, children, overrideMaterial, materialsParent, assetPrefixPath, baseFileName);