ValidateShape:
PUBLIC ShapeProc ~ {
PROC[context: REF Context, shape: REF ShapeInstance, data: REF] RETURNS[REF ShapeInstance];
Update shading and transform matrices, return visibility (based on clipping and "hidden")
render: REF RenderData ← NARROW[shape.renderData];
IF context.stopMe^ THEN RETURN[shape];
IF shape.shadingClass = NIL THEN G3dRender.LoadShadingClass[shape]; -- load default
IF Atom.GetPropFromList[shape.props, $Hidden] #
NIL
AND shape.class.type # $Light
THEN RETURN[NIL]; -- not visible, removed from scene temporarily
IF shape.positionInValid THEN G3dRender.SetPosition[ shape ];
IF shape.boundingRadius = 0.0 THEN GetBoundingSphere[ shape ];
IF shape.vtcesInValid THEN { -- do only if object or eyespace transform has moved
Transform vertices to eyespace, get clip state of vertices and whole shape
shape.clipState ← ShapeUtilities.XfmToEyeSpace[ context, shape ];
};
IF shape.class.validate #
NIL
THEN [] ← shape.class.validate[context, shape, data]; -- get shading, etc.
IF shape.clipState # out
THEN {
Transform vertices to screen coordinates, get screen extent for whole shape
ShapeUtilities.XfmToDisplay[context, shape ];
};
IF shape.clipState # out AND shape.surface # NIL THEN RETURN[shape] ELSE RETURN[NIL];
};
SetEyeSpace:
PUBLIC
PROC[ context:
REF Context ] ~ {
in, right, up, normal: Triple;
mtx: Xfm3D;
wndw: Rectangle;
viewSize, xSize, ySize, aspectRatio: REAL;
IF context.viewPort.h <= 0 OR context.viewPort.w <= 0 THEN RETURN[];
transform from world to eye
in ← G3dVector.Normalize[G3dVector.Sub[context.ptOfInterest, context.eyePoint]];
IF G3dVector.Null[in]
THEN
SIGNAL G3dRender.Error[[$MisMatch, "Eye and Pt of Interest identical"]];
right ← G3dVector.Normalize[G3dVector.Cross[in, context.upDirection]];
IF G3dVector.Null[right] THEN right ← [1.0, 0.0, 0.0]; -- looking straight down
up ← G3dVector.Normalize[G3dVector.Cross[right, in]];
normalize not really needed (to avoid roundoff problems)
context.eyeSpaceXfm ← G3dMatrix.Identity[];
context.eyeSpaceXfm[0][0] ← right.x;
context.eyeSpaceXfm[1][0] ← right.y;
context.eyeSpaceXfm[2][0] ← right.z;
context.eyeSpaceXfm[3][0] ← -G3dVector.Dot[right, context.eyePoint];
context.eyeSpaceXfm[0][1] ← up.x;
context.eyeSpaceXfm[1][1] ← up.y;
context.eyeSpaceXfm[2][1] ← up.z;
context.eyeSpaceXfm[3][1] ← -G3dVector.Dot[up, context.eyePoint];
context.eyeSpaceXfm[0][2] ← in.x;
context.eyeSpaceXfm[1][2] ← in.y;
context.eyeSpaceXfm[2][2] ← in.z;
context.eyeSpaceXfm[3][2] ← -G3dVector.Dot[in, context.eyePoint];
mtx ← G3dMatrix.Identity[]; -- Roll about z-axis, clockwise
mtx[0][0] ← RealFns.CosDeg[context.rollAngle];
mtx[0][1] ← -RealFns.SinDeg[context.rollAngle];
mtx[1][0] ← RealFns.SinDeg[context.rollAngle];
mtx[1][1] ← RealFns.CosDeg[context.rollAngle];
context.eyeSpaceXfm ← G3dMatrix.Mul[context.eyeSpaceXfm, mtx];
bound window by -1.0 < x, y < 1.0
IF NOT (context.window.w > 0.0 AND context.window.h > 0.0) THEN RETURN[];
aspectRatio ← context.pixelAspectRatio * (context.viewPort.w/context.viewPort.h);
xSize ← IF aspectRatio > 1.0 THEN 1.0 ELSE aspectRatio;
ySize ← IF aspectRatio < 1.0 THEN 1.0 ELSE 1.0 / aspectRatio;
wndw.x ← MIN[xSize, MAX[-xSize, context.window.x] ];
wndw.w ← MIN[xSize-wndw.x, context.window.w ];
wndw.y ← MIN[ySize, MAX[-ySize, context.window.y] ];
wndw.h ← MIN[ySize-wndw.y, context.window.h ];
viewSize ← 2.0*RealFns.TanDeg[context.fieldOfView/2.0];
-- scale factor for angle of view
generate clipping planes
context.clippingPlanes[Near] ← [0., 0., 1., -context.hitherLimit];
context.clippingPlanes[Far] ← [0., 0., -1., context.yonLimit];
normalize plane equation for true distances
normal ← G3dVector.Normalize[[1., 0., -(wndw.x * viewSize/2.)]];
context.clippingPlanes[Left] ← [normal.x, 0., normal.z, 0.];
normal ← G3dVector.Normalize[[-1., 0., (wndw.x + wndw.w) * viewSize/2.]];
context.clippingPlanes[Right] ← [normal.x, 0., normal.z, 0.];
normal ← G3dVector.Normalize[[0., 1., -(wndw.y * viewSize/2.)]];
context.clippingPlanes[Bottom] ← [0., normal.y, normal.z, 0.];
normal ← G3dVector.Normalize[[0., -1., (wndw.y + wndw.h) * viewSize/2.]];
context.clippingPlanes[Top] ← [0., normal.y, normal.z, 0.];
compute the transformation from the eye coord sys to normalized display coordinates (0.—1.)
context.eyeToNdc.addX ← -(wndw.x / wndw.w);
context.eyeToNdc.addY ← -(wndw.y / wndw.h);
context.eyeToNdc.addZ ← 1.0/(1.0 - context.hitherLimit/context.yonLimit);
context.eyeToNdc.scaleX ← 1.0/(wndw.w * viewSize / 2.0);
context.eyeToNdc.scaleY ← 1.0/(wndw.h * viewSize / 2.0);
context.eyeToNdc.scaleZ ← -context.hitherLimit/(1. - context.hitherLimit/context.yonLimit);
};