1 module gamelayer; 2 3 import std.stdio; 4 5 import derelict.sdl.sdl; 6 import derelict.opengl.gl; 7 8 import dlib.math.vector; 9 import dlib.math.matrix; 10 import dlib.math.affine; 11 import dlib.geometry.triangle; 12 import dlib.image.color; 13 14 import dgl.core.layer; 15 import dgl.core.event; 16 import dgl.core.drawable; 17 import dgl.graphics.material; 18 import dgl.graphics.shapes; 19 import dgl.graphics.lamp; 20 import dgl.scene.tbcamera; 21 import dgl.vfs.vfs; 22 import dgl.asset.dgl; 23 import dgl.scene.scene; 24 25 import dmech.world; 26 import dmech.rigidbody; 27 import dmech.geometry; 28 import dmech.shape; 29 import dmech.bvh; 30 import dmech.contact; 31 32 import cc; 33 import gameobj; 34 import tpcamera; 35 36 // TODO: This function is total hack, 37 // need to rewrite BVH module to handle Triangle ranges, 38 // and add a method to Scene that will lazily return 39 // transformed triangles for entities. 40 BVHTree!Triangle sceneBVH(Scene scene) 41 { 42 Triangle[] tris; 43 foreach(entity; scene.entities) 44 { 45 if (entity.type == 0) 46 if (entity.meshId > -1) 47 { 48 Matrix4x4f mat = Matrix4x4f.identity; 49 mat *= translationMatrix(entity.position); 50 mat *= entity.rotation.toMatrix4x4; 51 mat *= scaleMatrix(entity.scaling); 52 53 auto mesh = scene.mesh(entity.meshId); 54 foreach(fgroup; mesh.fgroups) 55 foreach(tri; fgroup.tris) 56 { 57 Triangle tri2 = tri; 58 tri2.v[0] = tri.v[0] * mat; 59 tri2.v[1] = tri.v[1] * mat; 60 tri2.v[2] = tri.v[2] * mat; 61 tri2.normal = entity.rotation.rotate(tri.normal); 62 tri2.barycenter = (tri2.v[0] + tri2.v[1] + tri2.v[2]) / 3; 63 64 tris ~= tri2; 65 } 66 } 67 } 68 return new BVHTree!Triangle(tris, 4); 69 } 70 71 class GameLayer: Layer 72 { 73 EventManager emanager; 74 VirtualFileSystem vfs; 75 76 PhysicsWorld world; 77 RigidBody activeBody; 78 79 enum double fixedDelta = 1.0 / 60.0; 80 81 Scene scene; 82 BVHTree!Triangle bvh; 83 84 GameObject poRobot; 85 CharacterController ccRobot; 86 TrackballCamera camera; 87 ThirdPersonCamera tpcamera; 88 89 this(uint w, uint h, int depth, EventManager emanager) 90 { 91 super(0, 0, w, h, LayerType.Layer3D, depth); 92 alignToWindow = true; 93 94 this.emanager = emanager; 95 96 // Create VFS 97 vfs = new VirtualFileSystem(); 98 vfs.mount("data/testlevel"); 99 100 // Create pysics world 101 world = new PhysicsWorld(10000); 102 103 // Create floor object 104 auto geomFloorBox = new GeomBox(Vector3f(100, 1, 100)); 105 RigidBody bFloor = world.addStaticBody(Vector3f(0, -2, 0)); 106 world.addShapeComponent(bFloor, geomFloorBox, Vector3f(0, 0, 0), 1); 107 108 buildPyramid(Vector3f(5, 0, 0), 4, 0); 109 110 // Create robot object 111 Vector3f initPosition = Vector3f(4.0f, 6.0f, 0.0f); 112 ccRobot = new CharacterController(world, initPosition, 1.0f); 113 poRobot = new GameObject(); 114 poRobot.drawable = new ShapeSphere(1.0f); 115 poRobot.shape = ccRobot.rbody.shapes[0]; 116 addDrawable(poRobot); 117 118 auto geomPlatform = new GeomBox(Vector3f(1, 1, 1)); 119 auto platformBody = world.addDynamicBody(Vector3f(-5, 5, 0)); 120 platformBody.bounce = 0.8f; 121 world.addShapeComponent(platformBody, geomPlatform, Vector3f(0, 0, 0), 1.0f); 122 auto platformObj = new GameObject(); 123 platformObj.drawable = new ShapeBox(Vector3f(1, 1, 1)); 124 platformObj.shape = platformBody.shapes[0]; 125 addDrawable(platformObj); 126 127 // Create lamp 128 Lamp lamp = new Lamp(Vector4f(10.0f, 20.0f, 5.0f, 1.0f)); 129 addDrawable(lamp); 130 131 // Create camera 132 tpcamera = new ThirdPersonCamera(); 133 addModifier(tpcamera); 134 135 // Create scene 136 auto istrm = vfs.openForInput("testlevel.dgl"); 137 scene = loadScene(istrm, vfs); 138 addDrawable(scene); 139 bvh = sceneBVH(scene); 140 world.bvhRoot = bvh.root; 141 } 142 143 double time = 0.0; 144 override void onUpdate(EventManager emngr) 145 { 146 time += emngr.deltaTime; 147 if (time >= fixedDelta) 148 { 149 time -= fixedDelta; 150 151 if (emngr.key_pressed[SDLK_DOWN]) ccRobot.move(-10.0f); 152 if (emngr.key_pressed[SDLK_UP]) ccRobot.move(10.0f); 153 if (emngr.key_pressed[SDLK_LEFT]) ccRobot.turn(-5.0f); 154 if (emngr.key_pressed[SDLK_RIGHT]) ccRobot.turn(5.0f); 155 if (emngr.key_pressed[SDLK_SPACE]) ccRobot.jump(3.0f); 156 157 ccRobot.update(); 158 159 world.update(fixedDelta); 160 } 161 162 ccRobot.updateMatrix(); 163 poRobot.localTransformation = ccRobot.localMatrix; 164 tpcamera.playerDirection = ccRobot.direction; 165 tpcamera.playerPosition = ccRobot.rbody.position; 166 } 167 168 void buildPyramid(Vector3f pyramidPosition, uint pyramidSize, uint pyramidGeom = 0) 169 { 170 float size = 1.0f; 171 172 float cubeHeight = 2.0f; 173 174 auto box = new ShapeBox(Vector3f(size, cubeHeight * 0.5f, size)); 175 auto cyl = new ShapeCylinder(2.0f, 1.0f); 176 auto con = new ShapeCone(2.0f, 1.0f); 177 auto sph = new ShapeSphere(1.0f); 178 179 float width = size * 2.0f; 180 float height = cubeHeight; 181 float horizontal_spacing = 0.1f; 182 float veritcal_spacing = 0.1f; 183 184 auto geomBox = new GeomBox(Vector3f(size, cubeHeight * 0.5f, size)); 185 auto geomCylinder = new GeomCylinder(2.0f, 1.0f); 186 auto geomSphere = new GeomSphere(size); 187 auto geomCone = new GeomCone(2.0f, 1.0f); 188 189 foreach(i; 0..pyramidSize) 190 foreach(e; i..pyramidSize) 191 { 192 auto position = pyramidPosition + Vector3f( 193 (e - i * 0.5f) * (width + horizontal_spacing) - ((width + horizontal_spacing) * 5), 194 6.0f + (height + veritcal_spacing * 0.5f) + i * height + 0.26f, 195 -3); 196 197 Geometry g; 198 Drawable gobj; 199 200 switch(pyramidGeom) 201 { 202 case 0: 203 g = geomBox; 204 gobj = box; 205 break; 206 case 1: 207 g = geomCylinder; 208 gobj = cyl; 209 break; 210 case 2: 211 g = geomSphere; 212 gobj = sph; 213 break; 214 case 4: 215 g = geomCone; 216 gobj = con; 217 break; 218 default: 219 assert(0); 220 } 221 222 auto b = world.addDynamicBody(position, 0); 223 world.addShapeComponent(b, g, Vector3f(0, 0, 0), 1); 224 225 auto gameObj = new GameObject(); 226 gameObj.drawable = gobj; 227 gameObj.shape = b.shapes[0]; 228 229 Material mat = new Material(); 230 auto col = Color4f((randomUnitVector3!float + 0.5f).normalized); 231 mat.ambientColor = col; 232 mat.diffuseColor = col; 233 gameObj.material = mat; 234 235 addDrawable(gameObj); 236 } 237 } 238 }