## Documentation

- Overview
- Website
- Tutorials
- Class Index

CopperLicht API Documentation
All tutorials

# CopperLicht Tutorial: 2D Overlays

This tutorial demonstrates 2d text overlays, how to caculate the 2d position from a 3d position and how to use the OnAnimate handler.
The final result of this tutorial will look about like this:
The 2d overlays in action over a couple of billboards

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

## Writing CopperLicht code

For this tutorial we don't need the 3d editor CopperCube, everything we are doing here is writing code. To keep this simple and short, the following is the full code of this example. I'll explain it in detail below.

    <html>
    <head>
    	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
    	<script type="text/javascript" src="copperlicht.js"></script>
    </head>
    <body>
    	<b>Tutorial 04: 2D Overlays.</b><br/>
    	Demonstrates 2d text overlays, how to caculate the 2d position from a 3d position and how to use the OnAnimate handler.
    	<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.
    		</div>
    		<div style="display:block; color:#ffffff; padding:5px; position:absolute; left:20px; top:20px; background-color:#000000; height:20px; width:60px; border-radius:5px; border:1px solid #777777; opacity:0.5;" id="originlabel">
    			The Origin
    		</div>
    	</div>
    	<script type="text/javascript">
    	<!--
    	main = function()
    	{
    		// create the 3d engine
    		var engine = new CL3D.CopperLicht('3darea');

    		if (!engine.initRenderer())
    			return; // this browser doesn't support WebGL

    		// add a new 3d scene

    		var scene = new CL3D.Scene();
    		engine.addScene(scene);

    		scene.setBackgroundColor(CL3D.createColor(1, 0, 0, 0));
    		scene.setRedrawMode(CL3D.Scene.REDRAW_WHEN_SCENE_CHANGED);

    		// add a transparent billboard scene node with a text sign
    		for (var i=0; i<50; ++i)
    		{
    			var billboard = new CL3D.BillboardSceneNode();
    			billboard.setSize(30, 30);
    			billboard.Pos.X = Math.random() * 80 - 40;
    			billboard.Pos.Y = Math.random() * 80 - 40;
    			billboard.Pos.Z = Math.random() * 80 - 40;
    			billboard.getMaterial(0).Tex1 = engine.getTextureManager().getTexture("particle.png", true);
    			billboard.getMaterial(0).Type = CL3D.Material.EMT_TRANSPARENT_ADD_COLOR;
    			scene.getRootSceneNode().addChild(billboard);
    		}

    		// add a user controlled camera with a first person shooter style camera controller
    		var cam = new CL3D.CameraSceneNode();
    		cam.Pos.X = 50;
    		cam.Pos.Y = 20;

    		var animator = new CL3D.AnimatorCameraFPS(cam, engine);
    		cam.addAnimator(animator);
    		animator.lookAt(new CL3D.Vect3d(0,20,0));

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

    		// draw handler
    		var pos3d = new CL3D.Vect3d(0,0,0);

    		engine.OnAnimate = function()
    		{
    			var element = document.getElementById('originlabel');
    			if (element)
    			{
    				// set the position of the label to the 2d position of the 3d point

    				var pos2d = engine.get2DPositionFrom3DPosition(pos3d);
    				var hide = false;

    				if (pos2d)
    				{
    					element.style.left = pos2d.X;
    					element.style.top = pos2d.Y;

    					// hide if outside of the border
    					hide = pos2d.X < 0 || pos2d.Y < 0 ||
    						pos2d.X > engine.getRenderer().getWidth()-60 ||
    						pos2d.Y > engine.getRenderer().getHeight()-20;
    				}
    				else
    					hide = true;

    				element.style.display = hide ? 'none' : 'block';
    			}
    		}
    	}

    	main();
    	-->
    	</script>
    </body>
    </html>

Create a .html file and paste this code into there, place the copperlicht.js file from the CopperLicht SDK in the same directory, and add a.png file named particle.png which is used in this example as textures.

## What the code does

