Copyright (C) 1994, Digital Equipment Corp.
Digital Internal Use Only
Created on Mon Feb 14 16:01:56 PST 1994 by najork
MODULE OrthoCameraGO EXPORTS OrthoCameraGO, OrthoCameraGOProxy;
IMPORT CameraGO, CameraGOPrivate, GO, GOPrivate, GraphicsBase,
GraphicsBasePrivate, Matrix4, Mth, Point3, PointProp, PointPropPrivate,
Prop, RealProp, RealPropPrivate, TransformPropPrivate;
PROCEDURE New (from, to, up : Point3.T; height : REAL) : T =
VAR
cam := NEW (T).init ();
BEGIN
cam.setProp (CameraGO.From.bind (PointProp.NewConst (from)));
cam.setProp (CameraGO.To.bind (PointProp.NewConst (to)));
cam.setProp (CameraGO.Up.bind (PointProp.NewConst (up)));
cam.setProp (Height.bind (RealProp.NewConst (height)));
RETURN cam;
END New;
REVEAL
T = Public BRANDED OBJECT
lookat : Matrix4.T;
aspect : REAL;
height : REAL;
OVERRIDES
init := Init;
draw := Draw;
view := View;
damageIfDependent := DamageIfDependent;
END;
PROCEDURE Init (self : T) : T =
BEGIN
EVAL CameraGO.T.init (self);
IF MkProxyT # NIL AND self.proxy = NIL THEN
MkProxyT (self);
END;
RETURN self;
END Init;
PROCEDURE DamageIfDependent (self : T; pn : Prop.Name) =
BEGIN
IF pn = CameraGO.From OR pn = CameraGO.To OR pn = CameraGO.Up OR
pn = CameraGO.Aspect OR pn = Height OR pn = GO.Transform THEN
self.damaged := TRUE;
END;
END DamageIfDependent;
PROCEDURE Draw (self : T; state : GraphicsBase.T) =
BEGIN
IF self.damaged THEN
state.push (self);
WITH tm = GO.Transform.getState (state),
from = Matrix4.TransformPoint3 (tm, CameraGO.From.getState (state)),
to = Matrix4.TransformPoint3 (tm, CameraGO.To.getState (state)),
up = Matrix4.TransformPoint3 (tm, CameraGO.Up.getState (state)) DO
self.lookat := Matrix4.LookatViewMatrix (from, to, up);
self.flag := TRUE;
self.aspect := CameraGO.Aspect.getState (state);
self.height := Height.getState (state);
self.damaged := FALSE;
END;
(* If the transformation state contains a non-uniform matrix,
the viewing parallelepiped might be distorted. In this case,
it is not possible to determine a correct value for height ... *)
state.pop (self);
END;
END Draw;
PROCEDURE View (self : T; state : GraphicsBase.T) =
VAR
near : REAL;
far : REAL;
BEGIN
self.flag := FALSE;
(*** map the bounding sphere into viewing coordinates ***)
WITH bs = state.getBoundingVolume(),
tm = self.lookat,
center = Point3.T {
tm[0][0] * bs.center.x + tm[0][1] * bs.center.y +
tm[0][2] * bs.center.z + tm[0][3],
tm[1][0] * bs.center.x + tm[1][1] * bs.center.y +
tm[1][2] * bs.center.z + tm[1][3],
tm[2][0] * bs.center.x + tm[2][1] * bs.center.y +
tm[2][2] * bs.center.z + tm[2][3]},
radius = bs.radius * Mth.sqrt (tm[0][0] * tm[0][0] +
tm[1][0] * tm[1][0] +
tm[2][0] * tm[2][0]) DO
near := center.z + radius;
far := center.z - radius;
(* Handle singularity "near = far" *)
IF near = far THEN
near := near + 0.01;
far := far - 0.01;
END;
END;
(*** Set the viewing and projection transformations. ***)
state.setViewProjTransform (self.lookat,
Matrix4.OrthoProjMatrix (self.height,
self.aspect,
near, far));
END View;
***************************************************************************
Module body
***************************************************************************
BEGIN
Height := NEW (RealProp.Name).init (10.0);
END OrthoCameraGO.