<> <> <> <> DIRECTORY Atom USING [ GetPropFromList, PropList, PutPropOnList ], Real USING [ Fix, Float ], Rope USING [ ROPE ], G3dMatrix USING [ Transform, MakeRotate ], G3dSpline USING [ CoeffsSequence, Interpolate, InterpolateCyclic, Position ], ThreeDBasics USING [ Context, Error, Pair, PairSequence, ShapeInstance, ShapeProc, Triple, TripleSequence, VertexInfoProc ], SceneUtilities USING [ FindShape ], Animation3D USING [ ViewProc ]; Animation3DImpl: CEDAR PROGRAM IMPORTS Atom, G3dMatrix, G3dSpline, Real, SceneUtilities, ThreeDBasics EXPORTS Animation3D ~ BEGIN <> Context: TYPE ~ ThreeDBasics.Context; Pair: TYPE ~ ThreeDBasics.Pair; PairSequence: TYPE ~ ThreeDBasics.PairSequence; Triple: TYPE ~ ThreeDBasics.Triple; -- RECORD [ x, y, z: REAL]; TripleSequence: TYPE ~ ThreeDBasics.TripleSequence; ShapeInstance: TYPE ~ ThreeDBasics.ShapeInstance; ViewProc: TYPE ~ Animation3D.ViewProc; LORA: TYPE ~ LIST OF REF ANY; <> GetProp: PROC [propList: Atom.PropList, prop: REF ANY] RETURNS [REF ANY] ~ Atom.GetPropFromList; PutProp: PROC [propList: Atom.PropList, prop: REF ANY, val: REF ANY] RETURNS [Atom.PropList] ~ Atom.PutPropOnList; <> MoveEyePointInOrbit: PUBLIC PROC[ context: REF Context, eyePt, lookingAt, axis, base: Triple, displayProc: ViewProc, framesPerRev: NAT, startAt, endAt: NAT _ 0 ] ~ { theta: REAL _ 360. / framesPerRev; currentEyePt: Triple; FOR i: NAT IN [startAt .. endAt] DO IF context.stopMe^ THEN RETURN[]; currentEyePt _ G3dMatrix.Transform[ eyePt, G3dMatrix.MakeRotate[ axis: axis, theta: theta * i, base: base ] ]; <> context.frameNumber _ i; displayProc[ context, currentEyePt, lookingAt, context.frameNumber ]; ENDLOOP; context.frameNumber _ 0; }; MoveCtrOfInterestInOrbit: PUBLIC PROC[ context: REF Context, eyePt, lookingAt, axis, base: Triple, displayProc: ViewProc, framesPerRev: NAT, startAt, endAt: NAT _ 0 ] ~ { theta: REAL _ 360. / framesPerRev; currentLookingAt: Triple; FOR i: NAT IN [startAt .. endAt] DO IF context.stopMe^ THEN RETURN[]; currentLookingAt _ G3dMatrix.Transform[ lookingAt, G3dMatrix.MakeRotate[ axis: axis, theta: theta * i, base: base ] ]; <> context.frameNumber _ i; displayProc[ context, eyePt, currentLookingAt, context.frameNumber ]; ENDLOOP; context.frameNumber _ 0; }; MoveOnLine: PUBLIC PROC[ context: REF Context, eyePt, lookingAt, toEyePt, toLookingAt: Triple, displayProc: ViewProc, framesOnLine: NAT, startAt, endAt: NAT _ 0 ] ~ { currentEyePt, currentLookingAt: Triple; FOR i: NAT IN [startAt .. endAt] DO IF context.stopMe^ THEN RETURN[]; currentEyePt.x _ eyePt.x + (toEyePt.x - eyePt.x) * i / (framesOnLine-1); currentEyePt.y _ eyePt.y + (toEyePt.y - eyePt.y) * i / (framesOnLine-1); currentEyePt.z _ eyePt.z + (toEyePt.z - eyePt.z) * i / (framesOnLine-1); currentLookingAt.x _ lookingAt.x + (toLookingAt.x - lookingAt.x) * i / (framesOnLine-1); currentLookingAt.y _ lookingAt.y + (toLookingAt.y - lookingAt.y) * i /(framesOnLine-1); currentLookingAt.z _ lookingAt.z + (toLookingAt.z - lookingAt.z) * i / (framesOnLine-1); context.frameNumber _ i; displayProc[ context, currentEyePt, currentLookingAt, context.frameNumber ]; ENDLOOP; context.frameNumber _ 0; }; MoveOnOpenCurve: PUBLIC PROC[ context: REF Context, eyePts, lookingAts: REF TripleSequence, displayProc: ViewProc, framesOnCurve: NAT, startAt, endAt: NAT _ 0 ] ~ { currentEyePt, currentLookingAt: REF TripleSequence; epCoeffs: G3dSpline.CoeffsSequence _ G3dSpline.Interpolate[eyePts]; ciCoeffs: G3dSpline.CoeffsSequence _ G3dSpline.Interpolate[lookingAts]; currentEyePt _ ExpandCurve[epCoeffs, framesOnCurve]; currentLookingAt _ ExpandCurve[ciCoeffs, framesOnCurve]; IF context.stopMe^ THEN RETURN[]; FOR i: NAT IN [startAt .. endAt] DO j: NAT _ i MOD framesOnCurve; context.frameNumber _ i; displayProc[ context, currentEyePt[j], currentLookingAt[j], context.frameNumber ]; ENDLOOP; context.frameNumber _ 0; }; MoveOnClosedCurve: PUBLIC PROC[ context: REF Context, eyePts, lookingAts: REF TripleSequence, displayProc: ViewProc, framesOnCurve: NAT, startAt, endAt: NAT _ 0 ] ~ { currentEyePt, currentLookingAt: REF TripleSequence; epCoeffs: G3dSpline.CoeffsSequence _ G3dSpline.InterpolateCyclic[eyePts]; ciCoeffs: G3dSpline.CoeffsSequence _ G3dSpline.InterpolateCyclic[lookingAts]; currentEyePt _ ExpandCurve[epCoeffs, framesOnCurve]; currentLookingAt _ ExpandCurve[ciCoeffs, framesOnCurve]; FOR i: NAT IN [startAt .. endAt] DO j: NAT _ i MOD framesOnCurve; IF context.stopMe^ THEN RETURN[]; context.frameNumber _ i; displayProc[ context, currentEyePt[j], currentLookingAt[j], context.frameNumber ]; ENDLOOP; context.frameNumber _ 0; }; ExpandCurve: PROC[coeffs: G3dSpline.CoeffsSequence, numFrames: NAT] RETURNS[REF TripleSequence] ~ { points: REF TripleSequence _ NEW[TripleSequence[numFrames]]; framesPerSeg: REAL _ Real.Float[numFrames - 1] / (coeffs.length); FOR i: NAT IN [0..numFrames - 1) DO t: REAL _ i / framesPerSeg; -- distance, in segments, along curve seg: NAT _ Real.Fix[t]; -- segment t _ t - seg; -- position in segment points[i] _ G3dSpline.Position[coeffs[seg], t]; ENDLOOP; points[numFrames - 1] _ G3dSpline.Position[coeffs[coeffs.length - 1], 1.0]; points.length _ numFrames; RETURN[points]; }; <> ShowOpenCurve: PUBLIC PROC[ context: Context, eyePts, lookingAts: REF TripleSequence, numFrames: NAT, startAt: NAT _ 0 ] ~ { SIGNAL ThreeDBasics.Error[[$Unimplemented, "Sorry, ask Frank for an implementation"]]; }; ShowClosedCurve: PUBLIC PROC[ context: Context, eyePts, lookingAts: REF TripleSequence, numFrames: NAT, startAt: NAT _ 0 ] ~ { SIGNAL ThreeDBasics.Error[[$Unimplemented, "Sorry, ask Frank for an implementation"]]; }; ShowOrbit: PUBLIC PROC[ context: Context, startPt, axis, base: Triple, framesPerRev: NAT ] ~ { <> SIGNAL ThreeDBasics.Error[[$Unimplemented, "Sorry, ask Frank for an implementation"]]; }; <> SetTxtrTranslation: PUBLIC PROC[ context: REF Context, shapeName: Rope.ROPE, translation: Pair, frames: NAT ] ~{ <> shape: REF ShapeInstance _ SceneUtilities.FindShape[context, shapeName]; translation.x _ translation.x / frames; translation.y _ translation.y / frames; shape.shadingProps _ PutProp[ shape.shadingProps, $TxtrTranslation, NEW[Pair _ translation] ]; shape.shadingClass.loadVtxAux _ LoadTranslatedTxtrCoords; }; LoadTranslatedTxtrCoords: ThreeDBasics.VertexInfoProc ~ { -- load aux field in vtx <> frameNumber: NAT _ context.frameNumber; shape: REF ShapeInstance _ NARROW[ Atom.GetPropFromList[vtx.props, $Shape] ]; txtrIncr: REF Pair _ NARROW[GetProp[shape.shadingProps, $TxtrTranslation] ]; vtxAux: REF Pair _ NEW[Pair]; WITH data SELECT FROM input: LORA => { auxInfo: REF PairSequence _ NARROW[ input.first ]; index: INTEGER _ NARROW[ input.rest.first, REF INTEGER ]^; vtxAux.x _ auxInfo[index].x + txtrIncr.x * frameNumber; -- texture coords vtxAux.y _ auxInfo[index].y + txtrIncr.y * frameNumber; }; txtr: REF Pair => { vtxAux.x _ txtr.x + txtrIncr.x * frameNumber; vtxAux.y _ txtr.y + txtrIncr.y * frameNumber; }; ENDCASE => SIGNAL ThreeDBasics.Error[[$Unimplemented, "Unrecognized type"]]; vtx.aux _ vtxAux; RETURN[ vtx ]; }; <> SetShapeInterpolation: PUBLIC PROC[ context: REF Context, shapeName: Rope.ROPE, begin, end: REF ShapeInstance, frames: NAT ] ~{ <> shape: REF ShapeInstance _ SceneUtilities.FindShape[context, shapeName]; shape.shadingProps _ PutProp[ shape.shadingProps, $ShapeLerp, NEW[LORA _ LIST[ begin, end, NEW[ NAT _ frames] ] ] ]; shape.class.doBeforeFrame _ CONS[LerpShape, shape.class.doBeforeFrame]; }; LerpShape: ThreeDBasics.ShapeProc ~ { <> <> frameNumber: NAT _ context.frameNumber; list: LORA _ NARROW[GetProp[shape.shadingProps, $ShapeLerp] ]; begin: REF ShapeInstance _ NARROW[list.first]; end: REF ShapeInstance _ NARROW[list.rest.first]; lastFrame: NAT _ NARROW[list.rest.rest.first, REF NAT]^; alpha: REAL _ 1.0 * frameNumber / lastFrame; FOR i: NAT IN [0..shape.vertex.length) DO shape.vertex[i].x _ begin.vertex[i].x + alpha * (end.vertex[i].x -begin.vertex[i].x); shape.vertex[i].y _ begin.vertex[i].y + alpha * (end.vertex[i].y -begin.vertex[i].y); shape.vertex[i].z _ begin.vertex[i].z + alpha * (end.vertex[i].z -begin.vertex[i].z); ENDLOOP; FOR i: NAT IN [0..shape.shade.length) DO shape.shade[i].r _ begin.shade[i].r + alpha * (end.shade[i].r -begin.shade[i].r); shape.shade[i].g _ begin.shade[i].g + alpha * (end.shade[i].g -begin.shade[i].g); shape.shade[i].b _ begin.shade[i].b + alpha * (end.shade[i].b -begin.shade[i].b); ENDLOOP; shape.shadingInValid _ TRUE; RETURN[shape]; }; <> SetShapeManipulation: PUBLIC PROC[ context: REF Context, shapeName: Rope.ROPE, prop, propVal: REF ANY, proc: ThreeDBasics.ShapeProc ] ~ { <> shape: REF ShapeInstance _ SceneUtilities.FindShape[context, shapeName]; shape.shadingProps _ PutProp[ shape.shadingProps, prop, propVal ]; shape.class.doBeforeFrame _ CONS[ proc, NIL ]; }; AddShapeManipulation: PUBLIC PROC[ context: REF Context, shapeName: Rope.ROPE, prop, propVal: REF ANY, proc: ThreeDBasics.ShapeProc ] ~ { <> shape: REF ShapeInstance _ SceneUtilities.FindShape[context, shapeName]; shape.shadingProps _ PutProp[ shape.shadingProps, prop, propVal ]; shape.class.doBeforeFrame _ CONS[ proc, shape.class.doBeforeFrame ]; }; END.