Quellcode durchsuchen

merged with develop

Mark Sibly vor 7 Jahren
Ursprung
Commit
72b44597cf
100 geänderte Dateien mit 11387 neuen und 6615 gelöschten Zeilen
  1. 2 2
      ABOUT.HTML
  2. 38 0
      VERSIONS.TXT
  3. 179 175
      ducks-scene.mojo3d
  4. 4231 0
      hingechain-scene.mojo3d
  5. 4132 0
      jointchain-scene.mojo3d
  6. 1 0
      modules/assimp/assimp.monkey2
  7. 2 0
      modules/assimp/makefile.monkey2
  8. 1 1
      modules/assimp/module.json
  9. 81 2
      modules/bullet/bullet.monkey2
  10. 39 0
      modules/bullet/bullet_glue.h
  11. 1 1
      modules/miniz/native/miniz.h
  12. 18 20
      modules/mojo/app/app.monkey2
  13. 41 22
      modules/mojo/graphics/shader.monkey2
  14. 90 63
      modules/mojo/graphics/texture.monkey2
  15. 7 6
      modules/mojo/graphics/uniformblock.monkey2
  16. 11 4
      modules/mojo3d-loaders/loaders/assimp.monkey2
  17. 41 24
      modules/mojo3d-loaders/tests/castle.monkey2
  18. 0 27
      modules/mojo3d/assets/shaders/copy.glsl
  19. 0 72
      modules/mojo3d/assets/shaders/effect-bloom.glsl
  20. 74 0
      modules/mojo3d/assets/shaders/effects/bloom.glsl
  21. 7 8
      modules/mojo3d/assets/shaders/effects/monochrome.glsl
  22. 147 0
      modules/mojo3d/assets/shaders/effects/reflection.glsl
  23. 0 60
      modules/mojo3d/assets/shaders/fog-deferred.glsl
  24. 260 0
      modules/mojo3d/assets/shaders/imports/pbr.glsl
  25. 455 0
      modules/mojo3d/assets/shaders/imports/std.glsl
  26. 0 223
      modules/mojo3d/assets/shaders/lighting-deferred.glsl
  27. 0 310
      modules/mojo3d/assets/shaders/material-pbr-deferred.glsl
  28. 0 449
      modules/mojo3d/assets/shaders/material-pbr-forward.glsl
  29. 0 75
      modules/mojo3d/assets/shaders/material-sprite.glsl
  30. 0 125
      modules/mojo3d/assets/shaders/material-water.glsl
  31. 6 41
      modules/mojo3d/assets/shaders/materials/particle.glsl
  32. 86 0
      modules/mojo3d/assets/shaders/materials/pbr-default.glsl
  33. 26 0
      modules/mojo3d/assets/shaders/materials/sprite.glsl
  34. 50 0
      modules/mojo3d/assets/shaders/materials/water.glsl
  35. 26 0
      modules/mojo3d/assets/shaders/misc/copy.glsl
  36. 35 0
      modules/mojo3d/assets/shaders/misc/fog-deferred.glsl
  37. 30 0
      modules/mojo3d/assets/shaders/misc/lighting-deferred.glsl
  38. 43 0
      modules/mojo3d/assets/shaders/misc/skybox.glsl
  39. 0 38
      modules/mojo3d/assets/shaders/skybox-deferred.glsl
  40. 0 38
      modules/mojo3d/assets/shaders/skybox.glsl
  41. 9 3
      modules/mojo3d/loader/gltf2.monkey2
  42. 51 12
      modules/mojo3d/loader/gltf2loader.monkey2
  43. 2 1
      modules/mojo3d/mojo3d.monkey2
  44. 250 99
      modules/mojo3d/render/renderer.monkey2
  45. 23 12
      modules/mojo3d/render/renderqueue.monkey2
  46. 6 0
      modules/mojo3d/render/spritebuffer.monkey2
  47. 310 0
      modules/mojo3d/scene/components/joint.monkey2
  48. 41 3
      modules/mojo3d/scene/components/rigidbody.monkey2
  49. 17 50
      modules/mojo3d/scene/effects/bloomeffect.monkey2
  50. 0 78
      modules/mojo3d/scene/effects/fogeffect.monkey2
  51. 8 20
      modules/mojo3d/scene/effects/monochromeeffect.monkey2
  52. 26 0
      modules/mojo3d/scene/effects/reflectioneffect.monkey2
  53. 4 4
      modules/mojo3d/scene/entities/camera.monkey2
  54. 54 7
      modules/mojo3d/scene/entities/light.monkey2
  55. 4 4
      modules/mojo3d/scene/entities/model.monkey2
  56. 4 19
      modules/mojo3d/scene/entities/particlematerial.monkey2
  57. 5 0
      modules/mojo3d/scene/entities/particlesystem.monkey2
  58. 7 0
      modules/mojo3d/scene/entityexts.monkey2
  59. 74 87
      modules/mojo3d/scene/jsonifier/jsonifier.monkey2
  60. 99 33
      modules/mojo3d/scene/material.monkey2
  61. 94 121
      modules/mojo3d/scene/materials/pbrmaterial.monkey2
  62. 2 32
      modules/mojo3d/scene/materials/spritematerial.monkey2
  63. 16 29
      modules/mojo3d/scene/materials/watermaterial.monkey2
  64. 14 0
      modules/mojo3d/scene/mesh.monkey2
  65. 39 23
      modules/mojo3d/scene/posteffect.monkey2
  66. 2 5
      modules/mojo3d/scene/scene.monkey2
  67. 3 4
      modules/mojo3d/scene/world.monkey2
  68. 2 4
      modules/mojo3d/tests/alphacubes.monkey2
  69. 0 86
      modules/mojo3d/tests/anisotropic.monkey2
  70. BIN
      modules/mojo3d/tests/assets/Monkey2logo_64.png
  71. BIN
      modules/mojo3d/tests/assets/bluspark.png
  72. BIN
      modules/mojo3d/tests/assets/bouncyball/bouncyball.bin
  73. 0 589
      modules/mojo3d/tests/assets/bouncyball/bouncyball.gltf
  74. BIN
      modules/mojo3d/tests/assets/heightmap_256.BMP
  75. BIN
      modules/mojo3d/tests/assets/monkey2-logo.png
  76. 0 1
      modules/mojo3d/tests/assets/mossy-ground1.pbr/About these PBR files.txt
  77. BIN
      modules/mojo3d/tests/assets/mossy-ground1.pbr/color.png
  78. BIN
      modules/mojo3d/tests/assets/mossy-ground1.pbr/height.png
  79. BIN
      modules/mojo3d/tests/assets/mossy-ground1.pbr/metalness.png
  80. BIN
      modules/mojo3d/tests/assets/mossy-ground1.pbr/normal.png
  81. BIN
      modules/mojo3d/tests/assets/mossy-ground1.pbr/occlusion.png
  82. BIN
      modules/mojo3d/tests/assets/mossy-ground1.pbr/roughness.png
  83. BIN
      modules/mojo3d/tests/assets/mossy.pbr/color.png
  84. BIN
      modules/mojo3d/tests/assets/mossy.pbr/normal.png
  85. BIN
      modules/mojo3d/tests/assets/mossy.pbr/occlusion.png
  86. BIN
      modules/mojo3d/tests/assets/platform.glb
  87. BIN
      modules/mojo3d/tests/assets/terrain_256.png
  88. BIN
      modules/mojo3d/tests/assets/walker/walk.bin
  89. 0 2470
      modules/mojo3d/tests/assets/walker/walk.gltf
  90. BIN
      modules/mojo3d/tests/assets/water1.jpg
  91. 0 76
      modules/mojo3d/tests/bouncyball_gltf2.monkey2
  92. 0 324
      modules/mojo3d/tests/bouncyboxes.monkey2
  93. 0 88
      modules/mojo3d/tests/cubes.monkey2
  94. 0 94
      modules/mojo3d/tests/cubeseam.monkey2
  95. 0 78
      modules/mojo3d/tests/donut.monkey2
  96. 0 131
      modules/mojo3d/tests/ducks-scene.monkey2
  97. 46 38
      modules/mojo3d/tests/ducks.monkey2
  98. 15 7
      modules/mojo3d/tests/effects.monkey2
  99. 0 127
      modules/mojo3d/tests/fishes.monkey2
  100. 0 70
      modules/mojo3d/tests/glb_test.monkey2

+ 2 - 2
ABOUT.HTML

@@ -45,9 +45,9 @@ a:hover{
 
 <body>
 
-<h1>Monkey2 v2018.04</h1>
+<h1>Monkey2 v2018.05</h1>
 
-<h2>Mx2cc v1.1.12</h2>
+<h2>Mx2cc v1.1.13</h2>
 <h2>Ted2go v2.10</h2>
 
 <p>Welcome to monkey2, an open source, user friendly, cross platform programming language by Mark Sibly.

+ 38 - 0
VERSIONS.TXT

@@ -1,4 +1,42 @@
 
+***** Monkey-v2018.05 Mx2cc-v1.1.13 Ted2go-2.10 *****
+
+Added simple support for .hdr pixmap/texture/image loading (wont work on android).
+
+Added mojo3d HingeJoint. See tests/hingechain.monkey2
+
+Renamed mojo3d Constraint->Joint and PointToPointConstraint->BallSocketJoint.
+
+Added mojo3d support for 'spherical' sky textures. Also added TextureFlags.Envmap which must be used for envmap textures. Previously, cubemap+mipmap implied envmap but this is no longer true.
+
+Fixed a very gnarly bug in garbage collector. Thanks Mac767!
+
+Changed emscripten module builds so they generate .bc files instead of .a for a minor link speed up.
+
+Added experimental spot and point light texturing via new Light.Texture property. See tests/spotlight and tests/room for demos.
+
+Added RigidBody.LinearFactor and RigidBody.Angular factor properties - untested!
+
+Added support for multiple UVs to gltf2 and assimp loaders.
+
+Streamlined mojo3d tests dir.
+
+Added LinearDamping and AngularDamping properties to RigidBody, but can't get them to do anything so far - please have a play James!
+
+Added 'offset' version of ApplyImpulse to RigidBody.
+
+Added AmbientTexture and AmbientFactor to PbrMaterial. Like EmissiveFactor, AmbientFactor defaults to black so needs to be set to white to enable AmbientTexture.
+
+Major clean up of mojo3d material system. Minor cleanup of post effect system, mainly just added some helper methods in base PostEffect class.
+
+Added multidimensional array initializers, eg: New Int[2,2]( 1,2,3,4 ). Array length much match number of elements exactly or runtime error.
+
+Added first physics constraint component to mojo3d, PointToPointConstraint - should probably be renamed joint IMO. Stay tuned...
+
+Added low budget OpenUrl for emscripten. It just replaces current page with the given URL so effectively ends app too.
+
+Added zlib module and DataBuffer.Compress and DataBuffer.Decompress.
+
 ***** Monkey-v2018.04 Mx2cc-v1.1.12 Ted2go-2.10 *****
 
 Added GetPixel and GetPixelARGB to both Image and Canvas classes - canvas version will be slow as hell, eg: 3 secs for 16x16! Image versions still relies on the 'managed pixmap hack', but I should be able to improve on the speed of this for desktop targets.

Datei-Diff unterdrückt, da er zu groß ist
+ 179 - 175
ducks-scene.mojo3d


+ 4231 - 0
hingechain-scene.mojo3d

@@ -0,0 +1,4231 @@
+{
+	"assetsDir":"modules/mojo3d/tests/assets/",
+	"instances":[{
+		"ctor":{
+			"args":[true],
+			"decl":"mojo3d.Scene.New",
+			"type":"Void(Bool)"
+		},
+		"id":0,
+		"state":{
+			"AmbientLight":[0.05000000074505806,0.15000000596046448,0.25,0.25],
+			"ClearColor":[0.20000000298023224,0.60000002384185791,1,1],
+			"FogColor":[0.20000000298023224,0.60000002384185791,1,1],
+			"FogFar":200
+		},
+		"type":"mojo3d.Scene"
+	},{
+		"ctor":{
+			"args":[null],
+			"decl":"mojo3d.Camera.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":1,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,2.5,-5]
+		},
+		"type":"mojo3d.Camera"
+	},{
+		"ctor":{
+			"args":["@1"],
+			"decl":"mojo3d.FlyBehaviour.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":2,
+		"type":"mojo3d.FlyBehaviour"
+	},{
+		"ctor":{
+			"args":[null],
+			"decl":"mojo3d.Light.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":3,
+		"state":{
+			"CastsShadow":true,
+			"LocalMatrix":[0.70710676908493042,0,0.70710676908493042,-0.49999997019767761,0.70710676908493042,0.49999997019767761,-0.49999997019767761,-0.70710676908493042,0.49999997019767761,0,0,0]
+		},
+		"type":"mojo3d.Light"
+	},{
+		"ctor":{
+			"args":[[0.69999998807907104,1,0,1],1,1],
+			"decl":"mojo3d.PbrMaterial.New",
+			"type":"Void(std.graphics.Color,Float,Float)"
+		},
+		"id":4,
+		"type":"mojo3d.PbrMaterial"
+	},{
+		"ctor":{
+			"args":[[-100,-1,-100,100,0,100],1,1,1],
+			"decl":"mojo3d.Mesh.CreateBox",
+			"type":"mojo3d.Mesh(std.geom.Box<monkey.types.Float>,Int,Int,Int)"
+		},
+		"id":5,
+		"type":"mojo3d.Mesh"
+	},{
+		"ctor":{
+			"args":["@5","@4",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Mesh,mojo3d.Material,mojo3d.Entity)"
+		},
+		"id":6,
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@6"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":7,
+		"state":{
+			"Box":[-100,-1,-100,100,0,100]
+		},
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@6"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":8,
+		"state":{
+			"Mass":0
+		},
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":[[1,0,0,1],0.05000000074505806,0.20000000298023224],
+			"decl":"mojo3d.PbrMaterial.New",
+			"type":"Void(std.graphics.Color,Float,Float)"
+		},
+		"id":9,
+		"type":"mojo3d.PbrMaterial"
+	},{
+		"ctor":{
+			"args":[[-0.20000000298023224,-0.44999998807907104,-0.0099999997764825821,0.20000000298023224,0.44999998807907104,0.0099999997764825821],1,1,1],
+			"decl":"mojo3d.Mesh.CreateBox",
+			"type":"mojo3d.Mesh(std.geom.Box<monkey.types.Float>,Int,Int,Int)"
+		},
+		"id":10,
+		"type":"mojo3d.Mesh"
+	},{
+		"ctor":{
+			"args":["@10","@9",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Mesh,mojo3d.Material,mojo3d.Entity)"
+		},
+		"id":11,
+		"state":{
+			"Visible":false
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@11"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":12,
+		"state":{
+			"Box":[-0.20000000298023224,-0.44999998807907104,-0.0099999997764825821,0.20000000298023224,0.44999998807907104,0.0099999997764825821]
+		},
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@11"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":13,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":14,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,10,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@14","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":15,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@14","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":16,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":17,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,11,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@17","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":18,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@17","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":19,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@17"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":20,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@16",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":21,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,12,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@21","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":22,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@21","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":23,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@21"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":24,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@19",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":25,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,13,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@25","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":26,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@25","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":27,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@25"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":28,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@23",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":29,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,14,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@29","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":30,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@29","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":31,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@29"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":32,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@27",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":33,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,15,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@33","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":34,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@33","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":35,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@33"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":36,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@31",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":37,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,16,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@37","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":38,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@37","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":39,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@37"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":40,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@35",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":41,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,17,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@41","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":42,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@41","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":43,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@41"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":44,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@39",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":45,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,18,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@45","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":46,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@45","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":47,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@45"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":48,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@43",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":49,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,19,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@49","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":50,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@49","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":51,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@49"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":52,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@47",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":53,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,20,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@53","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":54,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@53","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":55,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@53"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":56,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@51",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":57,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,21,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@57","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":58,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@57","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":59,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@57"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":60,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@55",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":61,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,22,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@61","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":62,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@61","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":63,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@61"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":64,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@59",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":65,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,23,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@65","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":66,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@65","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":67,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@65"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":68,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@63",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":69,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,24,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@69","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":70,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@69","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":71,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@69"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":72,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@67",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":73,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,25,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@73","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":74,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@73","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":75,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@73"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":76,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@71",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":77,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,26,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@77","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":78,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@77","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":79,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@77"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":80,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@75",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":81,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,27,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@81","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":82,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@81","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":83,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@81"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":84,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@79",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":85,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,28,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@85","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":86,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@85","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":87,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@85"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":88,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@83",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":89,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,29,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@89","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":90,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@89","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":91,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@89"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":92,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@87",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":93,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,30,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@93","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":94,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@93","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":95,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@93"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":96,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@91",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":97,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,31,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@97","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":98,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@97","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":99,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@97"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":100,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@95",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":101,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,32,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@101","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":102,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@101","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":103,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@101"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":104,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@99",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":105,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,33,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@105","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":106,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@105","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":107,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@105"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":108,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@103",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":109,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,34,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@109","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":110,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@109","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":111,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@109"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":112,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@107",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":113,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,35,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@113","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":114,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@113","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":115,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@113"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":116,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@111",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":117,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,36,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@117","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":118,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@117","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":119,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@117"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":120,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@115",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":121,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,37,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@121","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":122,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@121","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":123,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@121"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":124,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@119",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":125,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,38,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@125","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":126,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@125","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":127,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@125"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":128,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@123",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":129,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,39,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@129","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":130,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@129","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":131,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@129"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":132,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@127",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":133,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,40,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@133","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":134,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@133","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":135,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@133"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":136,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@131",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":137,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,41,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@137","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":138,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@137","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":139,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@137"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":140,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@135",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":141,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,42,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@141","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":142,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@141","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":143,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@141"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":144,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@139",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":145,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,43,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@145","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":146,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@145","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":147,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@145"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":148,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@143",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":149,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,44,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@149","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":150,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@149","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":151,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@149"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":152,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@147",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":153,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,45,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@153","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":154,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@153","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":155,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@153"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":156,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@151",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":157,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,46,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@157","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":158,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@157","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":159,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@157"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":160,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@155",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":161,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,47,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@161","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":162,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@161","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":163,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@161"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":164,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@159",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":165,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,48,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@165","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":166,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@165","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":167,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@165"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":168,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@163",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":169,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,49,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@169","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":170,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@169","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":171,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@169"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":172,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@167",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":173,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,50,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@173","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":174,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@173","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":175,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@173"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":176,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@171",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":177,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,51,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@177","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":178,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@177","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":179,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@177"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":180,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@175",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":181,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,52,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@181","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":182,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@181","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":183,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@181"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":184,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@179",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":185,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,53,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@185","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":186,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@185","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":187,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@185"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":188,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@183",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":189,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,54,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@189","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":190,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@189","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":191,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@189"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":192,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@187",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":193,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,55,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@193","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":194,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@193","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":195,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@193"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":196,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@191",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":197,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,56,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@197","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":198,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@197","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":199,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@197"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":200,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@195",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":201,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,57,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@201","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":202,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@201","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":203,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@201"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":204,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@199",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":205,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,58,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@205","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":206,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@205","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":207,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@205"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":208,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@203",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":209,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,59,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@209","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":210,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@209","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":211,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@209"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":212,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@207",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":213,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,60,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@213","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":214,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@213","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":215,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@213"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":216,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@211",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":217,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,61,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@217","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":218,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@217","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":219,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@217"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":220,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@215",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":221,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,62,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@221","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":222,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@221","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":223,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@221"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":224,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@219",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":225,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,63,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@225","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":226,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@225","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":227,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@225"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":228,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@223",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":229,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,64,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@229","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":230,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@229","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":231,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@229"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":232,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@227",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":233,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,65,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@233","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":234,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@233","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":235,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@233"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":236,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@231",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":237,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,66,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@237","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":238,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@237","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":239,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@237"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":240,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@235",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":241,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,67,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@241","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":242,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@241","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":243,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@241"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":244,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@239",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":245,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,68,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@245","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":246,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@245","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":247,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@245"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":248,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@243",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":249,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,69,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@249","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":250,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@249","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":251,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@249"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":252,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@247",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":253,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,70,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@253","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":254,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@253","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":255,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@253"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":256,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@251",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":257,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,71,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@257","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":258,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@257","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":259,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@257"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":260,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@255",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":261,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,72,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@261","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":262,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@261","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":263,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@261"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":264,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@259",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":265,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,73,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@265","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":266,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@265","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":267,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@265"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":268,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@263",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":269,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,74,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@269","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":270,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@269","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":271,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@269"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":272,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@267",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":273,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,75,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@273","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":274,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@273","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":275,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@273"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":276,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@271",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":277,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,76,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@277","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":278,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@277","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":279,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@277"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":280,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@275",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":281,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,77,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@281","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":282,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@281","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":283,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@281"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":284,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@279",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":285,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,78,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@285","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":286,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@285","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":287,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@285"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":288,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@283",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":289,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,79,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@289","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":290,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@289","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":291,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@289"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":292,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@287",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":293,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,80,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@293","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":294,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@293","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":295,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@293"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":296,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@291",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":297,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,81,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@297","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":298,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@297","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":299,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@297"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":300,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@295",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":301,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,82,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@301","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":302,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@301","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":303,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@301"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":304,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@299",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":305,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,83,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@305","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":306,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@305","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":307,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@305"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":308,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@303",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":309,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,84,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@309","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":310,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@309","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":311,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@309"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":312,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@307",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":313,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,85,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@313","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":314,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@313","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":315,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@313"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":316,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@311",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":317,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,86,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@317","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":318,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@317","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":319,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@317"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":320,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@315",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":321,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,87,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@321","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":322,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@321","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":323,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@321"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":324,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@319",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":325,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,88,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@325","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":326,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@325","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":327,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@325"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":328,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@323",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":329,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,89,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@329","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":330,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@329","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":331,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@329"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":332,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@327",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":333,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,90,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@333","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":334,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@333","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":335,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@333"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":336,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@331",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":337,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,91,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@337","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":338,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@337","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":339,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@337"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":340,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@335",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":341,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,92,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@341","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":342,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@341","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":343,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@341"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":344,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@339",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":345,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,93,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@345","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":346,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@345","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":347,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@345"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":348,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@343",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":349,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,94,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@349","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":350,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@349","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":351,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@349"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":352,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@347",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":353,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,95,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@353","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":354,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@353","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":355,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@353"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":356,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@351",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":357,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,96,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@357","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":358,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@357","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":359,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@357"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":360,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@355",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":361,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,97,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@361","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":362,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@361","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":363,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@361"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":364,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@359",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":365,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,98,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@365","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":366,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@365","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":367,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@365"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":368,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@363",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":369,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,99,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@369","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":370,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@369","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":371,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@369"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":372,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@367",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":373,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,100,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@373","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":374,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@373","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":375,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@373"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":376,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@371",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":377,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,101,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@377","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":378,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@377","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":379,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@377"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":380,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@375",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":381,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,102,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@381","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":382,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@381","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":383,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@381"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":384,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@379",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":385,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,103,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@385","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":386,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@385","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":387,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@385"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":388,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@383",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":389,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,104,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@389","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":390,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@389","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":391,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@389"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":392,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@387",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":393,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,105,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@393","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":394,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@393","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":395,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@393"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":396,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@391",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":397,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,106,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@397","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":398,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@397","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":399,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@397"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":400,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@395",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":401,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,107,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@401","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":402,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@401","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":403,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@401"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":404,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@399",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":405,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,108,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@405","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":406,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@405","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":407,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@405"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":408,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@403",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":409,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,109,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@409","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":410,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@409","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":411,
+		"state":{
+			"Mass":0
+		},
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@409"],
+			"decl":"mojo3d.HingeJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":412,
+		"state":{
+			"Axis":[1,0,0],
+			"ConnectedBody":"@407",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.HingeJoint"
+	}]
+}

+ 4132 - 0
jointchain-scene.mojo3d

@@ -0,0 +1,4132 @@
+{
+	"assetsDir":"modules/mojo3d/tests/assets/",
+	"instances":[{
+		"ctor":{
+			"args":[true],
+			"decl":"mojo3d.Scene.New",
+			"type":"Void(Bool)"
+		},
+		"id":0,
+		"state":{
+			"AmbientLight":[0.05000000074505806,0.15000000596046448,0.25,0.25],
+			"ClearColor":[0.20000000298023224,0.60000002384185791,1,1],
+			"FogColor":[0.20000000298023224,0.60000002384185791,1,1],
+			"FogFar":200
+		},
+		"type":"mojo3d.Scene"
+	},{
+		"ctor":{
+			"args":[null],
+			"decl":"mojo3d.Camera.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":1,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,2.5,-5]
+		},
+		"type":"mojo3d.Camera"
+	},{
+		"ctor":{
+			"args":["@1"],
+			"decl":"mojo3d.FlyBehaviour.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":2,
+		"type":"mojo3d.FlyBehaviour"
+	},{
+		"ctor":{
+			"args":[null],
+			"decl":"mojo3d.Light.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":3,
+		"state":{
+			"CastsShadow":true,
+			"LocalMatrix":[0.70710676908493042,0,0.70710676908493042,-0.49999997019767761,0.70710676908493042,0.49999997019767761,-0.49999997019767761,-0.70710676908493042,0.49999997019767761,0,0,0]
+		},
+		"type":"mojo3d.Light"
+	},{
+		"ctor":{
+			"args":[[0.69999998807907104,1,0,1],1,1],
+			"decl":"mojo3d.PbrMaterial.New",
+			"type":"Void(std.graphics.Color,Float,Float)"
+		},
+		"id":4,
+		"type":"mojo3d.PbrMaterial"
+	},{
+		"ctor":{
+			"args":[[-100,-1,-100,100,0,100],1,1,1],
+			"decl":"mojo3d.Mesh.CreateBox",
+			"type":"mojo3d.Mesh(std.geom.Box<monkey.types.Float>,Int,Int,Int)"
+		},
+		"id":5,
+		"type":"mojo3d.Mesh"
+	},{
+		"ctor":{
+			"args":["@5","@4",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Mesh,mojo3d.Material,mojo3d.Entity)"
+		},
+		"id":6,
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@6"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":7,
+		"state":{
+			"Box":[-100,-1,-100,100,0,100]
+		},
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@6"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":8,
+		"state":{
+			"Mass":0
+		},
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":[[1,0,0,1],0.05000000074505806,0.20000000298023224],
+			"decl":"mojo3d.PbrMaterial.New",
+			"type":"Void(std.graphics.Color,Float,Float)"
+		},
+		"id":9,
+		"type":"mojo3d.PbrMaterial"
+	},{
+		"ctor":{
+			"args":[[-0.10000000149011612,-0.44999998807907104,-0.10000000149011612,0.10000000149011612,0.44999998807907104,0.10000000149011612],1,1,1],
+			"decl":"mojo3d.Mesh.CreateBox",
+			"type":"mojo3d.Mesh(std.geom.Box<monkey.types.Float>,Int,Int,Int)"
+		},
+		"id":10,
+		"type":"mojo3d.Mesh"
+	},{
+		"ctor":{
+			"args":["@10","@9",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Mesh,mojo3d.Material,mojo3d.Entity)"
+		},
+		"id":11,
+		"state":{
+			"Visible":false
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@11"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":12,
+		"state":{
+			"Box":[-0.10000000149011612,-0.44999998807907104,-0.10000000149011612,0.10000000149011612,0.44999998807907104,0.10000000149011612]
+		},
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@11"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":13,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":14,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,10,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@14","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":15,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@14","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":16,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":17,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,11,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@17","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":18,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@17","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":19,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@17"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":20,
+		"state":{
+			"ConnectedBody":"@16",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":21,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,12,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@21","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":22,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@21","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":23,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@21"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":24,
+		"state":{
+			"ConnectedBody":"@19",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":25,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,13,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@25","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":26,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@25","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":27,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@25"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":28,
+		"state":{
+			"ConnectedBody":"@23",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":29,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,14,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@29","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":30,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@29","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":31,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@29"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":32,
+		"state":{
+			"ConnectedBody":"@27",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":33,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,15,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@33","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":34,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@33","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":35,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@33"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":36,
+		"state":{
+			"ConnectedBody":"@31",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":37,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,16,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@37","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":38,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@37","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":39,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@37"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":40,
+		"state":{
+			"ConnectedBody":"@35",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":41,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,17,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@41","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":42,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@41","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":43,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@41"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":44,
+		"state":{
+			"ConnectedBody":"@39",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":45,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,18,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@45","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":46,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@45","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":47,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@45"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":48,
+		"state":{
+			"ConnectedBody":"@43",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":49,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,19,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@49","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":50,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@49","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":51,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@49"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":52,
+		"state":{
+			"ConnectedBody":"@47",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":53,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,20,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@53","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":54,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@53","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":55,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@53"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":56,
+		"state":{
+			"ConnectedBody":"@51",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":57,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,21,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@57","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":58,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@57","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":59,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@57"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":60,
+		"state":{
+			"ConnectedBody":"@55",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":61,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,22,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@61","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":62,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@61","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":63,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@61"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":64,
+		"state":{
+			"ConnectedBody":"@59",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":65,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,23,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@65","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":66,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@65","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":67,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@65"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":68,
+		"state":{
+			"ConnectedBody":"@63",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":69,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,24,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@69","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":70,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@69","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":71,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@69"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":72,
+		"state":{
+			"ConnectedBody":"@67",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":73,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,25,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@73","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":74,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@73","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":75,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@73"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":76,
+		"state":{
+			"ConnectedBody":"@71",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":77,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,26,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@77","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":78,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@77","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":79,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@77"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":80,
+		"state":{
+			"ConnectedBody":"@75",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":81,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,27,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@81","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":82,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@81","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":83,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@81"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":84,
+		"state":{
+			"ConnectedBody":"@79",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":85,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,28,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@85","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":86,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@85","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":87,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@85"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":88,
+		"state":{
+			"ConnectedBody":"@83",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":89,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,29,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@89","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":90,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@89","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":91,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@89"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":92,
+		"state":{
+			"ConnectedBody":"@87",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":93,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,30,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@93","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":94,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@93","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":95,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@93"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":96,
+		"state":{
+			"ConnectedBody":"@91",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":97,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,31,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@97","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":98,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@97","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":99,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@97"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":100,
+		"state":{
+			"ConnectedBody":"@95",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":101,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,32,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@101","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":102,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@101","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":103,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@101"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":104,
+		"state":{
+			"ConnectedBody":"@99",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":105,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,33,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@105","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":106,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@105","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":107,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@105"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":108,
+		"state":{
+			"ConnectedBody":"@103",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":109,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,34,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@109","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":110,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@109","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":111,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@109"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":112,
+		"state":{
+			"ConnectedBody":"@107",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":113,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,35,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@113","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":114,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@113","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":115,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@113"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":116,
+		"state":{
+			"ConnectedBody":"@111",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":117,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,36,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@117","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":118,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@117","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":119,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@117"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":120,
+		"state":{
+			"ConnectedBody":"@115",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":121,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,37,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@121","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":122,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@121","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":123,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@121"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":124,
+		"state":{
+			"ConnectedBody":"@119",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":125,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,38,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@125","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":126,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@125","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":127,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@125"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":128,
+		"state":{
+			"ConnectedBody":"@123",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":129,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,39,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@129","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":130,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@129","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":131,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@129"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":132,
+		"state":{
+			"ConnectedBody":"@127",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":133,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,40,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@133","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":134,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@133","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":135,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@133"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":136,
+		"state":{
+			"ConnectedBody":"@131",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":137,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,41,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@137","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":138,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@137","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":139,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@137"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":140,
+		"state":{
+			"ConnectedBody":"@135",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":141,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,42,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@141","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":142,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@141","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":143,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@141"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":144,
+		"state":{
+			"ConnectedBody":"@139",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":145,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,43,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@145","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":146,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@145","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":147,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@145"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":148,
+		"state":{
+			"ConnectedBody":"@143",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":149,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,44,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@149","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":150,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@149","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":151,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@149"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":152,
+		"state":{
+			"ConnectedBody":"@147",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":153,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,45,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@153","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":154,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@153","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":155,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@153"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":156,
+		"state":{
+			"ConnectedBody":"@151",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":157,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,46,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@157","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":158,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@157","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":159,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@157"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":160,
+		"state":{
+			"ConnectedBody":"@155",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":161,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,47,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@161","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":162,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@161","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":163,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@161"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":164,
+		"state":{
+			"ConnectedBody":"@159",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":165,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,48,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@165","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":166,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@165","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":167,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@165"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":168,
+		"state":{
+			"ConnectedBody":"@163",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":169,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,49,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@169","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":170,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@169","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":171,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@169"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":172,
+		"state":{
+			"ConnectedBody":"@167",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":173,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,50,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@173","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":174,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@173","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":175,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@173"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":176,
+		"state":{
+			"ConnectedBody":"@171",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":177,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,51,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@177","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":178,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@177","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":179,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@177"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":180,
+		"state":{
+			"ConnectedBody":"@175",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":181,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,52,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@181","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":182,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@181","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":183,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@181"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":184,
+		"state":{
+			"ConnectedBody":"@179",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":185,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,53,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@185","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":186,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@185","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":187,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@185"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":188,
+		"state":{
+			"ConnectedBody":"@183",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":189,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,54,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@189","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":190,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@189","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":191,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@189"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":192,
+		"state":{
+			"ConnectedBody":"@187",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":193,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,55,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@193","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":194,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@193","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":195,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@193"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":196,
+		"state":{
+			"ConnectedBody":"@191",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":197,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,56,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@197","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":198,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@197","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":199,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@197"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":200,
+		"state":{
+			"ConnectedBody":"@195",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":201,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,57,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@201","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":202,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@201","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":203,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@201"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":204,
+		"state":{
+			"ConnectedBody":"@199",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":205,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,58,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@205","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":206,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@205","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":207,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@205"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":208,
+		"state":{
+			"ConnectedBody":"@203",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":209,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,59,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@209","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":210,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@209","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":211,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@209"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":212,
+		"state":{
+			"ConnectedBody":"@207",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":213,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,60,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@213","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":214,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@213","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":215,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@213"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":216,
+		"state":{
+			"ConnectedBody":"@211",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":217,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,61,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@217","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":218,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@217","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":219,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@217"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":220,
+		"state":{
+			"ConnectedBody":"@215",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":221,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,62,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@221","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":222,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@221","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":223,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@221"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":224,
+		"state":{
+			"ConnectedBody":"@219",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":225,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,63,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@225","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":226,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@225","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":227,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@225"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":228,
+		"state":{
+			"ConnectedBody":"@223",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":229,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,64,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@229","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":230,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@229","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":231,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@229"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":232,
+		"state":{
+			"ConnectedBody":"@227",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":233,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,65,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@233","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":234,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@233","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":235,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@233"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":236,
+		"state":{
+			"ConnectedBody":"@231",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":237,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,66,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@237","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":238,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@237","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":239,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@237"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":240,
+		"state":{
+			"ConnectedBody":"@235",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":241,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,67,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@241","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":242,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@241","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":243,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@241"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":244,
+		"state":{
+			"ConnectedBody":"@239",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":245,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,68,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@245","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":246,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@245","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":247,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@245"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":248,
+		"state":{
+			"ConnectedBody":"@243",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":249,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,69,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@249","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":250,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@249","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":251,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@249"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":252,
+		"state":{
+			"ConnectedBody":"@247",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":253,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,70,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@253","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":254,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@253","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":255,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@253"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":256,
+		"state":{
+			"ConnectedBody":"@251",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":257,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,71,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@257","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":258,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@257","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":259,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@257"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":260,
+		"state":{
+			"ConnectedBody":"@255",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":261,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,72,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@261","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":262,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@261","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":263,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@261"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":264,
+		"state":{
+			"ConnectedBody":"@259",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":265,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,73,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@265","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":266,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@265","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":267,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@265"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":268,
+		"state":{
+			"ConnectedBody":"@263",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":269,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,74,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@269","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":270,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@269","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":271,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@269"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":272,
+		"state":{
+			"ConnectedBody":"@267",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":273,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,75,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@273","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":274,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@273","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":275,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@273"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":276,
+		"state":{
+			"ConnectedBody":"@271",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":277,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,76,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@277","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":278,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@277","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":279,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@277"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":280,
+		"state":{
+			"ConnectedBody":"@275",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":281,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,77,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@281","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":282,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@281","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":283,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@281"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":284,
+		"state":{
+			"ConnectedBody":"@279",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":285,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,78,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@285","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":286,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@285","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":287,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@285"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":288,
+		"state":{
+			"ConnectedBody":"@283",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":289,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,79,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@289","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":290,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@289","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":291,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@289"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":292,
+		"state":{
+			"ConnectedBody":"@287",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":293,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,80,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@293","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":294,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@293","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":295,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@293"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":296,
+		"state":{
+			"ConnectedBody":"@291",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":297,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,81,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@297","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":298,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@297","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":299,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@297"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":300,
+		"state":{
+			"ConnectedBody":"@295",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":301,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,82,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@301","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":302,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@301","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":303,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@301"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":304,
+		"state":{
+			"ConnectedBody":"@299",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":305,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,83,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@305","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":306,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@305","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":307,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@305"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":308,
+		"state":{
+			"ConnectedBody":"@303",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":309,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,84,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@309","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":310,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@309","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":311,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@309"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":312,
+		"state":{
+			"ConnectedBody":"@307",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":313,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,85,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@313","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":314,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@313","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":315,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@313"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":316,
+		"state":{
+			"ConnectedBody":"@311",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":317,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,86,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@317","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":318,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@317","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":319,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@317"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":320,
+		"state":{
+			"ConnectedBody":"@315",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":321,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,87,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@321","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":322,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@321","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":323,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@321"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":324,
+		"state":{
+			"ConnectedBody":"@319",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":325,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,88,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@325","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":326,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@325","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":327,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@325"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":328,
+		"state":{
+			"ConnectedBody":"@323",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":329,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,89,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@329","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":330,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@329","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":331,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@329"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":332,
+		"state":{
+			"ConnectedBody":"@327",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":333,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,90,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@333","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":334,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@333","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":335,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@333"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":336,
+		"state":{
+			"ConnectedBody":"@331",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":337,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,91,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@337","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":338,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@337","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":339,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@337"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":340,
+		"state":{
+			"ConnectedBody":"@335",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":341,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,92,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@341","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":342,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@341","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":343,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@341"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":344,
+		"state":{
+			"ConnectedBody":"@339",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":345,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,93,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@345","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":346,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@345","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":347,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@345"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":348,
+		"state":{
+			"ConnectedBody":"@343",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":349,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,94,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@349","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":350,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@349","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":351,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@349"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":352,
+		"state":{
+			"ConnectedBody":"@347",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":353,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,95,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@353","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":354,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@353","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":355,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@353"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":356,
+		"state":{
+			"ConnectedBody":"@351",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":357,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,96,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@357","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":358,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@357","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":359,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@357"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":360,
+		"state":{
+			"ConnectedBody":"@355",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":361,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,97,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@361","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":362,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@361","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":363,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@361"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":364,
+		"state":{
+			"ConnectedBody":"@359",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":365,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,98,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@365","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":366,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@365","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":367,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@365"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":368,
+		"state":{
+			"ConnectedBody":"@363",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":369,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,99,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@369","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":370,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@369","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":371,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@369"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":372,
+		"state":{
+			"ConnectedBody":"@367",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":373,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,100,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@373","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":374,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@373","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":375,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@373"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":376,
+		"state":{
+			"ConnectedBody":"@371",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":377,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,101,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@377","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":378,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@377","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":379,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@377"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":380,
+		"state":{
+			"ConnectedBody":"@375",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":381,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,102,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@381","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":382,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@381","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":383,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@381"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":384,
+		"state":{
+			"ConnectedBody":"@379",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":385,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,103,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@385","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":386,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@385","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":387,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@385"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":388,
+		"state":{
+			"ConnectedBody":"@383",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":389,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,104,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@389","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":390,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@389","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":391,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@389"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":392,
+		"state":{
+			"ConnectedBody":"@387",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":393,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,105,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@393","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":394,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@393","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":395,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@393"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":396,
+		"state":{
+			"ConnectedBody":"@391",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":397,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,106,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@397","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":398,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@397","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":399,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@397"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":400,
+		"state":{
+			"ConnectedBody":"@395",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":401,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,107,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@401","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":402,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@401","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":403,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@401"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":404,
+		"state":{
+			"ConnectedBody":"@399",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":405,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,108,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@405","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":406,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@405","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":407,
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@405"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":408,
+		"state":{
+			"ConnectedBody":"@403",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	},{
+		"ctor":{
+			"args":["@11",null],
+			"decl":"mojo3d.Model.New",
+			"type":"Void(mojo3d.Model,mojo3d.Entity)"
+		},
+		"id":409,
+		"state":{
+			"LocalMatrix":[1,0,0,0,1,0,0,0,1,0,109,0],
+			"Visible":true
+		},
+		"type":"mojo3d.Model"
+	},{
+		"ctor":{
+			"args":["@409","@12"],
+			"decl":"mojo3d.BoxCollider.New",
+			"type":"Void(mojo3d.Entity,mojo3d.BoxCollider)"
+		},
+		"id":410,
+		"type":"mojo3d.BoxCollider"
+	},{
+		"ctor":{
+			"args":["@409","@13"],
+			"decl":"mojo3d.RigidBody.New",
+			"type":"Void(mojo3d.Entity,mojo3d.RigidBody)"
+		},
+		"id":411,
+		"state":{
+			"Mass":0
+		},
+		"type":"mojo3d.RigidBody"
+	},{
+		"ctor":{
+			"args":["@409"],
+			"decl":"mojo3d.BallSocketJoint.New",
+			"type":"Void(mojo3d.Entity)"
+		},
+		"id":412,
+		"state":{
+			"ConnectedBody":"@407",
+			"Pivot":[0,-0.5,0]
+		},
+		"type":"mojo3d.BallSocketJoint"
+	}]
+}

+ 1 - 0
modules/assimp/assimp.monkey2

@@ -2,6 +2,7 @@
 Namespace assimp
 
 #Import "<libc>"
+#Import "<zlib>"
 
 #Import "makefile"
 

+ 2 - 0
modules/assimp/makefile.monkey2

@@ -242,6 +242,7 @@ Namespace assimp
 #Import "assimp/contrib/irrXML/irrXML.cpp"
 
 'zlib
+#rem
 #Import "assimp/contrib/zlib/adler32.c"
 #Import "assimp/contrib/zlib/compress.c"
 #Import "assimp/contrib/zlib/crc32.c"
@@ -257,6 +258,7 @@ Namespace assimp
 #Import "assimp/contrib/zlib/trees.c"
 #Import "assimp/contrib/zlib/uncompr.c"
 #Import "assimp/contrib/zlib/zutil.c"
+#end
 
 'unzip
 '#Import "assimp/contrib/unzip/ioapi.c"

+ 1 - 1
modules/assimp/module.json

@@ -2,5 +2,5 @@
 	"module":"assimp",
 	"about":"Assimp 3d importer",
 	"version":"1.0.0",
-	"depends":["libc"]
+	"depends":["libc","zlib"]
 }

+ 81 - 2
modules/bullet/bullet.monkey2

@@ -229,6 +229,9 @@ Class btDynamicsWorld Extends btCollisionWorld
 		
 	Method removeRigidBody( body:btRigidBody ) Virtual
 		
+	Method addConstraint( constraint:btTypedConstraint,disableCollisionsBetweenLinkedBodies:Bool=False )
+		
+	Method removeConstraint( constraint:btTypedConstraint )
 End
 
 Class btDiscreteDynamicsWorld Extends btDynamicsWorld
@@ -545,10 +548,10 @@ Class btRigidBody Extends btCollisionObject
 		
 	Method setLinearVelocity( lin_vel:btVector3 )
 		
-	Method setAngularVelocity( ang_vel:btVector3 )
-	
 	Method getLinearVelocity:btVector3()
 		
+	Method setAngularVelocity( ang_vel:btVector3 )
+	
 	Method getAngularVelocity:btVector3()
 		
 	Method applyForce( force:btVector3,rel_pos:btVector3 )
@@ -563,5 +566,81 @@ Class btRigidBody Extends btCollisionObject
 		
 	Method applyTorqueImpulse( torque:btVector3 )
 		
+	Method setDamping( lin_damping:btScalar,ang_damping:btScalar )
+		
+	Method getLinearDamping:btScalar()
+		
+	Method getAngularDamping:btScalar()
+		
+	Method getLinearFactor:btVector3()
+		
+	Method setLinearFactor( factor:btVector3 )
+		
+	Method getAngularFactor:btVector3()
+		
+	Method setAngularFactor( factor:btVector3 )
+		
+End
+
+Const BT_CONSTRAINT_ERP:Int
+Const BT_CONSTRAINT_STOP_ERP:Int
+Const BT_CONSTRAINT_CFM:Int
+Const BT_CONSTRAINT_STOP_CFM:Int
+
+Class btTypedConstraint Extends btObject
+	
+	Method setParam( num:Int,value:btScalar,axis:Int=-1 )
+
+	Method getParam:btScalar( num:Int,axis:Int=-1 )
+End
+
+Class btPoint2PointConstraint Extends btTypedConstraint="bbBullet::Point2PointConstraint"
+	
+	Method New( rbA:btRigidBody,rbB:btRigidBody,pivotInA:btVector3,pivotInB:btVector3 )
+
+	Method New( rbA:btRigidBody,pivotInA:btVector3 )
+		
+	Method setPivotA( pivotA:btVector3 )
+		
+	Method setPivotB( pivotB:btVector3 )
+		
+	Method getPivotA:btVector3()
+		
+	Method getPivotB:btVector3()
+		
+End
+
+Class btHingeConstraint Extends btTypedConstraint="bbBullet::HingeConstraint"
+
+ 	method New( rbA:btRigidBody,rtB:btRigidBody,pivotInA:btVector3,pivotInB:btVector3,axisInA:btVector3,axisInB:btVector3,useReferenceFrameA:Bool=False)
+ 
+ 	Method New( rbA:btRigidBody,pivotInA:btVector3,axisInA:btVector3,useReferenceFrameA:Bool=False)
+ 
+ 	Method New( rbA:btRigidBody,rbB:btRigidBody,rbAFrame:btTransform,rbBFrame:btTransform,useReferenceFrameA:Bool=False )
+ 	
+ 	Method New( rbA:btRigidBody,rbAFrame:btTransform,useReferenceFrameA:Bool=False )
+	 	
+	Method getFrameOffsetA:btTransform()
+		
+	Method getFrameOffsetB:btTransform()
+		
+	Method getLowerLimit:btScalar()
+		
+	Method getUpperLimit:btScalar()
+		
+	Method setLimit( low:btScalar,high:btScalar,_softness:btScalar=.9,_biasFactor:btScalar=.3,_relaxationFactor:btScalar=1.0 )
+End
+
+Class btSliderConstraint Extends btTypedConstraint="bbBullet::SliderConstraint"
+	
+	Method New( rbA:btRigidBody,rbB:btRigidBody,frameInA:btTransform,frameInB:btTransform,useLinearReferenceFrameA:Bool )
+ 
+	Method New( rbB:btRigidBody,frameInB:btTransform,useLinearReferenceFrameA:Bool )
+End
+
+Class btFixedConstraint Extends btTypedConstraint="bbBullet::FixedConstraint"
+	
+	Method New( rbA:btRigidBody,rbB:btRigidBody,frameInA:btTransform,frameInB:btTransform )
+		
 End
 

+ 39 - 0
modules/bullet/bullet_glue.h

@@ -10,6 +10,45 @@ namespace bbBullet{
 	
 	btTransform getWorldTransform( btMotionState *self );
 	
+	struct Point2PointConstraint : public btPoint2PointConstraint{
+		
+		Point2PointConstraint(btRigidBody* rbA,btRigidBody* rbB, const btVector3& pivotInA,const btVector3& pivotInB):
+		btPoint2PointConstraint(*rbA,*rbB,pivotInA,pivotInB){}
+
+		Point2PointConstraint(btRigidBody* rbA,const btVector3& pivotInA):
+		btPoint2PointConstraint(*rbA,pivotInA){}
+	};
+
+	struct HingeConstraint : public btHingeConstraint{
+			
+		HingeConstraint(btRigidBody *rbA, btRigidBody *rbB, const btVector3 &pivotInA, const btVector3 &pivotInB, const btVector3 &axisInA, const btVector3 &axisInB, bool useReferenceFrameA=false):
+		btHingeConstraint(*rbA, *rbB, pivotInA, pivotInB, axisInA, axisInB, useReferenceFrameA){}
+ 
+		HingeConstraint(btRigidBody *rbA, const btVector3 &pivotInA, const btVector3 &axisInA, bool useReferenceFrameA=false):
+		btHingeConstraint(*rbA, pivotInA, axisInA, useReferenceFrameA){}
+ 
+		HingeConstraint(btRigidBody *rbA, btRigidBody *rbB, const btTransform &rbAFrame, const btTransform &rbBFrame, bool useReferenceFrameA=false):
+		btHingeConstraint(*rbA, *rbB, rbAFrame, rbBFrame, useReferenceFrameA){}
+ 
+		HingeConstraint(btRigidBody *rbA, const btTransform &rbAFrame, bool useReferenceFrameA=false):
+		btHingeConstraint(*rbA, rbAFrame, useReferenceFrameA){}
+	};
+	
+	struct SliderConstraint : public btSliderConstraint{
+
+		SliderConstraint(btRigidBody *rbA, btRigidBody *rbB, const btTransform &frameInA, const btTransform &frameInB, bool useLinearReferenceFrameA):
+		btSliderConstraint(*rbA,*rbB, frameInA, frameInB, useLinearReferenceFrameA){}
+ 
+		SliderConstraint(btRigidBody *rbB, const btTransform &frameInB, bool useLinearReferenceFrameA):
+		btSliderConstraint(*rbB, frameInB, useLinearReferenceFrameA){}
+	};
+	
+	struct FixedConstraint : public btFixedConstraint{
+		
+		FixedConstraint(btRigidBody* rbA,btRigidBody* rbB, const btTransform& frameInA,const btTransform& frameInB):
+		btFixedConstraint(*rbA,*rbB,frameInA,frameInB){}
+	};
+	
 	struct MotionState : public btMotionState{
 		
 		virtual void setWorldTransform( btTransform *worldTrans ){

+ 1 - 1
modules/miniz/native/miniz.h

@@ -25,7 +25,7 @@
 //#define MINIZ_NO_ZLIB_APIS
 
 // Define MINIZ_NO_ZLIB_COMPATIBLE_NAME to disable zlib names, to prevent conflicts against stock zlib.
-//#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
+#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
 
 // Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc.
 // Note if MINIZ_NO_MALLOC is defined then the user must always provide custom user alloc/free/realloc

+ 18 - 20
modules/mojo/app/app.monkey2

@@ -18,7 +18,7 @@ Global App:AppInstance
 
 Contains information describing a display mode.
 
-See [[AppInstance.DisplayMode]] for more information.
+See [[AppInstance.DesktopMode]] for more information.
 
 #end
 Struct DisplayMode
@@ -29,6 +29,7 @@ Struct DisplayMode
 	Field hertz:Int
 	
 	Operator To:String()
+	
 		Return "DisplayMode("+width+","+height+","+depth+","+hertz+")"
 	End
 	
@@ -40,6 +41,17 @@ The AppInstance class is mainly reponsible for running the app 'event loop', but
 
 A global instance of the AppInstance class is stored in the [[App]] global variable, so you can use any member of the AppInstance simply by prefixing it with 'App.', eg: App.MilliSecs
 
+There are a number of config settings that can be used to control app behaviour. See [[std:std.filesystem.SetConfig|SetConfig]] for more information about config settings.
+
+| Config setting		  			| Possible values					| Default value
+|:----------------------------------|:----------------------------------|:-------------
+| "MOJO\_OPENGL\_PROFILE"			| "es", "compatibility" or "core" 	| "compatibility" on macos and linux, "es" on all other targets. Uses 'Angle' for es support on windows.
+| "MOJO\_OPENGL\_VERSION\_MAJOR"	| Open gl major version				| 2
+| "MOJO\_OPENGL\_VERSION\_MINOR"	| Open gl minor version				| 0
+| "MOJO\_COLOR\_BUFFER\_BITS"		| Minimum color bit depth			| 8
+| "MOJO\_DEPTH\_BUFFER\_BITS"		| Minimum depth buffer bit depth	| 0
+| "MOJO\_STENCIL\_BUFFER\_BITS"		| Minimum stencil buffer bit depth	| 0
+
 #end
 Class AppInstance
 	
@@ -88,23 +100,11 @@ Class AppInstance
 	#end
 	Field SdlEventFilter:Void( event:SDL_Event Ptr )
 
-	#rem monkeydoc Create a new app instance.
+	#rem monkeydoc Creates a new app instance.
 	
-	The following environment variables can be set prior to constructing a new AppInstance:
+	Creates a new AppInstance objects and initializes the global [[App]] variable with it.
 	
-	MOJO\_OPENGL\_PROFILE : Should be set to one of "es", "compatibility" or "core". Defaults to "compatibility" on macos and linux, "es" on all other targets. Uses 'Angle' for es support on windows.
-
-	MOJO\_OPENGL\_VERSION\_MAJOR : defaults to "2".
-
-	MOJO\_OPENGL\_VERSION\_MINOR : defaults to "1".
-
-	MOJO\_COLOR\_BUFFER\_BITS : Minimum depth buffer bit depth. defaults to "8".
-	
-	MOJO\_DEPTH\_BUFFER\_BITS : Minimum depth buffer bit depth. defaults to "0".
-
-	MOJO\_STENCIL\_BUFFER\_BITS : Minimum stencil buffer bit depth. defaults to "0".
-	
-	Environment variables may be set using the [[std::std.filesystem.SetEnv|SetEnv]] function.
+	A runtime error will occur if more than 1 AppInstance is created.
 	
 	#end
 	Method New()
@@ -112,16 +112,14 @@ Class AppInstance
 		App=Self
 		
 		SDL_Init( SDL_INIT_VIDEO|SDL_INIT_JOYSTICK|SDL_INIT_GAMECONTROLLER )
+
+		libc.atexit( SDL_Quit )
 		
 		SDL_SetHint( "SDL_MOUSE_FOCUS_CLICKTHROUGH","1" )
 
 		SDL_FlushEvents( SDL_JOYDEVICEADDED,SDL_JOYDEVICEADDED )
 		SDL_FlushEvents( SDL_CONTROLLERDEVICEADDED,SDL_CONTROLLERDEVICEADDED )
 		
-		'possible fix for linux crashing at exit (can't reproduce myself).
-		'		
-		libc.atexit( SDL_Quit )
-		
 		AppInit()
 		
 		Keyboard.Init()

+ 41 - 22
modules/mojo/graphics/shader.monkey2

@@ -130,20 +130,24 @@ Class GLProgram
 			For Local u:=Eachin _uniforms[i]
 			
 				Select u.type
+				Case GL_BOOL
+
+					glUniform1i( u.location,ublock.GetInt( u.uniformId ) )
+
 				Case GL_INT
-				
+
 					glUniform1i( u.location,ublock.GetInt( u.uniformId ) )
-					
+
 				Case GL_FLOAT
-				
+
 					glUniform1f( u.location,ublock.GetFloat( u.uniformId ) )
-					
+
 				Case GL_FLOAT_VEC2
-				
+
 					glUniform2fv( u.location,1,ublock.GetVec2fv( u.uniformId ) )
-					
+
 				Case GL_FLOAT_VEC3
-				
+
 					glUniform3fv( u.location,1,ublock.GetVec3fv( u.uniformId ) )
 					
 				Case GL_FLOAT_VEC4
@@ -211,7 +215,7 @@ Class Shader
 		
 			def=def.Trim()
 			If Not def Continue
-			
+
 			if Not def.Contains( " " ) def+=" 1"
 			
 			_defs+="#define "+def+"~n"
@@ -346,15 +350,16 @@ Class Shader
 	'
 	Method SplitSource:String[]( source:String )
 		
-		Local i0:=_source.Find( "~n//@vertex" )
+		Local i0:=source.Find( "~n//@vertex" )
 		If i0=-1 
 			Print "Shader source:~n"+source
-			Assert( False,"Can't find //@vertex chunk" )
+			RuntimeError( "Can't find //@vertex chunk" )
 		Endif
-		Local i1:=source.Find( "~n//@fragment" )
+		
+		Local i1:=source.Find( "~n//@fragment",i0+1 )
 		If i1=-1
 			Print "Shader source:~n"+source
-			Assert( False,"Can't find //@fragment chunk" )
+			RuntimeError( "Can't find //@fragment chunk" )
 		Endif
 			
 		Local cs:=source.Slice( 0,i0 )+"~n"
@@ -364,23 +369,37 @@ Class Shader
 		Local chunks:=New String[3]
 		
 		'Find //@imports in common section
-		Repeat
-			Local i:=cs.Find( "~n//@import" )
-			If i=-1 Exit
 		
-			Local p:=cs.Slice( 10 ).Trim()
-			If Not p.StartsWith( "~q" ) Or Not p.EndsWith( "~q" )
+		i0=0
+		
+		Repeat
+			i0=cs.Find( "~n//@import",i0 )
+			If i0=-1 Exit
+			
+			Local i1:=cs.Find( "~n",i0+1 )
+			If i1=-1 RuntimeError( "Malformed @import directive in shader" )
+				
+			Local f:=cs.Slice( i0+11,i1 ).Trim()
+			i0=i1
+			
+			If Not f.StartsWith( "~q" ) Or Not f.EndsWith( "~q" )
+				RuntimeError( "Malformed @import directive in shader" )
 				Exit
 			Endif
-			p=p.Slice(1,-1)
-			Local s:=LoadString( "asset::shaders/"+p )
-			If Not s Exit
-		
-			Local tchunks:=SplitSource( s )
+			
+			f=f.Slice(1,-1)
+			Local path:="asset::shaders/imports/"+f+".glsl"
+			Local src:=LoadString( path )
+			Assert( src,"Can't import shader from "+path )
+			
+			Local tchunks:=SplitSource( src )
+			
 			chunks[0]+=tchunks[0]
 			chunks[1]+=tchunks[1]
 			chunks[2]+=tchunks[2]
 			
+'			Print "Imported "+f
+		
 		Forever
 		
 		chunks[0]+=cs

+ 90 - 63
modules/mojo/graphics/texture.monkey2

@@ -30,6 +30,7 @@ Function glInternalFormat:GLenum( format:PixelFormat )
 	Case PixelFormat.RGB8 Return GL_RGB
 	Case PixelFormat.RGBA8 Return GL_RGBA
 '	Case PixelFormat.RGBA16F Return GL_RGBA
+	Case PixelFormat.RGB32F Return BBGL_ES ? GL_RGB Else GL_RGB32F
 	Case PixelFormat.RGBA32F Return BBGL_ES ? GL_RGBA Else GL_RGBA32F
 	Case PixelFormat.Depth32 Return GL_DEPTH_COMPONENT
 	End
@@ -45,6 +46,7 @@ Function glFormat:GLenum( format:PixelFormat )
 	Case PixelFormat.RGB8 Return GL_RGB
 	Case PixelFormat.RGBA8 Return GL_RGBA
 '	Case PixelFormat.RGBA16F Return GL_RGBA
+	Case PixelFormat.RGB32F Return GL_RGB
 	Case PixelFormat.RGBA32F Return GL_RGBA
 	Case PixelFormat.Depth32 Return GL_DEPTH_COMPONENT
 	End
@@ -60,6 +62,7 @@ Function glType:GLenum( format:PixelFormat )
 	Case PixelFormat.RGB8 Return GL_UNSIGNED_BYTE
 	Case PixelFormat.RGBA8 Return GL_UNSIGNED_BYTE
 '	Case PixelFormat.RGBA16F Return GL_HALF_FLOAT
+	Case PixelFormat.RGB32F Return GL_FLOAT
 	Case PixelFormat.RGBA32F Return GL_FLOAT
 	Case PixelFormat.Depth32 Return GL_UNSIGNED_INT
 	End
@@ -67,33 +70,7 @@ Function glType:GLenum( format:PixelFormat )
 	Return GL_UNSIGNED_BYTE
 End
 
-Function ClearTexImage2D( glTarget:GLenum,width:Int,height:Int,format:PixelFormat,color:Color )
-	
-	glCheck()
-	
-	Local gliformat:=glInternalFormat( format )
-	Local glformat:=glFormat( format )
-	Local gltype:=glType( format )
-	
-	glTexImage2D( glTarget,0,gliformat,width,height,0,glformat,gltype,Null )
-	
-	If Not IsDepth( format )
-		
-		Local image:=New Pixmap( width,1,format )
-		image.Clear( color )
-		
-		For Local iy:=0 Until height
-			glTexSubImage2D( glTarget,0,0,iy,width,1,glformat,gltype,image.Data )
-		Next
-		
-		glFlush() 'macos nvidia bug!
-	
-	Endif
-	
-	glCheck()
-End
-
-Function UploadTexImage2D( glTarget:GLenum,image:Pixmap,mipmap:Bool,envface:Bool )
+Function UploadTexImage2D( glTarget:GLenum,image:Pixmap,mipmap:Bool,envmap:Bool )
 	
 	glCheck()
 	
@@ -108,15 +85,29 @@ Function UploadTexImage2D( glTarget:GLenum,image:Pixmap,mipmap:Bool,envface:Bool
 	Repeat
 		
 		Local width:=image.Width,height:=image.Height
-
-		If envface		
-			For Local y:=0 until height
-				Local p:=image.PixelPtr( 0,y )
-				'write miplevel to alpha!
-				For Local x:=0 Until width
-					p[x*4+3]=mip
+		
+		If envmap
+			'write mip level into alpha channel
+			Select format
+			Case PixelFormat.RGBA8
+				For Local y:=0 until height
+					Local p:=image.PixelPtr( 0,y )
+					'write miplevel to alpha!
+					For Local x:=0 Until width
+						p[x*4+3]=mip
+					Next
 				Next
-			Next
+			Case PixelFormat.RGBA32F
+				For Local y:=0 until height
+					Local p:=Cast<Float Ptr>( image.PixelPtr( 0,y ) )
+					'write miplevel to alpha!
+					For Local x:=0 Until width
+						p[x*4+3]=mip/255.0
+					Next
+				Next
+			Default
+				Assert( False )
+			End
 		Endif
 		
 		If image.Pitch=width * image.Depth
@@ -133,14 +124,38 @@ Function UploadTexImage2D( glTarget:GLenum,image:Pixmap,mipmap:Bool,envface:Bool
 		
 		glFlush() 'macos nvidia bug!
 		
-		If Not mipmap Or Not envface Exit
+		If Not envmap Exit
 		
 		If image.Width=1 And image.Height=1 Exit
 		image=image.MipHalve()
 		mip+=1
 	Forever
 	
-	If mipmap And Not envface glGenerateMipmap( glTarget )
+	glCheck()
+End
+
+Function ClearTexImage2D( glTarget:GLenum,width:Int,height:Int,format:PixelFormat,color:Color )
+	
+	glCheck()
+	
+	Local gliformat:=glInternalFormat( format )
+	Local glformat:=glFormat( format )
+	Local gltype:=glType( format )
+	
+	glTexImage2D( glTarget,0,gliformat,width,height,0,glformat,gltype,Null )
+	
+	If Not IsDepth( format )
+		
+		Local image:=New Pixmap( width,1,format )
+		image.Clear( color )
+		
+		For Local iy:=0 Until height
+			glTexSubImage2D( glTarget,0,0,iy,width,1,glformat,gltype,image.Data )
+		Next
+		
+		glFlush() 'macos nvidia bug!
+	
+	Endif
 	
 	glCheck()
 End
@@ -153,11 +168,12 @@ Public
 |:--------------|:-----------
 | WrapS			| Wrap S texture coordinates
 | WrapT			| Wrap T texture coordinates
-| WrapST		| Enable WrapS and WrapT.
+| WrapST		| Wrap both S and T coordinates
 | Filter		| Enable magnification filtering
 | Mipmap		| Enable minification mipmapping, and minification filtering if Filter enabled.
-| FilterMipmap	| Enable Filter and Mipmap.
-| Dynamic		| Texture is frequently updated. This flag should be set if the texture contents are regularly updated and don't need to be preserved.
+| FilterMipmap	| Enable both filterin and mipmapping.
+| Dynamic		| The texture contents are regularly updated and don't need to be preserved.
+| Cubemap		| The texture is a cubmap.
 #end
 Enum TextureFlags
 	None=			$0000
@@ -168,6 +184,7 @@ Enum TextureFlags
 	
 	Dynamic=		$0100
 	Cubemap=		$0200
+	Envmap=			$0400
 	
 	WrapST=			WrapS|WrapT
 	FilterMipmap=	Filter|Mipmap
@@ -185,9 +202,17 @@ Enum CubeFace
 End
 
 #rem monkeydoc The Texture class.
+
+The "MOJO_TEXTURE_MAX_ANISOTROPY" config setting control the max anisotropy of mipmapped textures.
+
 #end
 Class Texture Extends Resource
 	
+	#rem monkeydoc Creates a new texture.
+	
+	The "MOJO_TEXTURE_MAX_ANISOTROPY" config setting control the max anisotropy of mipmapped textures.
+
+	#end
 	Method New( width:Int,height:Int,format:PixelFormat,flags:TextureFlags )
 		
 		Init( width,height,format,flags,Null )
@@ -197,13 +222,6 @@ Class Texture Extends Resource
 		
 		If flags & TextureFlags.Cubemap
 
-			'Nasty: cubemap mips always have mip level in alpha channel for env maps
-			'
-			If flags & TextureFlags.Mipmap And pixmap.Format<>PixelFormat.RGBA8
-				
-				pixmap=pixmap.Convert( PixelFormat.RGBA8 )
-			Endif
-
 			Local size:=pixmap.Size
 			
 			If size.x=size.y			'1x1?
@@ -318,9 +336,18 @@ Class Texture Extends Resource
 		Return Null
 	End
 
-	Function Load:Texture( path:String,flags:TextureFlags,flipNormalY:Bool=False )
-
-		Local pixmap:=Pixmap.Load( path,,True )
+	Function Load:Texture( path:String,flags:TextureFlags=TextureFlags.FilterMipmap,flipNormalY:Bool=False )
+		
+		Local format:=PixelFormat.Unknown
+		If flags & TextureFlags.Envmap
+			If ExtractExt( path )=".hdr"
+				format=PixelFormat.RGBA32F
+			Else
+				format=PixelFormat.RGBA8
+			Endif
+		Endif
+		
+		Local pixmap:=Pixmap.Load( path,format,True )
 		If Not pixmap Return Null
 		
 		If flipNormalY
@@ -406,7 +433,7 @@ Class Texture Extends Resource
 	Method Modified( r:Recti )
 		
 		If _managed 
-			Print "Texture Modified - Update managed"
+'			Print "Texture Modified - Update managed"
 			glReadPixels( r.X,r.Y,r.Width,r.Height,GL_RGBA,GL_UNSIGNED_BYTE,_managed.PixelPtr( r.X,r.Y ) )
 		Endif
 
@@ -485,7 +512,7 @@ Class Texture Extends Resource
 					glTexParameteri( _glTarget,GL_TEXTURE_MIN_FILTER,GL_NEAREST )
 				Endif
 				
-				If _flags & TextureFlags.Mipmap And Not (_flags & TextureFlags.Cubemap)
+				If _flags & TextureFlags.Mipmap And Not (_flags & (TextureFlags.Cubemap|TextureFlags.Envmap))
 '					If glexts.GL_texture_filter_anisotropic
 						Local max:Int=0
 						glGetIntegerv( GL_MAX_TEXTURE_MAX_ANISOTROPY,Varptr max )
@@ -501,42 +528,42 @@ Class Texture Extends Resource
 		
 		If _dirty & Dirty.TexImage
 			
-			Local mipmap:=(_flags & TextureFlags.Mipmap)<>0
-				
+			Local mipmap:=(_flags & TextureFlags.Mipmap)<>Null
+			Local envmap:=(_flags & TextureFlags.Envmap)<>Null
+			
 			Select _glTarget
 			Case GL_TEXTURE_2D
 				
 				If _managed
-					UploadTexImage2D( _glTarget,_managed,mipmap,False )
-					_dirty&=~Dirty.Mipmaps
+					UploadTexImage2D( _glTarget,_managed,mipmap,envmap )
+					If envmap mipmap=False
 				else
 					ClearTexImage2D( _glTarget,_size.x,_size.y,_format,Color.Black )
-					If mipmap _dirty|=Dirty.Mipmaps
 				Endif
 					
 			Case GL_TEXTURE_CUBE_MAP
 				
-				Local envface:=mipmap
-				
 				If _cubeFaces[0]._managed
 					For Local i:=0 Until 6
 						Local face:=_cubeFaces[i]
-						UploadTexImage2D( face._glTarget,face._managed,mipmap,envface )
+						UploadTexImage2D( face._glTarget,face._managed,mipmap,envmap )
 					Next
-					_dirty&=~Dirty.Mipmaps
+					If envmap mipmap=False
 				Else
 					For Local i:=0 Until 6
 						Local face:=_cubeFaces[i]
 						ClearTexImage2D( face._glTarget,face._size.x,face._size.y,face._format,Color.Black )
 					Next
-					If mipmap _dirty|=Dirty.Mipmaps
 				Endif
+				
 			End
 			
+			If mipmap glGenerateMipmap( _glTarget )
+			_dirty&=~Dirty.Mipmaps
+			
 		Endif
 		
 		If _dirty & Dirty.Mipmaps
-			
 			If _flags & TextureFlags.Mipmap 
 				glGenerateMipmap( _glTarget )
 				glCheck()

+ 7 - 6
modules/mojo/graphics/uniformblock.monkey2

@@ -230,7 +230,6 @@ Class UniformBlock Extends Resource
 	End
 
 	Method GetTexture:Texture( uniform:String )
-		
 		Local id:=GetUniformId( uniform,Type.Texture )
 		Return _uniforms[id].texture
 	End
@@ -297,7 +296,7 @@ Class UniformBlock Extends Resource
 
 #If __DEBUG__		
 		Assert( id,"Uniform '"+name+"' not found" )
-		Assert( _uniforms[id].type,"Uniform '"+name+"' does not found in UniformBlock" )
+		Assert( _uniforms[id].type,"Uniform '"+name+"' not found in UniformBlock" )
 		Assert( _uniforms[id].type=type,"Uniform '"+name+"' has incorrect type '"+_typenames[_uniforms[id].type]="', expecting type '"+_typenames[type]+"'" )
 #endif
 		Return id
@@ -359,14 +358,16 @@ Class UniformBlock Extends Resource
 		Return Cast<T Ptr>( Varptr _uniforms[id].floatData )[0]
 	End
 
-	Method GetDataPtr<T>:T Ptr( name:String,type:Type )
-		Local id:=GetUniformId( name,type )
-'		DebugAssert( _uniforms[id].type=type,"Invalid uniform type" )
+	Method GetDataPtr<T>:T Ptr( id:Int,type:Type )
+#If __DEBUG__
+		Assert( id,"Uniform '"+GetUniformName( id )+"' not found" )
+		Assert( _uniforms[id].type,"Uniform '"+GetUniformName( id )+"' not found in UniformBlock" )
+		Assert( _uniforms[id].type=type,"Uniform '"+GetUniformName( id )+"' has incorrect type '"+_typenames[_uniforms[id].type]="', expecting type '"+_typenames[type]+"'" )
+#endif
 		Return Cast<T Ptr>( Varptr _uniforms[id].floatData )
 	End
 	
 	Method GetFloatPtr:Float Ptr( id:Int,type:Type )
-		
 #If __DEBUG__
 		Assert( id,"Uniform '"+GetUniformName( id )+"' not found" )
 		Assert( _uniforms[id].type,"Uniform '"+GetUniformName( id )+"' not found in UniformBlock" )

+ 11 - 4
modules/mojo3d-loaders/loaders/assimp.monkey2

@@ -180,7 +180,8 @@ Class AssimpLoader
 		Local vp:=aimesh.mVertices
 		Local np:=aimesh.mNormals
 		Local cp:=aimesh.mColors[0]
-		Local tp:=aimesh.mTextureCoords[0]
+		Local tp0:=aimesh.mTextureCoords[0]
+		Local tp1:=aimesh.mTextureCoords[1]
 		
 		For Local i:=0 Until vertices.Length
 			
@@ -196,9 +197,14 @@ Class AssimpLoader
 				vertices[i].color=UInt(a) Shl 24 | UInt(color.b*a) Shl 16 | UInt(color.g*a) Shl 8 | UInt(color.r*a)
 			Endif
 
-			If tp 
-				vertices[i].texCoord0=New Vec2f( tp[i].x,tp[i].y )
+			If tp0 
+				vertices[i].texCoord0=New Vec2f( tp0[i].x,tp0[i].y )
 			Endif
+			
+			If tp1 
+				vertices[i].texCoord1=New Vec2f( tp1[i].x,tp1[i].y )
+			Endif
+			
 		Next
 		
 		Local indices:=New UInt[ aimesh.mNumFaces*3 ]
@@ -254,7 +260,8 @@ Class AssimpLoader
 		aiGetMaterialColor( aimaterial,AI_MATKEY_COLOR_DIFFUSE,0,0,Varptr aicolor )
 		diffuseColor=New Color( Pow( aicolor.r,2.2 ),Pow( aicolor.g,2.2 ),Pow( aicolor.b,2.2 ),aicolor.a )
 
-		Local material:=New PbrMaterial( boned )
+		Local material:=New PbrMaterial
+		material.Boned=boned
 		
 		material.Name=name
 		

+ 41 - 24
modules/mojo3d-loaders/tests/castle.monkey2

@@ -51,8 +51,7 @@ Function QCollide:QResult( collider:ConvexCollider,src:Vec3f,dst:Vec3f,moving:Bo
 	
 '		debug+=", "
 		
-		If cresult.normal.y>.7071
-'			Print "hitground "+cresult.normal
+		If cresult.normal.y>.7'9
 			qresult.hitground=True
 		Endif
 		
@@ -62,46 +61,53 @@ Function QCollide:QResult( collider:ConvexCollider,src:Vec3f,dst:Vec3f,moving:Bo
 			
 		Local plane:=New Planef( cresult.point,cresult.normal )
 		plane.d-=margin
-		
+
 		Local d0:=plane.Distance( src ),d1:=plane.Distance( dst )
 		
 		Local tline:=New Linef( src,dst-src )
 		
 		Local t:=plane.TIntersect( tline )
 		
-		If t>0 src=tline * t
+		If t>0 
+			src=tline * t
+		Endif
 		
 		If Not moving Or t>=1
 			dst=src
 			Exit
 		Endif
-			
+
 		Select state
 		Case 0
-			dst=plane.Nearest( dst )
-'			debug+="A "+P( plane )
+			
+			Local tdst:=plane.Nearest( dst )
+			
+			If plane.n.y<.1 And tdst.y>src.y
+				dst=src
+				Exit
+				Local t:=(tdst.y-src.y)/(tdst-src).Length
+				tdst=(tdst-src)*t+src
+				Print "Here!"
+			Endif
+			
+			dst=tdst
+			
 			plane0=plane
 			state=1
 		Case 1
 			Local v:=plane0.n.Cross( plane.n )
-			If v.Length>.001
+			
+			If v.Length>.00001
 				Local groove:=New Linef( src,v )
-'				Local d0:=plane0.Distance( dst )
 				dst=groove.Nearest( dst )
-'				debug+="B "+P( plane )+" d0="+F(d0)+" sd0="+F(plane0.Distance(src))+" dd0="+F(plane0.Distance(dst))
 				plane1=plane
 				state=2
 			Else
 				Print "QCollide OOPS2"
-'				debug+="C "+P( plane )
-				dst=plane.Nearest( dst )
-				plane0=plane
-				state=1
+				dst=src
+				Exit
 			Endif
 		Case 2
-'			Local d0:=plane0.Distance( dst )
-'			Local d1:=plane1.Distance( dst )
-'			debug+="D "+P( plane )+" d0="+F(d0)+" d1="+F(d1)
 			dst=src
 			Exit
 		End
@@ -128,6 +134,11 @@ Class CharacterController Extends Behaviour
 		Return _onground
 	End
 	
+	Property OnWall:Bool()
+		
+		Return _onwall
+	End
+	
 	Property StepDown:Float()
 		
 		Return _stepDown
@@ -145,6 +156,8 @@ Class CharacterController Extends Behaviour
 	
 	Field _onground:Bool
 	
+	Field _onwall:Bool
+	
 	Field _vel:Vec3f
 	
 	Method OnUpdate( elapsed:Float ) Override
@@ -180,21 +193,25 @@ Class CharacterController Extends Behaviour
 		
 		Local dst:=Entity.Position
 		
-		Local qres:=QCollide( Cast<ConvexCollider>( Entity.Collider ),src,dst,moving Or Not _onground )
+		Local qres:=QCollide( Cast<ConvexCollider>( Entity.Collider ),src,dst,True )'moving Or Not _onground )
 		dst=qres.position
-		
+#rem
 		If Not _jumping And Not qres.hitground And _onground
 			src=dst
 			dst.y-=_stepDown
 			qres=QCollide( Cast<ConvexCollider>( Entity.Collider ),src,dst,False )
 			dst=qres.position
 		Endif
-		
+#end		
 		_onground=qres.hitground
-
-		If _onground _jumping=False
+		_onwall=qres.hitwall
 		
-		_vel.y=dst.y-src.y
+		If _onground 
+			_jumping=False
+			_vel.y=0
+		Else
+			_vel.y=dst.y-src.y
+		Endif
 		
 		Entity.Position=dst
 	End
@@ -318,7 +335,7 @@ Class MyWindow Extends Window
 		Local controller:=_player.GetComponent<CharacterController>()
 
 '		canvas.DrawText( "y="+_player.Position.y+" onground="+controller.OnGround+" FPS="+App.FPS,0,0 )
-		canvas.DrawText( " onground="+controller.OnGround+" FPS="+App.FPS,0,0 )
+		canvas.DrawText( " onground="+controller.OnGround+" onwall="+controller.OnWall+" FPS="+App.FPS,0,0 )
 	End
 	
 End

+ 0 - 27
modules/mojo3d/assets/shaders/copy.glsl

@@ -1,27 +0,0 @@
-
-//@renderpasses 0
-
-uniform sampler2D r_AccumBuffer;
-
-uniform vec2 r_BufferCoordScale;
-
-varying vec2 v_TexCoord0;
-
-//@vertex
-
-attribute vec2 a_Position;	//0...1 (1=viewport size)
-attribute vec2 a_TexCoord0;	//0...1 (1=viewport size)
-
-void main(){
-
-	v_TexCoord0=a_TexCoord0 * r_BufferCoordScale;
-
-	gl_Position=vec4( a_Position * 2.0 - 1.0,-1.0,1.0 );
-}
-
-//@fragment
-
-void main(){
-
-	gl_FragColor=vec4( pow( texture2D( r_AccumBuffer,v_TexCoord0 ).rgb,vec3( 1.0/2.2 ) ),1.0 );
-}

+ 0 - 72
modules/mojo3d/assets/shaders/effect-bloom.glsl

@@ -1,72 +0,0 @@
-
-//@renderpasses 0,1,2,3
-
-uniform sampler2D m_SourceTexture;
-uniform vec2 m_SourceTextureSize;
-uniform vec2 m_SourceTextureScale;
-
-varying vec2 v_TexCoord0;
-
-//@vertex
-
-attribute vec2 a_Position;	//0...1 (1=viewport size)
-
-void main(){
-
-	v_TexCoord0=a_Position * m_SourceTextureScale;
-
-	gl_Position=vec4( a_Position * 2.0 - 1.0,-1.0,1.0 );
-}
-
-//@fragment
-
-const float weight0=0.227027,weight1=0.1945946,weight2=0.1216216,weight3=0.054054,weight4=0.016216;
-
-//apparently the same if linear filter enabled in texture...
-//const float weight0=0.2270270270,weight1=0.3162162162,weight2=0.0702702703;
-
-void main(){
-
-#if MX2_RENDERPASS==3
-
-	vec3 result=texture2D( m_SourceTexture,v_TexCoord0 ).rgb;
-
-#else
-
-	vec2 texel_size=1.0/m_SourceTextureSize;
-	
-	vec3 result=texture2D( m_SourceTexture,v_TexCoord0 ).rgb*weight0;
-	
-#if MX2_RENDERPASS==0 || MX2_RENDERPASS==2
-
-	result+=texture2D(m_SourceTexture,v_TexCoord0+vec2(texel_size.x*1.0,0.0)).rgb * weight1;
-	result+=texture2D(m_SourceTexture,v_TexCoord0-vec2(texel_size.x*1.0,0.0)).rgb * weight1;
-	result+=texture2D(m_SourceTexture,v_TexCoord0+vec2(texel_size.x*2.0,0.0)).rgb * weight2;
-	result+=texture2D(m_SourceTexture,v_TexCoord0-vec2(texel_size.x*2.0,0.0)).rgb * weight2;
-	result+=texture2D(m_SourceTexture,v_TexCoord0+vec2(texel_size.x*3.0,0.0)).rgb * weight3;
-	result+=texture2D(m_SourceTexture,v_TexCoord0-vec2(texel_size.x*3.0,0.0)).rgb * weight3;
-	result+=texture2D(m_SourceTexture,v_TexCoord0+vec2(texel_size.x*4.0,0.0)).rgb * weight4;
-	result+=texture2D(m_SourceTexture,v_TexCoord0-vec2(texel_size.x*4.0,0.0)).rgb * weight4;
-	
-#elif MX2_RENDERPASS==1
-
-	result+=texture2D(m_SourceTexture,v_TexCoord0+vec2(0.0,texel_size.y*1.0)).rgb * weight1;
-	result+=texture2D(m_SourceTexture,v_TexCoord0-vec2(0.0,texel_size.y*1.0)).rgb * weight1;
-	result+=texture2D(m_SourceTexture,v_TexCoord0+vec2(0.0,texel_size.y*2.0)).rgb * weight2;
-	result+=texture2D(m_SourceTexture,v_TexCoord0-vec2(0.0,texel_size.y*2.0)).rgb * weight2;
-	result+=texture2D(m_SourceTexture,v_TexCoord0+vec2(0.0,texel_size.y*3.0)).rgb * weight3;
-	result+=texture2D(m_SourceTexture,v_TexCoord0-vec2(0.0,texel_size.y*3.0)).rgb * weight3;
-	result+=texture2D(m_SourceTexture,v_TexCoord0+vec2(0.0,texel_size.y*4.0)).rgb * weight4;
-	result+=texture2D(m_SourceTexture,v_TexCoord0-vec2(0.0,texel_size.y*4.0)).rgb * weight4;
-
-#endif
-
-#if MX2_RENDERPASS==0
-	result=max( result-1.0,0.0 );
-#endif
-
-#endif
-	
-	gl_FragColor=vec4( result,1.0 );
-	
-}

+ 74 - 0
modules/mojo3d/assets/shaders/effects/bloom.glsl

@@ -0,0 +1,74 @@
+
+//@renderpasses 0,1,2,3
+
+uniform sampler2D r_SourceBuffer;
+uniform vec2 r_SourceBufferSize;
+uniform vec2 r_SourceBufferScale;
+
+varying vec2 v_TexCoord0;
+
+//@vertex
+
+attribute vec2 a_Position;	//0...1 (1=viewport size)
+
+void main(){
+
+	v_TexCoord0=a_Position * r_SourceBufferScale;
+
+	gl_Position=vec4( a_Position * 2.0 - 1.0,-1.0,1.0 );
+}
+
+//@fragment
+
+const float weight0=0.227027,weight1=0.1945946,weight2=0.1216216,weight3=0.054054,weight4=0.016216;
+
+//apparently the same if linear filter enabled in texture...
+//const float weight0=0.2270270270,weight1=0.3162162162,weight2=0.0702702703;
+
+void main(){
+
+#if MX2_RENDERPASS==3
+
+	vec3 result=texture2D( r_SourceBuffer,v_TexCoord0 ).rgb;
+
+#else
+
+	vec2 texel_size=1.0/r_SourceBufferSize;
+	
+	vec3 result=texture2D( r_SourceBuffer,v_TexCoord0 ).rgb*weight0;
+	
+#if MX2_RENDERPASS==0 || MX2_RENDERPASS==2
+
+	result+=texture2D(r_SourceBuffer,v_TexCoord0+vec2(texel_size.x*1.0,0.0)).rgb * weight1;
+	result+=texture2D(r_SourceBuffer,v_TexCoord0-vec2(texel_size.x*1.0,0.0)).rgb * weight1;
+	result+=texture2D(r_SourceBuffer,v_TexCoord0+vec2(texel_size.x*2.0,0.0)).rgb * weight2;
+	result+=texture2D(r_SourceBuffer,v_TexCoord0-vec2(texel_size.x*2.0,0.0)).rgb * weight2;
+	result+=texture2D(r_SourceBuffer,v_TexCoord0+vec2(texel_size.x*3.0,0.0)).rgb * weight3;
+	result+=texture2D(r_SourceBuffer,v_TexCoord0-vec2(texel_size.x*3.0,0.0)).rgb * weight3;
+	result+=texture2D(r_SourceBuffer,v_TexCoord0+vec2(texel_size.x*4.0,0.0)).rgb * weight4;
+	result+=texture2D(r_SourceBuffer,v_TexCoord0-vec2(texel_size.x*4.0,0.0)).rgb * weight4;
+	
+#elif MX2_RENDERPASS==1
+
+	result+=texture2D(r_SourceBuffer,v_TexCoord0+vec2(0.0,texel_size.y*1.0)).rgb * weight1;
+	result+=texture2D(r_SourceBuffer,v_TexCoord0-vec2(0.0,texel_size.y*1.0)).rgb * weight1;
+	result+=texture2D(r_SourceBuffer,v_TexCoord0+vec2(0.0,texel_size.y*2.0)).rgb * weight2;
+	result+=texture2D(r_SourceBuffer,v_TexCoord0-vec2(0.0,texel_size.y*2.0)).rgb * weight2;
+	result+=texture2D(r_SourceBuffer,v_TexCoord0+vec2(0.0,texel_size.y*3.0)).rgb * weight3;
+	result+=texture2D(r_SourceBuffer,v_TexCoord0-vec2(0.0,texel_size.y*3.0)).rgb * weight3;
+	result+=texture2D(r_SourceBuffer,v_TexCoord0+vec2(0.0,texel_size.y*4.0)).rgb * weight4;
+	result+=texture2D(r_SourceBuffer,v_TexCoord0-vec2(0.0,texel_size.y*4.0)).rgb * weight4;
+
+#endif
+
+#if MX2_RENDERPASS==0
+
+	result=max( result-1.0,0.0 );
+	
+#endif
+
+#endif
+	
+	gl_FragColor=vec4( result,1.0 );
+	
+}

+ 7 - 8
modules/mojo3d/assets/shaders/effect-monochrome.glsl → modules/mojo3d/assets/shaders/effects/monochrome.glsl

@@ -1,29 +1,28 @@
 //@renderpasses 0
 
-uniform vec2 m_SourceCoordScale;
+uniform sampler2D r_SourceBuffer;
+uniform vec2 r_SourceBufferScale;
 
-varying vec2 v_TexCoord0;
+varying vec2 v_SourceBufferCoords;
 
 //@vertex
 
-attribute vec2 a_Position;	//0...1 (1=viewport size)
-
+attribute vec2 a_Position;
+	
 void main(){
 
-	v_TexCoord0=a_Position * m_SourceCoordScale;
+	v_SourceBufferCoords=a_Position * r_SourceBufferScale;
 
 	gl_Position=vec4( a_Position * 2.0 - 1.0,-1.0,1.0 );
 }
 
 //@fragment
 
-uniform sampler2D m_SourceTexture;
-
 uniform float m_Level;
 
 void main(){
 
-	vec4 color=texture2D( m_SourceTexture,v_TexCoord0 );
+	vec4 color=texture2D( r_SourceBuffer,v_SourceBufferCoords );
 
 	float i=(color.r+color.g+color.b)/3.0;
 	

+ 147 - 0
modules/mojo3d/assets/shaders/effects/reflection.glsl

@@ -0,0 +1,147 @@
+
+TODO
+
+//@renderpasses 0
+
+//based on code by 'cireneikual' found at www.opengl.org - thanks!
+
+//current accum buffer
+uniform sampler2D r_SourceBuffer;
+uniform vec2 r_SourceBufferSize;
+uniform vec2 r_SourceBufferScale;
+
+//deferred buffers
+uniform sampler2D r_ColorBuffer;
+uniform sampler2D r_NormalBuffer;
+uniform sampler2D r_DepthBuffer;
+uniform vec2 r_BufferCoordScale;
+
+varying vec2 v_SourceCoords;
+varying vec2 v_BufferCoords;
+
+//@vertex
+
+attribute vec2 a_Position;
+
+void main(){
+
+	v_SourceCoords=a_Position * r_SourceBufferScale;
+	v_BufferCoords=a_Position * r_BufferCoordScale;
+
+	gl_Position=vec4( a_Position * 2.0 - 1.0,-1.0,1.0 );
+}
+
+//@fragment
+
+// Consts should help improve performance
+const float rayStep = 0.25;
+const float minRayStep = 0.1;
+const float searchDist = 5.0;
+const float searchDistInv = 0.2;
+
+const float maxDDepth = 1.0;
+const float maxDDepthInv = 1.0;
+
+const float reflectionSpecularFalloffExponent = 3.0;
+
+const int maxSteps = 20;
+const int numBinarySearchSteps = 5;
+  
+float fragmentDepth( vec2 projCoord ){
+
+	float dbdepth=texture2D( r_DepthBuffer,projCoord * r_BufferCoordScale ).r;
+        
+	return viewDepth( dbdepth );
+}
+
+vec2 projectedCoord( vec3 hitCoord ){
+
+	vec4 projCoord = r_ProjectonMatrix * vec4( hitCoord,1.0 );
+	
+	projCoord.xy = projCoord.xy / projCoord.w * 0.5 + 0.5;
+	
+	return projCoord.xy;
+}
+ 
+vec3 binarySearch( vec3 dir,inout vec3 hitCoord,out float dDepth ){
+
+	float depth;
+ 
+    for( int i=0;i<numBinarySearchSteps; ++i ){
+    
+    	vec2 projCoord=projectedCoord( hitCoord );
+        
+        depth=fragmentDepth( projCoord );
+ 
+        dDepth=hitCoord.z-depth;
+        
+        if( dDepth>0.0 ) hitCoord+=dir;
+	        
+        dir*=0.5;
+        
+        hitCoord-=dir;
+    }
+ 
+	vec2 projCoord=projectedCoord( hitCoord );
+ 
+	return vec3( projCoord.xy,depth );
+}
+ 
+ 
+vec4 rayCast( vec3 dir,inout vec3 hitCoord,out float dDepth ){
+
+    dir*=rayStep;
+ 
+    for( int i=0;i<maxSteps;++i ){
+    
+    	hitCoord+=dir;
+    	
+        vec2 projCoord=projectedCoord( hitCoord );
+        
+        float depth=fragmentDepth( projCoord );
+        
+        dDepth=hitCoord.z-depth;
+        
+        if( dDepth<0.0 ) return vec4( binarySearch( dir,hitCoord,dDepth ),1.0 );
+    }
+ 
+    return vec4( 0.0 );
+}
+ 
+ 
+void main(){
+
+	vec4 normal_r=texture2D( r_NormalBuffer,v_BufferCoords );
+	
+	if( normal_r.a==1.0 ){
+		gl_FragColor=vec4( 0.0 );
+		return;
+	}
+	
+	vec3 position=fragmentPosition();
+	
+	vec3 reflected=normalize( reflect( normalize( position ),normalize( normal_r.rgb ) ) );
+	
+  // Ray cast
+  
+    vec3 hitPos=viewPos;
+    float dDepth;
+ 
+    vec4 coords=rayCast( reflected * max(minRayStep, -viewPos.z), hitPos, dDepth );
+ 
+    vec2 dCoords = abs( vec2(0.5, 0.5)-coords.xy );
+ 
+    float screenEdgefactor = clamp( 1.0-( dCoords.x + dCoords.y ),0.0,1.0 );
+    
+    vec3  color=texture2D( r_ColorBuffer,coords.xy * r_BufferCoordScale ).rgb;
+    
+	float alpha=
+	
+	pow( specular, reflectionSpecularFalloffExponent ) *
+	screenEdgefactor * 
+	clamp( -reflected.z, 0.0, 1.0 ) *
+	clamp( ( searchDist-length( viewPos-hitPos )) * searchDistInv,0.0,1.0) *
+	coords.w );
+ 
+    gl_FragColor=vec4( color*alpha,alpha );
+}

+ 0 - 60
modules/mojo3d/assets/shaders/fog-deferred.glsl

@@ -1,60 +0,0 @@
-
-//@renderpasses 0
-
-varying vec2 v_ClipPosition;
-
-varying vec2 v_TexCoord0;
-
-//@vertex
-
-uniform vec2 r_BufferCoordScale;
-
-attribute vec2 a_Position;	//0...1 (1=viewport size)
-
-void main(){
-
-	v_ClipPosition=a_Position * 2.0 - 1.0;
-	
-	v_TexCoord0=a_Position * r_BufferCoordScale;
-	
-	gl_Position=vec4( v_ClipPosition,-1.0,1.0 );
-}
-
-//@fragment
-
-uniform mat4 r_InverseProjectionMatrix;
-
-uniform sampler2D r_DepthBuffer;
-uniform float r_DepthNear;
-uniform float r_DepthFar;
-
-uniform vec4 r_FogColor;
-uniform float r_FogNear;
-uniform float r_FogFar;
-
-float viewDepth( float depth ){
-
-	return r_DepthFar * r_DepthNear / ( r_DepthFar + depth * ( r_DepthNear - r_DepthFar ) );
-}
-
-void main(){
-
-	float fog=0.0;
-
-	float depth=texture2D( r_DepthBuffer,v_TexCoord0 ).r;
-	
-	if( depth<1.0 ){
-
-		depth=viewDepth( depth );
-		
-		vec4 vpos4=r_InverseProjectionMatrix * vec4( v_ClipPosition,-1.0,1.0 );
-		
-		vec3 vpos=vpos4.xyz/vpos4.w;
-		
-		vec3 v_Position=vpos/vpos.z*depth;
-		
-		fog=clamp( (length( v_Position )-r_FogNear)/(r_FogFar-r_FogNear),0.0,1.0 ) * r_FogColor.a;
-	}
-	
-	gl_FragColor=vec4( r_FogColor.rgb * fog,fog );
-}

+ 260 - 0
modules/mojo3d/assets/shaders/imports/pbr.glsl

@@ -0,0 +1,260 @@
+
+//@import "std"
+
+//@vertex
+
+//@fragment
+
+float pointAtten( float d,float r ){
+
+	float atten=max( 1.0-d*d/(r*r),0.0 );atten*=atten;
+	
+//	float d=length( lvec ),atten=1.0/(1.0+d*d);
+
+	return atten;
+}
+
+#if MX2_QUADPASS && MX2_LIGHTINGPASS
+
+void emitPbrFragment( vec3 color,float metalness,float roughness,vec3 position,vec3 normal ){
+
+	float glosiness=1.0-roughness;
+	vec3 color0=vec3( 0.04,0.04,0.04 );
+	vec3 diffuse=color * (1.0-metalness);
+	vec3 specular=(color-color0) * metalness + color0;
+	
+#if MX2_DIRECTIONALLIGHT
+
+	vec3 lvec=normalize( -r_LightViewMatrix[2].xyz );
+
+	float atten=1.0;
+	
+#elif MX2_POINTLIGHT
+
+	vec3 lvec=r_LightViewMatrix[3].xyz-position;
+
+	float atten=pointAtten( length( lvec ),r_LightRange );
+
+	lvec=normalize( lvec );
+	
+#elif MX2_SPOTLIGHT
+
+	vec3 lvec=r_LightViewMatrix[3].xyz-position;
+	
+	float atten=pointAtten( length( lvec ),r_LightRange );
+	
+	lvec=normalize( lvec );
+	
+	float cosangle=dot( -lvec,r_LightViewMatrix[2].xyz );
+	if( cosangle<0.0 ) return;				//behind spotlight direction
+	
+	float angle=acos( cosangle );
+	if( angle>r_LightOuterAngle ) return;	//outside outer cone
+
+	atten*=1.0-max( (angle-r_LightInnerAngle)/(r_LightOuterAngle-r_LightInnerAngle),0.0 );
+	
+#endif
+
+	vec3 vvec=normalize( -position );
+	vec3 hvec=normalize( lvec+vvec );
+
+	float hdotl=max( dot( hvec,lvec ),0.0 );
+	float ndotl=max( dot( normal,lvec ),0.0 );
+	float ndoth=max( dot( normal,hvec ),0.0 );
+	
+	float spow=pow( 2.0,glosiness * 12.0 );
+//	float spow=pow( 2048.0,glosiness );
+
+	float fnorm=(spow+2.0)/8.0;
+	
+	vec3 fschlick=specular + (1.0-specular) * pow( 1.0-hdotl,5.0 ) * glosiness;
+
+	specular=fschlick * pow( ndoth,spow ) * fnorm;
+	
+	vec3 light=r_LightColor.rgb * ndotl * atten;
+	
+#if MX2_POINTLIGHT
+
+	vec3 lpos=(r_InverseLightViewMatrix * vec4( position,1.0 )).xyz;
+	light*=pow( textureCube( r_LightCubeTexture,lpos ).rgb,vec3( 2.2 ) );
+
+#elif MX2_SPOTLIGHT
+
+	vec3 lpos=(r_InverseLightViewMatrix * vec4( position,1.0 )).xyz;
+	lpos.xy=lpos.xy/lpos.z * 0.5 + 0.5;
+	lpos.y=1.0-lpos.y;
+	light*=pow( texture2D( r_LightTexture,lpos.xy ).rgb,vec3( 2.2 ) ); 
+
+#endif
+	
+#if MX2_SHADOWTYPE
+	light*=shadowColor( position );
+#endif
+
+	vec3 frag=(diffuse+specular) * light;
+		
+	gl_FragColor=vec4( frag,1.0 );
+}
+
+#endif
+
+#if MX2_COLORPASS && MX2_DEFERREDPASS
+
+//deferred PBR lighting
+//
+void emitPbrFragment( vec4 color,vec3 ambient,vec3 emissive,float metalness,float roughness,float occlusion,vec3 normal ){
+
+	color*=v_Color;
+
+	float glosiness=1.0-roughness;
+	vec3 color0=vec3( 0.04,0.04,0.04 );
+	vec3 diffuse=color.rgb * (1.0-metalness);
+	vec3 specular=(color.rgb-color0) * metalness + color0;
+	
+	vec3 vvec=normalize( -v_Position );
+	float ndotv=max( dot( normal,vvec ),0.0 );
+	
+	vec3 ambEnv=sampleEnv( reflect( v_Position,normal ),roughness );
+	
+	/*
+	vec3 rvec=r_EnvMatrix * reflect( v_Position,normal );
+
+	float lod=textureCube( r_EnvTexture,rvec,r_EnvTextureMaxLod ).a * 255.0 - r_EnvTextureMaxLod;
+	if( lod>0.0 ) lod=textureCube( r_EnvTexture,rvec ).a * 255.0;
+
+//	float lod=textureCube( r_EnvTexture,rvec ).a * 255.0;
+//	if( lod==0.0 ) lod=textureCube( r_EnvTexture,rvec,r_EnvTextureMaxLod ).a * 255.0 - r_EnvTextureMaxLod;
+
+	vec3 ambEnv=pow( textureCube( r_EnvTexture,rvec,max( roughness*r_EnvTextureMaxLod-lod,0.0 ) ).rgb,vec3( 2.2 ) ) * r_EnvColor.rgb;
+	*/
+
+	vec3 fschlick0=specular + (1.0-specular) * pow( 1.0-ndotv,5.0 ) * glosiness;
+
+	vec3 ambDiffuse=diffuse * (r_AmbientDiffuse.rgb+ambient);
+		
+	vec3 ambSpecular=fschlick0 * ambEnv;
+	
+	vec3 frag=(ambDiffuse + ambSpecular) * occlusion + emissive;
+	
+#if MX2_DEFERREDRENDERER
+	//write ambient
+	gl_FragData[0]=vec4( min( frag,8.0 ),1.0 );
+	
+	//write color/metalness
+	gl_FragData[1]=vec4( color.rgb,metalness );
+	
+	//write normal/roughness
+	gl_FragData[2]=vec4( normal * 0.5 + 0.5,roughness );
+#endif
+}
+
+#endif
+
+#if MX2_COLORPASS && MX2_FORWARDPASS
+
+//forward PBR lighting
+//
+void emitPbrFragment( vec4 color,vec3 ambient,vec3 emissive,float metalness,float roughness,float occlusion,vec3 normal ){
+
+	color*=v_Color;
+
+	const vec3 color0=vec3( 0.04,0.04,0.04 );
+	
+	float glosiness=1.0-roughness;
+	vec3 diffuse=color.rgb * (1.0-metalness);
+	vec3 specular=(color.rgb-color0) * metalness + color0;
+	
+	vec3 vvec=normalize( -v_Position );
+	float ndotv=dot( normal,vvec );
+	
+	vec3 frag=vec3( 0.0 );
+	
+#if MX2_AMBIENTPASS
+	//ambient color
+	vec3 ambEnv=sampleEnv( reflect( v_Position,normal ),roughness );
+/*	
+	vec3 rvec=r_EnvMatrix * reflect( v_Position,normal );
+	
+	float lod=textureCube( r_EnvTexture,rvec,r_EnvTextureMaxLod ).a * 255.0 - r_EnvTextureMaxLod;
+	if( lod>0.0 ) lod=textureCube( r_EnvTexture,rvec ).a * 255.0;
+		
+//	float lod=textureCube( r_EnvTexture,rvec ).a * 255.0;
+//	if( lod==0.0 ) lod=textureCube( r_EnvTexture,rvec,r_EnvTextureMaxLod ).a * 255.0 - r_EnvTextureMaxLod;
+
+	vec3 ambEnv=pow( textureCube( r_EnvTexture,rvec,max( roughness*r_EnvTextureMaxLod-lod,0.0 ) ).rgb,vec3( 2.2 ) ) * r_EnvColor.rgb;
+*/
+	
+	vec3 fschlick0=specular + (1.0-specular) * pow( 1.0-ndotv,5.0 ) * glosiness;
+	
+	vec3 ambDiffuse=diffuse * (r_AmbientDiffuse.rgb+ambient);
+	
+	vec3 ambSpecular=fschlick0 * ambEnv;
+
+	frag+=( ambDiffuse + ambSpecular ) * occlusion + emissive;
+#endif
+
+#if MX2_LIGHTINGPASS
+	//lighting color
+	float spow=pow( 2.0,glosiness * 12.0 );				//specular power
+//	float spow=pow( 4096.0,glosiness );
+	float fnorm=(spow+2.0)/8.0;							//normalization factor
+	
+#if MX2_DIRECTIONALLIGHT
+
+	vec3 lvec=normalize( -r_LightViewMatrix[2].xyz );
+	
+	float atten=1.0;
+	
+#elif MX2_POINTLIGHT
+
+	vec3 lvec=r_LightViewMatrix[3].xyz-v_Position;
+	
+	float atten=pointAtten( length( lvec ),r_LightRange );
+	
+	lvec=normalize( lvec );
+	
+#elif MX2_SPOTLIGHT
+
+	vec3 lvec=r_LightViewMatrix[3].xyz-v_Position;
+	
+	float atten=pointAtten( length( lvec ),r_LightRange );
+	
+	lvec=normalize( lvec );
+	
+	float cosangle=dot( -lvec,r_LightViewMatrix[2].xyz );
+	if( cosangle<0.0 ) return;				//behind spotlight direction
+	
+	float angle=acos( cosangle );
+	if( angle>r_LightOuterAngle ) return;	//outside outer cone
+
+	atten*=1.0-max( (angle-r_LightInnerAngle)/(r_LightOuterAngle-r_LightInnerAngle),0.0 );
+	
+#endif
+	vec3 hvec=normalize( lvec+vvec );
+
+	float ndotl=max( dot( normal,lvec ),0.0 );
+	float ndoth=max( dot( normal,hvec ),0.0 );
+	float hdotl=max( dot( hvec,lvec ),0.0 );
+	
+	vec3 fschlick=specular + (1.0-specular) * pow( 1.0-hdotl,5.0 ) * glosiness;
+	
+	vec3 fspecular=fschlick * pow( ndoth,spow ) * fnorm;
+	
+	vec3 light=r_LightColor.rgb * ndotl * atten;
+	
+	light=(diffuse+fspecular) * light;
+
+#if MX2_SHADOWTYPE
+	light*=shadowColor( v_Position );
+#endif
+
+	frag+=light;
+	
+#endif	//MX2_LIGHTINGPASS
+
+	color.rgb=frag;
+	
+	emitColorFragment( color );
+}
+
+#endif

+ 455 - 0
modules/mojo3d/assets/shaders/imports/std.glsl

@@ -0,0 +1,455 @@
+
+// **** MX2_RENDERPASS *****
+//
+// PASSTYPE		'mask=3,  0=quad, 1=deferred, 2=forward, 3=shadow
+// LIGHTTYPE	'mask=12, 0=none, 1=directional, 2=point, 3=spot
+// SHADOWTYPE	'mask=16, 0=no shadows, 1=shadows
+//
+#ifndef MX2_RENDERPASS
+#define MX2_RENDERPASS 0
+#endif
+
+#ifndef MX2_FORWARDRENDERER
+#define MX2_FORWARDRENDERER 0
+#endif
+
+#ifndef MX2_DEFERREDRENDERER
+#define MX2_DEFERREDRENDERER 0
+#endif
+
+#ifndef MX2_SRGBOUTPUT
+#define MX2_SRGBOUTPUT 0
+#endif
+
+#define MX2_PASSTYPE			((MX2_RENDERPASS & 3))
+#define MX2_LIGHTTYPE			((MX2_RENDERPASS & 12)>>2)
+#define MX2_SHADOWTYPE			((MX2_RENDERPASS & 16)>>4)
+
+#define MX2_DIRECTIONALLIGHT	(MX2_LIGHTTYPE==1)
+#define MX2_POINTLIGHT			(MX2_LIGHTTYPE==2)
+#define MX2_SPOTLIGHT			(MX2_LIGHTTYPE==3)
+
+#define MX2_QUADPASS			(MX2_PASSTYPE==0)
+#define MX2_DEFERREDPASS		(MX2_PASSTYPE==1)
+#define MX2_FORWARDPASS			(MX2_PASSTYPE==2)
+#define MX2_SHADOWPASS			(MX2_PASSTYPE==3)
+
+#define MX2_AMBIENTPASS			(MX2_PASSTYPE==1 || MX2_PASSTYPE==2)
+#define MX2_LIGHTINGPASS		(MX2_LIGHTTYPE!=0 && MX2_SHADOWPASS==0)
+#define MX2_COLORPASS			(MX2_AMBIENTPASS || MX2_LIGHTINGPASS)
+
+// ***** MX2_ATTRIBMASK *****
+//
+// Position		1
+// Normal		2
+// Color		4
+// TexCoord0	8
+// TexCoord1	16
+// Tangent		32
+// Weights		64
+// Bones		128
+
+#ifndef MX2_ATTRIBMASK
+#define MX2_ATTRIBMASK 0
+#endif
+#define MX2_TEXTURED			((MX2_ATTRIBMASK & 24)!=0)
+#define MX2_BUMPMAPPED			((MX2_ATTRIBMASK & 32)==32)
+#define MX2_BONED				((MX2_ATTRIBMASK & 192)==192)
+
+//***** CONSTS *****
+//
+const float pi=3.1415926535897932384626433832795;
+
+//***** RENDER *****
+//
+uniform float r_Time;
+uniform vec4 r_AmbientDiffuse;
+
+uniform samplerCube r_SkyTextureCube;
+uniform sampler2D r_SkyTexture2D;
+uniform bool r_SkyCube;
+
+uniform samplerCube r_EnvTextureCube;
+uniform sampler2D r_EnvTexture2D;
+uniform bool r_EnvCube;
+uniform float r_EnvTextureMaxLod;
+uniform vec4 r_EnvColor;
+uniform mat3 r_EnvMatrix;
+
+uniform float r_DepthNear;
+uniform float r_DepthFar;
+uniform float r_FogNear;
+uniform float r_FogFar;
+uniform vec4 r_FogColor;
+uniform mat4 r_InverseProjectionMatrix;
+uniform mat4 r_ProjectionMatrix;
+uniform mat4 r_ViewMatrix;
+
+// These only available in deferred renderer!
+uniform sampler2D r_AccumBuffer;
+uniform sampler2D r_ColorBuffer;
+uniform sampler2D r_NormalBuffer;
+uniform sampler2D r_DepthBuffer;
+uniform vec2 r_BufferCoordScale;
+uniform vec2 r_QuadCoordScale;
+uniform vec2 r_QuadCoordTrans;
+
+//***** LIGHTING *****
+//
+uniform mat4 r_LightViewMatrix;
+uniform mat4 r_InverseLightViewMatrix;
+uniform samplerCube r_LightCubeTexture;
+uniform sampler2D r_LightTexture;
+uniform vec4 r_LightColor;
+uniform float r_LightRange;
+uniform float r_LightInnerAngle;
+uniform float r_LightOuterAngle;
+
+//***** SHADOWS *****
+//
+uniform sampler2D r_ShadowCSMTexture;
+uniform samplerCube r_ShadowCubeTexture;
+uniform vec4 r_ShadowCSMSplits;
+uniform mat4 r_ShadowMatrix0;
+uniform mat4 r_ShadowMatrix1;
+uniform mat4 r_ShadowMatrix2;
+uniform mat4 r_ShadowMatrix3;
+uniform float r_ShadowAlpha;
+
+//***** INSTANCE *****
+//
+uniform mat4 i_ModelMatrix;
+uniform mat4 i_ModelViewMatrix;
+uniform mat4 i_ModelViewProjectionMatrix;
+uniform mat3 i_ModelViewNormalMatrix;
+uniform mat4 i_ModelBoneMatrices[96];
+uniform vec4  i_Color;
+uniform float i_Alpha;
+
+//***** MATERIAL *****
+//
+uniform mat3 m_TextureMatrix;
+
+//***** VARYINGS *****
+//
+varying vec2 v_ClipPosition;
+varying vec2 v_BufferCoords;
+varying vec3 v_Position;
+varying vec3 v_Normal;
+varying vec4 v_Color;
+varying vec2 v_TexCoord0;
+varying vec2 v_TexCoord1;
+varying mat3 v_TanMatrix;
+
+//@vertex
+
+//***** ATTRIBUTES *****
+//
+attribute vec4 a_Position;	//mask=1
+attribute vec3 a_Normal;	//mask=2
+attribute vec4 a_Color;		//mask=4
+attribute vec2 a_TexCoord0;	//mask=8
+attribute vec2 a_TexCoord1;	//mask=16
+attribute vec4 a_Tangent;	//mask=32
+attribute vec4 a_Weights;	//mask=64
+attribute vec4 a_Bones;		//mask=128
+
+void transformLightQuadVertex(){
+
+	vec2 qposition=a_Position.xy * r_QuadCoordScale + r_QuadCoordTrans;
+
+	v_ClipPosition=qposition * 2.0 - 1.0;
+	
+	v_BufferCoords=qposition * r_BufferCoordScale;
+	
+	gl_Position=vec4( v_ClipPosition,-1.0,1.0 );
+}
+
+void transformQuadVertex(){
+
+	v_ClipPosition=a_Position.xy * 2.0 - 1.0;
+	
+	v_BufferCoords=a_Position.xy * r_BufferCoordScale;
+	
+	gl_Position=vec4( v_ClipPosition,-1.0,1.0 );
+}
+
+void transformSpriteVertex(){
+
+	v_Position=(i_ModelViewMatrix * a_Position).xyz;
+
+	v_TexCoord0=(m_TextureMatrix * vec3(a_TexCoord0,1.0)).st;
+	
+	gl_Position=i_ModelViewProjectionMatrix * a_Position;
+}
+
+void transformVertex(){
+ 
+#if MX2_BONED
+	mat4 m0=i_ModelBoneMatrices[ int( a_Bones.x ) ];
+	mat4 m1=i_ModelBoneMatrices[ int( a_Bones.y ) ];
+	mat4 m2=i_ModelBoneMatrices[ int( a_Bones.z ) ];
+	mat4 m3=i_ModelBoneMatrices[ int( a_Bones.a ) ];
+	
+	vec4 position=
+		m0 * a_Position * a_Weights.x +
+		m1 * a_Position * a_Weights.y +
+		m2 * a_Position * a_Weights.z +
+		m3 * a_Position * a_Weights.a;
+#if MX2_COLORPASS
+	mat3 n0=mat3( m0[0].xyz,m0[1].xyz,m0[2].xyz );
+	mat3 n1=mat3( m1[0].xyz,m1[1].xyz,m1[2].xyz );
+	mat3 n2=mat3( m2[0].xyz,m2[1].xyz,m2[2].xyz );
+	mat3 n3=mat3( m3[0].xyz,m3[1].xyz,m3[2].xyz );
+
+	vec3 normal=normalize( 
+		n0 * a_Normal * a_Weights.x +
+		n1 * a_Normal * a_Weights.y +
+		n2 * a_Normal * a_Weights.z +
+		n3 * a_Normal * a_Weights.a );
+#if MX2_BUMPMAPPED
+	vec4 tangent=vec4( normalize( 
+		n0 * a_Tangent.xyz * a_Weights.x +
+		n1 * a_Tangent.xyz * a_Weights.y +
+		n2 * a_Tangent.xyz * a_Weights.z +
+		n3 * a_Tangent.xyz * a_Weights.a ),a_Tangent.w );
+#endif
+#endif
+#else	//MX2_BONED
+	vec4 position=a_Position;
+#if MX2_COLORPASS
+	vec3 normal=a_Normal;
+#if MX2_BUMPMAPPED	
+	vec4 tangent=a_Tangent;
+#endif
+#endif
+#endif
+
+	// view space position
+	v_Position=( i_ModelViewMatrix * position ).xyz;
+
+#if MX2_COLORPASS
+	// viewspace normal
+	v_Normal=i_ModelViewNormalMatrix * normal;
+	// vertex color
+	v_Color=a_Color * i_Color;
+	v_Color.a*=i_Alpha;
+#if MX2_TEXTURED
+	// texture coord0
+	v_TexCoord0=(m_TextureMatrix * vec3(a_TexCoord0,1.0)).st;
+	v_TexCoord1=a_TexCoord1;//(m_TextureMatrix * vec3(a_TexCoord1,1.0)).st;
+#if MX2_BUMPMAPPED
+	// viewspace tangent matrix
+	v_TanMatrix[2]=normalize( v_Normal );
+	v_TanMatrix[0]=normalize( i_ModelViewNormalMatrix * tangent.xyz );
+	v_TanMatrix[1]=cross( v_TanMatrix[0],v_TanMatrix[2] ) * tangent.a;
+#endif
+#endif
+#endif	//MX2_COLORPASS
+	
+	gl_Position=i_ModelViewProjectionMatrix * position;
+}
+
+//@fragment
+
+vec4 FloatToRGBA( float value ){
+
+	const float MaxFloat=0.9999999;
+	value=clamp( value,0.0,MaxFloat );
+	vec4 rgba=fract( vec4( 1.0, 255.0, 65025.0, 16581375.0 ) * value );
+	return rgba-rgba.yzww * vec4( 1.0/255.0, 1.0/255.0, 1.0/255.0, 0.0 );
+}
+
+float RGBAToFloat( vec4 rgba ){
+
+	return dot( rgba,vec4( 1.0, 1.0/255.0, 1.0/65025.0, 1.0/16581375.0 ) );
+}
+
+float viewDepth( float depthBufferDepth ){
+
+	return r_DepthFar * r_DepthNear / ( r_DepthFar + depthBufferDepth * ( r_DepthNear - r_DepthFar ) );
+}
+
+#if MX2_QUADPASS
+
+vec3 fragmentPosition(){
+
+	float depth=viewDepth( texture2D( r_DepthBuffer,v_BufferCoords ).r );
+
+	vec4 vpos4=r_InverseProjectionMatrix * vec4( v_ClipPosition,-1.0,1.0 );
+	
+	vec3 vpos=vpos4.xyz/vpos4.w;
+	
+	//debug z coord...
+	//
+	if( abs( vpos.z-r_DepthNear)>0.00001 ){
+//		gl_FragColor=vec4( 1.0,0.0,0.0,1.0 );
+//		return vec3( 0.0 );
+	}
+	
+	vec3 position=vpos/vpos.z*depth;
+	
+	return position;
+}
+
+#else
+
+vec3 fragmentPosition(){
+
+	return v_Position;
+}
+
+#endif
+
+#if MX2_LIGHTINGPASS && MX2_SHADOWTYPE
+
+float shadowColor( vec3 position ){
+
+#if MX2_DIRECTIONALLIGHT
+ 
+	if( position.z>=r_ShadowCSMSplits.w ) return 1.0;
+	
+	vec4 vpos=vec4( position,1.0 );
+	vec2 off;
+	
+	if( vpos.z<r_ShadowCSMSplits.x ){
+		vpos=r_ShadowMatrix0 * vpos;
+		off=vec2( 0.0,0.0 );
+	}else if( vpos.z<r_ShadowCSMSplits.y ){
+		vpos=r_ShadowMatrix1 * vpos;
+		off=vec2( 0.5,0.0 );
+	}else if( vpos.z<r_ShadowCSMSplits.z ){
+		vpos=r_ShadowMatrix2 * vpos;
+		off=vec2( 0.0,0.5 );
+	}else{
+		vpos=r_ShadowMatrix3 * vpos;
+		off=vec2( 0.5,0.5 );
+	}
+	
+	vec3 spos=vpos.xyz/vpos.w * vec3( 0.25,0.25,0.5 ) + vec3( 0.25,0.25,0.5 );
+	
+	float d=texture2D( r_ShadowCSMTexture,spos.xy+off ).r;
+	
+	if( spos.z>d ) return 1.0-r_ShadowAlpha;
+	
+	return 1.0;
+	
+#elif MX2_POINTLIGHT
+
+	vec4 vpos=vec4( position,1.0 );
+	
+	vec3 lpos=(r_ShadowMatrix0 * vpos).xyz;
+	
+	float d=RGBAToFloat( textureCube( r_ShadowCubeTexture,lpos ) );
+	
+	if( length(lpos) > d * r_LightRange ) return 1.0-r_ShadowAlpha;
+	
+	return 1.0;
+	
+#elif MX2_SPOTLIGHT
+
+	vec4 vpos=r_ShadowMatrix0 * vec4( position,1.0 );
+	
+	vec3 spos=vpos.xyz/vpos.w * vec3( 0.25,0.25,0.5 ) + vec3( 0.25,0.25,0.5 );
+
+	float d=texture2D( r_ShadowCSMTexture,spos.xy ).r;
+	
+	if( spos.z>d ) return 1.0-r_ShadowAlpha;
+	
+	return 1.0;
+	
+#endif
+}
+
+#endif
+
+/*
+float mipmapLod( vec2 tc ){
+    vec2 dx=dFdx( tc );
+    vec2 dy=dFdy( tc );
+    float dsqr=max( dot( dx,dx ),dot( dy,dy ) );
+    float lod=log2( dsqr ) * 0.5;
+    return max( lod,0.0 );
+}
+
+float mipmapLodCube( vec3 tv ){
+	vec2 tc;
+	vec3 at=abs( tv );
+	if( at.x>at.y && at.x>at.z ){
+		tc=vec2( tv.y,tv.z )/tv.x;
+	}else if( at.y>at.z ){
+		tc=vec2( tv.x,tv.z )/tv.y;
+	}else{
+		tc=vec2( tv.x,tv.y )/tv.z;
+	}
+	return mipmapLod( (tc+1.0)*0.5 );
+}
+*/
+
+vec3 sampleEnv( vec3 viewVec,float roughness ){
+
+	vec3 tv=r_EnvMatrix * viewVec;
+
+	if( r_EnvCube ){
+		
+//#ifdef GL_ES
+		float lod=textureCube( r_EnvTextureCube,tv ).a * 255.0;
+		if( lod==0.0 ) lod=textureCube( r_EnvTextureCube,tv,r_EnvTextureMaxLod ).a * 255.0 - r_EnvTextureMaxLod;
+		return pow( textureCube( r_EnvTextureCube,tv,max( roughness*r_EnvTextureMaxLod-lod,0.0 ) ).rgb,vec3( 2.2 ) ) * r_EnvColor.rgb;
+//#else
+//		return pow( textureCube( r_EnvTextureCube,tv,roughness*r_EnvTextureMaxLod ).rgb,vec3( 2.2 ) ) * r_EnvColor.rgb;
+//#endif
+		
+	}else{
+	
+		float p=-atan( tv.y,sqrt( tv.x*tv.x+tv.z*tv.z ) ) / pi + 0.5;
+		float y=atan( tv.x,tv.z ) / pi * 0.5 + 0.5;
+		vec2 tc=vec2( y,p );
+		
+//#ifdef GL_ES
+		float lod=texture2D( r_EnvTexture2D,tc ).a * 255.0;
+		if( lod==0.0 ) lod=texture2D( r_EnvTexture2D,tc,r_EnvTextureMaxLod ).a * 255.0 - r_EnvTextureMaxLod;
+		return pow( texture2D( r_EnvTexture2D,tc,max( roughness*r_EnvTextureMaxLod-lod,0.0 ) ).rgb,vec3( 2.2 ) ) * r_EnvColor.rgb;
+//else
+//		return pow( texture2DLod( r_EnvTexture2D,tc,max( mipmapLod( tc ),roughness*r_EnvTextureMaxLod ) ).rgb,vec3( 2.2 ) ) * r_EnvColor.rgb;
+	
+//#endif
+	}
+}
+
+#if MX2_FORWARDRENDERER || MX2_FORWARDPASS
+
+void emitLinearFragment( vec4 color ){
+
+#if MX2_SRGBOUTPUT
+	gl_FragColor=vec4( pow( color.rgb*color.a,vec3( 1.0/2.2 ) ),color.a );
+#else
+	gl_FragColor=vec4( color.rgb*color.a,color.a );
+#endif
+}
+
+void emitColorFragment( vec4 color ){
+
+	float fog=clamp( (length( v_Position )-r_FogNear)/(r_FogFar-r_FogNear),0.0,1.0 ) * r_FogColor.a;
+	
+	color.rgb=mix( color.rgb,r_FogColor.rgb,fog );
+	
+	emitLinearFragment( color );
+}
+
+#endif
+
+#if MX2_SHADOWPASS
+
+void emitShadowFragment(){
+
+#if MX2_DIRECTIONALLIGHT || MX2_SPOTLIGHT
+	gl_FragColor=vec4( vec3( gl_FragCoord.z ),1.0 );
+#elif MX2_POINTLIGHT
+	gl_FragColor=FloatToRGBA( min( length( v_Position )/r_LightRange,1.0 ) );
+#endif
+}
+
+#endif
+
+

+ 0 - 223
modules/mojo3d/assets/shaders/lighting-deferred.glsl

@@ -1,223 +0,0 @@
-
-//@renderpasses 2,6,10,14
-
-//renderpasses:
-//
-// 2=directional without shadows
-// 6=directional with  shadows
-// 10=point without shadows
-// 14=point with shadows
- 
-uniform mat4 r_InverseProjectionMatrix;
-
-#define MX2_POINT_LIGHT ((MX2_RENDERPASS&8)!=0)
-#define MX2_DIRECTIONAL_LIGHT ((MX2_RENDERPASS&8)==0)
-#define MX2_SHADOWED_LIGHT ((MX2_RENDERPASS&4)!=0)
-
-uniform vec2 r_BufferCoordScale;
-uniform sampler2D r_ColorBuffer;
-uniform sampler2D r_NormalBuffer;
-uniform sampler2D r_DepthBuffer;
-
-uniform float r_DepthNear;
-uniform float r_DepthFar;
-
-uniform mat4 r_LightViewMatrix;
-uniform float r_LightRange;
-uniform vec4 r_LightColor;
-
-#if MX2_SHADOWED_LIGHT
-
-uniform float r_ShadowAlpha;
-
-#if MX2_DIRECTIONAL_LIGHT
-uniform sampler2D r_ShadowCSMTexture;
-uniform vec4 r_ShadowCSMSplits;
-uniform mat4 r_ShadowMatrix0;
-uniform mat4 r_ShadowMatrix1;
-uniform mat4 r_ShadowMatrix2;
-uniform mat4 r_ShadowMatrix3;
-#else
-uniform samplerCube r_ShadowCubeTexture;
-uniform mat4 r_ShadowMatrix0;
-#endif
-
-#endif
-
-varying vec2 v_ClipPosition;
-varying vec2 v_TexCoord0;
-
-//@vertex
-
-attribute vec2 a_Position;	//0...1 (1=viewport size)
-
-void main(){
-
-	v_ClipPosition=a_Position * 2.0 - 1.0;
-	
-	v_TexCoord0=a_Position * r_BufferCoordScale;
-	
-	gl_Position=vec4( v_ClipPosition,-1.0,1.0 );
-}
-
-//@fragment
-
-vec3 v_Position;
-vec3 v_Normal;
-
-//can't handle 1!
-vec4 FloatToRGBA( float value ){
-
-	const float MaxFloat=0.9999999;
-
-	value=clamp( value,0.0,MaxFloat );
-
-	vec4 rgba=fract( vec4( 1.0, 255.0, 65025.0, 16581375.0 ) * value );
-	
-	return rgba-rgba.yzww * vec4( 1.0/255.0, 1.0/255.0, 1.0/255.0, 0.0 );
-}
-
-float RGBAToFloat( vec4 rgba ){
-
-	return dot( rgba,vec4( 1.0, 1.0/255.0, 1.0/65025.0, 1.0/16581375.0 ) );
-}
-
-float viewDepth( float depth ){
-
-	return r_DepthFar * r_DepthNear / ( r_DepthFar + depth * ( r_DepthNear - r_DepthFar ) );
-}
-
-#if MX2_SHADOWED_LIGHT
-
-#if MX2_DIRECTIONAL_LIGHT
-
-float shadowColor(){
-
-//	vec3 dx=dFdx( v_Position );
-//	vec3 dy=dFdy( v_Position );
-//	vec3 vn=vec4( cross( dx,dy ),0.0 );
-//	vec4 vpos=vec4( v_Position + v_Normal*0.01,1.0 );
-
-	if( v_Position.z>=r_ShadowCSMSplits.w ) return 1.0;//(1.0-r_ShadowAlpha)*0.5;
-	
-	vec4 vpos=vec4( v_Position,1.0 );
-	vec2 off;
-	
-	if( vpos.z<r_ShadowCSMSplits.x ){
-		vpos=r_ShadowMatrix0 * vpos;
-		off=vec2( 0.0,0.0 );
-	}else if( vpos.z<r_ShadowCSMSplits.y ){
-		vpos=r_ShadowMatrix1 * vpos;
-		off=vec2( 0.5,0.0 );
-	}else if( vpos.z<r_ShadowCSMSplits.z ){
-		vpos=r_ShadowMatrix2 * vpos;
-		off=vec2( 0.0,0.5 );
-	}else{
-		vpos=r_ShadowMatrix3 * vpos;
-		off=vec2( 0.5,0.5 );
-	}
-	
-	vec3 spos=vpos.xyz/vpos.w * vec3( 0.25,0.25,0.5 ) + vec3( 0.25,0.25,0.5 );
-	
-#if defined( MX2_RGBADEPTHTEXTURES )
-	float d=RGBAToFloat( texture2D( r_ShadowCSMTexture,spos.xy+off ) );
-#else
-	float d=texture2D( r_ShadowCSMTexture,spos.xy+off ).r;
-#endif
-	
-	if( spos.z>d ) return 1.0-r_ShadowAlpha;
-	
-	return 1.0;
-}
-
-#else
-
-float shadowColor(){
-
-	vec4 vpos=vec4( v_Position,1.0 );
-	
-	vec3 lpos=(r_ShadowMatrix0 * vpos).xyz;
-	
-	float d=RGBAToFloat( textureCube( r_ShadowCubeTexture,lpos ) );
-	
-	if( length(lpos) > d * r_LightRange ) return 1.0-r_ShadowAlpha;
-	
-	return 1.0;
-}
-
-#endif
-
-#endif
-
-vec3 lightColor( vec3 color,float metalness,float roughness ){
-
-	vec3 normal=v_Normal;
-	float glosiness=1.0-roughness;
-	vec3 color0=vec3( 0.04,0.04,0.04 );
-	vec3 diffuse=color * (1.0-metalness);
-	vec3 specular=(color-color0) * metalness + color0;
-	
-#if MX2_DIRECTIONAL_LIGHT
-	vec3 lvec=normalize( -r_LightViewMatrix[2].xyz );
-	float atten=1.0;
-#else
-	// TODO: https://imdoingitwrong.wordpress.com/2011/01/31/light-attenuation/
-	vec3 lvec=r_LightViewMatrix[3].xyz-v_Position;
-	float atten=max( 1.0-length( lvec )/r_LightRange,0.0 );
-	lvec=normalize( lvec );
-#endif
-
-	vec3 vvec=normalize( -v_Position );
-	vec3 hvec=normalize( lvec+vvec );
-
-	float hdotl=max( dot( hvec,lvec ),0.0 );
-	float ndotl=max( dot( normal,lvec ),0.0 );
-	float ndoth=max( dot( normal,hvec ),0.0 );
-	
-	float spow=pow( 2.0,glosiness * 12.0 );
-//	float spow=pow( 2048.0,glosiness );
-	
-	float fnorm=(spow+2.0)/8.0;
-	
-	vec3 fschlick=specular + (1.0-specular) * pow( 1.0-hdotl,5.0 ) * glosiness;
-	
-	specular=fschlick * pow( ndoth,spow ) * fnorm;
-
-	vec3 light=r_LightColor.rgb * ndotl * atten;
-	
-#if MX2_SHADOWED_LIGHT
-
-	light*=shadowColor();
-	
-#endif
-	
-	return (diffuse+specular) * light;
-}
-
-void main(){
-
-	vec4 color_m=texture2D( r_ColorBuffer,v_TexCoord0 );
-	
-	vec4 normal_r=texture2D( r_NormalBuffer,v_TexCoord0 );
-	
-	float depth=viewDepth( texture2D( r_DepthBuffer,v_TexCoord0 ).r );
-
-	vec4 vpos4=r_InverseProjectionMatrix * vec4( v_ClipPosition,-1.0,1.0 );
-	
-	vec3 vpos=vpos4.xyz/vpos4.w;
-	
-	//debug z coord...
-	//
-	if( abs( vpos.z-r_DepthNear)>0.00001 ){
-		gl_FragColor=vec4( 1.0,0.0,0.0,1.0 );
-		return;
-	}
-	
-	v_Position=vpos/vpos.z*depth;
-	
-	v_Normal=normalize( normal_r.xyz * 2.0 - 1.0 );
-	
-	vec3 frag=lightColor( color_m.rgb,color_m.a,normal_r.a );
-	
-	gl_FragColor=vec4( min( frag,8.0 ),1.0 );
-}

+ 0 - 310
modules/mojo3d/assets/shaders/material-pbr-deferred.glsl

@@ -1,310 +0,0 @@
-//@renderpasses 1,4,12
-
-//renderpasses:
-//
-// 1 = ambient
-// 4 = directional shadows
-// 12 = point shadows
-
-#define MX2_COLORPASS ((MX2_RENDERPASS&3)!=0)
-#define MX2_POINT_LIGHT ((MX2_RENDERPASS&8)!=0)
-#define MX2_DIRECTIONAL_LIGHT ((MX2_RENDERPASS&8)==0)
- 
-//material uniforms
-
-#ifdef MX2_TEXTURED
-uniform mat3 m_TextureMatrix;
-#endif
-
-//renderer uniforms...
-
-uniform mat4 i_ModelViewMatrix;
-uniform mat4 i_ModelViewProjectionMatrix;
-uniform mat3 i_ModelViewNormalMatrix;
-
-#if MX2_COLORPASS
-
-uniform vec4  i_Color;
-uniform float i_Alpha;
-
-uniform vec4 r_AmbientDiffuse;
-uniform samplerCube r_EnvTexture;
-uniform float r_EnvTextureMaxLod;
-uniform vec4 r_EnvColor;
-uniform mat3 r_EnvMatrix;
-
-//pbr varyings...
-
-varying vec3 v_Position;
-varying vec3 v_Normal;
-varying vec4 v_Color;
-#ifdef MX2_TEXTURED
-varying vec2 v_TexCoord0;
-#ifdef MX2_BUMPMAPPED
-varying mat3 v_TanMatrix;
-#endif
-#endif
-
-#else	//MX2_COLORPASS
-
-#if MX2_POINT_LIGHT
-uniform float r_LightRange;
-#endif
-
-varying vec3 v_Position;
-
-#endif	//MX2_COLORPASS
-
-//@vertex
-
-#ifdef MX2_BONED
-uniform mat4 i_ModelBoneMatrices[96];
-#endif
-
-//vertex attribs....
-
-attribute vec4 a_Position;
-#ifdef MX2_BONED
-attribute vec4 a_Weights;
-attribute vec4 a_Bones;
-#endif
-
-#if MX2_COLORPASS
-
-attribute vec3 a_Normal;
-attribute vec4 a_Color;
-#ifdef MX2_TEXTURED
-attribute vec2 a_TexCoord0;
-#ifdef MX2_BUMPMAPPED
-attribute vec4 a_Tangent;
-#endif
-#endif
-
-#endif	//MX2_COLORPASS
-
-#ifdef MX2_BONED
-
-void main(){
-
-	mat4 m0=i_ModelBoneMatrices[ int( a_Bones.x ) ];
-	mat4 m1=i_ModelBoneMatrices[ int( a_Bones.y ) ];
-	mat4 m2=i_ModelBoneMatrices[ int( a_Bones.z ) ];
-	mat4 m3=i_ModelBoneMatrices[ int( a_Bones.a ) ];
-	
-	vec4 b_Position=
-		m0 * a_Position * a_Weights.x +
-		m1 * a_Position * a_Weights.y +
-		m2 * a_Position * a_Weights.z +
-		m3 * a_Position * a_Weights.a;
-		
-	// view space position
-	v_Position=( i_ModelViewMatrix * b_Position ).xyz;
-
-#if MX2_COLORPASS
-
-	mat3 n0=mat3( m0[0].xyz,m0[1].xyz,m0[2].xyz );
-	mat3 n1=mat3( m1[0].xyz,m1[1].xyz,m1[2].xyz );
-	mat3 n2=mat3( m2[0].xyz,m2[1].xyz,m2[2].xyz );
-	mat3 n3=mat3( m3[0].xyz,m3[1].xyz,m3[2].xyz );
-
-	vec3 b_Normal=normalize( 
-		n0 * a_Normal * a_Weights.x +
-		n1 * a_Normal * a_Weights.y +
-		n2 * a_Normal * a_Weights.z +
-		n3 * a_Normal * a_Weights.a );
-		
-#ifdef MX2_BUMPMAPPED
-	vec4 b_Tangent=vec4( normalize( 
-		n0 * a_Tangent.xyz * a_Weights.x +
-		n1 * a_Tangent.xyz * a_Weights.y +
-		n2 * a_Tangent.xyz * a_Weights.z +
-		n3 * a_Tangent.xyz * a_Weights.a ),a_Tangent.w );
-#endif
-
-	// viewspace normal
-	v_Normal=i_ModelViewNormalMatrix * b_Normal;
-	
-	// vertex color
-	v_Color=a_Color * i_Color;
-	v_Color.a*=i_Alpha;
-	
-#ifdef MX2_TEXTURED
-	// texture coord0
-	v_TexCoord0=(m_TextureMatrix * vec3(a_TexCoord0,1.0)).st;
-#ifdef MX2_BUMPMAPPED
-	// viewspace tangent matrix
-	v_TanMatrix[2]=normalize( v_Normal );
-	v_TanMatrix[0]=normalize( i_ModelViewNormalMatrix * b_Tangent.xyz );
-	v_TanMatrix[1]=cross( v_TanMatrix[0],v_TanMatrix[2] ) * b_Tangent.a;
-#endif
-#endif
-	
-#endif	//MX2_COLORPASS
-	
-	gl_Position=i_ModelViewProjectionMatrix * b_Position;
-}
-
-#else	//MX2_BONED
-
-void main(){
-
-	// view space position
-	v_Position=( i_ModelViewMatrix * a_Position ).xyz;
-
-#if MX2_COLORPASS
-
-	// viewspace normal
-	v_Normal=i_ModelViewNormalMatrix * a_Normal;
-	
-	// vertex color
-	v_Color=a_Color * i_Color;
-	v_Color.a*=i_Alpha;
-	
-#ifdef MX2_TEXTURED
-	// texture coord0
-	v_TexCoord0=(m_TextureMatrix * vec3(a_TexCoord0,1.0)).st;
-#ifdef MX2_BUMPMAPPED
-	// viewspace tangent matrix
-	v_TanMatrix[2]=normalize( v_Normal );
-	v_TanMatrix[0]=normalize( i_ModelViewNormalMatrix * a_Tangent.xyz );
-	v_TanMatrix[1]=cross( v_TanMatrix[0],v_TanMatrix[2] ) * a_Tangent.a;
-#endif
-#endif
-
-#endif	//MX2_COLORPASS
-	
-	gl_Position=i_ModelViewProjectionMatrix * a_Position;
-}
-
-#endif	//MX2_BONED
-
-//@fragment
-
-vec4 FloatToRGBA( float value ){
-
-	const float MaxFloat=0.9999999;
-
-	value=clamp( value,0.0,MaxFloat );
-
-	vec4 rgba=fract( vec4( 1.0, 255.0, 65025.0, 16581375.0 ) * value );
-	
-	return rgba-rgba.yzww * vec4( 1.0/255.0, 1.0/255.0, 1.0/255.0, 0.0 );
-}
-
-float RGBAToFloat( vec4 rgba ){
-
-	return dot( rgba,vec4( 1.0, 1.0/255.0, 1.0/65025.0, 1.0/16581375.0 ) );
-}
-
-#if MX2_COLORPASS
-
-void pbrWriteFragData( vec3 color,vec3 emissive,float metalness,float roughness,float occlusion,vec3 normal ){
-
-	float glosiness=1.0-roughness;
-	vec3 color0=vec3( 0.04,0.04,0.04 );
-	vec3 diffuse=color * (1.0-metalness);
-	vec3 specular=(color-color0) * metalness + color0;
-	
-	vec3 vvec=normalize( -v_Position );
-	float ndotv=max( dot( normal,vvec ),0.0 );
-	
-	vec3 rvec=r_EnvMatrix * reflect( v_Position,normal );
-
-	float lod=textureCube( r_EnvTexture,rvec,r_EnvTextureMaxLod ).a * 255.0 - r_EnvTextureMaxLod;
-	if( lod>0.0 ) lod=textureCube( r_EnvTexture,rvec ).a * 255.0;
-
-//	float lod=textureCube( r_EnvTexture,rvec ).a * 255.0;
-//	if( lod==0.0 ) lod=textureCube( r_EnvTexture,rvec,r_EnvTextureMaxLod ).a * 255.0 - r_EnvTextureMaxLod;
-
-	vec3 ambEnv=pow( textureCube( r_EnvTexture,rvec,max( roughness*r_EnvTextureMaxLod-lod,0.0 ) ).rgb,vec3( 2.2 ) ) * r_EnvColor.rgb;
-
-	vec3 fschlick0=specular + (1.0-specular) * pow( 1.0-ndotv,5.0 ) * glosiness;
-
-	vec3 ambDiffuse=diffuse * r_AmbientDiffuse.rgb;
-		
-	vec3 ambSpecular=fschlick0 * ambEnv;
-	
-	vec3 frag=(ambDiffuse + ambSpecular) * occlusion + emissive;
-	
-	//write ambient
-	gl_FragData[0]=vec4( min( frag,8.0 ),1.0 );
-	
-	//write color/metalness
-	gl_FragData[1]=vec4( color,metalness );
-	
-	//write normal/roughness
-	gl_FragData[2]=vec4( normal * 0.5 + 0.5,roughness );
-}
-
-#endif
-
-#if MX2_COLORPASS
-
-#ifdef MX2_TEXTURED
-uniform sampler2D m_ColorTexture;
-uniform sampler2D m_EmissiveTexture;
-uniform sampler2D m_MetalnessTexture;
-uniform sampler2D m_RoughnessTexture;
-uniform sampler2D m_OcclusionTexture;
-#ifdef MX2_BUMPMAPPED
-uniform sampler2D m_NormalTexture;
-#endif
-#endif
-
-uniform vec4 m_ColorFactor;
-uniform vec4 m_EmissiveFactor;
-uniform float m_MetalnessFactor;
-uniform float m_RoughnessFactor;
-
-void main(){
-
-#ifdef MX2_TEXTURED
-
-	vec3 color=pow( texture2D( m_ColorTexture,v_TexCoord0 ).rgb,vec3( 2.2 ) ) * m_ColorFactor.rgb;
-	vec3 emissive=pow( texture2D( m_EmissiveTexture,v_TexCoord0 ).rgb,vec3( 2.2 ) ) * m_EmissiveFactor.rgb;
-	float metalness=texture2D( m_MetalnessTexture,v_TexCoord0 ).b * m_MetalnessFactor;
-	float roughness=texture2D( m_RoughnessTexture,v_TexCoord0 ).g * m_RoughnessFactor;
-	float occlusion=texture2D( m_OcclusionTexture,v_TexCoord0 ).r;
-	
-#ifdef MX2_BUMPMAPPED
-	vec3 normal=texture2D( m_NormalTexture,v_TexCoord0 ).xyz * 2.0 - 1.0;
-	normal=normalize( v_TanMatrix * normal );
-#else
-	vec3 normal=normalize( v_Normal );
-#endif
-
-#else
-
-	vec3 color=m_ColorFactor.rgb;
-	vec3 emissive=m_EmissiveFactor.rgb;
-	float metalness=m_MetalnessFactor;
-	float roughness=m_RoughnessFactor;
-	float occlusion=1.0;
-	vec3 normal=normalize( v_Normal );
-
-#endif
-
-	pbrWriteFragData( color*v_Color.rgb,emissive,metalness,roughness,occlusion,normal );
-}
-	
-#else	//MX2_COLORPASS
-
-void main(){
-
-#if MX2_POINT_LIGHT
-
-	gl_FragColor=FloatToRGBA( length( v_Position )/r_LightRange );
-	
-#elif defined( MX2_RGBADEPTHTEXTURES )
-
-	gl_FragColor=FloatToRGBA( gl_FragCoord.z );
-
-#else
-
-	gl_FragColor=vec4( vec3( gl_FragCoord.z ),1.0 );
-	
-#endif
-
-}
-
-#endif

+ 0 - 449
modules/mojo3d/assets/shaders/material-pbr-forward.glsl

@@ -1,449 +0,0 @@
-//@renderpasses 1, 2,3,6,7, 10,11,14,15, 4,12
-
-//render passes:
-//
-// 1  = ambient.
-// 2  = lighting.
-// 4  = shadowed.
-// 8  = light type - 0=directional, 1=point
-
-#define MX2_COLORPASS ((MX2_RENDERPASS&3)!=0)
-
-#define MX2_AMBIENTPASS (MX2_RENDERPASS&1)
-#define MX2_LIGHTINGPASS (MX2_RENDERPASS&2)
-#define MX2_SHADOWEDPASS (MX2_RENDERPASS&4)
-
-#define MX2_POINT_LIGHT ((MX2_RENDERPASS&8)!=0)
-#define MX2_DIRECTIONAL_LIGHT ((MX2_RENDERPASS&8)==0)
- 
-//instance uniforms
-//
-uniform mat4 i_ModelViewMatrix;
-uniform mat4 i_ModelViewProjectionMatrix;
-uniform mat3 i_ModelViewNormalMatrix;
-
-#if defined( MX2_BONED )
-uniform mat4 i_ModelBoneMatrices[96];
-#endif
-
-#if MX2_COLORPASS
-uniform vec4  i_Color;
-uniform float i_Alpha;
-#endif
-
-//material uniforms
-//
-#if MX2_COLORPASS && defined( MX2_TEXTURED )
-uniform mat3 m_TextureMatrix;
-#endif
-
-#if MX2_AMBIENTPASS
-
-//renderer uniforms
-//
-uniform vec4 r_AmbientDiffuse;
-uniform samplerCube r_EnvTexture;
-uniform float r_EnvTextureMaxLod;
-uniform vec4 r_EnvColor;
-uniform mat3 r_EnvMatrix;
-
-#endif
-
-#if MX2_LIGHTINGPASS
-
-uniform mat4 r_LightViewMatrix;
-uniform vec4 r_LightColor;
-uniform float r_LightRange;
-
-#if MX2_SHADOWEDPASS
-
-uniform float r_ShadowAlpha;
-
-#if MX2_DIRECTIONAL_LIGHT
-uniform sampler2D r_ShadowCSMTexture;
-uniform vec4 r_ShadowCSMSplits;
-uniform mat4 r_ShadowMatrix0;
-uniform mat4 r_ShadowMatrix1;
-uniform mat4 r_ShadowMatrix2;
-uniform mat4 r_ShadowMatrix3;
-#else
-uniform samplerCube r_ShadowCubeTexture;
-uniform mat4 r_ShadowMatrix0;
-#endif
-
-#endif	//MX2_SHADOWEDPASS
-
-#endif	//MX2_LIGHTINGPASS
-
-#if !MX2_COLORPASS && MX2_POINT_LIGHT
-uniform float r_LightRange;
-#endif
-
-//pbr varyings...
-//
-varying vec3 v_Position;
-varying vec3 v_Normal;
-varying vec4 v_Color;
-#if MX2_COLORPASS && defined( MX2_TEXTURED )
-varying vec2 v_TexCoord0;
-#if defined( MX2_BUMPMAPPED )
-varying mat3 v_TanMatrix;
-#endif
-#endif
-
-//@vertex
-
-attribute vec4 a_Position;
-
-#if MX2_COLORPASS
-attribute vec3 a_Normal;
-attribute vec4 a_Color;
-#if defined( MX2_TEXTURED )
-attribute vec2 a_TexCoord0;
-#if defined( MX2_BUMPMAPPED )
-attribute vec4 a_Tangent;
-#endif
-#endif
-#endif
-	
-#if defined( MX2_BONED )
-
-attribute vec4 a_Weights;
-attribute vec4 a_Bones;
-
-void main(){
-
-	mat4 m0=i_ModelBoneMatrices[ int( a_Bones.x ) ];
-	mat4 m1=i_ModelBoneMatrices[ int( a_Bones.y ) ];
-	mat4 m2=i_ModelBoneMatrices[ int( a_Bones.z ) ];
-	mat4 m3=i_ModelBoneMatrices[ int( a_Bones.a ) ];
-	
-	vec4 b_Position=
-		m0 * a_Position * a_Weights.x +
-		m1 * a_Position * a_Weights.y +
-		m2 * a_Position * a_Weights.z +
-		m3 * a_Position * a_Weights.a;
-		
-	// view space position
-	v_Position=( i_ModelViewMatrix * b_Position ).xyz;
-
-#if MX2_COLORPASS
-
-	mat3 n0=mat3( m0[0].xyz,m0[1].xyz,m0[2].xyz );
-	mat3 n1=mat3( m1[0].xyz,m1[1].xyz,m1[2].xyz );
-	mat3 n2=mat3( m2[0].xyz,m2[1].xyz,m2[2].xyz );
-	mat3 n3=mat3( m3[0].xyz,m3[1].xyz,m3[2].xyz );
-
-	vec3 b_Normal=normalize( 
-		n0 * a_Normal * a_Weights.x +
-		n1 * a_Normal * a_Weights.y +
-		n2 * a_Normal * a_Weights.z +
-		n3 * a_Normal * a_Weights.a );
-		
-#if defined( MX2_BUMPMAPPED )
-	vec4 b_Tangent=vec4( normalize( 
-		n0 * a_Tangent.xyz * a_Weights.x +
-		n1 * a_Tangent.xyz * a_Weights.y +
-		n2 * a_Tangent.xyz * a_Weights.z +
-		n3 * a_Tangent.xyz * a_Weights.a ),a_Tangent.w );
-#endif
-
-	// viewspace normal
-	v_Normal=i_ModelViewNormalMatrix * b_Normal;
-	
-	// vertex color
-	v_Color=a_Color * i_Color;
-	v_Color.a*=i_Alpha;
-	
-#if MX2_COLORPASS && defined( MX2_TEXTURED )
-	// texture coord0
-	v_TexCoord0=(m_TextureMatrix * vec3(a_TexCoord0,1.0)).st;
-#if defined( MX2_BUMPMAPPED )
-	// viewspace tangent matrix
-	v_TanMatrix[2]=v_Normal;
-	v_TanMatrix[0]=i_ModelViewNormalMatrix * b_Tangent.xyz;
-	v_TanMatrix[1]=cross( v_TanMatrix[0],v_TanMatrix[2] ) * b_Tangent.a;
-#endif
-#endif
-	
-#endif	//MX2_COLORPASS
-	
-	gl_Position=i_ModelViewProjectionMatrix * b_Position;
-}
-
-#else	//MX2_BONED
-
-void main(){
-
-	// view space position
-	v_Position=(i_ModelViewMatrix * a_Position).xyz;
-
-#if MX2_COLORPASS
-
-	// viewspace normal
-	v_Normal=i_ModelViewNormalMatrix * a_Normal;
-	
-	// vertex color
-	v_Color=a_Color * i_Color;
-	v_Color.a*=i_Alpha;
-	
-#if defined( MX2_TEXTURED )
-	// texture coord0
-	v_TexCoord0=(m_TextureMatrix * vec3(a_TexCoord0,1.0)).st;
-#if defined( MX2_BUMPMAPPED )
-	// viewspace tangent matrix
-	v_TanMatrix[2]=v_Normal;
-	v_TanMatrix[0]=i_ModelViewNormalMatrix * a_Tangent.xyz;
-	v_TanMatrix[1]=cross( v_TanMatrix[0],v_TanMatrix[2] ) * a_Tangent.a;
-#endif
-#endif
-
-#endif	//MX2_COLORPASS
-	
-	gl_Position=i_ModelViewProjectionMatrix * a_Position;
-}
-
-#endif	//MX2_BONED
-
-//@fragment
-
-vec4 FloatToRGBA( float value ){
-
-	const float MaxFloat=0.9999999;
-
-	value=clamp( value,0.0,MaxFloat );
-
-	vec4 rgba=fract( vec4( 1.0, 255.0, 65025.0, 16581375.0 ) * value );
-	
-	return rgba-rgba.yzww * vec4( 1.0/255.0, 1.0/255.0, 1.0/255.0, 0.0 );
-}
-
-float RGBAToFloat( vec4 rgba ){
-
-	return dot( rgba,vec4( 1.0, 1.0/255.0, 1.0/65025.0, 1.0/16581375.0 ) );
-}
-
-#if MX2_COLORPASS
-
-uniform float r_FogNear;
-uniform float r_FogFar;
-uniform vec4 r_FogColor;
-
-#if MX2_SHADOWEDPASS
-
-#if MX2_DIRECTIONAL_LIGHT
-
-float shadowColor(){
-
-	if( v_Position.z>=r_ShadowCSMSplits.w ) return 1.0;//(1.0-r_ShadowAlpha)*0.5;
-
-	vec4 vpos=vec4( v_Position,1.0 );
-	vec2 off;
-	
-	if( vpos.z<r_ShadowCSMSplits.x ){
-		vpos=r_ShadowMatrix0 * vpos;
-		off=vec2( 0.0,0.0 );
-	}else if( vpos.z<r_ShadowCSMSplits.y ){
-		vpos=r_ShadowMatrix1 * vpos;
-		off=vec2( 0.5,0.0 );
-	}else if( vpos.z<r_ShadowCSMSplits.z ){
-		vpos=r_ShadowMatrix2 * vpos;
-		off=vec2( 0.0,0.5 );
-	}else{
-		vpos=r_ShadowMatrix3 * vpos;
-		off=vec2( 0.5,0.5 );
-	}
-	
-	vec3 spos=vpos.xyz/vpos.w * vec3( 0.25,0.25,0.5 ) + vec3( 0.25,0.25,0.5 );
-
-#if defined( MX2_RGBADEPTHTEXTURES )
-	float d=RGBAToFloat( texture2D( r_ShadowCSMTexture,spos.xy+off ) );
-#else
-	float d=texture2D( r_ShadowCSMTexture,spos.xy+off ).r;
-#endif
-	
-	if( spos.z>d ) return 1.0-r_ShadowAlpha;
-	
-	return 1.0;
-}
-
-#else	//MX2_DIRECTIONAL_LIGHT
-
-float shadowColor(){
-
-	vec4 vpos=vec4( v_Position,1.0 );
-	
-	vec3 lpos=(r_ShadowMatrix0 * vpos).xyz;
-	
-	float d=RGBAToFloat( textureCube( r_ShadowCubeTexture,lpos ) );
-	
-	if( length(lpos) > d * r_LightRange ) return 1.0-r_ShadowAlpha;
-	
-	return 1.0;
-}
-
-#endif	//MX2_DIRECTIONAL_LIGHT
-
-#endif	//MX2_SHADOWEDPASS
-
-vec3 lighting( vec3 color,vec3 emissive,float metalness,float roughness,float occlusion,vec3 normal ){
-
-	const vec3 color0=vec3( 0.04,0.04,0.04 );
-	
-	float glosiness=1.0-roughness;
-	vec3 diffuse=color * (1.0-metalness);
-	vec3 specular=(color-color0) * metalness + color0;
-	
-	vec3 vvec=normalize( -v_Position );
-	float ndotv=dot( normal,vvec );
-	
-	vec3 frag=vec3( 0.0 );
-	
-#if MX2_AMBIENTPASS
-
-	//ambient color
-	vec3 rvec=r_EnvMatrix * reflect( v_Position,normal );
-	
-	float lod=textureCube( r_EnvTexture,rvec,r_EnvTextureMaxLod ).a * 255.0 - r_EnvTextureMaxLod;
-	if( lod>0.0 ) lod=textureCube( r_EnvTexture,rvec ).a * 255.0;
-//	float lod=textureCube( r_EnvTexture,rvec ).a * 255.0;
-//	if( lod==0.0 ) lod=textureCube( r_EnvTexture,rvec,r_EnvTextureMaxLod ).a * 255.0 - r_EnvTextureMaxLod;
-
-	vec3 ambEnv=pow( textureCube( r_EnvTexture,rvec,max( roughness*r_EnvTextureMaxLod-lod,0.0 ) ).rgb,vec3( 2.2 ) ) * r_EnvColor.rgb;
-	
-	vec3 fschlick0=specular + (1.0-specular) * pow( 1.0-ndotv,5.0 ) * glosiness;
-	
-	vec3 ambDiffuse=diffuse * r_AmbientDiffuse.rgb;
-	
-	vec3 ambSpecular=fschlick0 * ambEnv;
-
-	frag+=( ambDiffuse + ambSpecular ) * occlusion + emissive;
-
-#endif
-
-#if MX2_LIGHTINGPASS
-
-	//lighting color
-	float spow=pow( 2.0,glosiness * 12.0 );				//specular power
-//	float spow=pow( 4096.0,glosiness );
-	float fnorm=(spow+2.0)/8.0;							//normalization factor
-	
-#if MX2_DIRECTIONAL_LIGHT
-	vec3 lvec=normalize( -r_LightViewMatrix[2].xyz );
-	float atten=1.0;
-#else
-	vec3 lvec=r_LightViewMatrix[3].xyz-v_Position;
-	float atten=max( 1.0-length( lvec )/r_LightRange,0.0 );
-	lvec=normalize( lvec );
-#endif
-
-	vec3 hvec=normalize( lvec+vvec );
-
-	float ndotl=max( dot( normal,lvec ),0.0 );
-	float ndoth=max( dot( normal,hvec ),0.0 );
-	float hdotl=max( dot( hvec,lvec ),0.0 );
-	
-	vec3 fschlick=specular + (1.0-specular) * pow( 1.0-hdotl,5.0 ) * glosiness;
-	
-	vec3 fspecular=fschlick * pow( ndoth,spow ) * fnorm;
-	
-	vec3 light=r_LightColor.rgb * ndotl * atten;
-	
-	light=(diffuse+fspecular) * light;
-
-#if MX2_SHADOWEDPASS
-
-	light*=shadowColor();
-	
-#endif
-
-	frag+=light;
-
-#endif	//MX2_LIGHTINGPASS
-
-	return frag;
-}
-
-#if defined( MX2_TEXTURED )
-uniform sampler2D m_ColorTexture;
-uniform sampler2D m_EmissiveTexture;
-uniform sampler2D m_MetalnessTexture;
-uniform sampler2D m_RoughnessTexture;
-uniform sampler2D m_OcclusionTexture;
-uniform sampler2D m_NormalTexture;
-#endif
-
-uniform vec4 m_ColorFactor;
-uniform vec4 m_EmissiveFactor;
-uniform float m_MetalnessFactor;
-uniform float m_RoughnessFactor;
-
-void main(){
-
-#if defined( MX2_TEXTURED )
-	vec4 rgba=texture2D( m_ColorTexture,v_TexCoord0 );
-	vec3 color=pow( rgba.rgb,vec3( 2.2 ) ) * m_ColorFactor.rgb;
-	vec3 emissive=pow( texture2D( m_EmissiveTexture,v_TexCoord0 ).rgb,vec3( 2.2 ) ) * m_EmissiveFactor.rgb;
-	float metalness=texture2D( m_MetalnessTexture,v_TexCoord0 ).b * m_MetalnessFactor;
-	float roughness=texture2D( m_RoughnessTexture,v_TexCoord0 ).g * m_RoughnessFactor;
-	float occlusion=texture2D( m_OcclusionTexture,v_TexCoord0 ).r;
-	float alpha=rgba.a * m_ColorFactor.a;
-	
-#if defined( MX2_BUMPMAPPED )
-	vec3 normal=texture2D( m_NormalTexture,v_TexCoord0 ).xyz * 2.0 - 1.0;
-	normal=normalize( v_TanMatrix * normal );
-#else
-	vec3 normal=normalize( v_Normal );
-#endif
-	
-#else
-	vec3 color=m_ColorFactor.rgb;
-	vec3 emissive=m_EmissiveFactor.rgb;
-	float metalness=m_MetalnessFactor;
-	float roughness=m_RoughnessFactor;
-	float occlusion=1.0;
-	float alpha=m_ColorFactor.a;
-	
-	vec3 normal=normalize( v_Normal );
-#endif
-
-	//perform lighting
-	vec3 frag=lighting( color*v_Color.rgb,emissive,metalness,roughness,occlusion,normal );
-	
-	alpha*=v_Color.a;
-	
-	frag*alpha;
-	
-	//apply fog
-	float fog=clamp( (length( v_Position )-r_FogNear)/(r_FogFar-r_FogNear),0.0,1.0 ) * r_FogColor.a;
-
-#if MX2_AMBIENTPASS
-	frag=mix( frag,r_FogColor.rgb,fog );
-#else
-	frag=mix( frag,vec3(0.0),fog );
-#endif
-	alpha=mix( alpha,1.0,fog );
-
-#if defined( MX2_SRGBOUTPUT )
-	gl_FragColor=vec4( pow( frag,vec3( 1.0/2.2 ) ),alpha );
-#else
-	gl_FragColor=vec4( frag,alpha );
-#endif
-
-}
-
-#else	//MX2_COLORPASS
-
-void main(){
-
-#if MX2_POINT_LIGHT
-	gl_FragColor=FloatToRGBA( min( length( v_Position )/r_LightRange,1.0 ) );
-#elif defined( MX2_RGBADEPTHTEXTURES )
-	gl_FragColor=FloatToRGBA( gl_FragCoord.z ),1.0 );
-#else
-	gl_FragColor=vec4( vec3( gl_FragCoord.z ),1.0 );
-#endif
-
-}
-
-#endif	//MX2_COLORPASS

+ 0 - 75
modules/mojo3d/assets/shaders/material-sprite.glsl

@@ -1,75 +0,0 @@
-
-//@renderpasses 1,3
-
-//render uniforms
-
-uniform vec4 r_FogColor;
-
-uniform float r_FogNear;
-
-uniform float r_FogFar;
-
-//material uniforms
-
-uniform mat3 m_TextureMatrix;
-
-//instance uniforms...
-
-uniform mat4 i_ModelViewProjectionMatrix;
-
-uniform mat4 i_ModelViewMatrix;
-
-uniform float i_Alpha;
-
-//varyings...
-
-varying vec3 v_Position;
-varying vec2 v_TexCoord0;
-
-//@vertex
-
-attribute vec4 a_Position;
-
-attribute vec2 a_TexCoord0;
-
-void main(){
-
-	v_Position=(i_ModelViewMatrix * a_Position).xyz;
-
-	v_TexCoord0=(m_TextureMatrix * vec3(a_TexCoord0,1.0)).st;
-	
-	gl_Position=i_ModelViewProjectionMatrix * a_Position;
-}
-
-//@fragment
-
-uniform sampler2D m_ColorTexture;
-
-uniform vec4 m_ColorFactor;
-
-uniform float m_AlphaDiscard;
-
-void main(){
-
-	vec4 color=texture2D( m_ColorTexture,v_TexCoord0 );
-
-	float alpha=color.a * m_ColorFactor.a * i_Alpha;
-	
-	if( alpha<m_AlphaDiscard ) discard;
-
-	vec3 frag=pow( color.rgb,vec3( 2.2 ) ) * m_ColorFactor.rgb;
-	
-	float fog=clamp( (length( v_Position )-r_FogNear)/(r_FogFar-r_FogNear),0.0,1.0 ) * r_FogColor.a;
-	
-	frag=mix( frag,r_FogColor.rgb,fog );
-	
-	alpha*=1.0-fog;
-	
-	frag*=alpha;
-	
-#if defined( MX2_SRGBOUTPUT )
-	gl_FragColor=vec4( pow( frag,vec3( 1.0/2.2 ) ),alpha );
-#else
-	gl_FragColor=vec4( frag,alpha );
-#endif
-}

+ 0 - 125
modules/mojo3d/assets/shaders/material-water.glsl

@@ -1,125 +0,0 @@
-//@renderpasses 1
-
-//material uniforms
-
-uniform mat3 m_TextureMatrix;
-
-//renderer uniforms
-
-uniform mat4 i_ModelViewMatrix;
-uniform mat4 i_ModelViewProjectionMatrix;
-uniform mat3 i_ModelViewNormalMatrix;
-
-uniform vec4 r_AmbientDiffuse;
-uniform samplerCube r_EnvTexture;
-uniform mat3 r_EnvMatrix;
-
-//pbr varyings...
-
-varying vec3 v_Position;
-varying vec2 v_TexCoord0;
-varying vec3 v_Normal;
-varying mat3 v_TanMatrix;
-
-//@vertex
-
-//vertex attribs....
-
-attribute vec4 a_Position;
-
-attribute vec2 a_TexCoord0;
-attribute vec3 a_Normal;
-attribute vec4 a_Tangent;
-
-void main(){
-
-	// texture coord0
-	v_TexCoord0=(m_TextureMatrix * vec3(a_TexCoord0,1.0)).st;
-
-	// view space position
-	v_Position=( i_ModelViewMatrix * a_Position ).xyz;
-
-	// viewspace normal
-	v_Normal=i_ModelViewNormalMatrix * a_Normal;
-	
-	// viewspace tangent matrix
-	v_TanMatrix[2]=v_Normal;
-	v_TanMatrix[0]=i_ModelViewNormalMatrix * a_Tangent.xyz;
-	v_TanMatrix[1]=cross( v_TanMatrix[0],v_TanMatrix[2] ) * a_Tangent.a;
-	
-	gl_Position=i_ModelViewProjectionMatrix * a_Position;
-}
-
-//@fragment
-
-void main0( vec3 color,vec3 emissive,float metalness,float roughness,float occlusion,vec3 normal ){
-
-	normal=normalize( v_TanMatrix * normal );
-
-	vec3 color0=vec3( 0.04,0.04,0.04 );
-	
-	vec3 diffuse=color * (1.0-metalness);
-	
-	vec3 specular=(color-color0) * metalness + color0;
-	
-	vec3 rvec=r_EnvMatrix * reflect( v_Position,normal );
-	
-	float lod=textureCube( r_EnvTexture,rvec,10.0 ).a * 255.0 - 10.0;
-	
-	if( lod>0.0 ) lod=textureCube( r_EnvTexture,rvec ).a * 255.0;
-	
-	vec3 env=pow( textureCube( r_EnvTexture,rvec,max( roughness*10.0-lod,0.0 ) ).rgb,vec3( 2.2 ) );
-
-	vec3 vvec=normalize( -v_Position );
-	
-	float ndotv=max( dot( normal,vvec ),0.0 );
-	
-	vec3 fschlick=specular + (1.0-specular) * pow( 1.0-ndotv,5.0 ) * (1.0-roughness);
-
-	vec3 ambdiff=diffuse * r_AmbientDiffuse.rgb;
-		
-	vec3 ambspec=env * fschlick;
-	
-	vec3 frag=(ambdiff+ambspec) * occlusion + emissive;
-	
-	gl_FragData[0]=vec4( min( frag,8.0 ),1.0 );
-	
-	gl_FragData[1]=vec4( color,metalness );
-	
-	gl_FragData[2]=vec4( normal * 0.5 + 0.5,roughness );
-}
-
-uniform float r_Time;
-
-uniform sampler2D m_ColorTexture;
-uniform vec4 m_ColorFactor;
-
-uniform float m_Metalness;
-uniform float m_Roughness;
-
-uniform sampler2D m_NormalTexture0;
-uniform sampler2D m_NormalTexture1;
-
-uniform vec2 m_Velocity0;
-uniform vec2 m_Velocity1;
-
-void main(){
-
-	vec3 color=pow( texture2D( m_ColorTexture,v_TexCoord0 ).rgb,vec3( 2.2 ) ) * m_ColorFactor.rgb;
-
-	vec3 normal0=texture2D( m_NormalTexture0,v_TexCoord0 + m_Velocity0 * r_Time ).xyz * 2.0 - 1.0;
-	
-	vec3 normal1=texture2D( m_NormalTexture1,v_TexCoord0 + m_Velocity1 * r_Time ).xyz * 2.0 - 1.0;
-	
-	vec3 normal=normalize( normal0+normal1 );
-	
-	vec3 emissive=vec3( 0.0 );
-	
-	float metalness=m_Metalness;
-	
-	float roughness=m_Roughness;
-	
-	float occlusion=1.0;
-
-	main0( color,emissive,metalness,roughness,occlusion,normal );
-}

+ 6 - 41
modules/mojo3d/assets/shaders/material-particle.glsl → modules/mojo3d/assets/shaders/materials/particle.glsl

@@ -1,56 +1,21 @@
 
-//@renderpasses 1,3
+//@renderpasses 2,6,10
 
-//renderer uniforms
-
-uniform float r_Time;
-
-uniform mat4 r_ProjectionMatrix;
-
-uniform mat4 r_ViewMatrix;
-
-uniform vec4 r_FogColor;
-
-uniform float r_FogNear;
-
-uniform float r_FogFar;
-
-//instance uniforms
-
-uniform mat4 i_ModelViewMatrix;
-
-uniform mat4 i_ModelMatrix;
-
-uniform float i_Alpha;
+//@import "std"
 
 //material uniforms
-
+//
 uniform sampler2D m_ColorTexture;
-
 uniform vec4 m_ColorFactor;
 
-//pbuffer uniforms
-
+//buffer uniforms
+//
 uniform vec3 x_Gravity;		//gravity of particle
-
 uniform float x_Duration;	//duration of particle
-
 uniform float x_Fade;		//start fade out time
 
-//varyings...
-
-varying vec3 v_Position;
-
-varying vec4 v_Color;
-
 //@vertex
 
-attribute vec3 a_Position;		//velocity
-
-attribute vec2 a_TexCoord0;		//s=time, t=size
-
-attribute vec4 a_Tangent;		//color
-
 void main(){
 
 	float t=(r_Time-a_TexCoord0.s);
@@ -59,7 +24,7 @@ void main(){
 
 	v_Color=m_ColorFactor * vec4( a_Tangent.rgb,a_Tangent.a * a * i_Alpha );
 	
-	vec4 position=i_ModelMatrix * vec4( a_Position * t,1.0 );
+	vec4 position=i_ModelMatrix * vec4( a_Position.xyz * t,1.0 );
 	
 	position.xyz+=x_Gravity * t * t * .5;
 	

+ 86 - 0
modules/mojo3d/assets/shaders/materials/pbr-default.glsl

@@ -0,0 +1,86 @@
+
+//@renderpasses 1,7,11,15,2,6,10,14,22,26,30
+
+//@import "pbr"
+
+//@vertex
+
+void main(){
+
+	transformVertex();
+}
+
+//@fragment
+
+#if MX2_COLORPASS	//is this a color pass?
+
+#if MX2_TEXTURED
+uniform sampler2D m_ColorTexture;
+uniform sampler2D m_AmbientTexture;
+uniform sampler2D m_EmissiveTexture;
+uniform sampler2D m_MetalnessTexture;
+uniform sampler2D m_RoughnessTexture;
+uniform sampler2D m_OcclusionTexture;
+#if MX2_BUMPMAPPED
+uniform sampler2D m_NormalTexture;
+#endif
+#endif
+
+uniform vec4 m_ColorFactor;
+uniform vec4 m_AmbientFactor;
+uniform vec4 m_EmissiveFactor;
+uniform float m_MetalnessFactor;
+uniform float m_RoughnessFactor;
+
+void main(){
+
+#if MX2_TEXTURED
+	vec4 color=texture2D( m_ColorTexture,v_TexCoord0 );
+	color.rgb=pow( color.rgb,vec3( 2.2 ) );
+	color*=m_ColorFactor;
+	
+	vec3 ambient=pow( texture2D( m_AmbientTexture,v_TexCoord1 ).rgb,vec3( 2.2 ) ) * m_AmbientFactor.rgb;
+	
+	vec3 emissive=pow( texture2D( m_EmissiveTexture,v_TexCoord0 ).rgb,vec3( 2.2 ) ) * m_EmissiveFactor.rgb;
+	
+	float metalness=texture2D( m_MetalnessTexture,v_TexCoord0 ).b * m_MetalnessFactor;
+	
+	float roughness=texture2D( m_RoughnessTexture,v_TexCoord0 ).g * m_RoughnessFactor;
+	
+	float occlusion=texture2D( m_OcclusionTexture,v_TexCoord0 ).r;
+	
+#if MX2_BUMPMAPPED
+	vec3 normal=texture2D( m_NormalTexture,v_TexCoord0 ).xyz * 2.0 - 1.0;
+	normal=normalize( v_TanMatrix * normal );
+#else
+	vec3 normal=normalize( v_Normal );
+#endif
+
+#else	//untextured...
+
+	vec4 color=m_ColorFactor;
+	
+	vec3 ambient=m_AmbientFactor.rgb;
+	
+	vec3 emissive=m_EmissiveFactor.rgb;
+	
+	float metalness=m_MetalnessFactor;
+	
+	float roughness=m_RoughnessFactor;
+	
+	float occlusion=1.0;
+	
+	vec3 normal=normalize( v_Normal );
+#endif
+
+	emitPbrFragment( color,ambient,emissive,metalness,roughness,occlusion,normal );
+}
+
+#else	//if not a color pass, must be a shadow pass...
+
+void main(){
+
+	emitShadowFragment();
+}
+
+#endif

+ 26 - 0
modules/mojo3d/assets/shaders/materials/sprite.glsl

@@ -0,0 +1,26 @@
+
+//@renderpasses 2,6,10
+
+//@import "std"
+
+//@vertex
+
+void main(){
+
+	transformSpriteVertex();
+}
+
+//@fragment
+
+uniform sampler2D m_ColorTexture;
+uniform vec4 m_ColorFactor;
+uniform float m_AlphaDiscard;
+
+void main(){
+
+	vec4 color=texture2D( m_ColorTexture,v_TexCoord0 ) * m_ColorFactor;
+	
+	if( color.a<m_AlphaDiscard ) discard;
+		
+	emitColorFragment( color );
+}

+ 50 - 0
modules/mojo3d/assets/shaders/materials/water.glsl

@@ -0,0 +1,50 @@
+
+//@renderpasses 1
+
+//@import "pbr"
+
+//@vertex
+
+void main(){
+
+	transformVertex();
+}
+
+//@fragment
+
+uniform sampler2D m_ColorTexture;
+uniform vec4 m_ColorFactor;
+
+uniform float m_Metalness;
+uniform float m_Roughness;
+
+uniform sampler2D m_NormalTexture0;
+uniform sampler2D m_NormalTexture1;
+
+uniform vec2 m_Velocity0;
+uniform vec2 m_Velocity1;
+
+void main(){
+
+	vec4 color=texture2D( m_ColorTexture,v_TexCoord0 );
+	color.rgb=pow( color.rgb,vec3( 2.2 ) );
+	color*=m_ColorFactor;
+
+	vec3 normal0=texture2D( m_NormalTexture0,v_TexCoord0 + m_Velocity0 * r_Time ).xyz * 2.0 - 1.0;
+	
+	vec3 normal1=texture2D( m_NormalTexture1,v_TexCoord0 + m_Velocity1 * r_Time ).xyz * 2.0 - 1.0;
+	
+	vec3 normal=normalize( v_TanMatrix * vec3( normal0+normal1 ) );
+	
+	vec3 ambient=vec3( 0.0 );
+	
+	vec3 emissive=vec3( 0.0 );
+	
+	float metalness=0.0;
+	
+	float roughness=0.0;
+	
+	float occlusion=1.0;
+
+	emitPbrFragment( color,ambient,emissive,metalness,roughness,occlusion,normal );
+}

+ 26 - 0
modules/mojo3d/assets/shaders/misc/copy.glsl

@@ -0,0 +1,26 @@
+
+//@renderpasses 0
+
+uniform sampler2D r_SourceBuffer;
+uniform vec2 r_SourceBufferScale;
+
+varying vec2 v_SourceBufferCoords;
+
+//@vertex
+
+attribute vec2 a_Position;
+attribute vec2 a_TexCoord0;
+
+void main(){
+
+	v_SourceBufferCoords=a_TexCoord0 * r_SourceBufferScale;
+
+	gl_Position=vec4( a_Position*2.0-1.0,-1.0,1.0 );
+}
+
+//@fragment
+
+void main(){
+
+	gl_FragColor=vec4( pow( texture2D( r_SourceBuffer,v_SourceBufferCoords ).rgb,vec3( 1.0/2.2 ) ),1.0 );
+}

+ 35 - 0
modules/mojo3d/assets/shaders/misc/fog-deferred.glsl

@@ -0,0 +1,35 @@
+
+//@renderpasses 0
+
+//@import "std"
+
+//@vertex
+
+void main(){
+
+	transformQuadVertex();
+}
+
+//@fragment
+
+void main(){
+
+	float fog=0.0;
+
+	float depth=texture2D( r_DepthBuffer,v_BufferCoords ).r;
+	
+	if( depth<1.0 ){
+
+		depth=viewDepth( depth );
+		
+		vec4 vpos4=r_InverseProjectionMatrix * vec4( v_ClipPosition,-1.0,1.0 );
+		
+		vec3 vpos=vpos4.xyz/vpos4.w;
+		
+		vec3 position=vpos/vpos.z*depth;
+		
+		fog=clamp( (length( position )-r_FogNear)/(r_FogFar-r_FogNear),0.0,1.0 ) * r_FogColor.a;
+	}
+	
+	gl_FragColor=vec4( r_FogColor.rgb * fog,fog );
+}

+ 30 - 0
modules/mojo3d/assets/shaders/misc/lighting-deferred.glsl

@@ -0,0 +1,30 @@
+
+//@renderpasses 4,8,12, 20,24,28
+
+//@import "pbr"
+
+//@vertex
+
+void main(){
+
+	transformLightQuadVertex();
+}
+
+//@fragment
+
+void main(){
+
+	vec4 color_m=texture2D( r_ColorBuffer,v_BufferCoords );
+	
+	vec4 normal_r=texture2D( r_NormalBuffer,v_BufferCoords );
+	
+	vec3 position=fragmentPosition();
+
+	vec3 normal=normalize( normal_r.xyz * 2.0 - 1.0 );
+	
+	emitPbrFragment( color_m.rgb,color_m.a,normal_r.a,position,normal );
+	
+//	gl_FragColor=vec4( 1.0,1.0,0.0,1.0 );
+}
+
+

+ 43 - 0
modules/mojo3d/assets/shaders/misc/skybox.glsl

@@ -0,0 +1,43 @@
+
+//@renderpasses 0
+
+//@import "std"
+
+//@vertex
+
+void main(){
+
+	transformQuadVertex();
+}
+
+//@fragment
+
+void main(){
+
+	vec4 clip=r_InverseProjectionMatrix * vec4( v_ClipPosition,1.0,1.0 );
+	
+	vec3 tv=r_EnvMatrix * (clip.xyz/clip.w);
+	
+	vec3 frag;
+
+	if( r_SkyCube ){
+
+		frag=pow( textureCube( r_SkyTextureCube,tv ).rgb,vec3( 2.2 ) );
+
+	}else{
+
+		float p=-atan( tv.y,sqrt( tv.x*tv.x+tv.z*tv.z ) ) / pi + 0.5;
+		
+		float y=atan( tv.x,tv.z ) / pi * 0.5 + 0.5;
+		
+		frag=pow( texture2D( r_SkyTexture2D,vec2( y,p ) ).rgb,vec3( 2.2 ) );
+	}
+	
+#if MX2_DEFERREDRENDERER
+	gl_FragData[0]=vec4( frag,1.0 );					//accum
+	gl_FragData[1]=vec4( 0.0,0.0,0.0,1.0 );				//color_m
+	gl_FragData[2]=vec4( 0.5,0.5,0.5,1.0 );				//normal_r
+#else
+	emitLinearFragment( vec4( frag,1.0 ) );
+#endif
+}

+ 0 - 38
modules/mojo3d/assets/shaders/skybox-deferred.glsl

@@ -1,38 +0,0 @@
-
-//@renderpasses 0
-
-varying vec2 v_ClipPosition;
-
-//@vertex
-
-attribute vec2 a_Position;	//0...1
-
-void main(){
-
-	v_ClipPosition=a_Position * 2.0 - 1.0;
-
-	gl_Position=vec4( v_ClipPosition,1.0,1.0 );
-}
-
-//@fragment
-
-uniform mat3 r_EnvMatrix;
-
-uniform samplerCube r_SkyTexture;
-
-uniform mat4 r_InverseProjectionMatrix;
-
-void main(){
-
-	vec4 clip=r_InverseProjectionMatrix * vec4( v_ClipPosition,1.0,1.0 );
-
-	vec3 tv=r_EnvMatrix * (clip.xyz/clip.w);
-	
-	vec3 frag=pow( textureCube( r_SkyTexture,tv ).rgb,vec3( 2.2 ) );
-	
-	gl_FragData[0]=vec4( frag,1.0 );					//accum
-	
-	gl_FragData[1]=vec4( 0.0,0.0,0.0,1.0 );				//color_m
-	
-	gl_FragData[2]=vec4( 0.5,0.5,1.0,1.0 );				//normal_r
-}

+ 0 - 38
modules/mojo3d/assets/shaders/skybox.glsl

@@ -1,38 +0,0 @@
-
-//@renderpasses 0
-
-varying vec2 v_ClipPosition;
-
-//@vertex
-
-attribute vec2 a_Position;	//0...1
-
-void main(){
-
-	v_ClipPosition=a_Position * 2.0 - 1.0;
-
-	gl_Position=vec4( v_ClipPosition,1.0,1.0 );
-}
-
-//@fragment
-
-uniform mat3 r_EnvMatrix;
-
-uniform samplerCube r_SkyTexture;
-
-uniform mat4 r_InverseProjectionMatrix;
-
-void main(){
-
-	vec4 clip=r_InverseProjectionMatrix * vec4( v_ClipPosition,1.0,1.0 );
-
-	vec3 tv=r_EnvMatrix * (clip.xyz/clip.w);
-	
-	vec3 color=textureCube( r_SkyTexture,tv ).rgb;
-	
-#if defined( MX2_LINEAROUTPUT )
-	gl_FragColor=vec4( pow( color,vec3( 2.2 ) ),1.0 );
-#else
-	gl_FragColor=vec4( color,1.0 );
-#endif
-}

+ 9 - 3
modules/mojo3d/loader/gltf2.monkey2

@@ -75,6 +75,7 @@ Class Gltf2Material
 	Field emissiveFactor:Vec3f=New Vec3f(0)
 	Field occlusionTexture:Gltf2Texture
 	Field normalTexture:Gltf2Texture
+	Field doubleSided:Bool
 	Field alphaMode:String
 End
 
@@ -86,6 +87,7 @@ Class Gltf2Primitive
 	Field TANGENT:Gltf2Accessor
 	Field COLOR_0:Gltf2Accessor
 	Field TEXCOORD_0:Gltf2Accessor
+	Field TEXCOORD_1:Gltf2Accessor
 	Field JOINTS_0:Gltf2Accessor
 	Field WEIGHTS_0:Gltf2Accessor
 	Field indices:Gltf2Accessor
@@ -110,8 +112,8 @@ Class Gltf2Node
 	Field rotation:Quatf=New Quatf
 	Field scale:Vec3f=New Vec3f(1)
 	Field matrix:Mat4f=New Mat4f
-	Field mesh:Gltf2Mesh
 	Field hasMatrix:Bool
+	Field mesh:Gltf2Mesh
 End
 
 #rem monkeydoc @hidden
@@ -382,6 +384,8 @@ Class Gltf2Asset
 			materials[i]=material
 			
 			material.name=jmaterial.GetString( "name" )
+			
+			material.doubleSided=jmaterial.GetBool( "doubleSided" )
 
 			Local jpbr:=jmaterial.GetObject( "pbrMetallicRoughness" )
 			If jpbr
@@ -471,6 +475,9 @@ Class Gltf2Asset
 				If jattribs.Contains( "TEXCOORD_0" )
 					prim.TEXCOORD_0=accessors[jattribs.GetNumber( "TEXCOORD_0" )]
 				Endif
+				If jattribs.Contains( "TEXCOORD_1" )
+					prim.TEXCOORD_1=accessors[jattribs.GetNumber( "TEXCOORD_1" )]
+				Endif
 				If jattribs.Contains( "JOINTS_0" )
 					prim.JOINTS_0=accessors[jattribs.GetNumber( "JOINTS_0" )]
 				Endif
@@ -643,8 +650,7 @@ Class Gltf2Asset
 				
 			If jnode.Contains( "matrix" )
 				node.matrix=GetMat4f( jnode.GetArray( "matrix" ) )
-			Else
-				node.matrix=Mat4f.Translation( node.translation ) * Mat4f.Rotation( node.rotation ) * Mat4f.Scaling( node.scale )
+				node.hasMatrix=True
 			Endif
 			
 			If jnode.Contains( "mesh" )

+ 51 - 12
modules/mojo3d/loader/gltf2loader.monkey2

@@ -162,7 +162,11 @@ Class Gltf2Loader
 	
 	Method GetMaterial:Material( material:Gltf2Material,textured:Bool,boned:Bool )
 		
-		If Not material Return New PbrMaterial( Color.Magenta,0,1,boned )
+		If Not material
+			Local mat:=New PbrMaterial( Color.Magenta,0,1 )
+			mat.Boned=boned
+			Return mat
+		Endif
 		
 		If _materialCache.Contains( material ) Return _materialCache[material]
 		
@@ -180,7 +184,8 @@ Class Gltf2Loader
 			normalTexture=GetTexture( material.normalTexture )
 		Endif
 			
-		Local mat:=New PbrMaterial( boned )
+		Local mat:=New PbrMaterial
+		mat.Boned=boned
 		
 		mat.Name=material.name
 		
@@ -217,6 +222,10 @@ Class Gltf2Loader
 		Case "BLEND" mat.BlendMode=BlendMode.Alpha
 		End
 			
+		If material.doubleSided
+			mat.CullMode=CullMode.None
+		Endif
+			
 		_materialCache[material]=mat
 		Return mat
 	End
@@ -230,11 +239,28 @@ Class Gltf2Loader
 		Return matrix
 	End
 	
-	Method GetMatrix:Mat4f( node:Gltf2Node )
+	Method GetWorldMatrix:Mat4f( node:Gltf2Node )
+		
+		Return node.parent ? GetWorldMatrix( node.parent ) * GetLocalMatrix( node ) Else GetLocalMatrix( node )
+	End
+	
+	Method GetLocalMatrix:Mat4f( node:Gltf2Node )
+		
+		Local matrix:Mat4f
+		
+		If node.hasMatrix Return FlipMatrix( node.matrix )
+		
+		Local v:=node.translation
+		v.z=-v.z
 		
-		Local matrix:=FlipMatrix( node.matrix )
+		Local q:=node.rotation
+		q.v.x=-q.v.x
+		q.v.y=-q.v.y
+		q.w=-q.w
 		
-		Return node.parent ? GetMatrix( node.parent ) * matrix Else matrix
+		Local s:=node.scale
+		
+		Return Mat4f.Translation( v ) * Mat4f.Rotation( q ) * Mat4f.Scaling( s )
 	End
 	
 	Method LoadPrimitive:Mesh( prim:Gltf2Primitive )
@@ -306,7 +332,7 @@ Class Gltf2Loader
 		
 		If prim.TEXCOORD_0
 			If prim.TEXCOORD_0.componentType=GLTF_FLOAT And prim.TEXCOORD_0.type="VEC2"
-'				Print "Gltf2 primitive has texcoords"
+'				Print "Gltf2 primitive has texcoords0"
 				Local datap:=GetData( prim.TEXCOORD_0 )
 				Local stride:=prim.TEXCOORD_0.bufferView.byteStride ?Else 8
 				For Local i:=0 Until vcount
@@ -318,6 +344,20 @@ Class Gltf2Loader
 			Endif
 		Endif
 		
+		If prim.TEXCOORD_1
+			If prim.TEXCOORD_1.componentType=GLTF_FLOAT And prim.TEXCOORD_1.type="VEC2"
+'				Print "Gltf2 primitive has texcoords1"
+				Local datap:=GetData( prim.TEXCOORD_1 )
+				Local stride:=prim.TEXCOORD_1.bufferView.byteStride ?Else 8
+				For Local i:=0 Until vcount
+					vertices[i].texCoord1=Cast<Vec2f Ptr>( datap )[0]
+					datap+=stride
+				Next
+			Else
+				Print "Unsupported gltf2 primitive TEXCOORD_1 format"
+			Endif
+		Endif
+		
 		If prim.JOINTS_0
 			Local datap:=GetData( prim.JOINTS_0 )
 			If prim.JOINTS_0.componentType=GLTF_UNSIGNED_SHORT And prim.JOINTS_0.type="VEC4"
@@ -402,7 +442,7 @@ Class Gltf2Loader
 		
 		If node.mesh
 			
-			Local matrix:=New AffineMat4f( GetMatrix( node ) )
+			Local matrix:=New AffineMat4f( GetWorldMatrix( node ) )
 
 			For Local prim:=Eachin node.mesh.primitives
 				
@@ -440,7 +480,7 @@ Class Gltf2Loader
 		
 		model.Name=node.name
 		
-		model.LocalMatrix=New AffineMat4f( FlipMatrix( node.matrix ) )
+		model.LocalMatrix=New AffineMat4f( GetLocalMatrix( node ) )
 		
 		Local id:=_entities.Length
 		_entities.Add( model )
@@ -691,11 +731,10 @@ Class Gltf2Loader
 		
 		For Local i:=0 Until n
 			
-			Local entity:=_entities[ _nodeIds[skin.joints[i]] ]
-			Local matrix:=datap ? FlipMatrix( Cast<Mat4f Ptr>( datap )[0] ) Else New Mat4f
+			Local matrix:=datap ? New AffineMat4f( FlipMatrix( Cast<Mat4f Ptr>( datap )[0] ) ) Else New AffineMat4f
 			
-			_bones[i].entity=entity
-			_bones[i].offset=New AffineMat4f( matrix )
+			_bones[i].entity=_entities[ _nodeIds[skin.joints[i]] ]
+			_bones[i].offset=matrix
 			
 			If datap datap+=stride
 		Next

+ 2 - 1
modules/mojo3d/mojo3d.monkey2

@@ -30,6 +30,7 @@ Using reflection..
 #Import "scene/components/animator"
 #Import "scene/components/rigidbody"
 #Import "scene/components/collider"
+#Import "scene/components/joint"
 #Import "scene/components/behaviour"
 #Import "scene/components/flybehaviour"
 #Import "scene/components/movebehaviour"
@@ -50,6 +51,7 @@ Using reflection..
 
 #Import "scene/effects/bloomeffect"
 #Import "scene/effects/monochromeeffect"
+#Import "scene/effects/reflectioneffect"
 
 #Import "scene/jsonifier/jsonifier"
 #Import "scene/jsonifier/invocation"
@@ -59,7 +61,6 @@ Using reflection..
 #Import "scene/mesh"
 #Import "scene/meshprims"
 #Import "scene/bttypeconvs"
-'#Import "scene/util3d"
 
 #Import "render/renderer"
 #Import "render/renderqueue"

+ 250 - 99
modules/mojo3d/render/renderer.monkey2

@@ -1,9 +1,19 @@
 
 Namespace mojo3d
 
+#rem monkeydoc The mojo3d Renderer class.
+
+A renderer is an object that renders scenes. There is normally only ever one renderer created and it is created for you automatically when required so you don't normally need to worry about renderers at all.
+
+When a new renderer is created, the config setting `MOJO3D\_RENDERER` can be used to control the type of renderer created. Use "deferred" to create a deferred renderer and "foward" to create a forward renderer. See [[std:std.filesystem.SetConfig|SetConfig]] for more information about config settings. By default, a deferred renderer is created for desktop and web targets and a forward renderer for mobile targets.
+
+#end
 Class Renderer
 
-	#rem monkeydoc Creates a new renderer
+	#rem monkeydoc Creates a new renderer.
+
+When a new renderer is created, the config setting `MOJO3D\_RENDERER` can be used to control the type of renderer created. Use "deferred" to create a deferred renderer and "foward" to create a forward renderer. See [[std:std.filesystem.SetConfig|SetConfig]] for more information about config settings. By default, a deferred renderer is created for desktop and web targets and a forward renderer for mobile targets.
+	
 	#end
 	Method New()
 		
@@ -12,24 +22,22 @@ Class Renderer
 		_direct=False
 		_deferred=False
 		
-		Select GetConfig( "MOJO3D_RENDERER" )
+		Local cfg:=GetConfig( "MOJO3D_RENDERER" )
+		
+		Select cfg
 		Case "deferred"
-			
 			_deferred=True
-			
 		Case "forward"
-			
 			_deferred=False
-		
-		Default
-			
+		Case ""
 #If __DESKTOP_TARGET__ Or __WEB_TARGET__
-
 			_deferred=True
 #else
-
 			_deferred=False
 #endif
+		Default
+			RuntimeError( "Unrecognized MOJO3D_RENDERER config setting value '"+cfg+"'" )
+		
 		End
 		
 		Print "GL_VERSION="+opengl.glGetString( opengl.GL_VERSION )
@@ -39,6 +47,10 @@ Class Renderer
 		Else
 			Print "Renderer is using forward rendering"
 		Endif
+		
+		If _deferred _defs="MX2_DEFERREDRENDERER" Else _defs="MX2_FORWARDRENDERER"
+		
+		_defs+=";MX2_LINEAROUTPUT"
 	End
 	
 	#rem monkeydoc True if renderer is using deferred rendering.
@@ -52,7 +64,7 @@ Class Renderer
 	#end
 	Property ShaderDefs:String()
 		
-		Return "MX2_LINEAROUTPUT=1~n"'MX2_RGBADEPTHTEXTURES=1~n"
+		Return _defs
 	End
 	
 	#rem monkeydoc Size of the cascaded shadow map texture.
@@ -150,27 +162,69 @@ Class Renderer
 			color.b=Pow( color.b,2.2 )
 		
 			_gdevice.Clear( color,1.0 )
-
 		Endif
 	End
 	
 	Method RenderDeferredLighting( light:Light )
 		
-		Local renderPass:=2
+		Local renderPass:=0
+		
+		Local lvmatrix:=_viewMatrix * light.Matrix
+		
+		Local qscale:=New Vec2f( 1 )
+		Local qtrans:=New Vec2f( 0 )
 		
 		Select light.Type
 		Case LightType.Directional
-			If light.CastsShadow RenderCSMShadows( light ) ; renderPass|=4
+			
+			If light.CastsShadow RenderDirectionalShadows( light ) ; renderPass|=16
+			renderPass|=4
+			
 		Case LightType.Point
-			If light.CastsShadow RenderPSMShadows( light ) ; renderPass|=4
+
+			Local r:=light.Range
+			
+			If lvmatrix.t.z<-r 
+'				Print "clip1, z="+lvmatrix.t.z
+				Return
+			Endif
+			
+			If lvmatrix.t.z>r
+				Local box:=New Boxf( lvmatrix.t+New Vec3f( -r ),lvmatrix.t+New Vec3f( r ) )
+				Local cmin:=New Vec2f( 1 ),cmax:=New Vec2f( 0 )
+				For Local i:=0 Until 8
+					Local v:=(_projMatrix * box.Corner( i ) ).XY * 0.5 + 0.5
+					cmin.x=Min( cmin.x,v.x );cmin.y=Min( cmin.y,v.y )
+					cmax.x=Max( cmax.x,v.x );cmax.y=Max( cmax.y,v.y )
+				Next
+				If cmin.x>=1.0 Or cmin.y>=1.0 Return
+				If cmax.x<0.0 Or cmax.y<0.0 Return
+				qscale=cmax-cmin
+				qtrans=cmin
+			Endif
+			
+			If light.CastsShadow RenderPointShadows( light ) ; renderPass|=16
 			renderPass|=8
+			
+		Case LightType.Spot
+			
+			If light.CastsShadow RenderSpotShadows( light ) ; renderPass|=16
+			renderPass|=12
+
+		Default
+			Return
 		End
 		
+		_runiforms.SetVec2f( "QuadCoordScale",qscale )
+		_runiforms.SetVec2f( "QuadCoordTrans",qtrans )
+		_runiforms.SetMat4f( "LightViewMatrix",lvmatrix )
+		_runiforms.SetMat4f( "InverseLightViewMatrix",-lvmatrix )
 		_runiforms.SetColor( "LightColor",light.Color )
 		_runiforms.SetFloat( "LightRange",light.Range )
-		_runiforms.SetMat4f( "LightViewMatrix",_viewMatrix * light.Matrix )
-		
-		_runiforms.SetMat4f( "InverseProjectionMatrix",_invProjMatrix )
+		_runiforms.SetFloat( "LightInnerAngle",light.InnerAngle*Pi/180.0 )
+		_runiforms.SetFloat( "LightOuterAngle",light.OuterAngle*Pi/180.0 )
+		_runiforms.SetTexture( "LightCubeTexture",light.Texture ?Else _whiteCubeTexture )
+		_runiforms.SetTexture( "LightTexture",light.Texture ?Else _whiteTexture )
 		
 		_gdevice.ColorMask=ColorMask.All
 		_gdevice.DepthMask=False
@@ -183,6 +237,8 @@ Class Renderer
 		
 		_gdevice.RenderTarget=_renderTarget1
 		
+		_runiforms.SetMat4f( "InverseProjectionMatrix",_invProjMatrix )
+		
 		RenderQuad()
 		
 		_gdevice.RenderTarget=_renderTarget0
@@ -211,19 +267,30 @@ Class Renderer
 		
 		For Local light:=Eachin _scene.Lights
 			
-			Local renderPass:=first ? 3 Else 2
+			Local renderPass:=2
 			
 			Select light.Type
 			Case LightType.Directional			
-				If light.CastsShadow RenderCSMShadows( light ) ; renderPass|=4
+				If light.CastsShadow RenderDirectionalShadows( light ) ; renderPass|=16
+				renderPass|=4
 			Case LightType.Point
-				If light.CastsShadow RenderPSMShadows( light ) ; renderPass|=4
+				If light.CastsShadow RenderPointShadows( light ) ; renderPass|=16
 				renderPass|=8
+			Case LightType.Spot
+				If light.CastsShadow RenderSpotShadows( light ) ; renderPass|=16
+				renderPass|=12
 			End
 			
+			Local lvmatrix:=_viewMatrix * light.Matrix
+			
+			_runiforms.SetMat4f( "LightViewMatrix",lvmatrix )
+			_runiforms.SetMat4f( "InverseLightViewMatrix",-lvmatrix )
 			_runiforms.SetColor( "LightColor",light.Color )
 			_runiforms.SetFloat( "LightRange",light.Range )
-			_runiforms.SetMat4f( "LightViewMatrix",_viewMatrix * light.Matrix )
+			_runiforms.SetFloat( "LightInnerAngle",light.InnerAngle*Pi/180.0 )
+			_runiforms.SetFloat( "LightOuterAngle",light.OuterAngle*Pi/180.0 )
+			_runiforms.SetTexture( "LightCubeTexture",light.Texture ?Else _whiteCubeTexture )
+			_runiforms.SetTexture( "LightTexture",light.Texture ?Else _whiteTexture )
 
 			_gdevice.ColorMask=ColorMask.All
 			_gdevice.DepthMask=first
@@ -241,7 +308,7 @@ Class Renderer
 			_gdevice.DepthMask=True
 			_gdevice.DepthFunc=DepthFunc.LessEqual
 			_gdevice.BlendMode=BlendMode.Opaque
-			_gdevice.RenderPass=1
+			_gdevice.RenderPass=2
 			
 			RenderOpaqueOps()
 		Endif
@@ -276,6 +343,16 @@ Class Renderer
 			RenderOpaqueForward()
 		Endif
 	End
+	
+	Method RenderSelfIlluminated()
+		
+		_gdevice.ColorMask=ColorMask.All
+		_gdevice.DepthMask=True
+		_gdevice.DepthFunc=DepthFunc.LessEqual
+		_gdevice.RenderPass=1
+		
+		RenderSelfIlluminatedOps()
+	End
 
 	Method RenderTransparent()
 
@@ -283,14 +360,18 @@ Class Renderer
 		
 		For Local light:=Eachin _scene.Lights
 			
-			Local renderPass:=first ? 3 Else 2	'amgient+light or just light
+			Local renderPass:=2
 			
 			Select light.Type
 			Case LightType.Directional			
-	'			If light.CastsShadow RenderCSMShadows( light ) ; renderPass|=4
+	'			If light.CastsShadow RenderDirectionalShadows( light ) ; renderPass|=16
+				renderPass|=4
 			Case LightType.Point
-	'			If light.CastsShadow RenderPSMShadows( light ) ; renderPass|=4
+	'			If light.CastsShadow RenderPointShadows( light ) ; renderPass|=16
 				renderPass|=8
+			Case LightType.Spot
+	'			If light.CastsShadow RenderSpotShadows( light ) ; renderPass|=16
+				renderPass|=12
 			End
 			
 			_runiforms.SetColor( "LightColor",light.Color )
@@ -313,14 +394,14 @@ Class Renderer
 			_gdevice.ColorMask=ColorMask.All
 			_gdevice.DepthMask=False
 			_gdevice.DepthFunc=DepthFunc.LessEqual
-			_gdevice.RenderPass=1
+			_gdevice.RenderPass=2
 			
 			RenderTransparentOps()
 		Endif
 		
 	End
 	
-	Method RenderCSMShadows( light:Light )
+	Method RenderDirectionalShadows( light:Light )
 		
 		'Perhaps use a different device for CSM...?
 		'
@@ -339,11 +420,9 @@ Class Renderer
 		_gdevice.DepthFunc=DepthFunc.LessEqual
 		_gdevice.BlendMode=BlendMode.Opaque
 		_gdevice.CullMode=CullMode.Front
-		_gdevice.RenderPass=4
+		_gdevice.RenderPass=3|4
 
-		Local invLightMatrix:=light.InverseMatrix
-		
-		Local viewLight:=invLightMatrix * -_viewMatrix
+		Local viewLight:=light.InverseMatrix * _invViewMatrix
 		
 		For Local i:=0 Until _csmSplitDepths.Length-1
 			
@@ -387,7 +466,7 @@ Class Renderer
 			
 			_gdevice.Scissor=_gdevice.Viewport
 				
-			RenderShadowOps( invLightMatrix,lightProj )
+			RenderShadowOps( light.InverseMatrix,lightProj )
 		Next
 		
 		_gdevice.RenderTarget=t_rtarget
@@ -395,7 +474,7 @@ Class Renderer
 		_gdevice.Scissor=t_scissor
 	End
 	
-	Method RenderPSMShadows( light:Light )
+	Method RenderPointShadows( light:Light )
 	
 		'Perhaps use a different device for CSM...?
 		'
@@ -411,15 +490,14 @@ Class Renderer
 		_gdevice.DepthFunc=DepthFunc.LessEqual
 		_gdevice.BlendMode=BlendMode.Opaque
 		_gdevice.CullMode=CullMode.Back'Front
-		_gdevice.RenderPass=12
-		
-		Local lnear:=0.1
-		
-		Local lightProj:=Mat4f.Frustum( -lnear,+lnear,-lnear,+lnear,lnear,light.Range )
+		_gdevice.RenderPass=3|8
 		
-		Local invLightMatrix:=light.InverseMatrix
-		
-		Local viewLight:=invLightMatrix * _invViewMatrix
+		Local near:=0.1
+		Local lightProj:=Mat4f.Frustum( -near,+near,-near,+near,near,light.Range )
+		lightProj.k.z=1'(zfar+znear)/(zfar-znear)
+		lightProj.t.z=0'-(zfar*znear*2)/(zfar-znear)
+
+		Local viewLight:=light.InverseMatrix * _invViewMatrix
 		
 		_runiforms.SetFloat( "LightRange",light.Range )
 		_runiforms.SetMat4f( "ShadowMatrix0",viewLight )
@@ -430,7 +508,7 @@ Class Renderer
 			
 			_gdevice.Clear( Color.White,1.0 )
 			
-			Local viewMatrix:=New AffineMat4f( _psmFaceTransforms[i] ) * invLightMatrix
+			Local viewMatrix:=New AffineMat4f( _psmFaceTransforms[i] ) * light.InverseMatrix
 
 			RenderShadowOps( viewMatrix,lightProj )
 		Next
@@ -440,37 +518,72 @@ Class Renderer
 		_gdevice.Scissor=t_scissor
 	End
 	
-	Method RenderPostEffects()
+	Method RenderSpotShadows( light:Light )
+	
+		Local t_rtarget:=_gdevice.RenderTarget
+		Local t_viewport:=_gdevice.Viewport
+		Local t_scissor:=_gdevice.Scissor
 		
+		Local near:=0.1
+		Local lightProj:=Mat4f.Frustum( -near,+near,-near,+near,near,light.Range )
+		
+		Local viewLight:=light.InverseMatrix * _invViewMatrix
+		
+		_runiforms.SetFloat( "LightRange",light.Range )
+		_runiforms.SetMat4f( "ShadowMatrix0",lightProj * viewLight )
+		
+		_gdevice.RenderTarget=_csmTarget
+		_gdevice.Viewport=New Recti( 0,0,_csmTexture.Size/2 )
+		_gdevice.Scissor=_gdevice.Viewport
 		_gdevice.ColorMask=ColorMask.All
-		_gdevice.DepthMask=False
-		_gdevice.DepthFunc=DepthFunc.Always
-		_gdevice.CullMode=CullMode.None
+		_gdevice.DepthMask=True
+		
+		_gdevice.Clear( Color.White,1.0 )
+
+		_gdevice.DepthFunc=DepthFunc.LessEqual
+		_gdevice.BlendMode=BlendMode.Opaque
+		_gdevice.CullMode=CullMode.Front'Back
+		_gdevice.RenderPass=3|12
 
+		RenderShadowOps( light.InverseMatrix,lightProj )
+
+		_gdevice.RenderTarget=t_rtarget
+		_gdevice.Viewport=t_viewport
+		_gdevice.Scissor=t_scissor
+	End
+	
+	Method RenderPostEffects()
+		
+		PostEffect.BeginRendering( _gdevice,_runiforms )
+		
 		For Local effect:=Eachin _scene.PostEffects
 			
 			If Not effect.Enabled Continue
 			
+			_gdevice.ColorMask=ColorMask.All
+			_gdevice.DepthMask=False
+			_gdevice.CullMode=CullMode.None
+			_gdevice.DepthFunc=DepthFunc.Always
 			_gdevice.BlendMode=BlendMode.Opaque
 			_gdevice.RenderPass=0
 			
-			effect.Render( _gdevice )
+			effect.Render()
 		Next
-		
-	End
-	
-	Method RenderCopyQuad() Virtual
-		If _outputRenderTarget
-			RenderInvertedQuad()
-		Else
-			RenderQuad()
-		Endif
+
+		PostEffect.EndRendering()
 	End
 	
 	Method RenderCopy()
 		
 		If _direct Return
 		
+		Local rsize:=_gdevice.Viewport.Size
+		Local rtarget:=_gdevice.RenderTarget
+		Local rtexture:=rtarget.GetColorTexture( 0 )
+		_runiforms.SetTexture( "SourceBuffer",rtexture )
+		_runiforms.SetVec2f( "SourceBufferSize",Cast<Vec2f>( rsize ) )
+		_runiforms.SetVec2f( "SourceBufferScale",Cast<Vec2f>( rsize )/Cast<Vec2f>( rtexture.Size ) )
+
 		_gdevice.RenderTarget=_outputRenderTarget
 		_gdevice.Resize( _outputRenderTargetSize )
 		_gdevice.Viewport=_outputViewport
@@ -489,27 +602,36 @@ Class Renderer
 		_gdevice.RenderTarget=Null
 		_gdevice.Resize( Null )
 	End
+	
+	Method RenderCopyQuad() Virtual	'So VRRenderer can override, ie: cheeze it for now!
 
-	Method RenderQuad()
+		If _outputRenderTarget
+			RenderInvertedQuad()
+		Else
+			RenderQuad()
+		Endif
+	End
+	
+	Method RenderInvertedQuad()
 
 		Global _vertices:=New VertexBuffer( New Vertex3f[](
-			New Vertex3f( 0,1,0,0,1 ),
-			New Vertex3f( 1,1,0,1,1 ),
-			New Vertex3f( 1,0,0,1,0 ),
-			New Vertex3f( 0,0,0,0,0 ) ) )
+			New Vertex3f( 0,1,0,0,0 ),
+			New Vertex3f( 1,1,0,1,0, ),
+			New Vertex3f( 1,0,0,1,1 ),
+			New Vertex3f( 0,0,0,0,1 ) ) )
 			
 		_gdevice.VertexBuffer=_vertices
 		
 		_gdevice.Render( 4,1 )
 	End
 	
-	Method RenderInvertedQuad()
+	Method RenderQuad()
 
 		Global _vertices:=New VertexBuffer( New Vertex3f[](
-			New Vertex3f( 0,1,0,0,0 ),
-			New Vertex3f( 1,1,0,1,0, ),
-			New Vertex3f( 1,0,0,1,1 ),
-			New Vertex3f( 0,0,0,0,1 ) ) )
+			New Vertex3f( 0,1,0,0,1 ),
+			New Vertex3f( 1,1,0,1,1 ),
+			New Vertex3f( 1,0,0,1,0 ),
+			New Vertex3f( 0,0,0,0,0 ) ) )
 			
 		_gdevice.VertexBuffer=_vertices
 		
@@ -541,6 +663,11 @@ Class Renderer
 		RenderRenderOps( _renderQueue.OpaqueOps,_viewMatrix,_projMatrix )
 	End
 	
+	Method RenderSelfIlluminatedOps()
+		
+		RenderRenderOps( _renderQueue.SelfIlluminatedOps,_viewMatrix,_projMatrix )
+	End
+	
 	Method RenderTransparentOps()
 		
 		RenderRenderOps( _renderQueue.TransparentOps,_viewMatrix,_projMatrix )
@@ -554,7 +681,7 @@ Class Renderer
 		_runiforms.SetMat4f( "ProjectionMatrix",projMatrix )
 		_runiforms.SetMat4f( "ViewProjectionMatrix",viewProjMatrix )
 		_runiforms.SetMat4f( "InverseProjectionMatrix",-projMatrix )
-		
+
 		Local instance:Entity=Null,first:=True
 		Local material:Material
 		Local bones:Mat4f[]
@@ -578,26 +705,21 @@ Class Renderer
 				_iuniforms.SetMat4f( "ModelViewProjectionMatrix",modelViewProjMat )
 				_iuniforms.SetColor( "Color",instance ? instance.Color Else Color.White )
 				_iuniforms.SetFloat( "Alpha",instance ? instance.Alpha Else 1.0 )
-				
 			Endif
 				
-			If op.bones _iuniforms.SetMat4fArray( "ModelBoneMatrices",op.bones )
+			If op.bones
+				_iuniforms.SetMat4fArray( "ModelBoneMatrices",op.bones )
+			Endif
 				
-			If op.uniforms _gdevice.BindUniformBlock( op.uniforms )
+			If op.uniforms 
+				_gdevice.BindUniformBlock( op.uniforms )
+			Endif
 						
 			If op.material<>material
-				
 				material=op.material
-				
-				If op.blendMode=BlendMode.Opaque
-					_gdevice.Shader=material.GetOpaqueShader()
-				Else
-					_gdevice.Shader=material.GetTransparentShader()
-				Endif
-				
+				_gdevice.Shader=op.shader
 				_gdevice.BindUniformBlock( material.Uniforms )
 				_gdevice.CullMode=material.CullMode
-				
 			Endif
 
 			_gdevice.BlendMode=op.blendMode
@@ -650,7 +772,7 @@ Class Renderer
 						
 			If op.material<>material
 				material=op.material
-				_gdevice.Shader=material.GetShadowShader()
+				_gdevice.Shader=material.GetRenderShader()
 				_gdevice.BindUniformBlock( material.Uniforms )
 			Endif
 			
@@ -671,6 +793,7 @@ Class Renderer
 	
 	Field _direct:Bool=False
 	Field _deferred:Bool=True
+	Field _defs:String
 	
 	Field _gdevice:GraphicsDevice
 	
@@ -696,6 +819,9 @@ Class Renderer
 
 	Field _renderTarget0:RenderTarget	'all buffers
 	Field _renderTarget1:RenderTarget	'accum buffer only
+
+	Field _effectBuffer:Texture
+	Field _effectTarget:RenderTarget
 	
 	Field _csmSize:=2048
 	Field _csmSplits:Float[]
@@ -725,6 +851,9 @@ Class Renderer
 	Field _invProjMatrix:Mat4f
 	
 	Field _ambientRendered:Bool
+	
+	Field _whiteCubeTexture:Texture
+	Field _whiteTexture:Texture
 
 	Global _current:Renderer
 	
@@ -742,18 +871,17 @@ Class Renderer
 		_gdevice.BindUniformBlock( _runiforms )
 		_gdevice.BindUniformBlock( _iuniforms )
 		
-		_defaultEnv=Texture.Load( "asset::textures/env_default.jpg",TextureFlags.FilterMipmap|TextureFlags.Cubemap )
+		_defaultEnv=Texture.Load( "asset::textures/env_default.jpg",TextureFlags.FilterMipmap|TextureFlags.Cubemap|TextureFlags.Envmap )
 		
-		_copyShader=Shader.Open( "copy" )
+		_skyboxShader=Shader.Open( "misc/skybox",ShaderDefs )
+
+		_copyShader=Shader.Open( "misc/copy" )
 		
 		If _deferred 
-			_skyboxShader=Shader.Open( "skybox-deferred",ShaderDefs )
-			_deferredLightingShader=Shader.Open( "lighting-deferred",ShaderDefs )
-			_deferredFogShader=Shader.Open( "fog-deferred",ShaderDefs )
-		Else
-			_skyboxShader=Shader.Open( "skybox",ShaderDefs )
+			_deferredLightingShader=Shader.Open( "misc/lighting-deferred",ShaderDefs )
+			_deferredFogShader=Shader.Open( "misc/fog-deferred",ShaderDefs )
 		Endif
-		
+
 		_renderQueue=New RenderQueue
 		
 		_psmFaceTransforms=New Mat3f[]( 
@@ -764,9 +892,15 @@ Class Renderer
 			New Mat3f( +1,0, 0, 0,-1,0,  0,0,+1 ),	'+Z
 			New Mat3f( -1,0, 0, 0,-1,0,  0,0,-1 ) )	'-Z
 			
+		Local pixmap:=New Pixmap( 1,1,PixelFormat.I8 )
+		pixmap.Clear( Color.White )
+		_whiteCubeTexture=New Texture( pixmap,TextureFlags.Cubemap )
+		
+		_whiteTexture=Texture.ColorTexture( Color.White )
+			
 		ValidateSize( New Vec2i( 1920,1080 ) )
 	End
-
+	
 	Method ValidateSize( size:Vec2i )
 		
 		If _direct Return
@@ -885,21 +1019,38 @@ Class Renderer
 		
 		_scene=scene
 		
-		_runiforms.SetTexture( "SkyTexture",_scene.SkyTexture )
+		Local sky:=_scene.SkyTexture
+		
+		If sky
+			If sky.Flags & TextureFlags.Cubemap
+				_runiforms.SetTexture( "SkyTextureCube",sky )
+				_runiforms.SetTexture( "SkyTexture2D",_whiteTexture )
+				_runiforms.SetInt( "SkyCube",1 )
+			Else
+				_runiforms.SetTexture( "SkyTextureCube",_whiteCubeTexture )
+				_runiforms.SetTexture( "SkyTexture2D",sky )
+				_runiforms.SetInt( "SkyCube",0 )
+			Endif
+		Else
+			_runiforms.SetTexture( "SkyTextureCube",Null )
+			_runiforms.SetTexture( "SkyTexture2D",Null )
+		Endif
+				
 		_runiforms.SetColor( "ClearColor",_scene.ClearColor )
 		_runiforms.SetColor( "AmbientDiffuse",_scene.AmbientLight )
 		
-		Local env:Texture
+		Local env:=(_scene.EnvTexture ?Else _scene.SkyTexture) ?Else _defaultEnv
 		
-		If _scene.EnvTexture
-			env=_scene.EnvTexture
-		ElseIf _scene.SkyTexture
-			env=_scene.SkyTexture
+		If env.Flags & TextureFlags.Cubemap
+			_runiforms.SetTexture( "EnvTextureCube",env )
+			_runiforms.SetTexture( "EnvTexture2D",_whiteTexture )
+			_runiforms.SetInt( "EnvCube",1 )
 		Else
-			env=_defaultEnv
+			_runiforms.SetTexture( "EnvTextureCube",_whiteCubeTexture )
+			_runiforms.SetTexture( "EnvTexture2D",env )
+			_runiforms.SetInt( "EnvCube",0 )
 		Endif
 		
-		_runiforms.SetTexture( "EnvTexture",env )
 		_runiforms.SetFloat( "EnvTextureMaxLod",Log2( env.Size.x ) )
 		_runiforms.SetColor( "EnvColor",_scene.EnvColor )
 		
@@ -951,7 +1102,7 @@ Class Renderer
 		
 		For Local r:=Eachin _scene.Renderables
 		
-			_renderQueue.CastsShadow=r.CastsShadow
+			_renderQueue.AddShadowOps=r.CastsShadow
 			
 			r.OnRender( _renderQueue )
 		Next

+ 23 - 12
modules/mojo3d/render/renderqueue.monkey2

@@ -22,6 +22,7 @@ Class RenderOp
 	
 	Field blendMode:BlendMode
 	Field distance:Float
+	Field shader:Shader
 End
 
 Public
@@ -47,13 +48,13 @@ Class RenderQueue
 		_eyeLen=_eyePos.Length
 	End
 	
-	Property CastsShadow:Bool()
+	Property AddShadowOps:Bool()
 		
-		Return _castsShadow
+		Return _addShadowOps
 		
-	Setter( castsShadow:Bool )
+	Setter( addShadowOps:Bool )
 		
-		_castsShadow=castsShadow
+		_addShadowOps=addShadowOps
 	End
 
 	Property OpaqueOps:Stack<RenderOp>()
@@ -61,6 +62,11 @@ Class RenderQueue
 		Return _opaqueOps
 	End
 	
+	Property SelfIlluminatedOps:Stack<RenderOp>()
+		
+		Return _selfillumOps
+	End
+	
 	Property TransparentOps:Stack<RenderOp>()
 	
 		Return _transparentOps
@@ -78,6 +84,7 @@ Class RenderQueue
 
 	Method Clear()
 		_opaqueOps.Clear()
+		_selfillumOps.Clear()
 		_transparentOps.Clear()
 		_shadowOps.Clear()
 		_spriteOps.Clear()	
@@ -88,16 +95,19 @@ Class RenderQueue
 		op.blendMode=op.material.BlendMode
 		If op.instance And op.instance.Alpha<1 And op.blendMode=BlendMode.Opaque op.blendMode=BlendMode.Alpha
 			
+		Local stack:Stack<RenderOp>
+		
 		If op.blendMode=BlendMode.Opaque
-			DebugAssert( op.material.GetOpaqueShader(),"Material has no opaque shader" )
-			_opaqueOps.Push( op )
+			stack=_opaqueOps
+			op.shader=op.material.GetRenderShader()
+			If _addShadowOps _shadowOps.Add( op )
 		Else
-			DebugAssert( op.material.GetTransparentShader(),"Material has no transparent shader" )
+			stack=_transparentOps
+			op.shader=op.material.GetRenderShader()
 			op.distance=op.instance ? op.instance.Position.Distance( _eyePos ) Else _eyeLen
-			_transparentOps.Push( op )
 		Endif
-			
-		If _castsShadow And op.material.GetShadowShader() _shadowOps.Push( op )
+		
+		stack.Add( op )
 	End
 	
 	Method AddSpriteOp( op:SpriteOp )
@@ -154,7 +164,7 @@ Class RenderQueue
 	End
 	
 	Method AddSpriteOp( sprite:Sprite )
-		DebugAssert( sprite.Material.GetTransparentShader(),"Sprites must be transparent!" )
+		DebugAssert( sprite.Material.GetRenderShader(),"Sprites must be transparent!" )
 		Local op:=New SpriteOp
 		op.sprite=sprite
 		AddSpriteOp( op )
@@ -166,9 +176,10 @@ Class RenderQueue
 	
 	Field _eyePos:Vec3f
 	Field _eyeLen:Float
-	Field _castsShadow:Bool
+	Field _addShadowOps:Bool
 	
 	Field _opaqueOps:=New Stack<RenderOp>
+	Field _selfillumOps:=New Stack<RenderOp>
 	Field _transparentOps:=New Stack<RenderOp>
 	Field _shadowOps:=New Stack<RenderOp>
 	

+ 6 - 0
modules/mojo3d/render/spritebuffer.monkey2

@@ -20,6 +20,7 @@ Class SpriteBuffer
 		Local n:=spriteOps.Length
 		
 		If n*4>_vbuffer.Length
+			Local len:=_vbuffer.Length
 			_vbuffer.Resize( Max( _vbuffer.Length*3/2,n*4 ) )
 		Endif
 		
@@ -119,15 +120,19 @@ Class SpriteBuffer
 			
 			vp[0].position=matrix * New Vec3f( -handle.x,1-handle.y,0 )
 			vp[0].texCoord0=New Vec2f( texrect.min.x,texrect.min.y )
+			vp[0].color=~0
 			
 			vp[1].position=matrix * New Vec3f( 1-handle.x,1-handle.y,0 )
 			vp[1].texCoord0=New Vec2f( texrect.max.x,texrect.min.y )
+			vp[1].color=~0
 
 			vp[2].position=matrix * New Vec3f( 1-handle.x,-handle.y,0 )
 			vp[2].texCoord0=New Vec2f( texrect.max.x,texrect.max.y )
+			vp[2].color=~0
 			
 			vp[3].position=matrix * New Vec3f( -handle.x,-handle.y,0 )
 			vp[3].texCoord0=New Vec2f( texrect.min.x,texrect.max.y )
+			vp[3].color=~0
 			
 			'bump vertex/index
 			vp+=4
@@ -170,6 +175,7 @@ Class SpriteBuffer
 		
 		op.blendMode=_material.BlendMode
 		op.distance=_distance
+		op.shader=_material.GetRenderShader()
 		
 		_renderOps.Add( op )
 	End

+ 310 - 0
modules/mojo3d/scene/components/joint.monkey2

@@ -0,0 +1,310 @@
+Namespace mojo3d
+
+Private
+
+'Global nullBody:btRigidBody=New btRigidBody( 0,Null,Null,Null )
+
+Public
+
+Class Joint Extends Component
+	
+	Const ERP:=0		'error reduction parameter - http://bulletphysics.org/mediawiki-1.5.8/index.php/Definitions
+	Const STOP_ERP:=1
+	Const CFM:=2
+	Const STOP_CFM:=3	'constraint force mixing
+	
+	Const Type:=New ComponentType( "Joint",-20,ComponentTypeFlags.Singleton )
+	
+	Method New( entity:Entity )
+		
+		Super.New( entity,Type )
+	End
+	
+	Method New( entity:Entity,joint:Joint )
+		
+		Super.New( entity,Type )
+	End
+
+	Method SetParam( param:Int,value:Float )
+		
+		If _btconstraint _btconstraint.setParam( param+1,value )
+		
+		_params[param]=value
+	End
+	
+	Method GetParam:Float( param:Int )
+		
+		Return _params[param]
+	End
+	
+Protected
+
+	Field _rvisible:Bool
+	
+	Field _params:=New Float[4]
+
+	Field _btconstraint:btTypedConstraint
+	
+	Method OnCreate() Abstract
+	
+	Method OnBeginUpdate() Override
+		
+		Validate()
+	End
+
+	Method OnDestroy() Override
+		
+		If Not _btconstraint Return
+		
+		Entity.Scene.World.btWorld.removeConstraint( _btconstraint )
+		_btconstraint.destroy()
+		_btconstraint=Null
+	End
+	
+	Method Validate()
+
+		Local rvisible:=Entity.ReallyVisible
+		
+		If rvisible=_rvisible Return
+		
+		If rvisible
+			If Not _btconstraint 
+				OnCreate()
+'				_btconstraint.setParam( ERP+1,_params[ERP] )
+'				_btconstraint.setParam( STOP_ERP+1,_params[STOP_ERP] )
+'				_btconstraint.setParam( CFM+1,_params[CFM] )
+'				_btconstraint.setParam( STOP_CFM+1,_params[STOP_CFM] )
+			Endif
+			Entity.Scene.World.btWorld.addConstraint( _btconstraint )
+		Else
+			If _btconstraint Entity.Scene.World.btWorld.removeConstraint( _btconstraint )
+		Endif
+		
+		_rvisible=rvisible
+	End
+	
+End
+
+Class BallSocketJoint Extends Joint
+	
+	Method New( entity:Entity )
+		
+		Super.New( entity )
+		
+		AddInstance()
+	End
+	
+	Method New( entity:Entity,joint:BallSocketJoint )
+		
+		Super.New( entity,joint )
+		
+		ConnectedBody=joint.ConnectedBody
+		Pivot=joint.Pivot
+		
+		AddInstance( joint )
+	End
+	
+	[jsonify=1]
+	Property ConnectedBody:RigidBody()
+		
+		Return _connected
+		
+	Setter( body:RigidBody )
+		
+		_connected=body
+	End
+	
+	[jsonify=1]
+	Property Pivot:Vec3f()
+		
+		Return _pivot1
+		
+	Setter( pivot:Vec3f )
+		
+		_pivot1=pivot
+	End
+	
+	Protected
+	
+	Field _connected:RigidBody
+	Field _pivot1:Vec3f
+	
+	Method OnCreate() Override
+		
+		Local btBody1:=Entity.GetComponent<RigidBody>().btBody
+		Assert( btBody1,"BallSocketJoint: No rigid body" )	'todo: fail nicely
+		
+		If _connected
+			Local btBody2:=_connected.btBody
+			Assert( btBody2,"BallSocketJoint: No rigid body" )	'todo: fail nicely
+			Local tform:=_connected.Entity.InverseMatrix * Entity.Matrix
+			Local pivot2:=tform * _pivot1
+			_btconstraint=New btPoint2PointConstraint( btBody1,btBody2,_pivot1,pivot2 )
+		Else
+			_btconstraint=New btPoint2PointConstraint( btBody1,_pivot1 )
+		End
+	End
+		
+End
+
+Class HingeJoint Extends Joint
+
+	Method New( entity:Entity )
+		
+		Super.New( entity )
+		
+		Axis=New Vec3f( 0,1,0 )
+		MinAngle=180
+		MaxAngle=-180
+		
+		AddInstance()
+	End
+	
+	Method New( entity:Entity,joint:HingeJoint )
+		
+		Super.New( entity,joint )
+		
+		ConnectedBody=joint.ConnectedBody
+		Pivot=joint.Pivot
+		Axis=joint.Axis
+		MinAngle=joint.MinAngle
+		MaxAngle=joint.MaxAngle
+		
+		AddInstance( joint )
+	End
+	
+	[jsonify=1]
+	Property ConnectedBody:RigidBody()
+		
+		Return _connected
+		
+	Setter( body:RigidBody )
+		
+		_connected=body
+	End
+	
+	[jsonify=1]
+	Property Pivot:Vec3f()
+		
+		Return _pivot1
+		
+	Setter( pivot:Vec3f )
+		
+		_pivot1=pivot
+	End
+	
+	[jsonify=1]
+	Property Axis:Vec3f()
+		
+		Return _axis1
+		
+	Setter( axis:Vec3f )
+		
+		_axis1=axis
+	End
+	
+	Property MinAngle:Float()
+		
+		Return _minAngle
+		
+	Setter( angle:Float ) 
+		
+		_minAngle=angle
+		
+		SetLimits()
+	End
+	
+	Property MaxAngle:Float()
+		
+		Return _maxAngle
+		
+	Setter( angle:Float ) 
+		
+		_maxAngle=angle
+		
+		SetLimits()
+	End
+	
+	Protected
+	
+	Field _connected:RigidBody
+	Field _pivot1:Vec3f
+	Field _axis1:Vec3f
+	Field _minAngle:Float
+	Field _maxAngle:Float
+	
+	Method SetLimits()
+		
+		If Not _btconstraint Return
+		
+		Cast<btHingeConstraint>(_btconstraint).setLimit( _minAngle*Pi/180,_maxAngle*Pi/180 )
+	End
+	
+	Method OnCreate() Override
+		
+		Local btBody1:=Entity.GetComponent<RigidBody>().btBody
+		Assert( btBody1,"HingeJoint: No rigid body" )	'todo: fail nicely
+		
+		If _connected
+			Local btBody2:=_connected.btBody
+			Assert( btBody2,"HingeJoint: No rigid body" )	'todo: fail nicely
+			Local tform:=_connected.Entity.InverseMatrix * Entity.Matrix
+			Local pivot2:=tform * _pivot1
+			Local axis2:=tform.m * _axis1
+			_btconstraint=New btHingeConstraint( btBody1,btBody2,_pivot1,pivot2,_axis1,axis2 )
+		Else
+			_btconstraint=New btHingeConstraint( btBody1,_pivot1,_axis1 )
+		End
+		
+		SetLimits()
+	End
+	
+End
+
+Class FixedJoint Extends Joint
+
+	Method New( entity:Entity )
+		
+		Super.New( entity )
+		
+		AddInstance()
+	End
+	
+	Method New( entity:Entity,joint:HingeJoint )
+		
+		Super.New( entity,joint )
+		
+		ConnectedBody=joint.ConnectedBody
+		
+		AddInstance( joint )
+	End
+	
+	[jsonify=1]
+	Property ConnectedBody:RigidBody()
+		
+		Return _connected
+		
+	Setter( body:RigidBody )
+		
+		_connected=body
+	End
+	
+	Protected
+	
+	Field _connected:RigidBody
+	
+	Method OnCreate() Override
+		
+		Local btBody1:=Entity.GetComponent<RigidBody>()?.btBody
+		Assert( btBody1,"FixedJoint: No rigid body" )	'todo: fail nicely
+
+		Local btBody2:=_connected?.btBody
+		Assert( btBody2,"FixedJoint: No connected rigid body" )	'todo: fail nicely
+		
+		Local tform:=_connected.Entity.InverseMatrix * Entity.Matrix
+		
+		_btconstraint=New btFixedConstraint( btBody1,btBody2,New AffineMat4f,tform )
+	End
+	
+End
+

+ 41 - 3
modules/mojo3d/scene/components/rigidbody.monkey2

@@ -165,6 +165,46 @@ Class RigidBody Extends Component
 		_dirty|=Dirty.Collisions
 	End
 	
+	[jsonify=1]
+	Property LinearDamping:Float()
+		
+		Return _btbody.getLinearDamping()
+		
+	Setter( damping:Float )
+		
+		_btbody.setDamping( damping,_btbody.getAngularDamping() )
+	End
+	
+	[jsonify=1]
+	Property AngularDamping:Float()
+		
+		Return _btbody.getAngularDamping()
+	
+	Setter( damping:Float )
+		
+		_btbody.setDamping( _btbody.getLinearDamping(),damping )
+	End
+	
+	[jsonify=1]
+	Property LinearFactor:Vec3f()
+		
+		Return _btbody.getLinearFactor()
+	
+	Setter( factor:Vec3f )
+		
+		_btbody.setLinearFactor( factor )
+	End
+
+	[jsonify=1]	
+	Property AngularFactor:Vec3f()
+		
+		Return _btbody.getAngularFactor()
+	
+	Setter( factor:Vec3f )
+		
+		_btbody.setAngularFactor( factor )
+	End
+	
 	Property LinearVelocity:Vec3f()
 		
 		Return _btbody.getLinearVelocity()
@@ -182,7 +222,7 @@ Class RigidBody Extends Component
 		
 		_btbody.setAngularVelocity( avelocity )
 	End
-
+	
 	Property btBody:btRigidBody()
 	
 		Return _btbody
@@ -325,8 +365,6 @@ Class RigidBody Extends Component
 			
 			_btbody.setCollisionShape( collider?.Validate() )
 
-'			_btbody.setCollisionFlags( _btbody.getCollisionFlags() | btCollisionObject.CF_KINEMATIC_OBJECT )
-			
 '			If Cast<MeshCollider>( collider )
 '				_btbody.setCollisionFlags( _btbody.getCollisionFlags() | btCollisionObject.CF_CUSTOM_MATERIAL_CALLBACK )
 '			Else

+ 17 - 50
modules/mojo3d/scene/effects/bloomeffect.monkey2

@@ -10,9 +10,9 @@ Class BloomEffect Extends PostEffect
 	
 	#rem monkeydoc Creates a new bloom effect.
 	#end
-	Method New( passes:Int=2 )
+	Method New( passes:Int=1 )
 		
-		_shader=Shader.Open( "effect-bloom" )
+		_shader=Shader.Open( "effects/bloom" )
 		
 		_uniforms=New UniformBlock( 3 )
 		
@@ -29,68 +29,40 @@ Class BloomEffect Extends PostEffect
 		Return _passes
 	
 	Setter( passes:Int )
-		Assert( passes>0 And (passes&1)=0,"BloomEffect passes must be even and >0" )
+		Assert( passes>0,"BloomEffect passes must be >0" )
 		
 		_passes=passes
 	End
 	
 	Protected
 	
-	#rem monkeydoc @hidden
-	#end
-	Method OnRender() Override
-		
-		Local rsize:=Device.Viewport.Size
-		Local rtarget:=Device.RenderTarget
-		Local rtexture:=rtarget.GetColorTexture( 0 )
+	Method OnRender( target:RenderTarget,viewport:Recti ) Override
 		
-		If Not _target0 Or rsize.x>_target0.Size.x Or rsize.y>_target0.Size.y
+		Local size:=viewport.Size
+		Local source:=target.GetColorTexture( 0 )
 		
-			_texture0?.Discard()
-			_texture1?.Discard()
-			
-			_target0?.Discard()
-			_target1?.Discard()
-			
-			_texture0=New Texture( rsize.x,rsize.y,rtexture.Format,TextureFlags.Dynamic|TextureFlags.Filter )
-			_texture1=New Texture( rsize.x,rsize.y,rtexture.Format,TextureFlags.Dynamic|TextureFlags.Filter )
-
-			_target0=New RenderTarget( New Texture[]( _texture0 ),Null )
-			_target1=New RenderTarget( New Texture[]( _texture1 ),Null )
+		If Not _target0 Or size.x<>_target0.Size.x Or size.y<>_target0.Size.y
+			_target0=CreateRenderTarget( size,source.Format,TextureFlags.Dynamic )
+			_target1=CreateRenderTarget( size,source.Format,TextureFlags.Dynamic )
 		Endif
-
+		
 		Device.Shader=_shader
 		Device.BindUniformBlock( _uniforms )
-
-		Local target:=_target0
-		Local source:=rtexture
 		
-		For Local i:=0 Until _passes
-
-			_uniforms.SetTexture( "SourceTexture",source )
-			_uniforms.SetVec2f( "SourceTextureSize",source.Size )
-			_uniforms.SetVec2f( "SourceTextureScale",Cast<Vec2f>( rsize )/Cast<Vec2f>( source.Size ) )
-
-			Device.RenderTarget=target
+		Local rtarget:=_target0
+		
+		For Local i:=0 Until _passes*2
+			
+			Super.SetRenderTarget( rtarget,New Recti( 0,0,size ) )
 			Device.RenderPass=i ? 2-(i&1) Else 0	'0,1,2,1,2,1,2...
 			
 			RenderQuad()
 			
-			If target=_target0
-				source=_texture0
-				target=_target1
-			Else
-				source=_texture1
-				target=_target0
-			Endif
-			
+			rtarget=rtarget=_target0 ? _target1 Else _target0
 		Next
 		
-		_uniforms.SetTexture( "SourceTexture",source )
-		_uniforms.SetVec2f( "SourceTextureSize",source.Size )
-		_uniforms.SetVec2f( "SourceTextureScale",Cast<Vec2f>( rsize )/Cast<Vec2f>( source.Size ) )
+		Super.SetRenderTarget( target,viewport )
 		
-		Device.RenderTarget=rtarget
 		Device.BlendMode=BlendMode.Additive
 		Device.RenderPass=3
 		
@@ -101,12 +73,7 @@ Class BloomEffect Extends PostEffect
 	
 	Field _shader:Shader
 	Field _uniforms:UniformBlock
-	
 	Field _passes:Int=4
-	
-	Field _texture0:Texture
-	Field _texture1:Texture
-	
 	Field _target0:RenderTarget
 	Field _target1:RenderTarget
 	

+ 0 - 78
modules/mojo3d/scene/effects/fogeffect.monkey2

@@ -1,78 +0,0 @@
-
-Namespace mojo3d
-
-#rem The FogEffect class.
-
-This class implements a 'fog' post processing effect.
-
-#end
-Class FogEffect Extends PostEffect
-
-	#rem monkeydoc Creates a new fog effect.
-	#end	
-	Method New( color:Color=std.graphics.Color.Sky,near:Float=0,far:Float=1000 )
-
-		_shader=Shader.Open( "effect-fog" )
-		
-		_uniforms=New UniformBlock( 3 )
-		
-		Color=color
-		Near=near
-		Far=far
-	End
-
-	#rem monkeydoc Color of the fog.
-	#end
-	Property Color:Color()
-		
-		Return _uniforms.GetColor( "Color" )
-	
-	Setter( color:Color )
-		
-		_uniforms.SetColor( "Color",color )
-	End
-
-	#rem monkeydoc Near distance of the fog.
-	#end	
-	Property Near:Float()
-		
-		Return _uniforms.GetFloat( "Near" )
-	
-	Setter( near:Float )
-		
-		_uniforms.SetFloat( "Near",near )
-	End
-	
-	#rem monkeydoc Far distance of the fog.
-	#end	
-	Property Far:Float()
-		
-		Return _uniforms.GetFloat( "Far" )
-	
-	Setter( far:Float )
-		
-		_uniforms.SetFloat( "Far",far )
-	End
-	
-	Protected
-	
-	#rem monkeydoc @hidden
-	#end
-	Method OnRender() Override
-		
-		Device.Shader=_shader
-		
-		Device.BindUniformBlock( _uniforms )
-
-		Device.BlendMode=BlendMode.Alpha
-		
-		RenderQuad()
-	End
-	
-	Private
-	
-	Field _shader:Shader
-	
-	Field _uniforms:UniformBlock
-	
-End

+ 8 - 20
modules/mojo3d/scene/effects/monochromeeffect.monkey2

@@ -9,7 +9,7 @@ Class MonochromeEffect Extends PostEffect
 	#end
 	Method New( level:Float=1.0 )
 		
-		_shader=Shader.Open( "effect-monochrome" )
+		_shader=Shader.Open( "effects/monochrome" )
 		
 		_uniforms=New UniformBlock( 3 )
 		
@@ -32,28 +32,17 @@ Class MonochromeEffect Extends PostEffect
 
 	Protected
 	
-	#rem monkeydoc @hidden
-	#end	
-	Method OnRender() Override
+	Method OnRender( target:RenderTarget,viewport:Recti ) Override
 		
-		Local rsize:=Device.Viewport.Size
-		Local rtarget:=Device.RenderTarget
-		Local rtexture:=rtarget.GetColorTexture( 0 )
+		Local size:=viewport.Size
+		Local source:=target.GetColorTexture( 0 )
 		
-		If Not _target Or rsize.x>_target.Size.x Or rsize.y>_target.Size.y
-			
-			_target?.Discard()
-			_texture?.Discard()
-			
-			_texture=New Texture( rsize.x,rsize.y,rtexture.Format,Null )
-			_target=New RenderTarget( New Texture[]( _texture ),Null )
+		If Not _target Or size.x>_target.Size.x Or size.y>_target.Size.y
+			_target=CreateRenderTarget( size,source.Format,TextureFlags.Dynamic )
 		End
-					
-		_uniforms.SetTexture( "SourceTexture",rtexture )
-		_uniforms.SetVec2f( "SourceTextureSize",rsize )
-		_uniforms.SetVec2f( "SourceCoordScale",Cast<Vec2f>( rsize )/Cast<Vec2f>( rtexture.Size ) )
 		
-		Device.RenderTarget=_target
+		Super.SetRenderTarget( _target,New Recti( 0,0,size ) )
+
 		Device.Shader=_shader
 		Device.BindUniformBlock( _uniforms )
 		
@@ -65,6 +54,5 @@ Class MonochromeEffect Extends PostEffect
 	Field _shader:Shader
 	Field _uniforms:UniformBlock
 	Field _target:RenderTarget
-	Field _texture:Texture
 	
 End

+ 26 - 0
modules/mojo3d/scene/effects/reflectioneffect.monkey2

@@ -0,0 +1,26 @@
+
+Namespace mojo3d
+
+#rem monkeydoc The ReflectionEffect class.
+#end
+Class ReflectionEffect Extends PostEffect
+
+	#rem monkeydoc Creates a new monochrome effect shader.
+	#end
+	Method New()
+		
+		_shader=Shader.Open( "effects/reflection" )
+		
+		_uniforms=New UniformBlock( 3 )
+	End
+	
+	Protected
+	
+	Method OnRender( target:RenderTarget,viewport:Recti ) Override
+	End
+	
+	Private
+	
+	Field _shader:Shader
+	Field _uniforms:UniformBlock
+End

+ 4 - 4
modules/mojo3d/scene/entities/camera.monkey2

@@ -17,9 +17,9 @@ Class Camera Extends Entity
 		Far=100
 		FOV=90
 		
-		AddInstance()
-		
 		Visible=True
+		
+		AddInstance()
 	End
 
 	Method New( view:View,parent:Entity=Null )
@@ -32,9 +32,9 @@ Class Camera Extends Entity
 		Far=100
 		FOV=90
 		
-		AddInstance()
-		
 		Visible=True
+		
+		AddInstance()
 	End
 	
 	#rem monkeydoc Copies the camera.

+ 54 - 7
modules/mojo3d/scene/entities/light.monkey2

@@ -29,12 +29,15 @@ Class Light Extends Entity
 		
 		Name="Light"
 		Type=LightType.Directional
-		CastsShadow=False
+		Texture=Null
 		Range=10
-		
-		AddInstance()
+		InnerAngle=15
+		OuterAngle=30
+		CastsShadow=False
 		
 		Visible=True
+		
+		AddInstance()
 	End
 	
 	#rem monkeydoc Copies the light.
@@ -50,6 +53,7 @@ Class Light Extends Entity
 	
 	#rem monkeydoc The light type.
 	#end
+	[jsonify=1]
 	Property Type:LightType()
 		
 		Return _type
@@ -59,6 +63,16 @@ Class Light Extends Entity
 		_type=type
 	End
 	
+	[jsonify=1]
+	Property Texture:Texture()
+		
+		Return _texture
+	
+	Setter( texture:Texture )
+		
+		_texture=texture
+	End
+	
 	#rem monkeydoc Light shadows enabled flag.
 	#end
 	[jsonify=1]
@@ -83,6 +97,36 @@ Class Light Extends Entity
 		_range=range
 	End
 	
+	#rem monkeydoc The cone inner angle for spot lights, in degrees.
+	
+	Defaults to 0 degrees.
+		
+	#end
+	[jsonify=1]
+	Property InnerAngle:Float()
+		
+		Return _innerAngle
+	
+	Setter( angle:Float )
+		
+		_innerAngle=angle
+	End
+	
+	#rem monkeydoc The cone outer angle for spot lights, in degrees.
+	
+	Defaults to 45 degrees.
+		
+	#end
+	[jsonify=1]
+	Property OuterAngle:Float()
+		
+		Return _outerAngle
+	
+	Setter( angle:Float )
+		
+		_outerAngle=angle
+	End
+	
 	Protected
 
 	Method New( light:Light,parent:Entity )
@@ -90,8 +134,11 @@ Class Light Extends Entity
 		Super.New( light,parent )
 		
 		Type=light.Type
-		Color=light.Color
+		Texture=light.Texture
+		CastsShadow=light.CastsShadow
 		Range=light.Range
+		InnerAngle=light.InnerAngle
+		OuterAngle=light.OuterAngle
 		
 		AddInstance( light )
 	End
@@ -114,11 +161,11 @@ Class Light Extends Entity
 	Private
 	
 	Field _type:LightType
-	
+	Field _texture:Texture
 	Field _color:Color
-	
 	Field _range:Float
-	
+	Field _innerAngle:Float
+	Field _outerAngle:Float
 	Field _castsShadow:bool
 
 End

+ 4 - 4
modules/mojo3d/scene/entities/model.monkey2

@@ -20,9 +20,9 @@ Class Model Extends Renderable
 		
 		Name="Model"
 		
-		AddInstance()
-		
 		Visible=True
+		
+		AddInstance()
 	End
 	
 	Method New( mesh:Mesh,material:Material,parent:Entity=Null )
@@ -31,13 +31,13 @@ Class Model Extends Renderable
 		
 		Name="Model"
 		
-		AddInstance( New Variant[]( mesh,material,parent ) )
-		
 		Mesh=mesh
 		Materials=New Material[]( material )
 		Material=material
 		
 		Visible=True
+
+		AddInstance( New Variant[]( mesh,material,parent ) )
 	End
 	
 	#rem monkeydoc Copies the model.

+ 4 - 19
modules/mojo3d/scene/entities/particlematerial.monkey2

@@ -8,7 +8,9 @@ Class ParticleMaterial Extends Material
 	#rem monkeydoc Creates a new particle material.
 	#end	
 	Method New()
-
+		
+		ShaderName="materials/particle"
+		AttribMask=1|8|32
 		BlendMode=BlendMode.Additive
 		CullMode=CullMode.None
 		
@@ -31,23 +33,6 @@ Class ParticleMaterial Extends Material
 		Return New ParticleMaterial( Self )
 	End
 	
-	Method GetTransparentShader:Shader() Override
-		
-		Global _shader:Shader
-		
-		If Not _shader
-			
-			Local shader:="material-particle"
-			Local defs:=Renderer.GetCurrent().ShaderDefs
-				
-			_shader=Shader.Open( shader,defs )
-		
-		Endif
-		
-		Return _shader
-		
-	End
-	
 	Property ColorTexture:Texture()
 		
 		Return Uniforms.GetTexture( "ColorTexture" )
@@ -94,7 +79,7 @@ Class ParticleMaterial Extends Material
 	
 		Uniforms.SetFloat( "Fade",fade )
 	End
-
+	
 	Private
 	
 	Field _duration:Float

+ 5 - 0
modules/mojo3d/scene/entities/particlesystem.monkey2

@@ -12,6 +12,8 @@ Class ParticleSystem Extends Renderable
 		_material=New ParticleMaterial
 		
 		Visible=True
+		
+		AddInstance()
 	End
 
 	Method New( particleBuffer:ParticleBuffer,material:ParticleMaterial,parent:Entity=Null )
@@ -21,6 +23,8 @@ Class ParticleSystem Extends Renderable
 		_material=material
 		
 		Visible=True
+		
+		AddInstance( New Variant[]( particleBuffer,material,parent ) )
 	End
 
 	#rem monkeydoc Copies the particle system.
@@ -83,3 +87,4 @@ Class ParticleSystem Extends Renderable
 	Field _material:ParticleMaterial
 	
 End
+

+ 7 - 0
modules/mojo3d/scene/entityexts.monkey2

@@ -27,6 +27,13 @@ Class Entity Extension
 		Return GetComponent<Collider>()
 	End
 
+	#rem monkeydoc The joint attached to the entity.
+	#end
+	Property Joint:Joint()
+		
+		Return GetComponent<Joint>()
+	End
+
 	#rem monkeydoc The animator attached to the entity.
 	#end
 	Property Animator:Animator()

+ 74 - 87
modules/mojo3d/scene/jsonifier/jsonifier.monkey2

@@ -136,16 +136,17 @@ Public
 			jobjsById[id]=jobj
 		Next
 		
-		'copy of insts alreday created (ie: initial Scene)
-		Local tinsts:=_insts.ToArray(),id:=0
+		Local id:=0
 		
 		For Local i:=0 Until jinsts.Length
 			
 			Local jobj:=jinsts.GetObject( i )
 			If Not jobj.Contains( "ctor" ) Continue
 			
-			Local ctor:=Cast<Invocation>( Dejsonify( jobj["ctor"],Typeof<Invocation> ) )
-			ctor.Execute()
+			If jobj.GetNumber( "id" )>=_insts.Length
+				Local ctor:=Cast<Invocation>( Dejsonify( jobj["ctor"],Typeof<Invocation> ) )
+				ctor.Execute()
+			Endif
 			
 			For Local j:=id Until _insts.Length
 				
@@ -196,55 +197,47 @@ Public
 		Local type:=value.Type
 		Assert( type )
 
-		'handle primitive types
-		Select type
-		Case Typeof<Bool>
-			Return New JsonBool( Cast<Bool>( value ) )
-		Case Typeof<Short>
-			Return New JsonNumber( Cast<Short>( value ) )
-		Case Typeof<Int>
-			Return New JsonNumber( Cast<Int>( value ) )
-		Case Typeof<Float>
-			Return New JsonNumber( Cast<Float>( value ) )
-		Case Typeof<String>
-			Return New JsonString( Cast<String>( value ) )
+		Select type.Kind
+		Case "Primitive"
+			Select type
+			Case Typeof<Bool>
+				Return New JsonBool( Cast<Bool>( value ) )
+			Case Typeof<Short>
+				Return New JsonNumber( Cast<Short>( value ) )
+			Case Typeof<Int>
+				Return New JsonNumber( Cast<Int>( value ) )
+			Case Typeof<Float>
+				Return New JsonNumber( Cast<Float>( value ) )
+			Case Typeof<String>
+				Return New JsonString( Cast<String>( value ) )
+			End
+		Case "Array"
+			Local n:=value.GetArrayLength()
+			Local jarray:=New JsonArray( n )
+			For Local i:=0 Until n
+				jarray[i]=Jsonify( value.GetArrayElement( i ) )
+			Next
+			Return jarray
+		Case "Enum"
+			Return New JsonNumber( value.EnumValue )
 		End
 		
-		'handle enums+references
-		Select type.Kind
-		Case "Class"
+		If IsInstanceType( type )
 			Local obj:=Cast<Object>( value )
 			If Not obj Return JsonValue.NullValue
 			Local inst:=_instsByObj[obj]
 			If inst Return New JsonString( "@"+inst.id )
-		Case "Enum"
-			Return New JsonNumber( value.EnumValue )
-		End
+			Return JsonValue.NullValue	'for objects that weren't added using AddInstance - should really never happen.
+'			RuntimeError( "Can't jsonify instance of type '"+type+"'" )
+		Endif
 		
 		'try custom jsonifiers
 		For Local jext:=Eachin JsonifierExt.All
 			Local jvalue:=jext.Jsonify( value,Self )
 			If jvalue Return jvalue
 		Next
-
-		Select type.Kind
-		Case "Unknown"
-			Local obj:=Cast<Object>( value )
-			If Not obj Return JsonValue.NullValue
-			Local inst:=_instsByObj[obj]
-			If inst Return New JsonString( "@"+inst.id )
-		Case "Class"
-			Return JsonValue.NullValue
-		Case "Array"
-			Local n:=value.GetArrayLength()
-			Local jarray:=New JsonArray( n )
-			For Local i:=0 Until n
-				jarray[i]=Jsonify( value.GetArrayElement( i ) )
-			Next
-			Return jarray
-		End
 		
-		RuntimeError( "TODO: No jsonifier found for type '"+type+"'" )
+		RuntimeError( "No jsonifier found for type '"+type+"'" )
 		Return Null
 	End
 	
@@ -255,23 +248,34 @@ Public
 	
 	Method Dejsonify:Variant( jvalue:JsonValue,type:TypeInfo )
 		
-		'handle primitive types
-		Select type
-		Case Typeof<Bool>
-			Return jvalue.ToBool()
-		Case Typeof<Short>
-			Return Short( jvalue.ToNumber() )
-		Case Typeof<Int>
-			Return Int( jvalue.ToNumber() )
-		Case Typeof<Float>
-			Return Float( jvalue.ToNumber() )
-		Case Typeof<String>
-			Return jvalue.ToString()
+		Select type.Kind
+		Case "Primitive"
+			Select type
+			Case Typeof<Bool>
+				Return jvalue.ToBool()
+			Case Typeof<Short>
+				Return Short( jvalue.ToNumber() )
+			Case Typeof<Int>
+				Return Int( jvalue.ToNumber() )
+			Case Typeof<Float>
+				Return Float( jvalue.ToNumber() )
+			Case Typeof<String>
+				Return jvalue.ToString()
+			End
+		Case "Array"
+			Local elemType:=type.ElementType
+			Local jarray:=Cast<JsonArray>( jvalue )
+			Local n:=jarray.Length,v:=elemType.NewArray( n )
+			For Local i:=0 Until n
+				Local elem:=Dejsonify( jarray[i],elemType )
+				v.SetArrayElement( i,elem )
+			Next
+			Return v
+		Case "Enum"
+			Return type.MakeEnum( jvalue.ToNumber() )
 		End
 		
-		'handle references
-		Select type.Kind
-		Case "Class"
+		If IsInstanceType( type )
 			If jvalue.IsNull
 				Return type.NullValue
 			Elseif jvalue.IsString
@@ -279,9 +283,7 @@ Public
 				Assert( id>=0 And id<_insts.Length,"Dejsonify error" )
 				Return _insts[id].obj
 			Endif
-		Case "Enum"
-			Return type.MakeEnum( jvalue.ToNumber() )
-		End
+		Endif
 		
 		'try custom jsonifiers
 		For Local jext:=Eachin JsonifierExt.All
@@ -289,26 +291,6 @@ Public
 			If value Return value
 		Next
 
-		Select type.Kind
-		Case "Unknown"
-			If jvalue.IsString
-				Local id:=Int( jvalue.ToString().Slice( 1 ) )
-				Assert( id>=0 And id<_insts.Length,"Dejsonify error" )
-				Return _insts[id].obj
-			Endif
-		Case "Class"
-			Return type.NullValue
-		Case "Array"
-			Local elemType:=type.ElementType
-			Local jarray:=Cast<JsonArray>( jvalue )
-			Local n:=jarray.Length,v:=elemType.NewArray( n )
-			For Local i:=0 Until n
-				Local elem:=Dejsonify( jarray[i],elemType )
-				v.SetArrayElement( i,elem )
-			Next
-			Return v
-		End
-		
 		RuntimeError( "No dejsonifier found for type '"+type+"'" )
 		
 		Return Null
@@ -343,12 +325,23 @@ Public
 		Next
 		
 	End
+	
+	Method IsInstanceType:Bool( type:TypeInfo )
+		
+		If type.Kind="Class" Return True
+		
+		If type=Typeof<Texture> Return True	'Cheeze it for now!
+		
+		If type.Kind="Array" Return IsInstanceType( type.ElementType )
+		
+		Return False
+	End
 
-	Method DejsonifyState( obj:Object,jobj:JsonObject,type:TypeInfo,insts:Bool )
+	Method DejsonifyState( obj:Object,jobj:JsonObject,type:TypeInfo,instTypes:Bool )
 		
 		If type.Kind<>"Class" Return
 		
-		If type.SuperType DejsonifyState( obj,jobj,type.SuperType,insts )
+		If type.SuperType DejsonifyState( obj,jobj,type.SuperType,instTypes )
 
 		For Local d:=Eachin type.GetDecls()
 			
@@ -358,13 +351,7 @@ Public
 			
 			If Not Int( d.GetMetaValue( "jsonify" ) ) Continue
 			
-			Local type:=d.Type
-			
-			Local isinst:=type.Kind="Class" Or type.Kind="Unknown"
-			
-			If Not isinst And type.Kind="Array" And type.ElementType.Kind="Class" isinst=True
-				
-			If isinst<>insts Continue
+			If IsInstanceType( d.Type )<>instTypes Continue
 			
 			d.Set( obj,Dejsonify( jobj.GetValue( d.Name ),d.Type ) )
 		Next

+ 99 - 33
modules/mojo3d/scene/material.monkey2

@@ -5,6 +5,18 @@ Namespace mojo3d
 #end
 Class Material Extends Resource
 	
+	enum Attrib
+		Position=1
+		Normal=2
+		Color=4
+		TexCoord0=8
+		TexCoord1=16
+		Tangent=32
+		Weights=64
+		Bones=128
+	End
+		
+	
 	#rem monkeydoc Creates a copy of the material.
 	#end
 	Method Copy:Material() abstract
@@ -20,14 +32,41 @@ Class Material Extends Resource
 		_name=name
 	End
 	
-	#Rem monkeydoc @hidden The material uniforms.
+	Property ShaderName:String()
+		
+		Return _shaderName
 	
-	TODO: Should really be protected...
+	Setter( name:String )
+		
+		If name=_shaderName Return
+		
+		_shaderName=name
+		
+		Invalidate()
+	End
+	
+	Property AttribMask:Int()
+		
+		Return _attribMask
 
-	#End
-	Property Uniforms:UniformBlock()
+	Setter( mask:Int )
+		
+		If mask=_attribMask Return
+		
+		_attribMask=mask
+		
+		Invalidate()
+	End
 	
-		Return _uniforms
+	Property SelfIlluminated:Bool()
+		
+		Return _selfillum
+	
+	Setter( selfillum:Bool )
+		
+		If selfillum=_selfillum Return
+		
+		_selfillum=selfillum
 	End
 	
 	#Rem monkeydoc The material blendmode.
@@ -93,33 +132,24 @@ Class Material Extends Resource
 		
 		TextureMatrix=TextureMatrix.Scale( sx,sy )
 	End
+	
+	#Rem monkeydoc @hidden The material uniforms.
+	
+	TODO: Should really be protected...
 
-	#rem monkeydoc Gets material's opaque shader.
-	#end
-	Method GetOpaqueShader:Shader() Virtual
+	#End
+	Property Uniforms:UniformBlock()
 	
-		Return Null
+		Return _uniforms
 	End
-	
-	#rem monkeydoc Gets material's transparent shader.
+
+	#rem monkeydoc Gets material's shader for rendering.
 	#end
-	Method GetTransparentShader:Shader() Virtual
+	Method GetRenderShader:Shader()
 		
-		Return Null
-	End
-	
-	#rem monkeydoc Gets material's sprite shader.
-	#end
-	Method GetSpriteShader:Shader() Virtual
+		Validate()
 		
-		Return GetTransparentShader()
-	End
-	
-	#rem monkeydoc Gets material's shadow shader.
-	#end
-	Method GetShadowShader:Shader() Virtual
-	
-		Return GetOpaqueShader()
+		Return _shader
 	End
 	
 	Function LoadTexture:Texture( path:String,textureFlags:TextureFlags,flipy:Bool=False )
@@ -142,21 +172,39 @@ Class Material Extends Resource
 	
 	Protected
 	
-	Method New()
+	Method OnValidate() Virtual
+	End
+	
+	Method Invalidate()
 		
-		_uniforms=New UniformBlock( 3,True )
+		_shader=Null
+	End
+	
+	Method New()
+
+		_name="Material"
+		_attribMask=1
 		_blendMode=BlendMode.Opaque
 		_cullMode=CullMode.Back
+		_selfillum=False
+
+		_uniforms=New UniformBlock( 3,True )
 		
 		TextureMatrix=New AffineMat3f
 	End		
 	
 	Method New( material:Material )
 		
-		_uniforms=New UniformBlock( material._uniforms )
-
+		_name=material._name
+		_shaderName=material._shaderName
+		_attribMask=material._attribMask
 		_blendMode=material._blendMode
 		_cullMode=material._cullMode
+		_selfillum=material._selfillum
+		_shader=material._shader
+		_dirty=material._dirty
+
+		_uniforms=New UniformBlock( material._uniforms )
 
 		TextureMatrix=material.TextureMatrix
 	End
@@ -183,10 +231,28 @@ Class Material Extends Resource
 	End
 	
 	Private
-	
+
 	Field _name:String
-	Field _uniforms:UniformBlock
-	Field _blendMode:BlendMode
+	Field _shaderName:String
+	Field _attribMask:Int
+	Field _selfillum:Bool
 	Field _cullMode:CullMode
+	Field _blendMode:BlendMode
+	Field _uniforms:UniformBlock
+	Field _shader:Shader
+	Field _dirty:Bool=True
+	
+	Method Validate()
+		
+		If _shader Return
 
+		Local defs:=Renderer.GetCurrent().ShaderDefs
+		
+		defs+=";MX2_ATTRIBMASK "+_attribMask
+		
+		Local shaderName:=_shaderName ?Else "materials/default"
+			
+		_shader=mojo.graphics.Shader.Open( shaderName,defs )
+	End
+	
 End

+ 94 - 121
modules/mojo3d/scene/materials/pbrmaterial.monkey2

@@ -1,59 +1,10 @@
 
 Namespace mojo3d
 
-Private
-
-Function MakeColor:Color( jobj:JsonObject )
-	
-	Local r:=jobj.Contains( "r" ) ? jobj.GetNumber( "r" ) Else 1.0
-	Local g:=jobj.Contains( "g" ) ? jobj.GetNumber( "g" ) Else 1.0
-	Local b:=jobj.Contains( "b" ) ? jobj.GetNumber( "b" ) Else 1.0
-	Local a:=jobj.Contains( "a" ) ? jobj.GetNumber( "a" ) Else 1.0
-	
-	Return New Color( r,g,b,a )
-End
-
-Class JsonObject Extension
-
-	Method GetColor:Color( key:String )
-		
-		Local jobj:=GetObject( key )
-		If Not jobj Return Color.White
-		
-		Return MakeColor( jobj )
-	End
-End
-
-Public
-
 #rem monkeydoc The PbrMaterial class.
 #end
 Class PbrMaterial Extends Material
 	
-	Private
-	
-	Method Init( boned:Bool )
-		
-		_boned=boned
-
-		Uniforms.DefaultTexture=Texture.ColorTexture( Color.White )
-		
-		ColorTexture=Null
-		EmissiveTexture=Null
-		MetalnessTexture=Null
-		RoughnessTexture=Null
-		OcclusionTexture=Null
-		NormalTexture=Null
-		
-		ColorFactor=Color.White
-		EmissiveFactor=Color.Black
-		MetalnessFactor=1.0
-		RoughnessFactor=1.0
-	End
-	
-	Public
-	
-	
 	#rem monkeydoc Creates a new pbr material.
 	
 	All properties default to white or '1' except for emissive factor which defaults to black. 
@@ -69,32 +20,28 @@ Class PbrMaterial Extends Material
 	The above last 3 rules allow you to pack metalness, roughness and occlusion into a single texture.
 	
 	#end
-	Method New( boned:Bool=False )
+	Method New()
 		
-		Init( boned )
+		Init()
 		
-		AddInstance( New Variant[]( boned ) )
+		AddInstance()
 	End
 	
-	Method New( color:Color,metalness:Float=1.0,roughness:Float=1.0,boned:Bool=False )
+	Method New( color:Color,metalness:Float=1.0,roughness:Float=1.0 )
 		
-		Init( boned )
+		Init()
 		
 		ColorFactor=color
 		MetalnessFactor=metalness
 		RoughnessFactor=roughness
 		
-		AddInstance( New Variant[]( color,metalness,roughness,boned ) )
+		AddInstance( New Variant[]( color,metalness,roughness ) )
 	End
 	
 	Method New( material:PbrMaterial )
 		
 		Super.New( material )
 		
-		_textured=material._textured
-		_bumpmapped=material._bumpmapped
-		_boned=material._boned
-		
 		AddInstance( material )
 	End
 	
@@ -105,22 +52,17 @@ Class PbrMaterial Extends Material
 		Return New PbrMaterial( Self )
 	End
 	
-	Method GetOpaqueShader:Shader() Override
-		
-		ValidateShaders()
-		
-		Return _opaqueShader
-	End
+	'***** textures *****
 	
-	Method GetTransparentShader:Shader() Override
+	Property Boned:Bool()
 		
-		ValidateShaders()
+		Return (AttribMask & 192)=192
 		
-		Return _transparentShader
+	Setter( boned:Bool )
+		
+		If boned AttribMask|=192 Else AttribMask&=~192
 	End
 	
-	'***** textures *****
-	
 	Property ColorTexture:Texture()
 	
 		Return Uniforms.GetTexture( "ColorTexture" )
@@ -129,7 +71,18 @@ Class PbrMaterial Extends Material
 	
 		Uniforms.SetTexture( "ColorTexture",texture )
 		
-		If (Uniforms.NumTextures<>0)<>_textured _dirty=True
+		UpdateAttribMask()
+	End
+	
+	Property AmbientTexture:Texture()
+		
+		Return Uniforms.GetTexture( "AmbientTexture" )
+	
+	Setter( texture:Texture )
+		
+		Uniforms.SetTexture( "AmbientTexture",texture )
+
+		UpdateAttribMask()
 	End
 	
 	Property EmissiveTexture:Texture()
@@ -140,7 +93,7 @@ Class PbrMaterial Extends Material
 	
 		Uniforms.SetTexture( "EmissiveTexture",texture )
 		
-		If (Uniforms.NumTextures<>0)<>_textured _dirty=True
+		UpdateAttribMask()
 	End
 	
 	Property MetalnessTexture:Texture()
@@ -151,7 +104,7 @@ Class PbrMaterial Extends Material
 	
 		Uniforms.SetTexture( "MetalnessTexture",texture )
 		
-		If (Uniforms.NumTextures<>0)<>_textured _dirty=true
+		UpdateAttribMask()
 	End
 
 	Property RoughnessTexture:Texture()
@@ -162,7 +115,7 @@ Class PbrMaterial Extends Material
 	
 		Uniforms.SetTexture( "RoughnessTexture",texture )
 		
-		If (Uniforms.NumTextures<>0)<>_textured _dirty=true
+		UpdateAttribMask()
 	End
 	
 	Property OcclusionTexture:Texture()
@@ -173,7 +126,7 @@ Class PbrMaterial Extends Material
 	
 		Uniforms.SetTexture( "OcclusionTexture",texture )
 		
-		If (Uniforms.NumTextures<>0)<>_textured _dirty=true
+		UpdateAttribMask()
 	End
 	
 	Property NormalTexture:Texture()
@@ -184,7 +137,9 @@ Class PbrMaterial Extends Material
 	
 		Uniforms.SetTexture( "NormalTexture",texture )
 		
-		If (texture<>null)<>_bumpmapped _dirty=true
+		If texture AttribMask|=32 Else AttribMask&=~32
+			
+		UpdateAttribMask()
 	End
 	
 	'***** factors *****
@@ -198,6 +153,16 @@ Class PbrMaterial Extends Material
 		Uniforms.SetColor( "ColorFactor",color )
 	End
 	
+	[jsonify=1]
+	Property AmbientFactor:Color()
+	
+		Return Uniforms.GetColor( "AmbientFactor" )
+		
+	Setter( color:Color )
+	
+		Uniforms.SetColor( "AmbientFactor",color )
+	End
+	
 	[jsonify=1]
 	Property EmissiveFactor:Color()
 	
@@ -227,7 +192,7 @@ Class PbrMaterial Extends Material
 	
 		Uniforms.SetFloat( "RoughnessFactor",factor )
 	End
-
+	
 	#rem monkeydoc Loads a PbrMaterial from a 'file'.
 	
 	A .pbr file is actually a directory containing a number of textures in png format. These textures are:
@@ -250,12 +215,18 @@ Class PbrMaterial Extends Material
 
 		Local material:=New PbrMaterial
 		
-		Local texture:=LoadTexture( path,"color",textureFlags )
+		Local texture:=scene.LoadTexture( path,textureFlags )
+		If texture
+			material.ColorTexture=texture
+			Return material
+		Endif
+		
+		texture=LoadTexture( path,"color",textureFlags )
 		If texture
 			material.ColorTexture=texture
 		Endif
 		
-		texture=LoadTexture(path,"emissive",textureFlags )
+		texture=LoadTexture( path,"emissive",textureFlags )
 		If texture
 			material.EmissiveTexture=texture
 			material.EmissiveFactor=Color.White
@@ -298,57 +269,59 @@ Class PbrMaterial Extends Material
 		Return material
 	End
 	
-	Protected
+	Private
 	
-	Field _textured:Bool
-	Field _bumpmapped:Bool
 	Field _boned:Bool
 	
-	Field _opaqueShader:Shader
-	Field _transparentShader:Shader
-	Field _shadowShader:Shader
-	
-	Field _dirty:=True
-	
-	Method ValidateShaders()
-		
-		If Not _dirty Return
-		
-		_textured=True'False
-		_bumpmapped=False
+	Method Init()
 		
-		If Uniforms.NumTextures
-			_textured=True
-			_bumpmapped=(Uniforms.GetTexture( "NormalTexture" )<>null)
-		Endif
-		
-		Local defs:=Renderer.GetCurrent().ShaderDefs
-		
-		If _textured
-			defs+="MX2_TEXTURED~n"
-			If _bumpmapped
-				defs+="MX2_BUMPMAPPED~n"
-			Endif
-		Endif
+		Uniforms.DefaultTexture=Texture.ColorTexture( Color.White )
 		
-		If _boned defs+="MX2_BONED~n"
-			
-		_transparentShader=Shader.Open( "material-pbr-forward",defs )
+		ShaderName="materials/pbr-default"
+		AttribMask=1|2|4
 		
-		If Renderer.GetCurrent().Deferred
-			
-			_opaqueShader=Shader.Open( "material-pbr-deferred",defs )
+		ColorTexture=Null
+		AmbientTexture=Null
+		EmissiveTexture=Null
+		MetalnessTexture=Null
+		RoughnessTexture=Null
+		OcclusionTexture=Null
+		NormalTexture=Null
 		
-		Else
-			
-			_opaqueShader=_transparentShader
-			
-		Endif
+		ColorFactor=Color.White
+		AmbientFactor=Color.Black
+		EmissiveFactor=Color.Black
+		MetalnessFactor=1.0
+		RoughnessFactor=1.0
+	End
+	
+	Method UpdateAttribMask()
 		
-		_shadowShader=_opaqueShader
+		If Uniforms.NumTextures<>0 AttribMask|=24 Else AttribMask&=~24
+	End
+	
+End
+
+Private
+
+Function MakeColor:Color( jobj:JsonObject )
+	
+	Local r:=jobj.Contains( "r" ) ? jobj.GetNumber( "r" ) Else 1.0
+	Local g:=jobj.Contains( "g" ) ? jobj.GetNumber( "g" ) Else 1.0
+	Local b:=jobj.Contains( "b" ) ? jobj.GetNumber( "b" ) Else 1.0
+	Local a:=jobj.Contains( "a" ) ? jobj.GetNumber( "a" ) Else 1.0
+	
+	Return New Color( r,g,b,a )
+End
+
+Class JsonObject Extension
+
+	Method GetColor:Color( key:String )
 		
-		_dirty=False
+		Local jobj:=GetObject( key )
+		If Not jobj Return Color.White
 		
+		Return MakeColor( jobj )
 	End
-	
 End
+

+ 2 - 32
modules/mojo3d/scene/materials/spritematerial.monkey2

@@ -9,12 +9,13 @@ Class SpriteMaterial Extends Material
 	#end	
 	Method New()
 		
+		ShaderName="materials/sprite"
+		AttribMask=1|8
 		BlendMode=BlendMode.Alpha
 		CullMode=CullMode.None
 		
 		ColorTexture=Texture.ColorTexture( Color.White )
 		ColorFactor=Color.White
-		
 		AlphaDiscard=.5
 		
 		AddInstance()
@@ -34,37 +35,6 @@ Class SpriteMaterial Extends Material
 		Return New SpriteMaterial( Self )
 	End
 	
-	Method GetOpaqueShader:Shader() Override
-		
-		Global _shader:Shader
-		
-		If Not _shader
-			
-			Local shader:="material-sprite"
-			
-			Local defs:=Renderer.GetCurrent().ShaderDefs
-				
-			_shader=Shader.Open( shader,defs )
-		Endif
-		
-		Return _shader
-	End
-	
-	Method GetTransparentShader:Shader() Override
-		
-		Return GetOpaqueShader()
-	End
-	
-	Method GetSpriteShader:Shader() Override
-		
-		Return GetOpaqueShader()
-	End
-	
-	Method GetShadowShader:Shader() Override
-		
-		Return GetOpaqueShader()
-	End
-	
 	[jsonify=1]
 	Property ColorTexture:Texture()
 		

+ 16 - 29
modules/mojo3d/scene/materials/watermaterial.monkey2

@@ -8,17 +8,17 @@ Class WaterMaterial Extends Material
 	#rem monkeydoc Creates a new water material.
 	#end
 	Method New()
+
+		ShaderName="materials/water"
+		AttribMask=1|4|8|32
+		BlendMode=BlendMode.Opaque
+		CullMode=CullMode.None
 		
 		ColorTexture=Texture.ColorTexture( Color.White )
 		ColorFactor=Color.SeaGreen
-		
 		Metalness=0
 		Roughness=0
-		
-		Local normal:=Texture.ColorTexture( New Color( .5,.5,1 ) )
-		
-		NormalTextures=New Texture[]( normal,normal )
-		
+		NormalTextures=New Texture[]( Texture.FlatNormal(),Texture.FlatNormal() )
 		Velocities=New Vec2f[]( New Vec2f( 0,0 ),New Vec2f( 0,0 ) )
 	End
 	
@@ -34,36 +34,22 @@ Class WaterMaterial Extends Material
 		Return New WaterMaterial( Self )
 	End
 	
-	Method GetOpaqueShader:Shader() Override
-		
-		Global _shader:=Shader.Open( "material-water" )
-		
-		Assert( _shader )
-
-		Return _shader
-	End
-	
-	Method GetShadowShader:Shader() Override
-		
-		Return Null
-	End
-	
 	Property ColorTexture:Texture()
-		
-		Return Uniforms.GetTexture( "ColorTexture" )
 	
-	Setter( texture:Texture )
+		Return Uniforms.GetTexture( "ColorTexture" )
 		
+	Setter( texture:Texture )
+	
 		Uniforms.SetTexture( "ColorTexture",texture )
 	End
-	
+
 	Property ColorFactor:Color()
-		
-		Return Uniforms.GetColor( "ColorFactor" )
 	
-	Setter( factor:Color )
+		Return Uniforms.GetColor( "ColorFactor" )
+		
+	Setter( color:Color )
 	
-		Uniforms.SetColor( "ColorFactor",factor )
+		Uniforms.SetColor( "ColorFactor",color )
 	End
 	
 	Property Metalness:Float()
@@ -89,8 +75,9 @@ Class WaterMaterial Extends Material
 		Return New Texture[]( Uniforms.GetTexture( "NormalTexture0" ),Uniforms.GetTexture( "NormalTexture1" ) )
 	
 	Setter( textures:Texture[] )
-		Assert( textures.Length=2,"NormalTextures array must havre length 2" )
+		Assert( textures.Length=2,"NormalTextures array must have length 2" )
 		
+		Uniforms.SetTexture( "NormalTexture",textures[0] )
 		Uniforms.SetTexture( "NormalTexture0",textures[0] )
 		Uniforms.SetTexture( "NormalTexture1",textures[1] )
 	End

+ 14 - 0
modules/mojo3d/scene/mesh.monkey2

@@ -514,6 +514,20 @@ Class Mesh Extends Resource
 		InvalidateVertices()
 	End
 
+	#rem monkeydoc Copies texcoord0 to texcoord1.
+	#end
+	Method CopyTexCoords()
+
+		Local vertices:=_vertices.Data
+		
+		For Local i:=0 Until _vertices.Length
+		
+			vertices[i].texCoord1=vertices[i].texCoord0
+		Next
+		
+		InvalidateVertices()
+	End
+	
 	#rem monkeydoc Loads a mesh from a file.
 	
 	On its own, mojo3d can only load gltf2 format mesh and model files.

+ 39 - 23
modules/mojo3d/scene/posteffect.monkey2

@@ -18,46 +18,58 @@ Class PostEffect
 		
 		_enabled=enabled
 	End
-
+	
+	
 	#rem monkeydoc @hidden
 	#end	
-	Method Render( device:GraphicsDevice ) Virtual
+	Method Render()
 		
-		_device=device
+		OnRender( _gdevice.RenderTarget,_gdevice.Viewport )
+	End
+	
+	Function BeginRendering( gdevice:GraphicsDevice,runiforms:UniformBlock )
+
+		_gdevice=gdevice
+		_runiforms=runiforms
+	End
+	
+	Function EndRendering()
 		
-		OnRender()
+		_gdevice=Null
+		_runiforms=Null
 	End
 
 	Protected
 	
 	#rem monkeydoc @hidden
 	#end	
-	Method OnRender() Virtual
-	End
+	Method OnRender( target:RenderTarget,viewport:Recti ) Abstract
 	
-	#rem monkeydoc @hidden
-	#end	
 	Property Device:GraphicsDevice()
 		
-		Return _device
+		Return _gdevice
 	End
 	
-	#rem monkeydoc @hidden
-	#end	
-	Property SourceRect:Recti()
+	Method CreateRenderTarget:RenderTarget( size:Vec2i,format:PixelFormat,flags:TextureFlags )
 		
-		Return _device.Viewport
+		Local texture:=New Texture( size.x,size.y,format,flags )
+		Local target:=New RenderTarget( New Texture[]( texture ),Null )
+		Return target
 	End
 	
-	#rem monkeydoc @hidden
-	#end	
-	Property SourceTexture:Texture()
+	Method SetRenderTarget( target:RenderTarget,viewport:Recti )
 		
-		Return _device.RenderTarget.GetColorTexture( 0 )
+		Local rsize:=_gdevice.Viewport.Size
+		Local rtarget:=_gdevice.RenderTarget
+		Local rtexture:=rtarget.GetColorTexture( 0 )
+		_runiforms.SetTexture( "SourceBuffer",rtexture )
+		_runiforms.SetVec2f( "SourceBufferSize",Cast<Vec2f>( rtexture.Size ) )'rsize ) )
+		_runiforms.SetVec2f( "SourceBufferScale",Cast<Vec2f>( rsize )/Cast<Vec2f>( rtexture.Size ) )
+		
+		_gdevice.RenderTarget=target
+		_gdevice.Viewport=viewport
 	End
 	
-	#rem monkeydoc @hidden
-	#end	
 	Method RenderQuad()
 
 		Global _vertices:VertexBuffer
@@ -70,13 +82,17 @@ Class PostEffect
 			New Vertex3f( 0,0,0 ) ) )
 		Endif
 			
-		_device.VertexBuffer=_vertices
-		_device.Render( 4,1 )
-	End
+		_gdevice.VertexBuffer=_vertices
 		
+		_gdevice.Render( 4,1 )
+	End
+	
+	#rem monkeydoc @hidden
+	#end	
 	Private
 	
-	Global _device:GraphicsDevice
+	Global _gdevice:GraphicsDevice
+	Global _runiforms:UniformBlock
 	
 	Field _enabled:Bool=True
 	

+ 2 - 5
modules/mojo3d/scene/scene.monkey2

@@ -14,7 +14,7 @@ Class Scene
 		
 		If Not _current _current=Self
 			
-		_editable=editable
+		_editable=editable And TypeInfo.GetType( "mojo3d.Scene" )<>Null
 		
 		_clearColor=Color.Sky
 
@@ -25,13 +25,10 @@ Class Scene
 		_world=New World( Self )
 		
 		If _editable
-			Local type:=TypeInfo.GetType( "mojo3d.Scene" )
-			Assert( type And type.Kind="Class","mojo3d reflection must be enabled for editable scenes" )
 			_jsonifier=New Jsonifier
 			_jsonifier.AddInstance( Self,New Variant[]( true ) )
 			_editing=True
 		Endif
-		
 	End
 	
 	Property World:World()
@@ -313,7 +310,7 @@ Class Scene
 		Return _jsonifier
 	End
 	
-	Method LoadTexture:Texture( path:String,flags:TextureFlags,flipNormalY:Bool=False )
+	Method LoadTexture:Texture( path:String,flags:TextureFlags=TextureFlags.FilterMipmap,flipNormalY:Bool=False )
 		
 		Local texture:=Texture.Load( path,flags,flipNormalY )
 		If Not texture Return Null

+ 3 - 4
modules/mojo3d/scene/world.monkey2

@@ -91,7 +91,7 @@ Class World
 		
 		resetCollisions()
 		
-		_btworld.stepSimulation( elapsed )',_scene.MaxSubSteps,1.0/_scene.UpdateRate )
+		_btworld.stepSimulation( elapsed,_scene.MaxSubSteps,1.0/_scene.UpdateRate )
 		
 		Local n:=getNumCollisions()
 		
@@ -116,7 +116,6 @@ Class World
 		Next
 		
 		resetCollisions()
-		
 	End
 	
 	Property btWorld:btDynamicsWorld()
@@ -136,6 +135,8 @@ Class World
 		
 		btbody.setUserPointer( Cast<Void Ptr>( body ) )
 		
+'		btbody.setWorldTransform( body.Entity.Matrix )
+		
 		_btworld.addRigidBody( btbody,body.CollisionGroup,body.CollisionMask )
 	End
 	
@@ -158,8 +159,6 @@ Class World
 	
 	Field _btworld:btDynamicsWorld
 	
-	Field _newBodies:=New Stack<RigidBody>
-	
 	Field _bodies:=New Stack<RigidBody>
 
 End

+ 2 - 4
modules/mojo3d/tests/alphacubes.monkey2

@@ -22,8 +22,6 @@ Class MyWindow Extends Window
 
 		Super.New( title,width,height,flags )
 		
-		SetConfig( "MOJO3D_RENDERER","forward" )
-
 		'create scene
 		'		
 		_scene=New Scene
@@ -70,9 +68,9 @@ Class MyWindow Extends Window
 		
 		_scene.Update()
 		
-		_camera.Render( canvas )
+		_scene.Render( canvas )
 		
-		canvas.DrawText( "FPS="+App.FPS,Width,0,1,0 )
+		canvas.DrawText( "FPS="+App.FPS,0,0 )
 	End
 	
 End

+ 0 - 86
modules/mojo3d/tests/anisotropic.monkey2

@@ -1,86 +0,0 @@
-
-Namespace myapp
-
-#Import "<std>"
-#Import "<mojo>"
-#Import "<mojo3d>"
-
-#Import "assets/"
-
-Using std..
-Using mojo..
-Using mojo3d..
-
-Const MaxAnisotropy:=16
-			
-Class MyWindow Extends Window
-	
-	Field _scene:Scene
-	
-	Field _camera:Camera
-	
-	Field _ground:Model
-	
-	Method New( title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=WindowFlags.Resizable )
-
-		Super.New( title,width,height,flags )
-		
-		SetConfig( "MOJO_TEXTURE_MAX_ANISOTROPY",MaxAnisotropy )
-		
-		'create scene
-		'		
-		_scene=New Scene
-		
-		'for a totally 'black' scene
-		_scene.ClearColor=Color.Black		'clears screen to black
-		_scene.AmbientLight=Color.Black		'disables all ambient light
-		_scene.EnvColor=Color.Black			'disables all environmental reflections
-
-		'create camera
-		'
-		_camera=New Camera( Self )
-		_camera.Move( 0,2,0 )
-		New FlyBehaviour( _camera )
-
-		'createa simple 'grid' texture
-		'
-		Local pixmap:=New Pixmap( 16,16 )
-		pixmap.Clear( Color.Black )
-		For Local i:=0 Until 16
-			pixmap.SetPixelARGB( i,0,~0 )
-			pixmap.SetPixelARGB( 0,i,~0 )
-		Next
-		Local texture:=New Texture( pixmap,TextureFlags.FilterMipmap|TextureFlags.WrapST )
-		
-		'create material
-		'
-		Local material:=New PbrMaterial( Color.Black )
-		material.EmissiveTexture=texture
-		material.EmissiveFactor=Color.Red
-
-		material.ScaleTextureMatrix( 500,500 )
-		
-		'create ground
-		'		
-		_ground=Model.CreateBox( New Boxf( -500,-1,-500,500,0,500 ),10,10,10,material )
-	End
-	
-	Method OnRender( canvas:Canvas ) Override
-		
-		RequestRender()
-		
-		_scene.Update()
-		
-		_scene.Render( canvas )
-	End
-	
-End
-
-Function Main()
-	
-	New AppInstance
-	
-	New MyWindow
-	
-	App.Run()
-End

BIN
modules/mojo3d/tests/assets/Monkey2logo_64.png


BIN
modules/mojo3d/tests/assets/bluspark.png


BIN
modules/mojo3d/tests/assets/bouncyball/bouncyball.bin


+ 0 - 589
modules/mojo3d/tests/assets/bouncyball/bouncyball.gltf

@@ -1,589 +0,0 @@
-{
-  "accessors": [
-    {
-      "bufferView": 0,
-      "byteOffset": 0,
-      "componentType": 5126,
-      "count": 50,
-      "max": [
-        0.129409536719322,
-        0.5,
-        0.129409536719322
-      ],
-      "min": [
-        -0.129409536719322,
-        -0.5,
-        -0.129409536719322
-      ],
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 0,
-      "byteOffset": 600,
-      "componentType": 5126,
-      "count": 50,
-      "max": [
-        0.268908590078354,
-        1,
-        0.268908590078354
-      ],
-      "min": [
-        -0.268908590078354,
-        -1,
-        -0.268908560276031
-      ],
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 0,
-      "componentType": 5123,
-      "count": 144,
-      "max": [
-        49
-      ],
-      "min": [
-        0
-      ],
-      "type": "SCALAR"
-    },
-    {
-      "bufferView": 0,
-      "byteOffset": 1200,
-      "componentType": 5126,
-      "count": 204,
-      "max": [
-        0.5,
-        0.482962906360626,
-        0.5
-      ],
-      "min": [
-        -0.5,
-        -0.482962906360626,
-        -0.5
-      ],
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 0,
-      "byteOffset": 3648,
-      "componentType": 5126,
-      "count": 204,
-      "max": [
-        0.999999940395355,
-        0.963165760040283,
-        0.999999940395355
-      ],
-      "min": [
-        -1,
-        -0.963165700435638,
-        -1
-      ],
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 288,
-      "componentType": 5123,
-      "count": 720,
-      "max": [
-        203
-      ],
-      "min": [
-        0
-      ],
-      "type": "SCALAR"
-    },
-    {
-      "bufferView": 0,
-      "byteOffset": 6096,
-      "componentType": 5126,
-      "count": 204,
-      "max": [
-        0.5,
-        0.482962906360626,
-        0.5
-      ],
-      "min": [
-        -0.5,
-        -0.482962906360626,
-        -0.5
-      ],
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 0,
-      "byteOffset": 8544,
-      "componentType": 5126,
-      "count": 204,
-      "max": [
-        0.999999940395355,
-        0.963165760040283,
-        0.999999940395355
-      ],
-      "min": [
-        -1,
-        -0.963165760040283,
-        -1
-      ],
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 1728,
-      "componentType": 5123,
-      "count": 720,
-      "max": [
-        203
-      ],
-      "min": [
-        0
-      ],
-      "type": "SCALAR"
-    },
-    {
-      "bufferView": 1,
-      "byteOffset": 0,
-      "componentType": 5126,
-      "count": 20,
-      "max": [
-        0.9916666666666667
-      ],
-      "min": [
-        0.041666666666666664
-      ],
-      "type": "SCALAR"
-    },
-    {
-      "bufferView": 1,
-      "byteOffset": 80,
-      "componentType": 5126,
-      "count": 20,
-      "max": [
-        0,
-        2.7406444549560547,
-        0
-      ],
-      "min": [
-        0,
-        0.2996174097061157,
-        0
-      ],
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 1,
-      "byteOffset": 320,
-      "componentType": 5126,
-      "count": 20,
-      "max": [
-        1.3701729774475098,
-        1.5768864154815674,
-        1.3701729774475098
-      ],
-      "min": [
-        0.7761592268943787,
-        0.61479252576828,
-        0.7761592268943787
-      ],
-      "type": "VEC3"
-    }
-  ],
-  "animations": [
-    {
-      "channels": [
-        {
-          "sampler": 0,
-          "target": {
-            "node": 0,
-            "path": "scale"
-          }
-        },
-        {
-          "sampler": 1,
-          "target": {
-            "node": 0,
-            "path": "translation"
-          }
-        }
-      ],
-      "name": "Main",
-      "samplers": [
-        {
-          "input": 9,
-          "interpolation": "LINEAR",
-          "output": 11
-        },
-        {
-          "input": 9,
-          "interpolation": "LINEAR",
-          "output": 10
-        }
-      ]
-    }
-  ],
-  "asset": {
-    "generator": "qtek fbx2gltf",
-    "version": "2.0"
-  },
-  "bufferViews": [
-    {
-      "buffer": 0,
-      "byteLength": 10992,
-      "byteOffset": 0,
-      "target": 34962
-    },
-    {
-      "buffer": 0,
-      "byteLength": 560,
-      "byteOffset": 10992,
-      "target": 34962
-    },
-    {
-      "buffer": 0,
-      "byteLength": 3168,
-      "byteOffset": 11552,
-      "target": 34963
-    }
-  ],
-  "buffers": [
-    {
-      "byteLength": 14720,
-      "uri": "bouncyball.bin"
-    }
-  ],
-  "materials": [
-    {
-      "name": "Blue",
-      "emissiveFactor": [
-        0,
-        0,
-        0
-      ],
-      "pbrMetallicRoughness": {
-        "baseColorFactor": [
-          0,
-          0.0392156862745098,
-          0.9019607843137255,
-          1
-        ],
-        "metallicFactor": 0,
-        "roughnessFactor": 0.8213901449934544
-      }
-    },
-    {
-      "name": "Yellow",
-      "emissiveFactor": [
-        0,
-        0,
-        0
-      ],
-      "pbrMetallicRoughness": {
-        "baseColorFactor": [
-          0.9019607843137255,
-          0.9019607843137255,
-          0,
-          1
-        ],
-        "metallicFactor": 0,
-        "roughnessFactor": 0.8213901449934544
-      }
-    },
-    {
-      "name": "Red",
-      "emissiveFactor": [
-        0,
-        0,
-        0
-      ],
-      "pbrMetallicRoughness": {
-        "baseColorFactor": [
-          0.9019607843137255,
-          0,
-          0,
-          1
-        ],
-        "metallicFactor": 0,
-        "roughnessFactor": 0.8213901449934544
-      }
-    }
-  ],
-  "meshes": [
-    {
-      "name": "sphere_object1_Material0",
-      "primitives": [
-        {
-          "attributes": {
-            "NORMAL": 1,
-            "POSITION": 0
-          },
-          "indices": 2,
-          "material": 0
-        },
-        {
-          "attributes": {
-            "NORMAL": 4,
-            "POSITION": 3
-          },
-          "indices": 5,
-          "material": 1
-        },
-        {
-          "attributes": {
-            "NORMAL": 7,
-            "POSITION": 6
-          },
-          "indices": 8,
-          "material": 2
-        }
-      ]
-    }
-  ],
-  "nodes": [
-    {
-      "matrix": [
-        1.3701729774475098,
-        0,
-        0,
-        0,
-        0,
-        0.61479252576828,
-        0,
-        0,
-        0,
-        0,
-        1.3701729774475098,
-        0,
-        0,
-        0.2996174097061157,
-        0,
-        1
-      ],
-      "mesh": 0,
-      "name": "sphere_object1"
-    }
-  ],
-  "scene": 0,
-  "scenes": [
-    {
-      "nodes": [
-        0
-      ]
-    }
-  ],
-  "extras": {
-    "qtekModelViewerConfig": {
-      "preZ": true,
-      "materials": [
-        {
-          "name": "Blue",
-          "color": "#000ae6",
-          "emission": "#000000",
-          "alpha": 1,
-          "alphaCutoff": 0,
-          "emissionIntensity": 1,
-          "uvRepeat": {
-            "0": 1,
-            "1": 1
-          },
-          "parallaxOcclusionScale": 0.02,
-          "diffuseMap": "",
-          "normalMap": "",
-          "parallaxOcclusionMap": "",
-          "emissiveMap": "",
-          "metalness": 0,
-          "roughness": 0.8213901449934544,
-          "metalnessMap": "",
-          "roughnessMap": "",
-          "type": "pbrMetallicRoughness",
-          "targetMeshes": [
-            "sphere_object1_Material0"
-          ]
-        },
-        {
-          "name": "Yellow",
-          "color": "#e6e600",
-          "emission": "#000000",
-          "alpha": 1,
-          "alphaCutoff": 0,
-          "emissionIntensity": 1,
-          "uvRepeat": {
-            "0": 1,
-            "1": 1
-          },
-          "parallaxOcclusionScale": 0.02,
-          "diffuseMap": "",
-          "normalMap": "",
-          "parallaxOcclusionMap": "",
-          "emissiveMap": "",
-          "metalness": 0,
-          "roughness": 0.8213901449934544,
-          "metalnessMap": "",
-          "roughnessMap": "",
-          "type": "pbrMetallicRoughness",
-          "targetMeshes": [
-            "sphere_object1_Material0$1"
-          ]
-        },
-        {
-          "name": "Red",
-          "color": "#e60000",
-          "emission": "#000000",
-          "alpha": 1,
-          "alphaCutoff": 0,
-          "emissionIntensity": 1,
-          "uvRepeat": {
-            "0": 1,
-            "1": 1
-          },
-          "parallaxOcclusionScale": 0.02,
-          "diffuseMap": "",
-          "normalMap": "",
-          "parallaxOcclusionMap": "",
-          "emissiveMap": "",
-          "metalness": 0,
-          "roughness": 0.8213901449934544,
-          "metalnessMap": "",
-          "roughnessMap": "",
-          "type": "pbrMetallicRoughness",
-          "targetMeshes": [
-            "sphere_object1_Material0$2"
-          ]
-        }
-      ],
-      "takes": [],
-      "textureFlipY": false,
-      "zUpToYUp": false,
-      "shadow": true,
-      "environment": "auto",
-      "viewControl": {
-        "center": [
-          1.0690909624099731,
-          -1.1321967840194702,
-          0.9232351183891296
-        ],
-        "alpha": 10.229259828771838,
-        "beta": 33.79452028477864,
-        "distance": 47.03251490338545
-      },
-      "ground": {
-        "show": true
-      },
-      "mainLight": {
-        "shadow": true,
-        "shadowQuality": "medium",
-        "intensity": 0.8,
-        "color": "#fff",
-        "alpha": 45,
-        "beta": 45,
-        "$padAngle": [
-          0.25,
-          0.5
-        ]
-      },
-      "secondaryLight": {
-        "shadow": false,
-        "shadowQuality": "medium",
-        "intensity": 0,
-        "color": "#fff",
-        "alpha": 60,
-        "beta": -50,
-        "$padAngle": [
-          -0.2777777777777778,
-          0.6666666666666666
-        ]
-      },
-      "tertiaryLight": {
-        "shadow": false,
-        "shadowQuality": "medium",
-        "intensity": 0,
-        "color": "#fff",
-        "alpha": 89,
-        "beta": 0,
-        "$padAngle": [
-          0,
-          0.9888888888888889
-        ]
-      },
-      "ambientLight": {
-        "intensity": 0,
-        "color": "#fff"
-      },
-      "ambientCubemapLight": {
-        "texture": "./asset/texture/Barce_Rooftop_C.hdr",
-        "$texture": "Barce_Rooftop_C",
-        "$textureOptions": [
-          "pisa",
-          "Barce_Rooftop_C",
-          "Factory_Catwalk",
-          "Grand_Canyon_C",
-          "Ice_Lake",
-          "Hall",
-          "Old_Industrial_Hall"
-        ],
-        "exposure": 3,
-        "diffuseIntensity": 0.2,
-        "specularIntensity": 0.2,
-        "$intensity": 0.2
-      },
-      "postEffect": {
-        "enable": true,
-        "bloom": {
-          "enable": true,
-          "intensity": 0.1
-        },
-        "depthOfField": {
-          "enable": false,
-          "focalDistance": 4,
-          "focalRange": 1,
-          "blurRadius": 5,
-          "fstop": 10,
-          "quality": "medium",
-          "$qualityOptions": [
-            "low",
-            "medium",
-            "high",
-            "ultra"
-          ]
-        },
-        "screenSpaceAmbientOcclusion": {
-          "enable": false,
-          "radius": 1.5,
-          "quality": "medium",
-          "intensity": 1,
-          "$qualityOptions": [
-            "low",
-            "medium",
-            "high",
-            "ultra"
-          ]
-        },
-        "screenSpaceReflection": {
-          "enable": false,
-          "quality": "medium",
-          "maxRoughness": 0.8,
-          "$qualityOptions": [
-            "low",
-            "medium",
-            "high",
-            "ultra"
-          ]
-        },
-        "colorCorrection": {
-          "enable": true,
-          "exposure": 0,
-          "brightness": 0,
-          "contrast": 1,
-          "saturation": 1,
-          "lookupTexture": ""
-        },
-        "FXAA": {
-          "enable": false
-        }
-      }
-    }
-  },
-  "extensionsUsed": [
-    "KHR_materials_pbrSpecularGlossiness"
-  ]
-}

BIN
modules/mojo3d/tests/assets/heightmap_256.BMP


BIN
modules/mojo3d/tests/assets/monkey2-logo.png


+ 0 - 1
modules/mojo3d/tests/assets/mossy-ground1.pbr/About these PBR files.txt

@@ -1 +0,0 @@
-These texture files were created by FreePBR.com and may be used freely in your video games and 3d work at no cost. They may not however be redistributed on other websites or anywhere else other than FreePBR.com. We think that is more than fair. :) We also would greatly appreciate it if some sorrt of credit was given if you do indeed use these textures in a published game. Other than that, keep on creating and have fun. :)

BIN
modules/mojo3d/tests/assets/mossy-ground1.pbr/color.png


BIN
modules/mojo3d/tests/assets/mossy-ground1.pbr/height.png


BIN
modules/mojo3d/tests/assets/mossy-ground1.pbr/metalness.png


BIN
modules/mojo3d/tests/assets/mossy-ground1.pbr/normal.png


BIN
modules/mojo3d/tests/assets/mossy-ground1.pbr/occlusion.png


BIN
modules/mojo3d/tests/assets/mossy-ground1.pbr/roughness.png


BIN
modules/mojo3d/tests/assets/mossy.pbr/color.png


BIN
modules/mojo3d/tests/assets/mossy.pbr/normal.png


BIN
modules/mojo3d/tests/assets/mossy.pbr/occlusion.png


BIN
modules/mojo3d/tests/assets/platform.glb


BIN
modules/mojo3d/tests/assets/terrain_256.png


BIN
modules/mojo3d/tests/assets/walker/walk.bin


+ 0 - 2470
modules/mojo3d/tests/assets/walker/walk.gltf

@@ -1,2470 +0,0 @@
-{
-  "accessors": [
-    {
-      "bufferView": 0,
-      "byteOffset": 0,
-      "componentType": 5126,
-      "count": 956,
-      "max": [
-        0.307114273309708,
-        1.88036692142487,
-        0.301835179328918
-      ],
-      "min": [
-        -0.307114273309708,
-        0.00452733971178532,
-        -0.307114273309708
-      ],
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 0,
-      "byteOffset": 11472,
-      "componentType": 5126,
-      "count": 956,
-      "max": [
-        0.125,
-        0.375
-      ],
-      "min": [
-        0.125,
-        0.375
-      ],
-      "type": "VEC2"
-    },
-    {
-      "bufferView": 0,
-      "byteOffset": 19120,
-      "componentType": 5123,
-      "count": 956,
-      "max": [
-        12,
-        12,
-        11,
-        10
-      ],
-      "min": [
-        0,
-        0,
-        0,
-        0
-      ],
-      "type": "VEC4"
-    },
-    {
-      "bufferView": 0,
-      "byteOffset": 26768,
-      "componentType": 5126,
-      "count": 956,
-      "max": [
-        1,
-        0.916199564933777,
-        0.843633890151978,
-        0.322161793708801
-      ],
-      "min": [
-        0.0000332839408656582,
-        0,
-        0,
-        0
-      ],
-      "type": "VEC4"
-    },
-    {
-      "bufferView": 3,
-      "byteOffset": 0,
-      "componentType": 5123,
-      "count": 4320,
-      "max": [
-        955
-      ],
-      "min": [
-        0
-      ],
-      "type": "SCALAR"
-    },
-    {
-      "bufferView": 0,
-      "byteOffset": 42064,
-      "componentType": 5126,
-      "count": 59,
-      "max": [
-        0.297124952077866,
-        1.87145125865936,
-        0.291844874620438
-      ],
-      "min": [
-        -0.297124952077866,
-        0.00624265894293785,
-        -0.297124952077866
-      ],
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 0,
-      "byteOffset": 42772,
-      "componentType": 5126,
-      "count": 59,
-      "max": [
-        0.125,
-        0.125
-      ],
-      "min": [
-        0.125,
-        0.125
-      ],
-      "type": "VEC2"
-    },
-    {
-      "bufferView": 0,
-      "byteOffset": 43244,
-      "componentType": 5123,
-      "count": 59,
-      "max": [
-        12,
-        12,
-        11,
-        10
-      ],
-      "min": [
-        0,
-        0,
-        0,
-        0
-      ],
-      "type": "VEC4"
-    },
-    {
-      "bufferView": 0,
-      "byteOffset": 43716,
-      "componentType": 5126,
-      "count": 59,
-      "max": [
-        1,
-        0.862461030483246,
-        0.787990570068359,
-        0.279946267604828
-      ],
-      "min": [
-        0.00219220668077469,
-        0,
-        0,
-        0
-      ],
-      "type": "VEC4"
-    },
-    {
-      "bufferView": 3,
-      "byteOffset": 8640,
-      "componentType": 5123,
-      "count": 312,
-      "max": [
-        58
-      ],
-      "min": [
-        0
-      ],
-      "type": "SCALAR"
-    },
-    {
-      "bufferView": 1,
-      "byteOffset": 0,
-      "componentType": 5126,
-      "count": 13,
-      "max": [
-        0.7071069616676381,
-        0.7065039792525689,
-        0.18352295839579968,
-        0,
-        1.297598889720983e-36,
-        0.2595406240953048,
-        0.9991472703742983,
-        0,
-        1.00000001242492,
-        0.7065039938963843,
-        0.18352292110010368,
-        0,
-        2.3755418781675774e-7,
-        -5.071771698169818e-15,
-        1.60000004629283,
-        1
-      ],
-      "min": [
-        -0.7071069801562327,
-        -0.9999999688522121,
-        -0.18352298509004772,
-        0,
-        -1.0288886087161426e-7,
-        -0.08012979196722309,
-        -1.00000002106023,
-        0,
-        -0.7071069937475054,
-        -0.7065039378907493,
-        -0.18352295945499197,
-        0,
-        -5.58189149511033e-15,
-        -0.5467795687954656,
-        -1.5979803382428897,
-        1
-      ],
-      "type": "MAT4"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 0,
-      "componentType": 5126,
-      "count": 28,
-      "max": [
-        1.4416666666666669
-      ],
-      "min": [
-        0.041666666666666664
-      ],
-      "type": "SCALAR"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 112,
-      "componentType": 5126,
-      "count": 28,
-      "max": [
-        0.3787504732608795,
-        0.059866804629564285,
-        -0.19540420174598694
-      ],
-      "min": [
-        0.10466296225786209,
-        1.066356958290271e-8,
-        -0.19540420174598694
-      ],
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 448,
-      "componentType": 5126,
-      "count": 28,
-      "max": [
-        0,
-        0,
-        0,
-        1
-      ],
-      "min": [
-        0,
-        0,
-        0,
-        1
-      ],
-      "type": "VEC4"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 896,
-      "componentType": 5126,
-      "count": 28,
-      "max": [
-        1,
-        1,
-        1
-      ],
-      "min": [
-        1,
-        1,
-        1
-      ],
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 1232,
-      "componentType": 5126,
-      "count": 29,
-      "max": [
-        1.4416666666666669
-      ],
-      "min": [
-        0.041666666666666664
-      ],
-      "type": "SCALAR"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 1348,
-      "componentType": 5126,
-      "count": 29,
-      "max": [
-        0.10212353616952896,
-        0.05983922630548477,
-        -0.19540409743785858
-      ],
-      "min": [
-        -0.17865866422653198,
-        1.066356958290271e-8,
-        -0.19540409743785858
-      ],
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 1696,
-      "componentType": 5126,
-      "count": 29,
-      "max": [
-        0,
-        0,
-        0,
-        1
-      ],
-      "min": [
-        0,
-        0,
-        0,
-        1
-      ],
-      "type": "VEC4"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 2160,
-      "componentType": 5126,
-      "count": 29,
-      "max": [
-        1,
-        1,
-        1
-      ],
-      "min": [
-        1,
-        1,
-        1
-      ],
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 2508,
-      "componentType": 5126,
-      "count": 29,
-      "max": [
-        0.10212364047765732,
-        0.06039157137274742,
-        0.08743858337402344
-      ],
-      "min": [
-        -0.17833927273750305,
-        1.066356958290271e-8,
-        0.08743858337402344
-      ],
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 2856,
-      "componentType": 5126,
-      "count": 29,
-      "max": [
-        0,
-        0,
-        0,
-        1
-      ],
-      "min": [
-        0,
-        0,
-        0,
-        1
-      ],
-      "type": "VEC4"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 3320,
-      "componentType": 5126,
-      "count": 29,
-      "max": [
-        1,
-        1,
-        1
-      ],
-      "min": [
-        1,
-        1,
-        1
-      ],
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 3668,
-      "componentType": 5126,
-      "count": 29,
-      "max": [
-        0.3882029056549072,
-        0.059866804629564285,
-        0.08743848651647568
-      ],
-      "min": [
-        0.10466305911540985,
-        1.066356958290271e-8,
-        0.08743848651647568
-      ],
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 4016,
-      "componentType": 5126,
-      "count": 29,
-      "max": [
-        0,
-        0,
-        0,
-        1
-      ],
-      "min": [
-        0,
-        0,
-        0,
-        1
-      ],
-      "type": "VEC4"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 4480,
-      "componentType": 5126,
-      "count": 29,
-      "max": [
-        1,
-        1,
-        1
-      ],
-      "min": [
-        1,
-        1,
-        1
-      ],
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 4828,
-      "componentType": 5126,
-      "count": 29,
-      "max": [
-        0,
-        1.7387977838516235,
-        0.03374987840652466
-      ],
-      "min": [
-        0,
-        1.71110200881958,
-        -0.0334467813372612
-      ],
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 5176,
-      "componentType": 5126,
-      "count": 29,
-      "max": [
-        0.0256829595709123,
-        0.0005007423353603812,
-        0.00049700447537215,
-        0.9999997557907885
-      ],
-      "min": [
-        -0.01785916289340164,
-        0.00047956127536375424,
-        0.0004756569971589696,
-        0.9996698998145406
-      ],
-      "type": "VEC4"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 5640,
-      "componentType": 5126,
-      "count": 29,
-      "max": [
-        1.0000000000000002,
-        1.0000000000000002,
-        1.0000000000000002
-      ],
-      "min": [
-        0.9999999999999999,
-        0.9999999999999998,
-        0.9999999999999998
-      ],
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 5988,
-      "componentType": 5126,
-      "count": 2,
-      "max": [
-        1.4416666666666669
-      ],
-      "min": [
-        0.041666666666666664
-      ],
-      "type": "SCALAR"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 5996,
-      "componentType": 5126,
-      "count": 2,
-      "max": [
-        0.08011647313833238,
-        -0.06073546037077904,
-        0.08011647313833237
-      ],
-      "min": [
-        0.08011647313833235,
-        -0.06073546037077904,
-        0.08011647313833237
-      ],
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 6020,
-      "componentType": 5126,
-      "count": 2,
-      "max": [
-        3.75530232012281e-18,
-        -0.38268343236508967,
-        9.066101792051642e-18,
-        0.9238795325112868
-      ],
-      "min": [
-        -9.388255800307029e-19,
-        -0.38268343236508967,
-        -2.266525448012911e-18,
-        0.9238795325112868
-      ],
-      "type": "VEC4"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 6052,
-      "componentType": 5126,
-      "count": 2,
-      "max": [
-        1.0000000000000002,
-        1,
-        1.0000000000000002
-      ],
-      "min": [
-        0.9999999999999999,
-        1,
-        0.9999999999999999
-      ],
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 6076,
-      "componentType": 5126,
-      "count": 29,
-      "max": [
-        1.4333333333333336
-      ],
-      "min": [
-        0.03333333333333333
-      ],
-      "type": "SCALAR"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 6192,
-      "componentType": 5126,
-      "count": 29,
-      "max": [
-        -0.34327567463483477,
-        -0.5646079643917237,
-        -0.3825899012579683,
-        0.6209772332146184
-      ],
-      "min": [
-        -0.3963100561429893,
-        -0.5940892308030855,
-        -0.42289289031820115,
-        0.5858613604175246
-      ],
-      "type": "VEC4"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 6656,
-      "componentType": 5126,
-      "count": 28,
-      "max": [
-        1.4500000000000002
-      ],
-      "min": [
-        0.1
-      ],
-      "type": "SCALAR"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 6768,
-      "componentType": 5126,
-      "count": 28,
-      "max": [
-        -0.11154751992319904,
-        -2.227614974576578e-9,
-        -9.924262985301493e-9,
-        0.9937591009892606
-      ],
-      "min": [
-        -0.19375562757825307,
-        -3.0630453960360002e-9,
-        -1.0144504604253384e-8,
-        0.9810498238019093
-      ],
-      "type": "VEC4"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 7216,
-      "componentType": 5126,
-      "count": 28,
-      "max": [
-        -0.061867483469879365,
-        6.7151424641743684e-9,
-        -5.561533723753888e-9,
-        0.9980843724300587
-      ],
-      "min": [
-        -0.17346961800430458,
-        6.048687328187861e-9,
-        -6.2799025750352286e-9,
-        0.9848392212079292
-      ],
-      "type": "VEC4"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 7664,
-      "componentType": 5126,
-      "count": 2,
-      "max": [
-        -0.08011647313833237,
-        -0.060735460370778815,
-        0.08011647313833237
-      ],
-      "min": [
-        -0.08011647313833238,
-        -0.06073546037077904,
-        0.08011647313833237
-      ],
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 7688,
-      "componentType": 5126,
-      "count": 2,
-      "max": [
-        8.000390764101652e-17,
-        0.9238795325112867,
-        8.000390764101652e-17,
-        -0.3826834323650898
-      ],
-      "min": [
-        -3.3138703587753536e-17,
-        0.9238795325112867,
-        3.3138703587753536e-17,
-        -0.3826834323650898
-      ],
-      "type": "VEC4"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 7720,
-      "componentType": 5126,
-      "count": 2,
-      "max": [
-        1.0000000000000002,
-        1,
-        1.0000000000000002
-      ],
-      "min": [
-        0.9999999999999999,
-        1,
-        0.9999999999999999
-      ],
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 7744,
-      "componentType": 5126,
-      "count": 29,
-      "max": [
-        -0.35032506818952497,
-        -0.5181793742259639,
-        -0.34669574095674915,
-        0.6143522840977433
-      ],
-      "min": [
-        -0.43733678030753825,
-        -0.6164970852371117,
-        -0.48079020248750415,
-        0.5548516194390245
-      ],
-      "type": "VEC4"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 8208,
-      "componentType": 5126,
-      "count": 29,
-      "max": [
-        -0.1179497210369631,
-        7.2960567370699746e-9,
-        -1.1566850091859941e-8,
-        0.9930195684412783
-      ],
-      "min": [
-        -0.2182250838808589,
-        6.083173761707528e-9,
-        -1.2248243155057646e-8,
-        0.9758984643728014
-      ],
-      "type": "VEC4"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 8672,
-      "componentType": 5126,
-      "count": 29,
-      "max": [
-        -0.06883043527648022,
-        4.375810562473946e-8,
-        -9.039760573008193e-9,
-        0.9976283732831821
-      ],
-      "min": [
-        -0.2104509740317789,
-        4.202087980935973e-8,
-        -1.5189955259001044e-8,
-        0.9776044125969735
-      ],
-      "type": "VEC4"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 9136,
-      "componentType": 5126,
-      "count": 2,
-      "max": [
-        -0.08011647313833237,
-        -0.060735460370778815,
-        -0.08011647313833237
-      ],
-      "min": [
-        -0.08011647313833238,
-        -0.06073546037077926,
-        -0.08011647313833238
-      ],
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 9160,
-      "componentType": 5126,
-      "count": 2,
-      "max": [
-        3.3138703587753536e-17,
-        0.9238795325112868,
-        8.000390764101651e-17,
-        0.38268343236508967
-      ],
-      "min": [
-        -8.000390764101651e-17,
-        0.9238795325112868,
-        3.3138703587753536e-17,
-        0.3826834323650896
-      ],
-      "type": "VEC4"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 9192,
-      "componentType": 5126,
-      "count": 2,
-      "max": [
-        1.0000000000000004,
-        1,
-        1.0000000000000007
-      ],
-      "min": [
-        1,
-        1,
-        1
-      ],
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 9216,
-      "componentType": 5126,
-      "count": 29,
-      "max": [
-        -0.343444731652475,
-        -0.5558793258000364,
-        -0.3259296294201151,
-        0.617500033375863
-      ],
-      "min": [
-        -0.4900495809040575,
-        -0.6284700585352242,
-        -0.43653592424678644,
-        0.50871679025711
-      ],
-      "type": "VEC4"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 9680,
-      "componentType": 5126,
-      "count": 29,
-      "max": [
-        -0.10349640764329562,
-        2.0664895611674537e-10,
-        -1.0346681992879392e-8,
-        0.9946298274257276
-      ],
-      "min": [
-        -0.21569876964838308,
-        -9.737863953382407e-10,
-        -1.0392400893684155e-8,
-        0.9764599534912702
-      ],
-      "type": "VEC4"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 10144,
-      "componentType": 5126,
-      "count": 29,
-      "max": [
-        -0.050364139529761466,
-        1.640184618372893e-8,
-        -5.5468564316988404e-9,
-        0.9987309214445232
-      ],
-      "min": [
-        -0.20636874025867186,
-        1.5328995765290026e-8,
-        -8.050469704393677e-9,
-        0.9784742935019032
-      ],
-      "type": "VEC4"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 10608,
-      "componentType": 5126,
-      "count": 2,
-      "max": [
-        0.0801164731383324,
-        -0.06073546037077904,
-        -0.08011647313833235
-      ],
-      "min": [
-        0.08011647313833235,
-        -0.06073546037077904,
-        -0.08011647313833237
-      ],
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 10632,
-      "componentType": 5126,
-      "count": 2,
-      "max": [
-        6.410702056087227e-18,
-        0.38268343236508967,
-        4.533050896025822e-18,
-        0.9238795325112868
-      ],
-      "min": [
-        -1.8776511600614058e-18,
-        0.38268343236508967,
-        -6.4107020560872245e-18,
-        0.9238795325112868
-      ],
-      "type": "VEC4"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 10664,
-      "componentType": 5126,
-      "count": 2,
-      "max": [
-        1.0000000000000002,
-        1,
-        1.0000000000000002
-      ],
-      "min": [
-        0.9999999999999999,
-        1,
-        0.9999999999999999
-      ],
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 10688,
-      "componentType": 5126,
-      "count": 29,
-      "max": [
-        -0.37352379378857636,
-        -0.5760199987620502,
-        -0.34708724295824445,
-        0.6006692983826076
-      ],
-      "min": [
-        -0.4128239883703936,
-        -0.618794036498964,
-        -0.4103461623942859,
-        0.5737047525262833
-      ],
-      "type": "VEC4"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 11152,
-      "componentType": 5126,
-      "count": 29,
-      "max": [
-        -0.11039836731563783,
-        8.858239287575232e-10,
-        -1.0516184125613276e-8,
-        0.9938874184202361
-      ],
-      "min": [
-        -0.187059344927289,
-        6.851271898838119e-11,
-        -1.0553204128495013e-8,
-        0.9823486150422228
-      ],
-      "type": "VEC4"
-    },
-    {
-      "bufferView": 2,
-      "byteOffset": 11616,
-      "componentType": 5126,
-      "count": 29,
-      "max": [
-        -0.058074676265901945,
-        2.0036171020764496e-8,
-        -6.548683375121414e-9,
-        0.9983122417243065
-      ],
-      "min": [
-        -0.1636239282889574,
-        1.922864494882868e-8,
-        -8.63670163838025e-9,
-        0.9865227874161294
-      ],
-      "type": "VEC4"
-    }
-  ],
-  "animations": [
-    {
-      "channels": [
-        {
-          "sampler": 0,
-          "target": {
-            "node": 2,
-            "path": "rotation"
-          }
-        },
-        {
-          "sampler": 1,
-          "target": {
-            "node": 2,
-            "path": "scale"
-          }
-        },
-        {
-          "sampler": 2,
-          "target": {
-            "node": 2,
-            "path": "translation"
-          }
-        },
-        {
-          "sampler": 3,
-          "target": {
-            "node": 3,
-            "path": "rotation"
-          }
-        },
-        {
-          "sampler": 4,
-          "target": {
-            "node": 3,
-            "path": "scale"
-          }
-        },
-        {
-          "sampler": 5,
-          "target": {
-            "node": 3,
-            "path": "translation"
-          }
-        },
-        {
-          "sampler": 6,
-          "target": {
-            "node": 4,
-            "path": "rotation"
-          }
-        },
-        {
-          "sampler": 7,
-          "target": {
-            "node": 4,
-            "path": "scale"
-          }
-        },
-        {
-          "sampler": 8,
-          "target": {
-            "node": 4,
-            "path": "translation"
-          }
-        },
-        {
-          "sampler": 9,
-          "target": {
-            "node": 5,
-            "path": "rotation"
-          }
-        },
-        {
-          "sampler": 10,
-          "target": {
-            "node": 5,
-            "path": "scale"
-          }
-        },
-        {
-          "sampler": 11,
-          "target": {
-            "node": 5,
-            "path": "translation"
-          }
-        },
-        {
-          "sampler": 12,
-          "target": {
-            "node": 6,
-            "path": "rotation"
-          }
-        },
-        {
-          "sampler": 13,
-          "target": {
-            "node": 6,
-            "path": "scale"
-          }
-        },
-        {
-          "sampler": 14,
-          "target": {
-            "node": 6,
-            "path": "translation"
-          }
-        },
-        {
-          "sampler": 15,
-          "target": {
-            "node": 9,
-            "path": "rotation"
-          }
-        },
-        {
-          "sampler": 16,
-          "target": {
-            "node": 9,
-            "path": "scale"
-          }
-        },
-        {
-          "sampler": 17,
-          "target": {
-            "node": 9,
-            "path": "translation"
-          }
-        },
-        {
-          "sampler": 18,
-          "target": {
-            "node": 10,
-            "path": "rotation"
-          }
-        },
-        {
-          "sampler": 19,
-          "target": {
-            "node": 11,
-            "path": "rotation"
-          }
-        },
-        {
-          "sampler": 20,
-          "target": {
-            "node": 12,
-            "path": "rotation"
-          }
-        },
-        {
-          "sampler": 21,
-          "target": {
-            "node": 14,
-            "path": "rotation"
-          }
-        },
-        {
-          "sampler": 22,
-          "target": {
-            "node": 14,
-            "path": "scale"
-          }
-        },
-        {
-          "sampler": 23,
-          "target": {
-            "node": 14,
-            "path": "translation"
-          }
-        },
-        {
-          "sampler": 24,
-          "target": {
-            "node": 15,
-            "path": "rotation"
-          }
-        },
-        {
-          "sampler": 25,
-          "target": {
-            "node": 16,
-            "path": "rotation"
-          }
-        },
-        {
-          "sampler": 26,
-          "target": {
-            "node": 17,
-            "path": "rotation"
-          }
-        },
-        {
-          "sampler": 27,
-          "target": {
-            "node": 19,
-            "path": "rotation"
-          }
-        },
-        {
-          "sampler": 28,
-          "target": {
-            "node": 19,
-            "path": "scale"
-          }
-        },
-        {
-          "sampler": 29,
-          "target": {
-            "node": 19,
-            "path": "translation"
-          }
-        },
-        {
-          "sampler": 30,
-          "target": {
-            "node": 20,
-            "path": "rotation"
-          }
-        },
-        {
-          "sampler": 31,
-          "target": {
-            "node": 21,
-            "path": "rotation"
-          }
-        },
-        {
-          "sampler": 32,
-          "target": {
-            "node": 22,
-            "path": "rotation"
-          }
-        },
-        {
-          "sampler": 33,
-          "target": {
-            "node": 24,
-            "path": "rotation"
-          }
-        },
-        {
-          "sampler": 34,
-          "target": {
-            "node": 24,
-            "path": "scale"
-          }
-        },
-        {
-          "sampler": 35,
-          "target": {
-            "node": 24,
-            "path": "translation"
-          }
-        },
-        {
-          "sampler": 36,
-          "target": {
-            "node": 25,
-            "path": "rotation"
-          }
-        },
-        {
-          "sampler": 37,
-          "target": {
-            "node": 26,
-            "path": "rotation"
-          }
-        },
-        {
-          "sampler": 38,
-          "target": {
-            "node": 27,
-            "path": "rotation"
-          }
-        }
-      ],
-      "name": "Main",
-      "samplers": [
-        {
-          "input": 11,
-          "interpolation": "LINEAR",
-          "output": 13
-        },
-        {
-          "input": 11,
-          "interpolation": "LINEAR",
-          "output": 14
-        },
-        {
-          "input": 11,
-          "interpolation": "LINEAR",
-          "output": 12
-        },
-        {
-          "input": 15,
-          "interpolation": "LINEAR",
-          "output": 17
-        },
-        {
-          "input": 15,
-          "interpolation": "LINEAR",
-          "output": 18
-        },
-        {
-          "input": 15,
-          "interpolation": "LINEAR",
-          "output": 16
-        },
-        {
-          "input": 15,
-          "interpolation": "LINEAR",
-          "output": 20
-        },
-        {
-          "input": 15,
-          "interpolation": "LINEAR",
-          "output": 21
-        },
-        {
-          "input": 15,
-          "interpolation": "LINEAR",
-          "output": 19
-        },
-        {
-          "input": 15,
-          "interpolation": "LINEAR",
-          "output": 23
-        },
-        {
-          "input": 15,
-          "interpolation": "LINEAR",
-          "output": 24
-        },
-        {
-          "input": 15,
-          "interpolation": "LINEAR",
-          "output": 22
-        },
-        {
-          "input": 15,
-          "interpolation": "LINEAR",
-          "output": 26
-        },
-        {
-          "input": 15,
-          "interpolation": "LINEAR",
-          "output": 27
-        },
-        {
-          "input": 15,
-          "interpolation": "LINEAR",
-          "output": 25
-        },
-        {
-          "input": 28,
-          "interpolation": "LINEAR",
-          "output": 30
-        },
-        {
-          "input": 28,
-          "interpolation": "LINEAR",
-          "output": 31
-        },
-        {
-          "input": 28,
-          "interpolation": "LINEAR",
-          "output": 29
-        },
-        {
-          "input": 32,
-          "interpolation": "LINEAR",
-          "output": 33
-        },
-        {
-          "input": 34,
-          "interpolation": "LINEAR",
-          "output": 35
-        },
-        {
-          "input": 34,
-          "interpolation": "LINEAR",
-          "output": 36
-        },
-        {
-          "input": 28,
-          "interpolation": "LINEAR",
-          "output": 38
-        },
-        {
-          "input": 28,
-          "interpolation": "LINEAR",
-          "output": 39
-        },
-        {
-          "input": 28,
-          "interpolation": "LINEAR",
-          "output": 37
-        },
-        {
-          "input": 32,
-          "interpolation": "LINEAR",
-          "output": 40
-        },
-        {
-          "input": 32,
-          "interpolation": "LINEAR",
-          "output": 41
-        },
-        {
-          "input": 32,
-          "interpolation": "LINEAR",
-          "output": 42
-        },
-        {
-          "input": 28,
-          "interpolation": "LINEAR",
-          "output": 44
-        },
-        {
-          "input": 28,
-          "interpolation": "LINEAR",
-          "output": 45
-        },
-        {
-          "input": 28,
-          "interpolation": "LINEAR",
-          "output": 43
-        },
-        {
-          "input": 32,
-          "interpolation": "LINEAR",
-          "output": 46
-        },
-        {
-          "input": 32,
-          "interpolation": "LINEAR",
-          "output": 47
-        },
-        {
-          "input": 32,
-          "interpolation": "LINEAR",
-          "output": 48
-        },
-        {
-          "input": 28,
-          "interpolation": "LINEAR",
-          "output": 50
-        },
-        {
-          "input": 28,
-          "interpolation": "LINEAR",
-          "output": 51
-        },
-        {
-          "input": 28,
-          "interpolation": "LINEAR",
-          "output": 49
-        },
-        {
-          "input": 32,
-          "interpolation": "LINEAR",
-          "output": 52
-        },
-        {
-          "input": 32,
-          "interpolation": "LINEAR",
-          "output": 53
-        },
-        {
-          "input": 32,
-          "interpolation": "LINEAR",
-          "output": 54
-        }
-      ]
-    }
-  ],
-  "asset": {
-    "generator": "qtek fbx2gltf",
-    "version": "2.0"
-  },
-  "bufferViews": [
-    {
-      "buffer": 0,
-      "byteLength": 44660,
-      "byteOffset": 0,
-      "target": 34962
-    },
-    {
-      "buffer": 0,
-      "byteLength": 832,
-      "byteOffset": 44660,
-      "target": 34962
-    },
-    {
-      "buffer": 0,
-      "byteLength": 12080,
-      "byteOffset": 45492,
-      "target": 34962
-    },
-    {
-      "buffer": 0,
-      "byteLength": 9264,
-      "byteOffset": 57572,
-      "target": 34963
-    }
-  ],
-  "buffers": [
-    {
-      "byteLength": 66836,
-      "uri": "walk.bin"
-    }
-  ],
-  "materials": [
-    {
-      "name": "Wire",
-      "emissiveFactor": [
-        0.9019607843137255,
-        0,
-        0
-      ],
-      "extensions": {
-        "KHR_materials_pbrSpecularGlossiness": {
-          "diffuseFactor": [
-            0.9019607843137255,
-            0,
-            0,
-            1
-          ],
-          "specularFactor": [
-            0.10196078431372549,
-            0.10196078431372549,
-            0.10196078431372549
-          ],
-          "glossinessFactor": 0.5
-        }
-      }
-    },
-    {
-      "name": "Base",
-      "emissiveFactor": [
-        0,
-        0,
-        0
-      ],
-      "extensions": {
-        "KHR_materials_pbrSpecularGlossiness": {
-          "diffuseFactor": [
-            0,
-            0,
-            0,
-            1
-          ],
-          "specularFactor": [
-            0.10196078431372549,
-            0.10196078431372549,
-            0.10196078431372549
-          ],
-          "glossinessFactor": 0.5
-        }
-      }
-    }
-  ],
-  "meshes": [
-    {
-      "name": "Mesh_Material0",
-      "primitives": [
-        {
-          "attributes": {
-            "JOINTS_0": 2,
-            "POSITION": 0,
-            "TEXCOORD_0": 1,
-            "WEIGHTS_0": 3
-          },
-          "indices": 4,
-          "material": 0
-        },
-        {
-          "attributes": {
-            "JOINTS_0": 7,
-            "POSITION": 5,
-            "TEXCOORD_0": 6,
-            "WEIGHTS_0": 8
-          },
-          "indices": 9,
-          "material": 1
-        }
-      ]
-    }
-  ],
-  "nodes": [
-    {
-      "matrix": [
-        1,
-        0,
-        0,
-        0,
-        0,
-        1,
-        0,
-        0,
-        0,
-        0,
-        1,
-        0,
-        0,
-        0,
-        0,
-        1
-      ],
-      "mesh": 0,
-      "name": "Mesh",
-      "skin": 0
-    },
-    {
-      "children": [
-        2,
-        3,
-        4,
-        5,
-        6
-      ],
-      "matrix": [
-        1,
-        0,
-        0,
-        0,
-        0,
-        1,
-        0,
-        0,
-        0,
-        0,
-        1,
-        0,
-        0,
-        0,
-        0,
-        1
-      ],
-      "name": "layout"
-    },
-    {
-      "matrix": [
-        1,
-        0,
-        0,
-        0,
-        0,
-        1,
-        0,
-        0,
-        0,
-        0,
-        1,
-        0,
-        0.10908540338277817,
-        0.007917225360870361,
-        -0.19540420174598694,
-        1
-      ],
-      "name": "arm_L_goal1"
-    },
-    {
-      "matrix": [
-        1,
-        0,
-        0,
-        0,
-        0,
-        1,
-        0,
-        0,
-        0,
-        0,
-        1,
-        0,
-        -0.041061561554670334,
-        1.066356958290271e-8,
-        -0.19540409743785858,
-        1
-      ],
-      "name": "leg_L_goal1"
-    },
-    {
-      "matrix": [
-        1,
-        0,
-        0,
-        0,
-        0,
-        1,
-        0,
-        0,
-        0,
-        0,
-        1,
-        0,
-        -0.08989156037569046,
-        0.05766163021326065,
-        0.08743858337402344,
-        1
-      ],
-      "name": "leg_R_goal1"
-    },
-    {
-      "matrix": [
-        1,
-        0,
-        0,
-        0,
-        0,
-        1,
-        0,
-        0,
-        0,
-        0,
-        1,
-        0,
-        0.3882029056549072,
-        1.066356958290271e-8,
-        0.08743848651647568,
-        1
-      ],
-      "name": "arm_R_goal1"
-    },
-    {
-      "children": [
-        7,
-        9,
-        14,
-        19,
-        24
-      ],
-      "matrix": [
-        0.9999990460150695,
-        0.0009767210557009947,
-        -0.0009767215215899124,
-        0,
-        -0.0009418413642818668,
-        0.9993835218089064,
-        0.03509543092300879,
-        0,
-        0.001010397840414483,
-        -0.03509447752576613,
-        0.9993834883283782,
-        0,
-        0,
-        1.71110200881958,
-        0.03374987840652466,
-        1
-      ],
-      "name": "root"
-    },
-    {
-      "children": [
-        8
-      ],
-      "matrix": [
-        1.331580544223403e-7,
-        1.3877787807814457e-17,
-        0.9999999999999912,
-        0,
-        -0.9999999999999915,
-        6.125064648185297e-17,
-        1.3315805442190663e-7,
-        0,
-        -6.125064648185297e-17,
-        -1,
-        0,
-        0,
-        0,
-        0,
-        0,
-        1
-      ],
-      "name": "head_bone"
-    },
-    {
-      "matrix": [
-        0.9999999999999999,
-        -2.168404344971009e-19,
-        -1.3877787807814457e-17,
-        0,
-        -1.0842021724855044e-19,
-        1,
-        -8.809142651444724e-20,
-        0,
-        0,
-        1.3552527156068805e-19,
-        0.9999999999999999,
-        0,
-        0,
-        -2.168404344971009e-19,
-        -0.20000004768371582,
-        1
-      ],
-      "name": "head_bone_end_effector"
-    },
-    {
-      "children": [
-        10
-      ],
-      "matrix": [
-        0.7071067811865477,
-        1.3877787807814457e-17,
-        0.7071067811865476,
-        0,
-        -5.969888212248309e-18,
-        1,
-        0,
-        0,
-        -0.7071067811865477,
-        3.469446951953614e-18,
-        0.7071067811865477,
-        0,
-        0.08011647313833238,
-        -0.06073546037077904,
-        0.08011647313833237,
-        1
-      ],
-      "name": "arm_R_root"
-    },
-    {
-      "children": [
-        11
-      ],
-      "matrix": [
-        0.011257608597905144,
-        -0.11446542204609372,
-        0.9933634447695698,
-        0,
-        0.917545554229092,
-        0.3960659950484638,
-        0.03524036720436163,
-        0,
-        -0.3974712847025359,
-        0.9110594902211819,
-        0.10948599506254547,
-        0,
-        2.7755575615628914e-17,
-        -2.220446049250313e-16,
-        1.3877787807814457e-17,
-        1
-      ],
-      "name": "arm_R_bone1"
-    },
-    {
-      "children": [
-        12
-      ],
-      "matrix": [
-        1,
-        -1.904130303431728e-8,
-        8.301912282626667e-9,
-        0,
-        2.0545667389626487e-8,
-        0.9655471563735203,
-        -0.26022814763012936,
-        0,
-        -3.060804772830883e-9,
-        0.26022814763012964,
-        0.9655471563735208,
-        0,
-        4.5585011293480804e-8,
-        3.086052191569877e-9,
-        -0.5214316844940188,
-        1
-      ],
-      "name": "arm_R_bone2"
-    },
-    {
-      "children": [
-        13
-      ],
-      "matrix": [
-        0.9999999999999993,
-        -1.3284179367634152e-8,
-        -1.1297157027564952e-8,
-        0,
-        1.1143629130572208e-8,
-        0.9851037177266527,
-        -0.17196053879469503,
-        0,
-        1.3413226029879155e-8,
-        0.17196053879469492,
-        0.9851037177266524,
-        0,
-        3.3320748799026134e-8,
-        4.767711780928607e-10,
-        -0.3811449110507964,
-        1
-      ],
-      "name": "arm_R_bone3"
-    },
-    {
-      "matrix": [
-        1,
-        -1.6653345369377348e-16,
-        2.7755575615628914e-17,
-        0,
-        -1.1102230246251565e-16,
-        1,
-        0,
-        0,
-        2.7755575615628914e-17,
-        0,
-        0.9999999999999998,
-        0,
-        2.7755575615628914e-17,
-        0,
-        -0.8033324480056764,
-        1
-      ],
-      "name": "arm_R_bone3_end_effector"
-    },
-    {
-      "children": [
-        15
-      ],
-      "matrix": [
-        -0.7071067811865477,
-        6.938893903907228e-18,
-        0.7071067811865477,
-        0,
-        9.622294280808852e-19,
-        1,
-        6.938893903907228e-18,
-        0,
-        -0.7071067811865477,
-        0,
-        -0.7071067811865476,
-        0,
-        -0.08011647313833238,
-        -0.060735460370778815,
-        0.08011647313833237,
-        1
-      ],
-      "name": "leg_R_root"
-    },
-    {
-      "children": [
-        16
-      ],
-      "matrix": [
-        0.0003127647562193303,
-        -0.008904262574921468,
-        0.9999603073553489,
-        0,
-        0.8651231226820654,
-        0.5015420030419078,
-        0.004195448193306306,
-        0,
-        -0.5015594528857362,
-        0.865087471469046,
-        0.007860148106312193,
-        0,
-        -4.163336342344337e-17,
-        -2.220446049250313e-16,
-        0,
-        1
-      ],
-      "name": "leg_R_bone1"
-    },
-    {
-      "children": [
-        17
-      ],
-      "matrix": [
-        0.9999999999999997,
-        -2.576050761593507e-8,
-        -9.192067412788774e-9,
-        0,
-        1.94184820445642e-8,
-        0.9053448602044203,
-        -0.4246771527895501,
-        0,
-        1.926188996151379e-8,
-        0.42467715278955,
-        0.9053448602044204,
-        0,
-        4.5585011279603016e-8,
-        3.0860520805475744e-9,
-        -0.5214316844940187,
-        1
-      ],
-      "name": "leg_R_bone2"
-    },
-    {
-      "children": [
-        18
-      ],
-      "matrix": [
-        0.999999999999996,
-        -3.6092491495498535e-8,
-        -8.175138145952165e-8,
-        0,
-        -5.535752967134044e-10,
-        0.9122919994006253,
-        -0.4095400705804557,
-        0,
-        8.936245271540244e-8,
-        0.40954007058045433,
-        0.9122919994006214,
-        0,
-        3.3320748854537285e-8,
-        4.767711225817095e-10,
-        -0.3811449110507964,
-        1
-      ],
-      "name": "leg_R_bone3"
-    },
-    {
-      "matrix": [
-        1.0000000000000002,
-        -1.1102230246251565e-16,
-        -5.551115123125783e-17,
-        0,
-        -1.1102230246251565e-16,
-        1,
-        5.551115123125783e-17,
-        0,
-        -2.7755575615628914e-17,
-        -5.551115123125783e-17,
-        1,
-        0,
-        6.938893903907228e-18,
-        2.7755575615628914e-17,
-        -0.8033324480056764,
-        1
-      ],
-      "name": "leg_R_bone3_end_effector"
-    },
-    {
-      "children": [
-        20
-      ],
-      "matrix": [
-        -0.707106781186548,
-        -1.734723475976807e-17,
-        -0.7071067811865478,
-        0,
-        -5.969888212248309e-18,
-        1,
-        0,
-        0,
-        0.7071067811865479,
-        -1.0408340855860843e-17,
-        -0.707106781186548,
-        0,
-        -0.08011647313833238,
-        -0.06073546037077926,
-        -0.08011647313833237,
-        1
-      ],
-      "name": "leg_L_root"
-    },
-    {
-      "children": [
-        21
-      ],
-      "matrix": [
-        -0.001971520764457557,
-        0.053848580223104306,
-        0.9985471663941728,
-        0,
-        0.9406502904524712,
-        0.3389798200984154,
-        -0.016422930241824563,
-        0,
-        -0.3393716903007043,
-        0.9392513039511856,
-        -0.05132098838137236,
-        0,
-        0,
-        -2.220446049250313e-16,
-        0,
-        1
-      ],
-      "name": "leg_L_bone1"
-    },
-    {
-      "children": [
-        22
-      ],
-      "matrix": [
-        1.0000000000000004,
-        -2.0380670373576493e-8,
-        4.078802823270777e-9,
-        0,
-        2.0657071497787172e-8,
-        0.9528065559440093,
-        -0.3035781068359762,
-        0,
-        2.300815246658594e-9,
-        0.30357810683597636,
-        0.9528065559440095,
-        0,
-        4.5585011293480804e-8,
-        3.0860520805475744e-9,
-        -0.5214316844940187,
-        1
-      ],
-      "name": "leg_L_bone2"
-    },
-    {
-      "children": [
-        23
-      ],
-      "matrix": [
-        0.9999999999999993,
-        -1.7624569248475552e-8,
-        -2.980817417896908e-8,
-        0,
-        1.0295256203107783e-8,
-        0.973184055245276,
-        -0.23002729446262357,
-        0,
-        3.306297183952589e-8,
-        0.23002729446262302,
-        0.9731840552452757,
-        0,
-        3.33207488406595e-8,
-        4.767710670705583e-10,
-        -0.3811449110507963,
-        1
-      ],
-      "name": "leg_L_bone3"
-    },
-    {
-      "matrix": [
-        1.0000000000000002,
-        5.551115123125783e-17,
-        5.551115123125783e-17,
-        0,
-        5.551115123125783e-17,
-        1.0000000000000002,
-        -4.163336342344337e-17,
-        0,
-        -1.3877787807814457e-17,
-        -6.938893903907228e-18,
-        1.0000000000000004,
-        0,
-        5.551115123125783e-17,
-        0,
-        -0.8033324480056764,
-        1
-      ],
-      "name": "leg_L_bone3_end_effector"
-    },
-    {
-      "children": [
-        25
-      ],
-      "matrix": [
-        0.7071067811865478,
-        -6.938893903907228e-18,
-        -0.7071067811865476,
-        0,
-        9.622294280808852e-19,
-        1,
-        6.938893903907228e-18,
-        0,
-        0.7071067811865476,
-        0,
-        0.7071067811865477,
-        0,
-        0.0801164731383324,
-        -0.06073546037077904,
-        -0.08011647313833237,
-        1
-      ],
-      "name": "arm_L_root"
-    },
-    {
-      "children": [
-        26
-      ],
-      "matrix": [
-        0.0013311372808006983,
-        -0.02628076331575018,
-        0.999653714819827,
-        0,
-        0.9212641414912593,
-        0.3888334608959349,
-        0.008995626162872972,
-        0,
-        -0.388935225552935,
-        0.9209331469586867,
-        0.024729115569640914,
-        0,
-        -2.7755575615628914e-17,
-        -2.220446049250313e-16,
-        -1.3877787807814457e-17,
-        1
-      ],
-      "name": "arm_L_bone1"
-    },
-    {
-      "children": [
-        27
-      ],
-      "matrix": [
-        1,
-        -2.099252122134132e-8,
-        2.1939252359270967e-9,
-        0,
-        2.0585442239706708e-8,
-        0.9470524752700538,
-        -0.3210788206731546,
-        0,
-        4.66249158725951e-9,
-        0.3210788206731545,
-        0.9470524752700542,
-        0,
-        4.5585011314297486e-8,
-        3.0860520805475744e-9,
-        -0.5214316844940183,
-        1
-      ],
-      "name": "arm_L_bone2"
-    },
-    {
-      "children": [
-        28
-      ],
-      "matrix": [
-        0.9999999999999993,
-        -1.9477644552789997e-8,
-        -3.7389235998941395e-8,
-        0,
-        9.294988445596175e-9,
-        0.9669130921291693,
-        -0.2551055347314979,
-        0,
-        4.112099672576308e-8,
-        0.2551055347314972,
-        0.9669130921291688,
-        0,
-        3.3320748854537285e-8,
-        4.767711780928607e-10,
-        -0.3811449110507964,
-        1
-      ],
-      "name": "arm_L_bone3"
-    },
-    {
-      "matrix": [
-        1,
-        0,
-        0,
-        0,
-        1.6653345369377348e-16,
-        1,
-        0,
-        0,
-        0,
-        0,
-        1.0000000000000002,
-        0,
-        0,
-        -2.7755575615628914e-17,
-        -0.8033324480056765,
-        1
-      ],
-      "name": "arm_L_bone3_end_effector"
-    }
-  ],
-  "scene": 0,
-  "scenes": [
-    {
-      "nodes": [
-        0,
-        1
-      ]
-    }
-  ],
-  "skins": [
-    {
-      "inverseBindMatrices": 10,
-      "joints": [
-        7,
-        10,
-        11,
-        12,
-        15,
-        16,
-        17,
-        20,
-        21,
-        22,
-        25,
-        26,
-        27
-      ]
-    }
-  ],
-  "extras": {
-    "qtekModelViewerConfig": {
-      "preZ": true,
-      "materials": [
-        {
-          "name": "Wire",
-          "color": "#e60000",
-          "emission": "#e60000",
-          "alpha": 1,
-          "alphaCutoff": 0,
-          "emissionIntensity": 1,
-          "uvRepeat": {
-            "0": 1,
-            "1": 1
-          },
-          "parallaxOcclusionScale": 0.02,
-          "diffuseMap": "",
-          "normalMap": "",
-          "parallaxOcclusionMap": "",
-          "emissiveMap": "",
-          "specularColor": "#1a1a1a",
-          "glossiness": 0.5,
-          "specularMap": "",
-          "glossinessMap": "",
-          "type": "pbrSpecularGlossiness",
-          "targetMeshes": [
-            "Mesh_Material0"
-          ]
-        },
-        {
-          "name": "Base",
-          "color": "#000000",
-          "emission": "#000000",
-          "alpha": 1,
-          "alphaCutoff": 0,
-          "emissionIntensity": 1,
-          "uvRepeat": {
-            "0": 1,
-            "1": 1
-          },
-          "parallaxOcclusionScale": 0.02,
-          "diffuseMap": "",
-          "normalMap": "",
-          "parallaxOcclusionMap": "",
-          "emissiveMap": "",
-          "specularColor": "#1a1a1a",
-          "glossiness": 0.5,
-          "specularMap": "",
-          "glossinessMap": "",
-          "type": "pbrSpecularGlossiness",
-          "targetMeshes": [
-            "Mesh_Material0$1"
-          ]
-        }
-      ],
-      "takes": [],
-      "textureFlipY": false,
-      "zUpToYUp": false,
-      "shadow": true,
-      "environment": "auto",
-      "viewControl": {
-        "center": [
-          1.0690909624099731,
-          -1.1321967840194702,
-          0.9232351183891296
-        ],
-        "alpha": 10.229259828771838,
-        "beta": 33.79452028477864,
-        "distance": 19.502084087073698
-      },
-      "ground": {
-        "show": true
-      },
-      "mainLight": {
-        "shadow": true,
-        "shadowQuality": "medium",
-        "intensity": 0.8,
-        "color": "#fff",
-        "alpha": 45,
-        "beta": 45,
-        "$padAngle": [
-          0.25,
-          0.5
-        ]
-      },
-      "secondaryLight": {
-        "shadow": false,
-        "shadowQuality": "medium",
-        "intensity": 0,
-        "color": "#fff",
-        "alpha": 60,
-        "beta": -50,
-        "$padAngle": [
-          -0.2777777777777778,
-          0.6666666666666666
-        ]
-      },
-      "tertiaryLight": {
-        "shadow": false,
-        "shadowQuality": "medium",
-        "intensity": 0,
-        "color": "#fff",
-        "alpha": 89,
-        "beta": 0,
-        "$padAngle": [
-          0,
-          0.9888888888888889
-        ]
-      },
-      "ambientLight": {
-        "intensity": 0,
-        "color": "#fff"
-      },
-      "ambientCubemapLight": {
-        "texture": "./asset/texture/Barce_Rooftop_C.hdr",
-        "$texture": "Barce_Rooftop_C",
-        "$textureOptions": [
-          "pisa",
-          "Barce_Rooftop_C",
-          "Factory_Catwalk",
-          "Grand_Canyon_C",
-          "Ice_Lake",
-          "Hall",
-          "Old_Industrial_Hall"
-        ],
-        "exposure": 3,
-        "diffuseIntensity": 0.2,
-        "specularIntensity": 0.2,
-        "$intensity": 0.2
-      },
-      "postEffect": {
-        "enable": true,
-        "bloom": {
-          "enable": true,
-          "intensity": 0.1
-        },
-        "depthOfField": {
-          "enable": false,
-          "focalDistance": 4,
-          "focalRange": 1,
-          "blurRadius": 5,
-          "fstop": 10,
-          "quality": "medium",
-          "$qualityOptions": [
-            "low",
-            "medium",
-            "high",
-            "ultra"
-          ]
-        },
-        "screenSpaceAmbientOcclusion": {
-          "enable": false,
-          "radius": 1.5,
-          "quality": "medium",
-          "intensity": 1,
-          "$qualityOptions": [
-            "low",
-            "medium",
-            "high",
-            "ultra"
-          ]
-        },
-        "screenSpaceReflection": {
-          "enable": false,
-          "quality": "medium",
-          "maxRoughness": 0.8,
-          "$qualityOptions": [
-            "low",
-            "medium",
-            "high",
-            "ultra"
-          ]
-        },
-        "colorCorrection": {
-          "enable": true,
-          "exposure": 0,
-          "brightness": 0,
-          "contrast": 1,
-          "saturation": 1,
-          "lookupTexture": ""
-        },
-        "FXAA": {
-          "enable": false
-        }
-      }
-    }
-  },
-  "extensionsUsed": [
-    "KHR_materials_pbrSpecularGlossiness"
-  ]
-}

BIN
modules/mojo3d/tests/assets/water1.jpg


+ 0 - 76
modules/mojo3d/tests/bouncyball_gltf2.monkey2

@@ -1,76 +0,0 @@
-Namespace myapp
-
-#Import "<std>"
-#Import "<mojo>"
-#Import "<mojo3d>"
-
-#Import "assets/bouncyball/"
-
-Using std..
-Using mojo..
-Using mojo3d..
-
-Class MyWindow Extends Window
-	
-	Field _scene:Scene
-	
-	Field _camera:Camera
-	
-	Field _light:Light
-	
-	Field _model:Model
-	
-	Method New( title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=WindowFlags.Resizable )
-
-		Super.New( title,width,height,flags )
-		
-		_scene=Scene.GetCurrent()
-		
-		_scene.ClearColor=Color.Sky
-		
-		'create camera
-		'
-		_camera=New Camera( Self )
-		_camera.Move( 0,10,-5 )
-		
-		New FlyBehaviour( _camera )
-		
-		'create light
-		'
-		_light=New Light
-		_light.RotateX( 90 )
-		
-		'create donut - metallic silver...
-		
-		Local material:=New PbrMaterial( Color.Silver,1,0.5 )
-		
-		_model=Model.LoadBoned( "asset::bouncyball.gltf" )
-		
-		_model.Animator.Animate( 0 )
-		
-		_model.Move( 0,7,0 )
-		
-'		_model.Mesh.FitVertices( New Boxf( -1,1 ),False )
-	End
-	
-	Method OnRender( canvas:Canvas ) Override
-	
-		RequestRender()
-		
-		_scene.Update()
-		
-		_scene.Render( canvas )
-		
-		canvas.DrawText( "FPS="+App.FPS,0,0 )
-	End
-	
-End
-
-Function Main()
-
-	New AppInstance
-	
-	New MyWindow
-	
-	App.Run()
-End

+ 0 - 324
modules/mojo3d/tests/bouncyboxes.monkey2

@@ -1,324 +0,0 @@
-
-#Import "<std>"
-#Import "<mojo>"
-#Import "<mojo3d>"
-#Import "<bullet>"
- 
-Using std..
-Using mojo..
-Using mojo3d..
- 
-Const WALL_WIDTH:Int	= 20
-Const WALL_HEIGHT:Int	= 20
- 
-Class PhysBox
- 
-	Class PhysParams
-		Field mass:Float
-		Field group:Short
-		Field mask:Short
-	End
-	
-	Field box:Boxf
-	Field model:Model
-	Field collider:BoxCollider
-	Field body:RigidBody
- 
-	Field init:PhysParams
-	 
-	Method New (width:Float = 1, height:Float = 1, depth:Float = 1, mass:Float = 1, material:Material = Null, group:Int = 1, mask:Int = 1)
- 
-		' Store setup params for PhysBox.Start ()
-		
-'		SetConfig( "MOJO3D_RENDERER","forward" )
-		
-		init = New PhysParams
-		
-		init.mass	= mass
-		init.group	= group
-		init.mask	= mask
-		
-		If Not material
-			material = New PbrMaterial (Color.Red)
-		Endif
-		
-		box					= New Boxf (-width * 0.5, -height * 0.5, -depth * 0.5, width * 0.5, height * 0.5, depth * 0.5)
-		model				= Model.CreateBox (box, 1, 1, 1, material)
- 
-	End
- 
-	Method Start ()
- 
-		collider			= New BoxCollider (model)
-		body				= New RigidBody (model)
- 
-		collider.Box		= box
-	
-		body.Mass			= init.mass
-		body.CollisionGroup	= init.group
-		body.CollisionMask	= init.mask
-		
-		box					= Null
-		init				= Null
-		
-	End
-	 
-	Method Move (x:Float, y:Float, z:Float)
-		model.Move (x, y, z)
-	End
- 
-	Method Rotate (pitch:Float, roll:Float, yaw:Float, localspace:Bool = False)
-		model.Rotate (pitch, roll, yaw, localspace)
-	End
-	
-End
- 
-Class Game Extends Window
- 
-	Const CAMERA_MOVE:Float = 0.05
-	Const CAMERA_BOOST:Float = 4.0
-	
-	Field cam_boost:Float = 1.0
-	 
-	Field scene:Scene
-	Field cam:Camera
-	Field light:Light
-	
-	Field ground:PhysBox
- 
-	Field boxes:List <PhysBox>
-	Field bullets:List <PhysBox>
-	
-	Method New (title:String, width:Int, height:Int, flags:WindowFlags)
- 
-		Super.New (title, width, height, flags)
- 
-		SwapInterval = 1
-		
-		CreateArena (50)
-		
-	End
-	
-	Method CreateArena:Void (ground_size:Float = 100)
- 
-		SeedRnd (Millisecs ())
-		
-		scene					= Scene.GetCurrent ()
-		ground					= New PhysBox (ground_size, 1, ground_size, 0, New PbrMaterial (Color.Green * 0.25))
-		cam						= New Camera( Self )
-		light					= New Light
- 
-		scene.AmbientLight	= Color.White * 0.75
-		scene.ClearColor	= Color.Sky * 0.75
-		scene.ShadowAlpha	= .5
- 
-		cam.FOV = 100
-		cam.Move (0, 10, -10)
-		
-		ground.Start ()
-		
-		cam.Near				= 0.01
-		cam.Far					= 1000
-	
-		light.CastsShadow		= True
-		light.Range				= 1000
- 
-		light.Move (0, 20, 10)
-		
-'		cam.PointAt (ground.model)
-		light.PointAt (ground.model)
- 
-		boxes	= New List <PhysBox>
-		bullets	= New List <PhysBox>
- 
-		BuildWall (WALL_WIDTH, WALL_HEIGHT)
-		
-	End
- 
-	Method BuildWall (width:Int, height:Int)
-	
-		For Local y:Int = 0 Until height
-			For Local x:Int = 0 Until width
-				
-				Local color:Color = New Color (Rnd (0.4, 1.0), Rnd (0.4, 1.0), Rnd (0.4, 1.0))
-				
-				' Create new PhysBox...
-				
-				Local pb:PhysBox = New PhysBox (1, 1, 1, 1, New PbrMaterial (color))
-				
-				' Position PhysBox...
-				
-	 			pb.Move (x - (width / 2.0), (y + 1), 0)
-	
-				boxes.Add (pb)
-				
-				' Start its physics...
-				
-				pb.Start ()
-				
-			Next
-		Next
- 
-	End
- 
-	Method DropBox ()
- 
-		Local pb:PhysBox = New PhysBox (1, 1, 1, 1, New PbrMaterial (Color.Red))
-		
-		pb.Move (0, 50, 0)
- 
-		boxes.Add (pb)
-		
-		pb.Start ()
- 
-	End
-	
-	Method BumpWall ()
- 
-		Local vec:Vec3f = New Vec3f (0.0, 0.5, 0.0)
-	
-		'Local count:Int
-		
-		For Local pb:PhysBox = Eachin boxes
-			'If Not pb.collider Then Print "No collider"
-			'If Not pb.body Then Print "No body"
-			pb.body.ApplyImpulse (vec)
-			'pb.body.LinearVelocity=vec
-			'Print "Body count: " + count
-			'count = count + 1
-		Next
-		
-		'Print Millisecs ()
-		
-	End
-	
-	Method UpdateBoxes ()
- 
-		For Local pb:PhysBox = Eachin boxes
- 
-			If pb.model.Y < -20
- 
-				pb.model.Scale = pb.model.Scale * 0.75
- 
-				If pb.model.Scale.x < 0.01
-					pb.model.Destroy ()
-					boxes.Remove (pb)
-				Endif
- 
-			Endif
- 
-		Next
- 
-	End
- 
-	Method UpdateGame ()
-		
-		UpdateBoxes ()
-		
-		If Keyboard.KeyDown (Key.D)
-			DropBox ()
-		Endif
- 	
-		If Keyboard.KeyDown (Key.B)
-			BumpWall ()
-		Endif
- 	
-		If Keyboard.KeyHit (Key.Escape)
-			App.Terminate ()
-		Endif
- 	
- 		If Keyboard.KeyHit (Key.S)
-			light.CastsShadow = Not light.CastsShadow
-		Endif
-	 
- 		If Keyboard.KeyHit (Key.Space)
- 			
- 			For Local pb:PhysBox = Eachin boxes
-				pb.model.Destroy ()
-				boxes.Remove (pb)
-			Next
-			
-			BuildWall (WALL_WIDTH, WALL_HEIGHT)
-			
-		Endif
-	 
-		If Keyboard.KeyDown (Key.LeftShift)
-			cam_boost = CAMERA_BOOST
-		Else
-			cam_boost = 1.0
-		Endif
-		
-		If Keyboard.KeyDown (Key.A)
-			cam.Move (0.0, 0.0, CAMERA_MOVE * cam_boost)
-		Endif
- 
-		If Keyboard.KeyDown (Key.Z)
-			cam.Move (0.0, 0.0, -CAMERA_MOVE * cam_boost)
-		Endif
- 
-		If Keyboard.KeyDown (Key.Left)
-			cam.Rotate (0.0, 1.0, 0.0)
-		Endif
- 
-		If Keyboard.KeyDown (Key.Right)
-			cam.Rotate (0.0, -1.0, 0.0)
-		Endif
- 
-		If Keyboard.KeyDown (Key.Up)
-			cam.Rotate (1.0, 0.0, 0.0, True)
-		Endif
- 
-		If Keyboard.KeyDown (Key.Down)
-			cam.Rotate (-1.0, 0.0, 0.0, True)
-		Endif
-		
-	End
- 
-	Method ShadowText:Void (canvas:Canvas, s:String, x:Float, y:Float)
-		canvas.Color = Color.Black
-		canvas.DrawText	(s, x + 1, y + 1)
-		canvas.Color = Color.White
-		canvas.DrawText	(s, x, y)
-	End
- 
-	Method RenderText (canvas:Canvas)
-		
-		ShadowText (canvas, "FPS: " + App.FPS, 20.0, 20.0)
-		ShadowText (canvas, "A/Z + Cursors to move camera", 20.0, 40.0)
-		ShadowText (canvas, "SHIFT to boost", 20.0, 60.0)
-		ShadowText (canvas, "SPACE to rebuild wall", 20.0, 80.0)
-		ShadowText (canvas, "S to toggle shadows", 20.0, 100.0)
-		ShadowText (canvas, "B to boost boxes", 20.0, 120.0)
- 		ShadowText (canvas, "Boxes: " + boxes.Count (), 20.0, 160.0)
-		
-	End
-	
-	Method OnRender (canvas:Canvas) Override
- 
-		RequestRender ()
-		
-		UpdateGame ()
-		
-		scene.Update ()
-		
-		scene.Render (canvas)
- 
-		RenderText (canvas)
-		
-	End
-	
-End
- 
-Function Run3D (title:String, width:Int, height:Int, flags:WindowFlags = WindowFlags.Center)
- 
-	New AppInstance
-	New Game (title, width, height, flags)
- 
-	App.Run ()
- 
-End
- 
-Function Main ()
-	Run3D ("3D Scene", 960, 540, WindowFlags.Center)		' 1/4 HD!
-'	Run3D ("3D Scene", 1920, 1080, WindowFlags.Fullscreen) 
-End

+ 0 - 88
modules/mojo3d/tests/cubes.monkey2

@@ -1,88 +0,0 @@
-Namespace myapp
-
-#Reflect mojo3d
-
-#Import "<std>"
-#Import "<mojo>"
-#Import "<mojo3d>"
-
-#Import "assets/"
-
-Using std..
-Using mojo..
-Using mojo3d..
-
-Class MyWindow Extends Window
-	
-	Field _scene:Scene
-	
-	Field _camera:Camera
-	
-	Field _light:Light
-	
-	Method New( title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=WindowFlags.Resizable )
-
-		Super.New( title,width,height,flags )
-		
-		Print opengl.glGetString( opengl.GL_VERSION )
-		
-		_scene=New Scene
-		
-		_scene.Editing=True
-		
-		_scene.ClearColor=Color.Sky
-		
-		'create camera
-		'
-		_camera=New Camera( Self )
-		_camera.Name="Camera"
-		_camera.Near=.1
-		_camera.Far=1000
-		_camera.Move( 0,10,-10 )
-		
-		New FlyBehaviour( _camera )
-		
-		'create light
-		'
-		_light=New Light
-		_light.Rotate( 30,60,0 )
-		
-		'Create cube
-		'
-		Local cube:=Model.CreateBox( New Boxf( -1,1 ),1,1,1,New PbrMaterial( Color.White ) )
-		
-		cube.CastsShadow=False
-		
-		For Local x:=-50.0 To 50.0 Step 2.5
-			For Local z:=-50.0 To 50.0 Step 2.5
-				Local copy:=cube.Copy()
-				copy.Move( x,0,z )
-			Next
-		Next
-		
-		cube.Destroy()
-		
-		_scene.Save( "cubes-scene.mojo3d" )
-	End
-	
-	Method OnRender( canvas:Canvas ) Override
-		
-		RequestRender()
-		
-		_scene.Update()
-		
-		_scene.Render( canvas )
-		
-		canvas.DrawText( "Width="+Width+", Height="+Height+", FPS="+App.FPS,0,0 )
-	End
-	
-End
-
-Function Main()
-	
-	New AppInstance
-	
-	New MyWindow
-	
-	App.Run()
-End

+ 0 - 94
modules/mojo3d/tests/cubeseam.monkey2

@@ -1,94 +0,0 @@
-
-Namespace myapp
-
-#Import "<std>"
-#Import "<mojo>"
-#Import "<mojo3d>"
-
-#Import "assets/"
-
-Using std..
-Using mojo..
-Using mojo3d..
-
-Class MyWindow Extends Window
-	
-	Field _scene:Scene
-	
-	Field _camera:Camera
-	
-	Field _light:Light
-	
-	Field _donut:Model
-	
-	Method New( title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=WindowFlags.Resizable )
-
-		Super.New( title,width,height,flags )
-		
-		_scene=Scene.GetCurrent()
-		
-		_scene.AmbientLight=Color.Black
-		
-		_scene.ClearColor=Color.Black
-		
-		ToggleEnv()
-		
-		'create camera
-		'
-		_camera=New Camera( Self )
-		_camera.Move( 0,0,-5 )
-		New FlyBehaviour( _camera )
-		
-		'create white donut
-		'		
-		Local material:=New PbrMaterial( Color.White,1,1 )
-		
-		_donut=Model.CreateTorus( 2,.5,48,24,material )
-	End
-	
-	Method ToggleEnv()
-		
-		Global _filter:TextureFlags=Null
-		
-		_filter=_filter ? Null Else TextureFlags.FilterMipmap
-			
-		'little mini cubemap
-		Local pixmap:=New Pixmap( 4,3 )
-		pixmap.Clear( Color.Black )
-		pixmap.SetPixelARGB( 1,0,$ffff0000 )
-		pixmap.SetPixelARGB( 1,1,$ff00ff00 )
-		pixmap.SetPixelARGB( 1,2,$ff0000ff )
-		pixmap.SetPixelARGB( 0,1,$ffffff00 )
-		pixmap.SetPixelARGB( 2,1,$ffff00ff )
-		pixmap.SetPixelARGB( 3,1,$ff00ffff )
-		Local cubemap:=New Texture( pixmap,TextureFlags.Cubemap|_filter )
-		
-		_scene.EnvTexture=cubemap
-		
-	End
-	
-	Method OnRender( canvas:Canvas ) Override
-	
-		RequestRender()
-		
-		If Keyboard.KeyHit( Key.Space ) ToggleEnv()
-		
-		_donut.Rotate( .1,.2,.3 )
-		
-		_scene.Update()
-		
-		_scene.Render( canvas )
-		
-		canvas.DrawText( "Hit <space> to toggle cubemap filtering (ie: seamless cubemaps)",0,0 )
-	End
-	
-End
-
-Function Main()
-
-	New AppInstance
-	
-	New MyWindow
-	
-	App.Run()
-End

+ 0 - 78
modules/mojo3d/tests/donut.monkey2

@@ -1,78 +0,0 @@
-
-Namespace myapp
-
-#Import "<std>"
-#Import "<mojo>"
-#Import "<mojo3d>"
-
-#Import "assets/"
-
-Using std..
-Using mojo..
-Using mojo3d..
-
-Function Main()
-	
-	New AppInstance
-	
-	New MyWindow
-	
-	App.Run()
-End
-
-Class MyWindow Extends Window
-	
-	Field _scene:Scene
-	
-	Field _camera:Camera
-	
-	Field _light:Light
-	
-	Field _donut:Model
-	
-	Method New( title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=WindowFlags.Resizable )
-
-		Super.New( title,width,height,flags )
-		
-		SetConfig( "MOJO3D_RENDERER","forward" )
-		
-		_scene=New Scene
-		
-		_scene.ClearColor=Color.Sky
-		
-		'create camera
-		'
-		_camera=New Camera( Self )
-		_camera.Move( 0,10,-10 )
-		
-		New FlyBehaviour( _camera )
-		
-		'create light
-		'
-		_light=New Light
-		_light.Rotate( 75,15,0 )
-		
-		'create donut - metallic silver...
-		
-		Local material:=New PbrMaterial( Color.Silver,1,0.5 )
-		
-		_donut=Model.CreateTorus( 2,.5,48,24,material )
-		
-		_donut.Move( 0,10,0 )
-	End
-	
-	Method OnRender( canvas:Canvas ) Override
-	
-		RequestRender()
-		
-		_donut.Rotate( .1,.2,.3 )
-		
-		_scene.Update()
-		
-		_camera.Render( canvas )
-		
-		canvas.DrawText( "Width="+Width+", Height="+Height+", FPS="+App.FPS,0,0 )
-	End
-	
-End
-

+ 0 - 131
modules/mojo3d/tests/ducks-scene.monkey2

@@ -1,131 +0,0 @@
-
-Namespace myapp
-
-#Import "<std>"
-#Import "<mojo>"
-#Import "<mojo3d>"
-
-#Reflect mojo3d
-
-#Import "assets/duck.gltf/@/duck.gltf"
-
-Using std..
-Using mojo..
-Using mojo3d..
-
-Class MyWindow Extends Window
-	
-	Field _scene:Scene
-	
-	Field _camera:Camera
-	
-	Field _light:Light
-	
-	Field _ground:Model
-	
-	Field _ducks:=New Stack<Model>
-	
-	Method New( title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=WindowFlags.Resizable )
-
-		Super.New( title,width,height,flags )
-		
-		'create scene
-		'		
-		_scene=New Scene( True )
-		
-		'for softer shadows
-		'
-		_scene.ShadowAlpha=.6
-		
-		'create camera
-		'
-		_camera=New Camera( Self )
-		_camera.Move( 0,15,-20 )
-		New FlyBehaviour( _camera )
-		
-		'create light
-		'
-		_light=New Light
-		_light.CastsShadow=True
-		_light.Rotate( 75,15,0 )
-		
-		'create ground
-		'
-		_ground=Model.CreateBox( New Boxf( -50,-1,-50,50,0,50 ),1,1,1,New PbrMaterial( Color.Green,0,1 ) )
-		_ground.CastsShadow=False
-		
-		'create ducks
-		'		
-		Local duck:=Model.Load( "asset::duck.gltf/Duck.gltf" )
-		duck.Mesh.FitVertices( New Boxf( -1,1 ) )
-		
-		Local root:=duck.Copy()
-		root.Move( 0,10,0 )
-		root.Scale=New Vec3f( 3 )
-		
-		_ducks.Push( root )
-		
-		For Local m:=0.0 To 1.0 Step .125
-		
-			For Local i:=0.0 Until 360.0 Step 24
-			
-				Local copy:=duck.Copy( root )
-				
-				copy.RotateY( i )
-				
-				copy.Move( 0,0,6+m*16 )
-
-				copy.Scale=New Vec3f( 1 )
-				
-				Local materials:=copy.Materials.Slice( 0 )
-				
-				For Local j:=0 Until materials.Length
-				
-					Local material:=Cast<PbrMaterial>( materials[j].Copy() )
-					
-					material.MetalnessFactor=m
-					material.RoughnessFactor=i/360.0
-					
-					materials[j]=material
-				Next
-				
-				copy.Materials=materials
-				
-				_ducks.Push( copy )
-			Next
-		Next
-		
-		duck.Destroy()
-		
-		_ducks[0].AddComponent<RotateBehaviour>().Speed=New Vec3f( 0,.01,0 )
-		
-		Print "Saving.."
-		
-		_scene.Save( "ducks-scene.mojo3d","modules/mojo3d/tests/assets/" )	'note: assets path is a bit of a hack! Need access to compile time assets dir path.
-		
-		Print "Loading..."
-		
-		_scene=Scene.Load( "ducks-scene.mojo3d" )
-	End
-	
-	Method OnRender( canvas:Canvas ) Override
-
-		RequestRender()
-		
-		_scene.Update()
-		
-		_scene.Render( canvas )
-
-		canvas.DrawText( "FPS="+App.FPS,Width,0,1,0 )
-	End
-	
-End
-
-Function Main()
-	
-	New AppInstance
-	
-	New MyWindow
-	
-	App.Run()
-End

+ 46 - 38
modules/mojo3d/tests/ducks.monkey2

@@ -5,6 +5,9 @@ Namespace myapp
 #Import "<mojo>"
 #Import "<mojo3d>"
 
+'uncomment this to create a mojo3d scene file in monkey2 dir!
+'#Reflect mojo3d
+
 #Import "assets/duck.gltf/@/duck.gltf"
 
 Using std..
@@ -15,46 +18,27 @@ Class MyWindow Extends Window
 	
 	Field _scene:Scene
 	
-	Field _camera:Camera
-	
-	Field _light:Light
-	
-	Field _ground:Model
-	
-	Field _ducks:=New Stack<Model>
-	
 	Method New( title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=WindowFlags.Resizable )
 
 		Super.New( title,width,height,flags )
 		
-		'create scene
-		'		
-		_scene=New Scene
-		
-		'for softer shadows
-		'
-		_scene.ShadowAlpha=.6
+		CreateScene()
+	End
+	
+	Method CreateGround()
 		
-		'create camera
-		'
-		_camera=New Camera( Self )
-		_camera.Move( 0,15,-20 )
+		Local box:=New Boxf( -50,-1,-50,50,0,50 )
 		
-		New FlyBehaviour( _camera )
+		Local material:=New PbrMaterial( Color.Green,0,1 )
 		
-		'create light
-		'
-		_light=New Light
-		_light.CastsShadow=True
-		_light.Rotate( 75,15,0 )
+		Local model:=Model.CreateBox( box,1,1,1,material )
 		
-		'create ground
-		'
-		_ground=Model.CreateBox( New Boxf( -50,-1,-50,50,0,50 ),1,1,1,New PbrMaterial( Color.Green,0,1 ) )
-		_ground.CastsShadow=False
+		model.CastsShadow=False
 		
-		'create ducks
-		'		
+	End
+	
+	Method CreateDucks()
+
 		Local duck:=Model.Load( "asset::duck.gltf/Duck.gltf" )
 		duck.Mesh.FitVertices( New Boxf( -1,1 ) )
 		
@@ -62,7 +46,7 @@ Class MyWindow Extends Window
 		root.Move( 0,10,0 )
 		root.Scale=New Vec3f( 3 )
 		
-		_ducks.Push( root )
+		root.AddComponent<RotateBehaviour>().Speed=New Vec3f( 0,-.01,0 )
 		
 		For Local m:=0.0 To 1.0 Step .125
 		
@@ -89,24 +73,48 @@ Class MyWindow Extends Window
 				Next
 				
 				copy.Materials=materials
-				
-				_ducks.Push( copy )
-			
 			Next
 		Next
 		
 		duck.Destroy()
 	End
 	
+	Method CreateScene()
+		
+		'create scene
+		'		
+		_scene=New Scene( True )
+		
+		'for softer shadows
+		'
+		_scene.ShadowAlpha=.6
+		
+		'create camera
+		'
+		Local camera:=New Camera( Self )
+		camera.AddComponent<FlyBehaviour>()
+		camera.Move( 0,15,-20 )
+		
+		'create light
+		'
+		Local light:=New Light
+		light.CastsShadow=True
+		light.Rotate( 90,0,0 )
+		
+		CreateGround()
+		
+		CreateDucks()
+		
+		If _scene.Editable _scene.Save( "ducks-scene.mojo3d","modules/mojo3d/tests/assets/" ) ; _scene=Scene.Load( "ducks-scene.mojo3d" )
+	End
+	
 	Method OnRender( canvas:Canvas ) Override
 
 		RequestRender()
 		
-		_ducks[0].Rotate( 0,-.01,0 )
-		
 		_scene.Update()
 		
-		_camera.Render( canvas )
+		_scene.Render( canvas )
 
 		canvas.DrawText( "FPS="+App.FPS,Width,0,1,0 )
 	End

+ 15 - 7
modules/mojo3d/tests/bloom.monkey2 → modules/mojo3d/tests/effects.monkey2

@@ -22,18 +22,23 @@ Class MyWindow Extends Window
 	
 	Field _bloom:BloomEffect
 	
+	Field _mono:MonochromeEffect
+	
 	Method New( title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=WindowFlags.Resizable )
 
 		Super.New( title,width,height,flags )
 		
 		_scene=Scene.GetCurrent()
-		
 		_scene.ClearColor=Color.Black
 		
 		_bloom=New BloomEffect
-		
+		_bloom.Enabled=True
 		_scene.AddPostEffect( _bloom )
 		
+		_mono=New MonochromeEffect
+		_mono.Enabled=False
+		_scene.AddPostEffect( _mono )
+		
 		'create camera
 		'
 		_camera=New Camera( self )
@@ -45,10 +50,10 @@ Class MyWindow Extends Window
 		_light=New Light
 		_light.RotateX( 90 )
 		
-		Local material:=New PbrMaterial( Color.Black )
-		material.EmissiveFactor=New Color( 0,2,0 )
+		Local material:=New PbrMaterial( New Color( 2,.5,0,1 ),0,1 )
 		
 		_donut=Model.CreateTorus( 2,.5,48,24,material )
+		_donut.AddComponent<RotateBehaviour>().Speed=New Vec3f( .1,.2,.3 )
 		
 		_donut.Move( 0,10,0 )
 	End
@@ -57,12 +62,15 @@ Class MyWindow Extends Window
 		
 		RequestRender()
 		
-		_donut.Rotate( .1,.2,.3 )
+		If Keyboard.KeyHit( Key.Key1 ) _bloom.Enabled=Not _bloom.Enabled
+
+		If Keyboard.KeyHit( Key.Key2 ) _mono.Enabled=Not _mono.Enabled
 		
-		_scene.Render( canvas )
+		_scene.Update()
 		
-		canvas.DrawText( "FPS="+App.FPS,Width,0,1,0 )
+		_scene.Render( canvas )
 		
+		canvas.DrawText( "Bloom="+_bloom.Enabled+" (1) monochrome="+_mono.Enabled+" (2)",0,0 )
 	End
 	
 End

+ 0 - 127
modules/mojo3d/tests/fishes.monkey2

@@ -1,127 +0,0 @@
-Namespace myapp
-
-#Import "<std>"
-#Import "<mojo>"
-#Import "<mojo3d>"
-
-#Import "assets/fish.glb"
-
-Using std..
-Using mojo..
-Using mojo3d..
-
-Class MyWindow Extends Window
-	
-	Field _scene:Scene
-	
-	Field _camera:Camera
-	
-	Field _light:Light
-	
-	Field _ground:Model
-	
-	Field _ducks:=New Stack<Model>
-	
-	Method New( title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=WindowFlags.Resizable )
-
-		Super.New( title,width,height,flags )
-		
-		Print "GL_VERSION="+opengl.glGetString( opengl.GL_VERSION )
-		
-'		SetConfig( "MOJO3D_RENDERER_DEFERRED",1 )
-		
-		SwapInterval=1
-		
-		'create scene
-		'		
-		_scene=New Scene
-		
-		_scene.ClearColor=Color.Sky
-		
-		_scene.ShadowAlpha=.5
-		
-		'create camera
-		'
-		_camera=New Camera( Self )
-		_camera.Near=.1
-		_camera.Far=50
-		_camera.FOV=90
-		_camera.Move( 0,15,-20 )
-		
-		New FlyBehaviour( _camera )
-		
-		'create light
-		_light=New Light
-		_light.Rotate( 75,15,0 )
-		_light.Range=40
-		_light.CastsShadow=True
-
-		'create ground
-		'
-		_ground=Model.CreateBox( New Boxf( -50,-1,-50,50,0,50 ),1,1,1,New PbrMaterial( Color.Green,0,1 ) )
-		_ground.CastsShadow=False
-		
-		'create ducks
-		'		
-		Local duck:=Model.Load( "asset::fish.glb" )
-		duck.Mesh.FitVertices( New Boxf( -1,1 ) )
-		
-		Local root:=duck.Copy()
-		root.Move( 0,10,0 )
-		root.Scale=New Vec3f( 3 )
-		
-		_ducks.Push( root )
-		
-		For Local m:=0.0 To 1.0 Step .125
-		
-			For Local i:=0.0 Until 360.0 Step 24
-			
-				Local copy:=duck.Copy( root )
-				
-				copy.RotateY( i )
-				
-				copy.Move( 0,0,6+m*16 )
-				
-				copy.Scale=New Vec3f( 1 )
-				
-				For Local j:=0 Until copy.Materials.Length
-				
-					Local material:=Cast<PbrMaterial>( copy.Materials[j].Copy() )
-					
-					material.MetalnessFactor=m
-					material.RoughnessFactor=i/360.0
-					
-					copy.Materials[j]=material
-				Next
-				
-				_ducks.Push( copy )
-			
-			Next
-		Next
-		
-		duck.Destroy()
-	End
-	
-	Method OnRender( canvas:Canvas ) Override
-
-		RequestRender()
-		
-		_scene.Update()
-		
-		_scene.Render( canvas )
-
-		canvas.Scale( Width/640.0,Height/480.0 )
-		
-		canvas.DrawText( "Width="+Width+", Height="+Height+", FPS="+App.FPS,0,0 )
-	End
-	
-End
-
-Function Main()
-
-	New AppInstance
-	
-	New MyWindow
-	
-	App.Run()
-End

+ 0 - 70
modules/mojo3d/tests/glb_test.monkey2

@@ -1,70 +0,0 @@
-Namespace myapp
-
-#Import "<std>"
-#Import "<mojo>"
-#Import "<mojo3d>"
-
-#Import "assets/platform.glb"
-
-Using std..
-Using mojo..
-Using mojo3d..
-
-Class MyWindow Extends Window
-	
-	Field _scene:Scene
-	
-	Field _camera:Camera
-	
-	Field _light:Light
-	
-	Field _model:Model
-	
-	Method New( title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=WindowFlags.Resizable )
-
-		Super.New( title,width,height,flags )
-		
-		_scene=Scene.GetCurrent()
-		
-		_scene.ClearColor=Color.Sky
-		
-		'create camera
-		'
-		_camera=New Camera( Self )
-		_camera.Move( 0,10,-10 )
-		
-		New FlyBehaviour( _camera )
-		
-		'create light
-		'
-		_light=New Light
-		_light.RotateX( 90 )
-		
-		'load glb model
-		'
-		_model=Model.Load( "asset::platform.glb" )
-	End
-	
-	Method OnRender( canvas:Canvas ) Override
-	
-		RequestRender()
-		
-		_model.Rotate( 1,2,3 )
-		
-		_scene.Update()
-		
-		_scene.Render( canvas )
-		
-		canvas.DrawText( "Width="+Width+", Height="+Height+", FPS="+App.FPS,0,0 )
-	End
-	
-End
-
-Function Main()
-
-	New AppInstance
-	
-	New MyWindow
-	
-	App.Run()
-End

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.