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:

copperlicht tutorial 1
The 2d overlays in action over a couple of billboards


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 CopperLicht('3darea');
    
    if (!engine.initRenderer())
      return; // this browser doesn't support WebGL
      
    // add a new 3d scene
    
    var scene = new Scene();
    engine.addScene(scene);
    
    scene.setBackgroundColor(Core.createColor(1, 0, 0, 0));
    scene.setRedrawMode(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 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 = 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 CameraSceneNode();
    cam.Pos.X = 50;
    cam.Pos.Y = 20;
    
    var animator = new AnimatorCameraFPS(cam, engine);                    
    cam.addAnimator(animator);                    
    animator.lookAt(new Vect3d(0,20,0));      
    
    scene.getRootSceneNode().addChild(cam);
    scene.setActiveCamera(cam);        

    // move 2d overlay to this 3d position every frame
    var pos3d = new 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 CopperLicht('3darea');
    
    if (!engine.initRenderer())
      return; // this browser doesn't support WebGL
      
   // add a new 3d scene
    
    var scene = new Scene();
    engine.addScene(scene);
    
    scene.setBackgroundColor(Core.createColor(1, 0, 0, 0));
    scene.setRedrawMode(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 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 = 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 CameraSceneNode();
    cam.Pos.X = 50;
    cam.Pos.Y = 20;
    
    var animator = new AnimatorCameraFPS(cam, engine);                    
    cam.addAnimator(animator);                    
    animator.lookAt(new 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 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


© 2010 N.Gebhardt, Ambiera
Documentation generated by JsDoc Toolkit