BRender Tutorial Guide:4 Actor Hierarchies
Next|Prev|Up

4 Actor Hierarchies

The animations we have created up to now have described uncomplicated scenes containing basic geometric shapes, each individually specified and positioned. Now, consider how much more difficult it would be to describe a complex 3D animation containing spatially interdependent models - say a representation of our solar system. How would you describe the path of the Moon orbiting the Earth, which in turn orbits the Sun? Or the motion of the hands of a clock located inside a space ship hurtling through space?

Complex models or scenes are constructed as actor hierarchies. A hierarchy allows you to think of an actor in terms of its spatial relationship to another, parent, actor. An actor hierarchy can can then be broken down into a series of fairly simple spatial relationships, or transformations, between actors.

A hierarchical model of part of our solar system is represented in Figure 35.

Figure 35 Hierarchical model of solar system

The motion of the Moon can be described relative to the position of the Earth, and that of the Earth relative to the position of the Sun. If we can keep track of the motion of the Moon relative to the Earth and of the motion of the Earth relative to the Sun, then the Moon's path through space can be computed. The position of the Moon at any time can be described by the concatenation of a series of matrices representing relative displacements, or transformations.

BRTUTOR3.C implements a simple three-layer hierarchical tree structure. Compile and run it to create a `satellite' orbiting a `moon' orbiting a `planet' animation.

Note that `moon' is defined as a child of `planet',

	moon = BrActorAdd(planet,BrActorAllocate(BR_ACTOR_MODEL,NULL));
and `satellite' is defined as a child of `moon',

	satellite = BrActorAdd(moon,BrActorAllocate(BR_ACTOR_MODEL,NULL));
The actor hierarchy depicted in Figure 36 results.

Figure 36 Planet, Moon, Satellite actor hierarchy

All three models are created using the same model data file, sph16.dat, in which a number of triangular polygons are combined to approximate the surface of a sphere. A more accurate approximation could be obtained using sph32.dat or sph4096.dat. Substitute sph8.dat for a cruder approximation. As always, you'll find there's a trade-off between speed and image quality.

The `universe' (or root actor) co-ordinate system serves as an absolute frame of reference within the application and could be thought of as `World Space' (or the application coordinate system).

The `planet' is transformed into its parent co-ordinate system (`World Space'). The identity transform is assumed, since no transformation has been explicitly defined. Note that the camera has been translated 6 units along the positive zaxis to ensure that the `planet' is visible.

The `moon' is uniformly scaled before being translated +2 units in z, in the planet's co-ordinate system. Since the camera has been translated +6 units in z the net result, as far as the viewer is concerned, is to position the `moon' between the view position and the planet.


BRTUTOR3.C

/* 
 * Copyright (c) 1996 Argonaut Technologies Limited. All rights reserved.
 * Program to Display Planet, Moon Satellite Animation.
 */
