## Documentation

- Overview
- Website
- Tutorials
- Class Index

CopperLicht API Documentation
All tutorials

# CopperLicht Tutorial: Collision detection and response

This tutorial demonstrates how to do collision detection in CopperLicht.
The final result of this tutorial will look about like this:
A room where the user cannot move trough walls, and he can walk up stairs.

- Show live demo of this tutorial
- Download this tutorial as zip archive.

## Creating a room

In order to collide against walls, we need a room. Start up the 3d editor CopperCube and create a simple room, like in this example:
In the zip archive of this tutorial, you'll find a .ccb file named room.ccb which contains exactly this example, you can also use this one.
Use CopperCube to save the scene into a directory of your choice and publish the scene as WebGL/JavaScript (Choose Tools -> Test as JavaScript/WebGL). This will create a .ccbjs or .ccbz file with this scene which we can load using CopperLicht.

## Writing CopperLicht code

Now create a .html file in that directory and paste the following code into it. What it does will be explained in detail below.

    <html>
    <head>
    	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
    	<script type="text/javascript" src="copperlichtdata/copperlicht.js"></script>
    </head>
    <body>
    	<b>Tutorial 06: Collision detection.</b><br/>
    	Demonstrates how to do various ways of collision detection: Walking around in a room and picking the wall<br/><br/>
    	<div style="width:640px; margin:auto; position:relative; font-size: 9pt; color: #777777;">
    		<canvas id="3darea" width="640" height="480" style="background-color:#000000">
    		</canvas>
    		<div style="display:block; color:#ffffff; padding:5px; position:absolute; left:20px; top:420px; background-color:#000000; height:37px; width:300px; border-radius:5px; border:1px solid #777777; opacity:0.5;" id="helptext">
    			Look with the mouse, move with the cursor keys or WASD. Press space to 'shoot' a cube at the next wall.
    		</div>
    	</div>
    	<script type="text/javascript">
    	<!--
    	var engine = startCopperLichtFromFile('3darea', 'copperlichtdata/room.ccbjs');
    	var cubeCollisionPosition = null;
    	// this is called when loading the 3d scene has finished

    	engine.OnLoadingComplete = function()
    	{
    		var scene = engine.getScene();
    		if (!scene)
    			return;

    		// in the CopperCube 3d editor, we already created a camera which collides against the wall in this scene.
    		// But to demonstrate how this would work manually, we create a new camera here which does this as well:

    		// add a user controlled camera

    		var cam = new CL3D.CameraSceneNode();

    		// ensure to place the camera inside the room, or it will fall out, into the endless void

    		cam.Pos.X = -50;
    		cam.Pos.Y = 180;
    		cam.Pos.Z = -20;

    		// add an animator which makes the camera move by keyboard and mouse input

    		var animator = new CL3D.AnimatorCameraFPS(cam, engine);
    		animator.MoveSpeed = 0.2;
    		animator.RotateSpeed = 250;
    		animator.setLookByMouseDown(false); //  look when the mouse is moved
    		cam.addAnimator(animator);

    		animator.lookAt(new CL3D.Vect3d(-200,90,200));

    		scene.getRootSceneNode().addChild(cam);
    		scene.setActiveCamera(cam);

    		// add the collision response animator to collide against walls

    		var colanimator = new CL3D.AnimatorCollisionResponse(
    			new CL3D.Vect3d(20,40,20), // size of the player ellipsoid
    			new CL3D.Vect3d(0,30,0), // position of the eye in the ellipsoid
    			scene.getCollisionGeometry());

    		cam.addAnimator(colanimator);
    	}

    	// every time the user presses space, we want to do a collision test with the wall
    	// and create a cube where we hit the wall

    	document.onkeyup = function(event)
    	{
    		var scene = engine.getScene();
    		if (!scene)
    			return;

    		if (event.keyCode == 32) // space has been pressed
    		{
    			var cam = scene.getActiveCamera();

    			// calculate the start and end 3d point of the line, the beinning being
    			// the camera position and the end about 2000 units away in the direction of the
    			// camera target

    			var startLine = cam.getAbsolutePosition();
    			var endLine = startLine.add(cam.getTarget().substract(startLine).multiplyWithScal(2000));

    			// test our line for a collision with the world

    			var collisionPoint = scene.getCollisionGeometry().getCollisionPointWithLine(startLine, endLine, true, null);

    			if (collisionPoint)
    			{
    				// a collision has been found.
    				// create a cube at the point where the collision happened

    				if (!cubeCollisionPosition)
    				{
    					cubeCollisionPosition = new CL3D.CubeSceneNode();
    					scene.getRootSceneNode().addChild(cubeCollisionPosition);
    					cubeCollisionPosition.getMaterial(0).Tex1 = engine.getTextureManager().getTexture('ground_stone.jpg', true);
    				}

    				cubeCollisionPosition.Pos = collisionPoint;
    			}
    		}

    		// we need to call the key handler of the 3d engine as well, so that the user is
    		// able to move the camera using the keys
    		engine.handleKeyUp(event);
    	};
    	-->
    	</script>
    </body>
    </html>

Also, put a .jpg file named 'ground_stone.jpg' into that directory, so that the cube will have a texture.

## What the code does

