DIRECTORY Controls, Draw2d, Imager, ImagerBackdoor, Matrix3d, Controls3d, Real, ThreeDScenes, Vector3d, ViewerOps; Controls3dImpl: CEDAR PROGRAM IMPORTS Controls, Draw2d, ImagerBackdoor, Matrix3d, Real, ThreeDScenes, Vector3d, ViewerOps EXPORTS Controls3d ~ BEGIN OPEN Controls3d; lastAdjustedCamera: Camera _ NIL; CameraControlProc: ControlProc ~ { c: Camera ~ NARROW[control.data]; c.lastMoused _ control; lastAdjustedCamera _ c; IF control.mouse.state = down THEN { DoubleSet: PROC [control: Control, value: REAL] ~ { -- control.prev_control.value_value IF control.sliderDialRef # NIL THEN { Controls.SetSliderDialValue[control, value]; Controls.SetSliderDialValue[control, value]; }; }; IF control # c.xLocal THEN DoubleSet[c.xLocal, 0.0]; IF control # c.yLocal THEN DoubleSet[c.yLocal, 0.0]; IF control # c.zLocal THEN DoubleSet[c.zLocal, 0.0]; }; IF control.mouse.state # up THEN UpdateCamera[c]; IF c.proc # NIL THEN c.proc[control, c.data]; }; InitCamera: PUBLIC PROC [ origin: Triple _ [0.0, 0.0, 0.0], globalRotate: Triple _ [0.0, 0.0, 0.0], localRotate: Triple _ [0.0, 0.0, 0.0], move: Triple _ [0.0, 0.0, 0.0], scale: REAL _ 1.0, fieldOfView: REAL _ 0.0, zDistance: REAL _ 10.0, screenMove: Pair _ [0.0, 0.0], proc: CameraProc _ NIL, data: REF ANY _ NIL] RETURNS [c: Camera] ~ { c _ NEW[CameraRep _ [proc: proc, data: data]]; c.matrix _ NEW[Matrix3d.MatrixRep]; c.view _ NEW[Matrix3d.MatrixRep]; c.x _ Controls.NewControl["x", vSlider, c, -10.0, 10.0, origin.x, CameraControlProc]; c.y _ Controls.NewControl["y", vSlider, c, -10.0, 10.0, origin.y, CameraControlProc]; c.z _ Controls.NewControl["z", vSlider, c, -10.0, 10.0, origin.z, CameraControlProc]; c.xGlobal _ Controls.NewControl["xRot", dial, c, 0.0, 360.0, globalRotate.x, CameraControlProc]; c.yGlobal _ Controls.NewControl["yRot", dial, c, 0.0, 360., globalRotate.y, CameraControlProc]; c.zGlobal _ Controls.NewControl["zRot", dial, c, 0.0, 360.0, globalRotate.z, CameraControlProc]; c.xLocal _ Controls.NewControl["xLcl", dial, c, 0.0, 360.0, localRotate.x, CameraControlProc]; c.yLocal _ Controls.NewControl["yLcl", dial, c, 0.0, 360.0, localRotate.y, CameraControlProc]; c.zLocal _ Controls.NewControl["zLcl", dial, c, 0.0, 360.0, localRotate.z, CameraControlProc]; c.xMove _ Controls.NewControl["xMv", vSlider, c, -10.0, 10.0, move.x, CameraControlProc]; c.yMove _ Controls.NewControl["yMv", vSlider, c, -10.0, 10.0, move.y, CameraControlProc]; c.zMove _ Controls.NewControl["zMv", vSlider, c, -10.0, 10.0, move.z, CameraControlProc]; c.scale _ Controls.NewControl["scale", , c, 0, 100, scale, CameraControlProc,,,,,,,,,,,, exp]; c.fieldOfView _ Controls.NewControl["fov", vSlider, c, 0, 100,fieldOfView,CameraControlProc]; c.hScreen _ Controls.NewControl["xScr", vSlider, c, -2, 2, screenMove.x, CameraControlProc]; c.vScreen _ Controls.NewControl["yScr", vSlider, c, -2, 2, screenMove.y, CameraControlProc]; c.zDistance _ Controls.NewControl["zDist", vSlider, c, -2.0, 2., zDistance, CameraControlProc]; UpdateCamera[c]; }; ComputeNewMatrix: PUBLIC PROC [ origin: Triple _ [0.0, 0.0, 0.0], rotate: Triple _ [0.0, 0.0, 0.0], move: Triple _ [0.0, 0.0, 0.0], scale: REAL _ 0.0, fieldOfView: REAL _ 0.0, zDistance: REAL _ 0.0, m: Matrix _ NIL] RETURNS [Matrix] ~ { m _ Matrix3d.Identity[m]; m _ Matrix3d.Translate[m, Vector3d.Negate[origin], m]; m _ Matrix3d.Scale[m, scale, m]; m _ Matrix3d.Rotate[m, xAxis, rotate.x , , , m]; m _ Matrix3d.Rotate[m, yAxis, rotate.y, , , m]; m _ Matrix3d.Rotate[m, zAxis, rotate.z , , , m]; m _ Matrix3d.Translate[m, Vector3d.Add[origin, move], m]; IF fieldOfView # 0.0 AND zDistance # 0.0 THEN { t: Matrix _ Matrix3d.ObtainMatrix[]; m _ Matrix3d.Mul[m, Matrix3d.MakePerspective[1.0/zDistance, 0.0, fieldOfView, t], m]; Matrix3d.ReleaseMatrix[t]; }; RETURN[m]; }; InitContext: PUBLIC PROC [context: Context, camera: Camera, in: Matrix _ NIL] RETURNS [Matrix] ~ { Draw2d.Clear[context]; RETURN[GetViewMatrix[camera, context]]; }; UpdateCamera: PUBLIC PROC [camera: Camera] ~ { Change: PROC [control: Control] RETURNS [REAL] ~ { RETURN[control.value-control.valuePrev]; }; c: Camera _ camera; c.matrix _ SELECT camera.lastMoused FROM c.xLocal => Matrix3d.LocalRotate[c.matrix, xAxis, Change[c.xLocal], , , c.matrix], c.yLocal => Matrix3d.LocalRotate[c.matrix, yAxis, Change[c.yLocal], , , c.matrix], c.zLocal => Matrix3d.LocalRotate[c.matrix, zAxis, Change[c.zLocal], , , c.matrix], c.hScreen, c.vScreen => c.matrix, ENDCASE => ComputeNewMatrix[ [c.x.value, c.y.value, c.z.value], [c.xGlobal.value, c.yGlobal.value, c.zGlobal.value], [c.xMove.value, c.yMove.value, c.zMove.value], c.scale.value, c.fieldOfView.value, c.zDistance.value, c.matrix]; }; UpdateControl: PROC [control: Control, value: REAL] ~ { IF control.sliderDialRef = NIL THEN control.value _ value ELSE Controls.SetSliderDialValue[control, value]; }; UpdateGlobalRotates: PUBLIC PROC [camera: Camera, rotates: Triple] ~ { UpdateControl[camera.xGlobal, rotates.x]; UpdateControl[camera.yGlobal, rotates.y]; UpdateControl[camera.zGlobal, rotates.z]; UpdateCamera[camera]; }; UpdateLocalRotates: PUBLIC PROC [camera: Camera, rotates: Triple] ~ { UpdateControl[camera.xLocal, rotates.x]; UpdateControl[camera.yLocal, rotates.y]; UpdateControl[camera.zLocal, rotates.z]; UpdateCamera[camera]; }; UpdateOrigin: PUBLIC PROC [camera: Camera, origin: Triple] ~ { UpdateControl[camera.xMove, origin.x]; UpdateControl[camera.yMove, origin.y]; UpdateControl[camera.zMove, origin.z]; UpdateCamera[camera]; }; UpdateFieldOfView: PUBLIC PROC [camera: Camera, fieldOfView: REAL] ~ { UpdateControl[camera.fieldOfView, fieldOfView]; UpdateCamera[camera]; }; UpdateScale: PUBLIC PROC [camera: Camera, scale: REAL] ~ { UpdateControl[camera.scale, scale]; UpdateCamera[camera]; }; UpdateScreen: PUBLIC PROC [camera: Camera, screen: Pair] ~ { UpdateControl[camera.hScreen, screen.x]; UpdateControl[camera.vScreen, screen.y]; UpdateCamera[camera]; }; UpdateZDistance: PUBLIC PROC [camera: Camera, zDistance: REAL] ~ { UpdateControl[camera.zDistance, zDistance]; UpdateCamera[camera]; }; GetCameraMatrix: PUBLIC PROC [camera: Camera] RETURNS [Matrix] ~ { RETURN[camera.matrix]; }; GetViewMatrix: PUBLIC PROC [camera: Camera, context: Context] RETURNS [Matrix] ~ { m: Matrix ~ Matrix3d.Translate[ camera.matrix, [camera.hScreen.value, camera.vScreen.value, 0.0]]; RETURN[TransformByViewPort[m, context, camera.view]]; }; GetViewPort: PUBLIC PROC [context: Context] RETURNS [ViewPort] ~ { rectangle: Imager.Rectangle ~ ImagerBackdoor.GetBounds[context]; xo: INTEGER _ Real.RoundI[rectangle.w]/2; yo: INTEGER _ Real.RoundI[rectangle.h]/2; s: REAL _ 0.9*Real.Round[MIN[xo, yo]]; RETURN[[xo, yo, s, s]]; }; TransformByViewPort: PUBLIC PROC [in: Matrix, context: Context, out: Matrix _ NIL] RETURNS [Matrix] ~ { v: ViewPort _ GetViewPort[context]; RETURN[Matrix3d.Translate[Matrix3d.DiffScale[in, [v.xs, v.ys, 1.0]], [v.xo, v.yo, 0.0], out]]; }; SetContext3dView: PUBLIC PROC [context3d: Context3d, camera: Camera] ~ { eyePoint, ptOfInterest: Triple; m: Matrix _ Matrix3d.Identity[]; fov: REAL ~ IF camera.fieldOfView.value = 0.0 THEN 40.0 ELSE camera.fieldOfView.value; m _ Matrix3d.Rotate[m, [0.0, 1.0, 0.0], camera.yGlobal.value, , , m]; m _ Matrix3d.Rotate[m, [1.0, 0.0, 0.0], camera.xGlobal.value, , , m]; eyePoint _ Matrix3d.Transform[[0, 0, -camera.zDistance.value/MAX[.001, camera.scale.value]], m]; ptOfInterest _ [camera.xMove.value, camera.yMove.value, camera.zMove.value]; ptOfInterest _ Vector3d.Add[ptOfInterest, [camera.hScreen.value, camera.vScreen.value, 0.0]]; eyePoint _ Vector3d.Add[eyePoint, ptOfInterest]; ThreeDScenes.SetView[ context3d, eyePoint, ptOfInterest, fov, camera.zGlobal.value]; }; LastAdjustedCamera: PUBLIC PROC RETURNS [Camera] ~ { RETURN[lastAdjustedCamera]; }; InitHold: PUBLIC PROC [proc: ControlProc _ NIL, data: REF ANY _ NIL] RETURNS [h: Hold] ~ { h _ NEW[HoldRep]; h.x _ Controls.NewControl["ptx", vSlider, data, -1.0, 1.0, 0.0, proc]; h.y _ Controls.NewControl["pty", vSlider, data, -1.0, 1.0, 0.0, proc]; h.z _ Controls.NewControl["ptz", vSlider, data, -1.0, 1.0, 0.0, proc]; h.lng _ Controls.NewControl["lng", dial, data, 0.0, 360.0, 0.0, proc]; h.lat _ Controls.NewControl["lat", dial, data, 0.0, 360.0, 0.0, proc]; h.mag _ Controls.NewControl["mag", vSlider, data, -2.0, 2.0, 0.0, proc]; }; FocusHold: PUBLIC PROC [vector: Triple, hold: Hold] ~ { polar: Triple _ Vector3d.PolarFromCartesian[vector]; Controls.SetSliderDialValue[hold.lng, polar.x]; Controls.SetSliderDialValue[hold.lat, polar.y]; Controls.SetSliderDialValue[hold.mag, polar.z]; Controls.SetSliderDialValue[hold.x, 0.0]; Controls.SetSliderDialValue[hold.y, 0.0]; Controls.SetSliderDialValue[hold.z, 0.0]; }; PaintControls: PUBLIC PROC [c1, c2, c3, c4, c5, c6: Control _ NIL] ~ { IF c1 # NIL THEN ViewerOps.PaintViewer[c1.viewer, client, FALSE, c1]; IF c2 # NIL THEN ViewerOps.PaintViewer[c2.viewer, client, FALSE, c2]; IF c3 # NIL THEN ViewerOps.PaintViewer[c3.viewer, client, FALSE, c2]; IF c4 # NIL THEN ViewerOps.PaintViewer[c3.viewer, client, FALSE, c2]; IF c5 # NIL THEN ViewerOps.PaintViewer[c3.viewer, client, FALSE, c2]; IF c6 # NIL THEN ViewerOps.PaintViewer[c3.viewer, client, FALSE, c2]; }; ScreenPick: PUBLIC PROC [ points: TripleSequence, pairs: PairSequence, view: Matrix, mouse: Mouse] RETURNS [pointPicked: INTEGER] ~ { dist, max: REAL _ 100000.0; IF pairs.length < points.length THEN RETURN[-1]; IF pairs.maxLength < pairs.length OR points.maxLength < points.length THEN RETURN[-1]; IF mouse.state = down THEN FOR i: NAT IN[0..points.length) DO pairs[i] _ Matrix3d.TransformD[points[i], view]; ENDLOOP; pointPicked _ 0; FOR i: NAT IN[0..points.length) DO dx: REAL _ mouse.x-pairs[i].x; dy: REAL _ mouse.y-pairs[i].y; IF (dist _ dx*dx+dy*dy) < max THEN {max _ dist; pointPicked _ i}; ENDLOOP; }; END. .. GetRenderingMatrix: PUBLIC PROC [camera: Camera] RETURNS [Matrix] ~ { matrix: Matrix _ NEW[Matrix3d.MatrixRep]; matrix _ Matrix3d.Identity[matrix]; matrix _ Matrix3d.LocalTranslate[ matrix, [camera.x.value, camera.y.value, 10.0+camera.z.value], matrix]; matrix _ Matrix3d.LocalScale[matrix, camera.scale.value, matrix]; matrix _ Matrix3d.LocalRotate[matrix, [0.0, 1.0, 0.0], camera.yRot.value,,, matrix]; matrix _ Matrix3d.LocalRotate[matrix, [0.0, 0.0, 1.0], camera.zRot.value,,, matrix]; matrix _ Matrix3d.LocalRotate[matrix, [1.0, 0.0, 0.0], camera.xRot.value,,, matrix]; RETURN[matrix]; }; άControls3dImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Bloomenthal, February 26, 1987 7:29:59 pm PST Global Variables Camera Procedures Translate and scale to viewport; don't scale z so can compare z with w for near clipping: This needed to accommodate ThreeDWorld: Hold Procedures Miscellaneous Procedures matrix _ IF camera.fov.value = 0.0 THEN Matrix3d.Identity[matrix] ELSE Matrix3d.MakePerspective[0.1, 0.0, camera.fov.value, matrix]; Κ [˜šœ™Jšœ Οmœ1™Jšœ&˜&Jšœ&˜&Jšœ&˜&J˜J˜J˜—š‘œž œžœ˜FJšœ/˜/J˜J˜J˜—š‘ œž œžœ˜:Jšœ#˜#J˜J˜J˜—š‘ œž œ#˜˜>—Jšœ˜J˜—š‘œž œžœ ˜4Jšžœ˜J˜——š ™š‘œžœžœžœžœžœžœžœ˜ZJšœžœ ˜JšœF˜FJšœF˜FJšœF˜FJšœF˜FJšœF˜FJšœH˜HJ˜J™—šΟb œžœžœ!˜7Jšœ4˜4Jšœ/˜/Jšœ/˜/Jšœ/˜/Jšœ)˜)Jšœ)˜)Jšœ)˜)J˜——š ™codeš‘ œžœžœ$žœ˜FLšžœžœžœ*žœ˜ELšžœžœžœ*žœ˜ELšžœžœžœ*žœ˜ELšžœžœžœ*žœ˜ELšžœžœžœ*žœ˜ELšžœžœžœ*žœ˜EL˜L˜—š‘ œžœžœ˜JšœH˜HJšžœžœ˜"Jšœ žœ ˜J˜Jšžœžœžœ˜0Jšžœ žœ"žœžœ˜Vš žœžœžœžœžœž˜=Jšœ0˜0Jšžœ˜—J˜Jšœ˜šžœžœžœž˜"Jšœžœ˜Jšœžœ˜Jšžœžœ˜AJšžœ˜—J˜L˜——Jšžœ˜J˜˜š‘œžœžœžœ ˜EJšœžœ˜)J˜šœ žœ™"Jšžœ™Jšžœ>™B—Jšœ$˜$˜!J˜G—JšœA˜AJšœT˜TJšœT˜TJ˜TJšžœ ˜Jšœ˜J˜——J˜—…—(Ί3ρ