#include <stddef.h>
#include <stdio.h>
#include "brender.h"
#include "dosio.h"
int main(int argc, char **argv)
{
	br_pixelmap *screen_buffer, *back_buffer, *depth_buffer, *palette;
	br_actor *universe, *observer, *light, *planet, *moon, *satellite;
	int i;
	br_camera *camera_data;

/************* Initialise BRender and Graphics Hardware ************/
	BrBegin();
	/*
	 * Initialise screen buffer and set up CLUT (ignored in true colour) 
	 */
.      .      .
.      .      .
.      .      .
.      .      .
.      .      .
.      .      .
	BrZbBegin(screen_buffer->type, BR_PMT_DEPTH_16);

	back_buffer = BrPixelmapMatch(screen_buffer,BR_PMMATCH_OFFSCREEN);
	depth_buffer = BrPixelmapMatch(screen_buffer,BR_PMMATCH_DEPTH_16);

/*************** Build the World Database *****************/
	/*
	 * Load Root Actor
	 */
	universe = BrActorAllocate(BR_ACTOR_NONE,NULL);
	/* 
	 * Load and Enable Default Light Source
	 */
	light = BrActorAdd(universe,BrActorAllocate(BR_ACTOR_LIGHT,NULL));
	BrLightEnable(light);
	/*
	 * Load and Position Camera
	 */
	observer = BrActorAdd(universe,BrActorAllocate(BR_ACTOR_CAMERA,NULL));
	observer->t.type = BR_TRANSFORM_MATRIX34; 
	BrMatrix34Translate(&observer->t.t.mat,BR_SCALAR(0.0),BR_SCALAR(0.0),
                                                        BR_SCALAR(6.0));
	camera_data = (br_camera *)observer->type_data;
	camera_data->you_z = BR_SCALAR(50);
	/*
	 * Load Planet Model
	 */
	planet = BrActorAdd(universe,BrActorAllocate(BR_ACTOR_MODEL,NULL));
	planet->model = BrModelLoad("sph16.dat");
	BrModelAdd(planet->model);
	/*
	 * Load and Position Moon Model
	 */
	moon = BrActorAdd(planet,BrActorAllocate(BR_ACTOR_MODEL,NULL));
	moon->model = BrModelLoad("sph8.dat");
	BrModelAdd(moon->model);
	moon->t.type = BR_TRANSFORM_MATRIX34;
	BrMatrix34Scale(&moon->t.t.mat,BR_SCALAR(0.5),BR_SCALAR(0.5),BR_SCALAR(0.5));
	BrMatrix34PostTranslate(&moon->t.t.mat,BR_SCALAR(0.0),BR_SCALAR (0.0),
                                                        BR_SCALAR(2.0));
	/*
	 * Load and Position Satellite Model
	 */
	satellite = BrActorAdd(moon,BrActorAllocate(BR_ACTOR_MODEL,NULL));
	satellite->model = BrModelLoad("sph8.dat");
	BrModelAdd(satellite->model);
	satellite->t.type = BR_TRANSFORM_MATRIX34;
	BrMatrix34Scale(&satellite->t.t.mat,BR_SCALAR(0.25),BR_SCALAR (0.25), 
                                                      BR_SCALAR(0.25));
	BrMatrix34PostTranslate(&satellite->t.t.mat,BR_SCALAR(1.5),BR_SCALAR(0.0), 
                                                             BR_SCALAR(0.0)); 

/********************** Animation Loop ***********************/
	for(i=0; i < 1000; i++) {
				BrPixelmapFill(back_buffer,0);
				BrPixelmapFill(depth_buffer,0xFFFFFFFF);
				BrZbSceneRender(universe,observer,back_buffer,depth_buffer);
				BrPixelmapDoubleBuffer(screen_buffer,back_buffer);
				BrMatrix34PreRotateY(&planet->t.t.mat,BR_ANGLE_DEG(1.0));    
				BrMatrix34PreRotateY(&satellite->t.t.mat,BR_ANGLE_DEG(4.0));
				BrMatrix34PreRotateZ(&moon->t.t.mat,BR_ANGLE_DEG(1.5));
				BrMatrix34PostRotateZ(&satellite->t.t.mat,BR_ANGLE_DEG(2.5));
				BrMatrix34PostRotateY(&moon->t.t.mat,BR_ANGLE_DEG(-2.0)); 
	}
	/*
	 * Close down 
	 */
	BrPixelmapFree(depth_buffer);
	BrPixelmapFree(back_buffer);
	BrZbEnd();
.      .      .
.      .      .
.      .      .
.      .      .
.      .      .
.      .      .
	BrEnd();
	return 0;
}
BRTUTOR3.C

The satellite is also uniformly scaled before being translated +1.5 units in x, in the moon's co-ordinate system. From the viewer's perspective, (at x=0, y=0, z=6) in `World Space', the satellite is initially centred at (1.5, 0, 2). The first frame rendered is depicted below.

Figure 37 First frame

In the animation loop, PreRotate functions are used to set the planet and satellite rotating about their own yaxes, and the moon revolving around its own zaxis.

	 BrMatrix34PreRotateY(&planet->t.t.mat,BR_ANGLE_DEG(1.0));
	 BrMatrix34PreRotateY(&satellite->t.t.mat,BR_ANGLE_DEG(4.0));
	 BrMatrix34PreRotateZ(&moon->t.t.mat,BR_ANGLE_DEG(1.5));
The satellite is rotated to trace an orbit around the moon's zaxis. Note that the satellite's transformation is applied in the moon's coordinate space, not in `World Space'.

	 BrMatrix34PostRotateZ(&satellite->t.t.mat,BR_ANGLE_DEG(-2.5));
The moon (and `attached' satellite) is rotated to trace an orbit around the planet's y-axis.

	 BrMatrix34PostRotateY(&moon->t.t.mat,BR_ANGLE_DEG(-2.0));
To place either the moon or the satellite in geostationary orbit, simply delete the appropriate rotate command.

Feel free to experiment with this program and with BRTUTOR4.C. BRTUTOR4.C creates another planet-satellite animation using hierarchical models.


Generated with CERN WebMaker