As always, the first few lines of the html code are creating a canvas element inside a container. Inside this container, there is a <div>, used for the 2d overlay. The style of these divs with its absolute positioning is making it possible to move them over the canvas:

    <html>
    <head>
      <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
      <script type="text/javascript" src="copperlichtdata/copperlicht.js"></script>
    </head>
    <body>
      <b>Tutorial 06: Collision detection.</b><br/>
      Demonstrates how to do various ways of collision detection: Walking around in a room and picking the wall<br/><br/>
      <div style="width:640px; margin:auto; position:relative; font-size: 9pt; color: #777777;">
        <canvas id="3darea" width="640" height="480" style="background-color:#000000">
        </canvas>
        <div style="display:block; color:#ffffff; padding:5px; position:absolute; left:20px; top:420px; background-color:#000000; height:37px; width:300px; border-radius:5px; border:1px solid #777777; opacity:0.5;" id="helptext">
          Look with the mouse, move with the cursor keys or WASD. Press space to 'shoot' a cube at the next wall.
        </div>
      </div>

So let's start with the javascript code. First, we simply initialize the 3d engine and tell it to load the scene file we created in the editor. You might have to adjust the file name of the .ccbjs file to fit the name you picked when saving the scene. We also store a variable named cubeCollisionPosition where we later save a scene node used to mark the position where we hit the wall when 'shooting':

    <script type="text/javascript">
      <!--
      var engine = startCopperLichtFromFile('3darea', 'copperlichtdata/room.ccbjs');
      var cubeCollisionPosition = null;

Next, we add a camera to the scene when the .ccbjs file has finished loading. But this time, the camera should not only move when the user presses the cursor keys which is achieved using a AnimatorCameraFPS, we also want the camera to collide against walls. For this, we also add another animator which is named AnimatorCollisionResponse. The AnimatorCollisionResponse gets several parameters like the size of the player, and also the collision geometry as a triangle selector. Luckly, we don't have to create this triangle selector ourselves, we can simply use the one of the scene by calling scene.getCollisionGeometry(). This is done here:

      engine.OnLoadingComplete = function()
      {
        var scene = engine.getScene();
        if (!scene)
          return;

         // in the CopperCube 3d editor, we already created a camera which collides against the wall in this scene.
        // But to demonstrate how this would work manually, we create a new camera here which does this as well:

         // add a user controlled camera

        var cam = new CL3D.CameraSceneNode();

         // ensure to place the camera inside the room, or it will fall out, into the endless void

        cam.Pos.X = -50;
        cam.Pos.Y = 180;
        cam.Pos.Z = -20;

         // add an animator which makes the camera move by keyboard and mouse input

        var animator = new CL3D.AnimatorCameraFPS(cam, engine);
        animator.MoveSpeed = 0.2;
        animator.RotateSpeed = 250;
    	animator.setLookByMouseDown(false); //  look when the mouse is moved
        cam.addAnimator(animator);
        animator.lookAt(new CL3D.Vect3d(-200,90,200));

        scene.getRootSceneNode().addChild(cam);
        scene.setActiveCamera(cam);

         // add the collision response animator to collide against walls

        var colanimator = new CL3D.AnimatorCollisionResponse(
          new CL3D.Vect3d(20,40,20),   // size of the player ellipsoid
          new CL3D.Vect3d(0,30,0),   // position of the eye in the ellipsoid
          scene.getCollisionGeometry());

        cam.addAnimator(colanimator);
      }

Instead of scene.getCollisionGeometry(), we could have also supplied some other collision geometry represented as TriangleSelector. Triangle selectors in CopperLicht simply provide a way to access geometry. If you have a Mesh for example, you can create a new triangle selector using new MeshTriangleSelector(yourMesh, yourSceneNode);. If the mesh is big, you could use new OctTreeTriangleSelector(yourMesh, yourSceneNode) instead to speed up the collision queries a bit.
CopperLicht automaticly provides a triangle selector for all geometry where the 'Collision' attribute was checked in the editor via scene.getCollisionGeometry(), so you won't have to build it yourself.
You could try out the program already now, it should work and you can walk around in the room without being able to walk through walls. But to demonstrate another collision detection feature, we'll add this final code part:

      // every time the user presses space, we want to do a collision test with the wall
      // and create a cube where we hit the wall

      document.onkeyup = function(event)
      {
        var scene = engine.getScene();
        if (!scene)
          return;

        if (event.keyCode == 32) // space has been pressed
        {
          var cam = scene.getActiveCamera();

          // calculate the start and end 3d point of the line, the beinning being
          // the camera position and the end about 2000 units away in the direction of the
          // camera target

          var startLine = cam.getAbsolutePosition();
          var endLine = startLine.add(cam.getTarget().substract(startLine).multiplyWithScal(2000));

          // test our line for a collision with the world

          var collisionPoint = scene.getCollisionGeometry().getCollisionPointWithLine(startLine, endLine, true, null);

          if (collisionPoint)
          {
            // a collision has been found.
            // create a cube at the point where the collision happened

            if (!cubeCollisionPosition)
            {
              cubeCollisionPosition = new CL3D.CubeSceneNode();
              scene.getRootSceneNode().addChild(cubeCollisionPosition);
              cubeCollisionPosition.getMaterial(0).Tex1 = engine.getTextureManager().getTexture('ground_stone.jpg', true);
            }

            cubeCollisionPosition.Pos = collisionPoint;
          }
        }

        // we need to call the key handler of the 3d engine as well, so that the user is
        // able to move the camera using the keys
        engine.handleKeyUp(event);
      };
      -->
      </script>
      </body>
    </body>
    </html>

Basically, we just added a function which causes a cube to be created at the point of the wall we are looking at when pressing SPACE. To find this collision point, we used the getCollisionPointWithLine() function of the TriangleSelector class. It returns the collision point as Vect3d or null if there was no collision.
And that's it, now you know how to do basic collision detection in CopperLicht.
More Tutorials

© 2011-2018 N.Gebhardt, Ambiera
Documentation generated by JsDoc Toolkit