Copyright (C) 1994, Digital Equipment Corp.
Digital Internal Use Only
Created on Mon Feb 14 16:03:12 PST 1994 by najork
MODULE*************************************************************************** Module body ***************************************************************************PerspCameraGO EXPORTSPerspCameraGO ,PerspCameraGOProxy ; IMPORT CameraGO, CameraGOPrivate, GO, GOPrivate, GraphicsBase, GraphicsBasePrivate, Matrix4, Mth, Point3, PointProp, PointPropPrivate, Prop, RealProp, RealPropPrivate, TransformPropPrivate; PROCEDURENew (from, to, up : Point3.T; fovy : 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 (Fovy.bind (RealProp.NewConst (fovy))); RETURN cam; END New; REVEAL T = Public BRANDED OBJECT lookat : Matrix4.T; distance : REAL; aspect : REAL; fovy : REAL; OVERRIDES init := Init; draw := Draw; view := View; damageIfDependent := DamageIfDependent; END; PROCEDUREInit (self : T) : T = BEGIN EVAL CameraGO.T.init (self); IF MkProxyT # NIL AND self.proxy = NIL THEN MkProxyT (self); END; RETURN self; END Init; PROCEDUREDamageIfDependent (self : T; pn : Prop.Name) = BEGIN IF pn = CameraGO.From OR pn = CameraGO.To OR pn = CameraGO.Up OR pn = CameraGO.Aspect OR pn = Fovy OR pn = GO.Transform THEN self.damaged := TRUE; END; END DamageIfDependent; PROCEDUREDraw (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.distance := Point3.Distance (from, to); self.flag := TRUE; self.aspect := CameraGO.Aspect.getState (state); self.fovy := Fovy.getState (state); self.damaged := FALSE; END; (* If the transformation state contains a non-uniform matrix, it is not possible to determine a correct value for fovy ... *) state.pop (self); END; END Draw; PROCEDUREView (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 (* Needed: distance > near > far *) near := center.z + radius; far := center.z - radius; (* Handling bad cases (cases where the bounding sphere intersects the viewing plane) *) IF self.distance <= near THEN near := self.distance - 0.1; END; IF near <= far THEN far := near - 0.1; END; END; (*** Set the viewing and projection transformations. ***) state.setViewProjTransform (self.lookat, Matrix4.PerspProjMatrix (self.fovy, self.distance, self.aspect, near, far)); END View;
BEGIN Fovy := NEW (RealProp.Name).init (0.1); END PerspCameraGO.