Monday, July 16, 2012

Rotating Camera about Gladius Avatar

‹prev | My Chain | next›

I got a pretty sweet walking Gladius-based avatar put together last night. Tonight, I'd like to work with the camera so that it rotates nicely around the avatar.

I start by doing my new favorite thing in Gladius: adding another frame of reference to make subsequent movement and positioning easier. In this case, I add a frame of reference that is tied to the body of the avatar and then position the camera relative to this:
      function game(engine, resources) {
        var math = engine.math;
        var space = new engine.SimulationSpace();
        var cubicvr = engine.findExtension("gladius-cubicvr");

        // add avatar bits and pieces...

        space.add(new engine.Entity("camera-frame",
          [
            new engine.core.Transform()
          ],
          [],
          space.findNamed("body")
        ));

        space.add(new engine.Entity("camera",
          [
            new engine.core.Transform([0, 10, 23], [-Math.PI/8, 0, 0]),
            new cubicvr.Camera()
          ],
          ["avatar"],
          space.findNamed("camera-frame")
        ));

        // Game tasks here...
      }
Next, I add the gladius-input extension to my required modules so that I can use it to manipulate the camera:
  require(
    [ "gladius-core", "gladius-cubicvr", "gladius-input" ],
    function( Gladius, cubicvrExtension, inputExtension ) {
      var engine = new Gladius();

      // Set up mesh and materials

      function game(engine, resources) {
        // Game code here...
      }
    });
When I register the extension as listening to the web page's document element, however, I start seeing already completed errors. Oddly, this is resolved by defining the logic controllers in the game() core function. It is a bit frustrating not knowing if these errors are due to a missing input definition or because I have broken something else. I probably need to investigate this closer another day.

To define the controls, I first need to define the various input states in which my camera can be. For now, this will include "PanLeft" and "PanRight":
require(
    [ "gladius-core", "gladius-cubicvr", "gladius-input" ],
    function( Gladius, cubicvrExtension, inputExtension ) {
      var engine = new Gladius();

      // Set up mesh and materials...

      // Input states
      var cameraControls = new engine["gladius-input"].Map({
        "States": {
          "PanLeft":      [ "J" ],
          "PanRight":     [ "K" ]
        }
      });
      resources['camera_controls'] = cameraControls;


      function game(engine, resources) {
        // Game code here...
      }
    });
All that remains now is to add the input controller (based on the states defined above) and an actor to effect changes in the game based on these states:
      function game(engine, resources) {
        var math = engine.math;
        var space = new engine.SimulationSpace();
        var cubicvr = engine.findExtension("gladius-cubicvr");
        var input = engine.findExtension( "gladius-input" );


        // Add other bits and pieces to the game...

        // Camera input logic
        var cameraLogic = {
          "Update": function(event) {
            if (!this.owner.hasComponent("Controller")) return;

            var controller = this.owner.findComponent("Controller")
              , transform = this.owner.findComponent("Transform");

            var rotation;
            if (controller.states["PanLeft"]) {
              rotation = [0, -space.clock.delta * 0.001, 0];
            }
            if (controller.states["PanRight"])
              rotation = [0, space.clock.delta * 0.001, 0];

            if (rotation)
              transform.setRotation(math.vector3.add(rotation, transform.rotation));
          }
        };

        space.add(new engine.Entity("camera-frame",
          [
            new engine.core.Transform(),
            new input.Controller( resources.camera_controls ),
            new engine.logic.Actor( cameraLogic )
          ],
          [],
          space.findNamed("body")
        ));

        // The rest of the game here ...
      }
The result is that I watch the avatar from the side:


And rotate around to view from the front as well:


As I found yesterday when I got the avatar limbs swinging in unison, intermediate frames of reference come in extremely handy. There is a downside of additional code for these extra frames of reference. It is manageable, but I may need some higher level code for kids — at least when introducing these concepts.


Day #449

No comments:

Post a Comment