The first few lines of the html code are creating a canvas element inside a container. Inside this container, there are two <div>>'s, used for the 2d overlays. The style of these divs with its absolute positioning is making it possible to move them over the canvas. Notice that we set the ids of the <div>>'s to something meaningful, so that we have access to them later:

    <html>
    <head>
      <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
      <script type="text/javascript" src="copperlicht.js"></script>
    </head>
    <body>
      <b>Tutorial 04: 2D Overlays.</b><br/>
      Demonstrates 2d text overlays, how to caculate the 2d position from a 3d position and how to use the OnAnimate handler.
      <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.
        </div>
        <div style="display:block; color:#ffffff; padding:5px; position:absolute; left:20px; top:20px; background-color:#000000; height:20px; width:60px; border-radius:5px; border:1px solid #777777; opacity:0.5;" id="originlabel">
          The Origin
        </div>
      </div>

So let's start with the javascript code. First, we simply initialize the 3d engine and create a scene, and set it's background color and redraw mode:

     <script type="text/javascript">
      <!--
      main = function()
      {
        // create the 3d engine
        var engine = new CL3D.CopperLicht('3darea');

        if (!engine.initRenderer())
          return; // this browser doesn't support WebGL

       // add a new 3d scene

        var scene = new CL3D.Scene();
        engine.addScene(scene);

        scene.setBackgroundColor(CL3D.createColor(1, 0, 0, 0));
        scene.setRedrawMode(CL3D.Scene.REDRAW_WHEN_SCENE_CHANGED);

In oder to make the scene a little bit more interesting, we add 50 billboards at random positions:

        // add a transparent billboard scene node with a text sign
        for (var i=0; i<50; ++i)
        {
          var billboard = new CL3D.BillboardSceneNode();
          billboard.setSize(30, 30);
          billboard.Pos.X = Math.random() * 80 - 40;
          billboard.Pos.Y = Math.random() * 80 - 40;
          billboard.Pos.Z = Math.random() * 80 - 40;
          billboard.getMaterial(0).Tex1 = engine.getTextureManager().getTexture("particle.png", true);
          billboard.getMaterial(0).Type = CL3D.Material.EMT_TRANSPARENT_ADD_COLOR;
          scene.getRootSceneNode().addChild(billboard);
        }

And of course, we need a camera from which the 3d scene is rendered. We place it at 50, 20 and add an animator to it so that we can move the camera using the cursor keys and the mouse:

        // add a user controlled camera with a first person shooter style camera controller
        var cam = new CL3D.CameraSceneNode();
        cam.Pos.X = 50;
        cam.Pos.Y = 20;

        var animator = new CL3D.AnimatorCameraFPS(cam, engine);
        cam.addAnimator(animator);
        animator.lookAt(new CL3D.Vect3d(0,20,0));

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

And now for the more interesting part: We would like one of the 2D overlays we created above to move. For simplicity, we want the overlay to be over a 3d position. We use the origin, (0,0,0) in this example, but of course any other position is possible as well. To find the 2D position from a 3d position, we can use CopperLichts get2DPositionFrom3DPosition function. Notice that this function does not always return a 2D point, but sometimes null, for example when the point is behind the camera. In this case, we need to hide the 2D overlay, of course. And this is what we are doing with this code, which is called everytime the 3d engine in animating the scene. We do this by registering our function with the Copperlicht OnAnimate even handler:

          // move 2d overlay to this 3d position every frame
        var pos3d = new CL3D.Vect3d(0,0,0);

        engine.OnAnimate = function()
        {
          var element = document.getElementById('originlabel');
          if (element)
          {
            // set the position of the label to the 2d position of the 3d point

            var pos2d = engine.get2DPositionFrom3DPosition(pos3d);
            var hide = false;

            if (pos2d)
            {
              element.style.left = pos2d.X;
              element.style.top = pos2d.Y;

              // hide if outside of the border
              hide = pos2d.X < 0 || pos2d.Y < 0 ||
                pos2d.X > engine.getRenderer().getWidth()-60 ||
                pos2d.Y > engine.getRenderer().getHeight()-20;
            }
            else
              hide = true;

            element.style.display = hide ? 'none' : 'block';
          }
        }
      }

That's it basically. We put all this code into a function named 'main', so we only need to call it.

        main();

And that's it, now you know how to use 2D overlays in CopperLicht.
More Tutorials

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