-- File: Draw3dImpl.mesa
-- Last edited by Bier on December 18, 1982 1:32 am
-- Author: Eric Bier on July 3, 1983 1:34 pm
-- Contents: Some useful combinations of Graphics operations
DIRECTORY
CoordSys,
CSG,
CSGGraphics,
DisplayList3d,
Draw3d,
Graphics,
Matrix3d,
RealFns,
SVBoundBox,
SVPolygon3d,
SVVector2d,
SVVector3d;
Draw3dImpl: PROGRAM
IMPORTS CSGGraphics, Graphics, Matrix3d, RealFns, SVBoundBox, SVPolygon3d, SVVector2d, SVVector3d
EXPORTS Draw3d =
BEGIN
Camera: TYPE = CSGGraphics.Camera;
CoordSystem: TYPE = REF CoordSysObj;
CoordSysObj: TYPE = CoordSys.CoordSysObj;
CSGTree: TYPE = REF CSGTreeObj;
CSGTreeObj: TYPE = CSG.CSGTreeObj;
MasterObject: TYPE = DisplayList3d.MasterObject;
Matrix4by4: TYPE = Matrix3d.Matrix4by4;
Point2d: TYPE = Matrix3d.Point2d;
Point3d: TYPE = Matrix3d.Point3d;
Poly3d: TYPE = SVPolygon3d.Poly3d;
Primitive: TYPE = CSG.Primitive;
Composite: TYPE = CSG.Composite;
Vector: TYPE = SVVector3d.Vector;
Vector2d: TYPE = SVVector2d.Vector2d;
DrawCoordSys: PUBLIC PROC [dc: Graphics.Context, mat: Matrix4by4, camera: Camera] = {
origin: Point3d;
XAxis, YAxis, ZAxis: Vector;
-- assume that mat is a CAMERA to LOCAL transform matrix
-- The last column of a homogenous transform, is the origin of the coordinate system it represents in terms of the world coord system.
origin[1] ← mat[1][4]; origin[2] ← mat[2][4]; origin[3] ← mat[3][4];
-- The columns correspond to the directional vectors of the mat coord system.
XAxis ← [mat[1][1],mat[2][1],mat[3][1]];
YAxis ← [mat[1][2],mat[2][2],mat[3][2]];
ZAxis ← [mat[1][3],mat[2][3],mat[3][3]];
DrawVector[dc, XAxis, origin, camera];
Graphics.DrawChar[dc,'x];
DrawVector[dc, YAxis, origin, camera];
Graphics.DrawChar[dc,'y];
DrawVector[dc, ZAxis, origin, camera];
Graphics.DrawChar[dc,'z];
}; -- Could be faster if I expand out the Draw Vectors internally.
DrawVector: PUBLIC PROC [dc: Graphics.Context, v: Vector, origin: Point3d, camera: Camera] = {
-- assumes vector is in camera coordinates
VectorEnd: Point3d;
leftBarb, rightBarb, v50, v90: Vector;
leftBarb2d, rightBarb2d, v2d: Vector2d;
v ← SVVector3d.Normalize[v];
v50 ← SVVector3d.Scale[v, 50];
VectorEnd ← SVVector3d.Add[origin,v50];
-- the barbs on the arrow head are of length 10 and shoot off at 45 degrees from the vector, parallel to the xy plane. To find them, we project v onto the xy plane and rotate 45 degrees.
v2d ← SVVector3d.ProjectOntoXYPlane[v50];
rightBarb2d ← SVVector2d.VectorPlusAngle[v2d, 135];
leftBarb2d ← SVVector2d.VectorPlusAngle[v2d, -135];
rightBarb ← SVVector3d.Vector2DAsXYVector[rightBarb2d];
rightBarb ← SVVector3d.Scale[rightBarb, 10];
leftBarb ← SVVector3d.Vector2DAsXYVector[leftBarb2d];
leftBarb ← SVVector3d.Scale[leftBarb, 10];
-- rear facing vectors are shown with barbs
IF v[3] < 0 THEN {
CSGGraphics.SetCPAbsolute[dc, origin, camera];
CSGGraphics.DrawToAbsolute[dc, VectorEnd, camera];
CSGGraphics.DrawToAbsolute[dc, SVVector3d.Add[VectorEnd, rightBarb], camera];
CSGGraphics.SetCPAbsolute[dc, VectorEnd, camera];
CSGGraphics.DrawToAbsolute[dc, SVVector3d.Add[VectorEnd, leftBarb], camera];
}
-- forward facing vectors have filled-in tips.
ELSE {
headPoly: Poly3d ← SVPolygon3d.CreatePoly[3];
CSGGraphics.SetCPAbsolute[dc, origin, camera];
CSGGraphics.DrawToAbsolute[dc, VectorEnd, camera];
headPoly ← SVPolygon3d.AddPolyPoint[headPoly, VectorEnd];
headPoly ← SVPolygon3d.AddPolyPoint[headPoly,
SVVector3d.Add[VectorEnd, rightBarb]];
headPoly ← SVPolygon3d.AddPolyPoint[headPoly,
SVVector3d.Add[VectorEnd, leftBarb]];
CSGGraphics.DrawAreaAbsolute[dc, headPoly, camera];
};
v90 ← SVVector3d.Scale[v, 90];
CSGGraphics.SetCPAbsolute[dc, SVVector3d.Add[origin, v90], camera];
-- prepare to draw a character after this vector
};
DrawForwardVector: PUBLIC PROC [dc: Graphics.Context, v: Vector, origin: Point3d, camera: Camera] = {
-- assumes vector is in camera coordinates
VectorEnd: Point3d;
leftBarb, rightBarb: Vector;
leftBarb2d, rightBarb2d, v2d: Vector2d;
v ← SVVector3d.Normalize[v];
v ← SVVector3d.Scale[v, 50];
VectorEnd ← SVVector3d.Add[origin,v];
-- the barbs on the arrow head are of length 10 and shoot off at 45 degrees from the vector, parallel to the xy plane. To find them, we project v onto the xy plane and rotate 45 degrees.
v2d ← SVVector3d.ProjectOntoXYPlane[v];
rightBarb2d ← SVVector2d.VectorPlusAngle[v2d, 135];
leftBarb2d ← SVVector2d.VectorPlusAngle[v2d, -135];
rightBarb ← SVVector3d.Vector2DAsXYVector[rightBarb2d];
rightBarb ← SVVector3d.Scale[rightBarb, 10];
leftBarb ← SVVector3d.Vector2DAsXYVector[leftBarb2d];
leftBarb ← SVVector3d.Scale[leftBarb, 10];
-- rear facing vectors are shown with barbs
IF v[3] < 0 THEN {
--CSGGraphics.MoveToAbsolute[dc, origin, camera];
--CSGGraphics.DrawToAbsolute[dc, VectorEnd, camera];
--CSGGraphics.DrawToAbsolute[dc, SVVector3d.Add[VectorEnd, rightBarb], camera];
--CSGGraphics.MoveToAbsolute[dc, VectorEnd, camera];
--CSGGraphics.DrawToAbsolute[dc, SVVector3d.Add[VectorEnd, leftBarb], camera];
}
-- forward facing vectors have filled-in tips.
ELSE {
headPoly: Poly3d ← SVPolygon3d.CreatePoly[3];
CSGGraphics.SetCPAbsolute[dc, origin, camera];
CSGGraphics.DrawToAbsolute[dc, VectorEnd, camera];
headPoly ← SVPolygon3d.AddPolyPoint[headPoly, VectorEnd];
headPoly ← SVPolygon3d.AddPolyPoint[headPoly,
SVVector3d.Add[VectorEnd, rightBarb]];
headPoly ← SVPolygon3d.AddPolyPoint[headPoly,
SVVector3d.Add[VectorEnd, leftBarb]];
CSGGraphics.DrawAreaAbsolute[dc, headPoly, camera];
};
};
DrawLocalVector: PUBLIC PROC [dc: Graphics.Context, v: Vector, origin: Point3d, camera: Camera, localCS: CoordSystem] = { -- assumes v and origin are in localCS coords.
vCamera: Vector ← Matrix3d.UpdateVectorWithInverse[localCS.cameraWRTlocal, v];
originCamera: Point3d ← Matrix3d.Update[localCS.wrtCamera, origin];
vCamera ← SVVector3d.Normalize[vCamera];
vCamera ← SVVector3d.Scale[vCamera, 50];
DrawVector[dc, vCamera, originCamera, camera];
};
Draw2dVector: PUBLIC PROC [dc: Graphics.Context, vec: Vector2d, at: Point2d] = {
unitVec, vec50: Vector2d;
mag: REAL;
mag ← RealFns.SqRt[vec[1]*vec[1] + vec[2]*vec[2]];
unitVec[1] ← vec[1]/mag;
unitVec[2] ← vec[2]/mag;
vec50[1] ← unitVec[1]*50;
vec50[2] ← unitVec[2]*50;
Graphics.SetCP[dc, at[1], at[2]];
Graphics.DrawTo[dc, at[1]+vec50[1], at[2]+vec50[2]];
}; -- end of Draw2dVector
Draw2dCoordSys: PUBLIC PROC [dc: Graphics.Context, origin: Point2d, camera: Camera] = {
CSGGraphics.SetCPAbsolute[dc, [-1000, origin[2],0], camera];
CSGGraphics.DrawToAbsolute[dc, [1000, origin[2],0], camera];
CSGGraphics.SetCPAbsolute[dc, [origin[1], -1000,0], camera];
CSGGraphics.DrawToAbsolute[dc, [origin[1], 1000,0], camera];
}; -- assumes Point2d in CAMERA coords
DrawX: PUBLIC PROC [dc: Graphics.Context, point: Point2d, camera: Camera] = {
halfWidthOfX, halfHeightOfX: REAL;
halfWidthOfX ← 10; halfHeightOfX ← 10;
CSGGraphics.SetCPAbsolute[dc, [point[1]-halfWidthOfX, point[2]+halfHeightOfX, 0], camera];
CSGGraphics.DrawToAbsolute[dc, [point[1]+halfWidthOfX, point[2]-halfHeightOfX, 0], camera];
CSGGraphics.SetCPAbsolute[dc, [point[1]+halfWidthOfX, point[2]+halfHeightOfX, 0],camera];
CSGGraphics.DrawToAbsolute[dc, [point[1]-halfWidthOfX, point[2]-halfHeightOfX, 0], camera];
}; -- assumes point in CAMERA coords
DrawBoundBoxes: PUBLIC PROC [dc: Graphics.Context, tree: CSGTree, camera: Camera] = {
DrawNode[dc, tree.son, camera];
};
DrawNode: PRIVATE PROC [dc: Graphics.Context, node: REF ANY, camera: Camera] = {
WITH node SELECT FROM
prim: Primitive => {mo: MasterObject;
SVBoundBox.DrawBoundBox[dc, prim.boundBox, camera.screenCS];
mo ← NARROW[prim.mo];
mo.class.drawSubBoxes[dc, prim, camera.screenCS];
};
comp: Composite =>
{DrawNode[dc, comp.leftSolid, camera];
DrawNode[dc, comp.rightSolid, camera];
SVBoundBox.DrawBoundBox[dc, comp.boundBox, camera.screenCS];
};
ENDCASE => ERROR;
}; -- end of DrawNode
END.