graphicsDeploy api:
model.h
Library establishing a hierarchical modeling environment. Defines the Point (4-element homogeneous coordinates) and the Node structure -- the hierarchy is built of Nodes.
points and vectors
Points are four-element double arrays (x,y,z, and the homogeneous coordinate h). Vectors are just a Point typedef; I just added this so that there is a good conceptual distinction for function parameters and return values.
typedef struct {
   double x, y, z, h;
} Point;
#define newPoint(x,y,z) ((Point){(x),(y),(z),(1.0)})
#define pointAdd(p1,p2) (newPoint(p1.x+p2.x,p1.y+p2.y,p1.z+p2.z))
#define pointSub(p1,p2) (newPoint(p1.x-p2.x,p1.y-p2.y,p1.z-p2.z))
double distance(Point p1, Point p2);
#define ORIGIN newPoint(0.0, 0.0, 0.0)
#define UNIT_X newPoint(1.0, 0.0, 0.0)
#define UNIT_Y newPoint(0.0, 1.0, 0.0)
#define UNIT_Z newPoint(0.0, 0.0, 1.0)
typedef Point Vector;
#define newVector(x,y,z) ((Vector){(x),(y),(z),1.0})
void printPoint(Point point);
nodes
The hierarchy is built from nodes. The user manipulates pointers to nodes, but does not ever really need to see what they are, so node structure and content parameter structures are kept in another file. Nodes are divided into various types, with relevant functions for creating and manipulating each. Transformation nodes can be used to manipulate the size, location, and orientation of primitives, cameras, and lights. Attributes control the final appearance of primitives.
general modeling functions
This set of functions allows a user to create and insert Nodes to create a hierarchical model.
struct Node *new_model(void);
int ins_node(struct Node *model, struct Node *new_node);
camera modeling
cameras allow the user to specify the viewing parameters for a scene. both perspective and parellel projection cameras can be used, and there are functions for creating the standard set of orthogonal views (front, top, etc) using parallel projection cameras. cameras can also have orientation constraints given by 1.) fixed up directions (either y-axis up or a user specified alternative) and 2.) targetting. Targetting cameras allows the user to constrain the view plane normal to always point towards some invisible target node, which also sits in the hierarchy and can be transformed, animated etc. If a target is inserted into the hierarchy in the same place as an object, then in effect that object will be targetted by the camera.
struct Node *new_camera(void);
struct Node *new_camera_yup(void);
struct Node *new_camera_fixup(Point up_constraint);
struct Node *new_camera_isometric(void);
struct Node *new_camera_isometric_yup(void);
struct Node *new_camera_isometric_fixup(Point up_constraint);
struct Node *new_camera_top(void);
struct Node *new_camera_bottom(void);
struct Node *new_camera_front(void);
struct Node *new_camera_back(void);
struct Node *new_camera_left(void);
struct Node *new_camera_right(void);
struct Node *target(struct Node *camera);
int set_zoom(struct Node *camera, double zoom);
int set_clip_volume(struct Node *camera, double front_clip, double back_clip);
light modeling
ambient lighting is a constant parameter set using render-parameter functions (see render.h). the simplest lights are point and directional lights, which are fairly self explanatory. spot lights are point lights which are only at full intensity for the angle given by spot_angle, and then drop off to zero intensity in the angular region given by the penumbra_angle. much like cameras, spots can also be targetted to constrain the direction in which they point.
multi-point light sources (curves, areas, and volumes) emit light from more than one point (naturally...) this takes much longer to render, but can create some nice effects (in particular, this allows for generating soft shadows). multi-point light sources are implemented using sets of point lights, and the integer parameters for these functions indicate the number and spacing of points in various dimensions
#define MAX_SPOT_ANGLE 75.0
#define DEFAULT_SPOT_ANGLE 30.0
#define DEFAULT_PENUMBRA_ANGLE 10.0
#define MAX_DROPOFF 10
struct Node *directional_light(Color color);
struct Node *point_light(Color color);
struct Node *spot_light(Color color);
struct Node *target_spot(struct Node *spot_light);
struct Node *line_curve_light(int npoints, Color color);
struct Node *ring_curve_light(int npoints, Color color);
struct Node *square_area_light(int npoints_width, Color color);
struct Node *rectangle_area_light(int npoints_x, int npoints_z, Color color);
struct Node *circle_area_light(int npoints_diameter, Color color);
struct Node *ellipse_area_light(int npoints_x, int npoints_z, Color color);
struct Node *cube_volume_light(int npoints_width, Color color);
struct Node *parallelpiped_volume_light(int np_x, int np_y, int np_z,
Color color);
struct Node *sphere_volume_light(int npoints_diameter, Color color);
struct Node *ellipsoid_volume_light(int np_x, int np_y, int np_z, Color color);
struct Node *cylinder_volume_light(int np_diameter, int np_length, Color color);
int set_light_color(struct Node *light, Color color);
int set_spot_angle(struct Node *spot_light, double angle_degrees);
int set_penumbra_angle(struct Node *spot_light, double penumbra_angle);
primitive shapes
these are the elements of your model which will actually be drawn.
struct Node *line(void);
struct Node *circle(int n_segments);
struct Node *square(void);
struct Node *cube(void);
struct Node *cylinder(int n_segments, short cap_bottom, short cap_top);
struct Node *cone(int n_segments, short cap_bottom);
transformation nodes
these nodes create transformation matrices to manipulate points in the scene by translating, rotating, scaling, etc.
struct Node *identity(void);
struct Node *translate(double delta_x, double delta_y, double delta_z);
struct Node *scale(double scale_x, double scale_y, double scale_z);
struct Node *rotate_x(double angle_degrees);
struct Node *rotate_y(double angle_degrees);
struct Node *rotate_z(double angle_degrees);
struct Node *rotate_arbitrary(double angle, Point pivot, Point axis_end);
struct Node *shear_xy(double shear_x, double shear_y);
struct Node *shear_xz(double shear_x, double shear_z);
struct Node *shear_yz(double shear_y, double shear_z);
attribute nodes
these nodes manipulate the final rendered appearance of objects in the scene (color, opacity, specularity, etc.)
typedef enum {WIREFRAME, GARAUD_SHADING, PHONG_SHADING} ShadingType;
typedef enum {LAMBERT, PHONG, COOK_TORRENCE} SpecularityType;
typedef enum {FULL, TOP, TOP_BOTTOM, SIDES} MapType;
typedef enum {HORIZONTAL, VERTICAL} StaggerType;
struct Node *attr_defaults(void);
struct Node *attr_shading_type(ShadingType shadingtype);
struct Node *attr_specularity_type(SpecularityType specularitytype);
struct Node *attr_visibility(short visible);
struct Node *attr_shadow_casting(short casts_shadows);
struct Node *attr_shadow_receiving(short receives_shadows);
struct Node *attr_color(Color color);
struct Node *attr_specularity_color(Color color);
struct Node *attr_opacity_uniform(unsigned char opacity);
struct Node *attr_opacity(Color opacity_channels);
struct Node *attr_specularity(double roughness);
struct Node *attr_color_map(struct Image *color_map, short use_color_map_avg);
struct Node *attr_map_type(MapType maptype);
struct Node *attr_map_repeat(double repeat_u, double repeat_v);
struct Node *attr_map_offset(double offset_u, double offset_v);
struct Node *attr_map_stagger(double stagger);
struct Node *attr_map_stagger_type(StaggerType staggertype);
using cameras
Cameras are nodes in the hierarchy, and as such the location (view reference point) of the camera, the direction it points (view plane normal), and the direction it considers up (up vector) can be manipulated using transformation nodes (and animated by keying these nodes).
Perspective and isometric cameras begin at the origin pointing in the z-direction. If not given an up-constraint, cameras begin with y as the up direction. If constrained, the up vector always remains the same (it is often useful to use camera_yup() to create a camera with up always being y). View-plane normal constraints (which way the camera is pointing) are implicit in the orthogonal views (top, left, front, etc.), but you can also constrain the vpn by creating a target for the camera (using target()) -- the camera will then always point towards the target. What's really sweet is the target itself is a node in the hierarchy, so you can, for example, insert the target at the same place as some primitive or model, and then the camera will track that object.
The following code fragment demonstrates how to make a camera track a cube as the camera moves up in y. The resulting animation can be seen on the page for phase 6.
struct Node *scene, *cam, *tgt, *cam_trans;
scene = new_model();
cam = new_camera();
set_zoom(cam,3.0);
tgt = new_target(cam);
ins_node(scene,rotate_y(30.0));
ins_node(scene,translate(2.0, 0.0, 0.0));
ins_node(scene,cube());
ins_node(scene,tgt);
ins_node(scene,identity());
ins_node(scene,rotate_y(90.0));
ins_node(scene,(cam_trans=translate(0.0, 0.0, 0.0)));
ins_node(scene,cam);
make_keyed(cam_trans);
key_current(cam_trans, 0.0);
key_current(cam_trans, 1.0);
key_current(cam_trans, 2.0);
key_translate_y(cam_trans, 3.5, 0.5);
key_translate_y(cam_trans, 1.75, 1.5);