File: SVStretchImpl.mesa
Last edited by: Eric Bier on January 27, 1987 11:48:25 pm PST
Copyright © 1984 by Xerox Corporation. All rights reserved.
Contents: Interactive solidviews operations like dragging and stretching objects.
DIRECTORY
CastRays, CoordSys, CSG, SVScene, Imager, Matrix3d, SV2d, SV3d, SVEditUser, SVError, SVInterfaceTypes, SVModelTypes, SVRayTypes, SVSceneTypes, SVSelections, SVStretch, SVTransforms, SVVector3d, SVViewerUser;
SVStretchImpl: CEDAR PROGRAM
IMPORTS CastRays, CoordSys, CSG, SVScene, Matrix3d, SVEditUser, SVError, SVSelections, SVTransforms, SVVector3d, SVViewerUser
EXPORTS SVStretch =
BEGIN
Assembly: TYPE = SVSceneTypes.Assembly;
Camera: TYPE = SVModelTypes.Camera;
Classification: TYPE = SVRayTypes.Classification;
EditToolData: TYPE = SVEditUser.EditToolData;
Matrix4by4: TYPE = SV3d.Matrix4by4;
Point2d: TYPE = SV2d.Point2d;
Point3d: TYPE = SV3d.Point3d;
Primitive: TYPE = SVRayTypes.Primitive;
Ray: TYPE = SVRayTypes.Ray;
Scene: TYPE = SVSceneTypes.Scene;
Selection: TYPE = SVInterfaceTypes.Selection;
ToolData: TYPE = SVSceneTypes.ToolData;
Vector: TYPE = SV3d.Vector;
ViewerToolData: TYPE = SVInterfaceTypes.ViewerToolData;
StartDragAux: PRIVATE PROC [viewerToolData: ViewerToolData] RETURNS [drageeSel: Selection, planeAssem: Assembly, success: BOOL] = TRUSTED {
scene: Scene ← viewerToolData.scene;
success ← TRUE;
drageeSel ← SVSelections.TopMovee[];
IF drageeSel = NIL THEN {
viewerToolData.dragAssembly ← NIL;
SVError.Append["Please select a source to drag.", oneLiner];
SVError.Blink[];
success ← FALSE;
RETURN;
};
viewerToolData.dragAssembly ← drageeSel.coincident;
planeAssem ← SVSelections.TopPlaneCoincident[];
viewerToolData.dragTarget ← planeAssem;
IF planeAssem = NIL THEN {
SVError.Append["Please select a dragging plane.", oneLiner];
SVError.Blink[];
success ← FALSE;
RETURN;
};
Make sure the target has a working toolData.
SVScene.AddOrResizeToolToAssembly[planeAssem, scene];
};
DoDrawCoordFrame: PROC [dc: Imager.Context] = TRUSTED {
oldMode: Imager.PaintMode;
oldMode ← Imager.SetPaintMode[dc, invert];
SVDraw3d.DrawCoordSys[dc, dragee.coordSys.wrtCamera, camera];
[] ← Imager.SetPaintMode[dc, oldMode];
};
StartCameraDrag: PUBLIC PROC [viewerToolData: ViewerToolData, cameraPoint: Point2d] = TRUSTED {
Drag the source assembly. The origin of this assembly defines a plane parallel to the plane of the screen. We compute this plane. We cast a single ray at this plane and compute the current displacement between the assembly origin and this point. As we drag, we maintain this displacement.
editToolData: EditToolData ← viewerToolData.editToolData;
camera: Camera ← viewerToolData.camera;
scene: Scene ← viewerToolData.scene;
originCamera, hitPointCAMERA: Point3d;
dragee: Assembly;
drageeSel: Selection;
parallel, success: BOOL;
DoEraseSelection: PROC [dc: Imager.Context] = TRUSTED {
SVSelections.ComplementSelectionDC[dc, drageeSel, viewerToolData];
};
success ← TRUE;
drageeSel ← SVSelections.TopMovee[];
IF drageeSel = NIL THEN RETURN;
dragee ← drageeSel.coincident;
IF dragee = NIL THEN {
viewerToolData.dragAssembly ← NIL;
SVError.Append["Please select a source to drag.", oneLiner];
SVError.Blink[];
success ← FALSE;
RETURN;
};
viewerToolData.dragAssembly ← dragee;
IF NOT success THEN RETURN;
Find the origin of assembly in terms of camera.
originCamera ← Matrix3d.OriginOfMatrix[CoordSys.FindInTermsOfCamera[dragee.coordSys, camera.coordSys]];
Compute the dragging plane.
viewerToolData.dragPlaneDepth ← originCamera[3];
Cast a ray at the target plane. Returns result in CAMERA coordinates.
[hitPointCAMERA, parallel] ← RayMeetsCameraPlane[cameraPoint, viewerToolData.dragPlaneDepth, camera];
IF parallel THEN {
SVError.Append["StartCameraDrag: Dragging plane is parallel to ray.", oneLiner];
SVError.Blink[];
viewerToolData.dragTarget ← NIL;
RETURN;
};
Compute in CAMERA the displacement from hitPoint to origin.
viewerToolData.dragCameraVector ← SVVector3d.Sub[originCamera, hitPointCAMERA];
Draw a coordinate frame at the current spot (as a form of highlighting).
SVViewerUser.Painter[DoEraseSelection, viewerToolData];
};
StartDrag: PUBLIC PROC [viewerToolData: ViewerToolData, cameraPoint: Point2d] = TRUSTED {
Drag the source assembly. The origin of this assembly defines a plane parallel to the plane of target. We compute this plane. We cast a single ray at this plane and compute the current displacement between the assembly origin and this point. As we drag, we maintain this displacement.
editToolData: EditToolData ← viewerToolData.editToolData;
camera: Camera ← viewerToolData.camera;
originCamera, hitPointCAMERA, originTarget: Point3d;
plane: NAT;
drageeSel: Selection;
dragee, planeAssem: Assembly;
parallel, success: BOOL;
DoEraseSelection: PROC [dc: Imager.Context] = TRUSTED {
SVSelections.ComplementSelectionDC[dc, drageeSel, viewerToolData];
};
[drageeSel, planeAssem, success] ← StartDragAux[viewerToolData];
IF NOT success THEN RETURN;
dragee ← drageeSel.coincident;
Find the origin of assembly in terms of target.
originCamera ← Matrix3d.OriginOfMatrix[dragee.coordSys.wrtCamera];
originTarget ← CoordSys.FromCSToCS[originCamera, camera.coordSys, planeAssem.coordSys];
Compute the dragging plane.
[viewerToolData.dragPlaneDepth, plane] ← DepthFromTarget[planeAssem, originTarget];
Cast a ray at the target plane. Returns result in CAMERA coordinates.
[hitPointCAMERA, parallel] ← RayMeetsTargetPlane[cameraPoint, planeAssem, viewerToolData.dragPlaneDepth, plane, camera];
IF parallel THEN {
SVError.Append["StartDrag: Dragging plane is parallel to ray.", oneLiner];
SVError.Blink[];
viewerToolData.dragTarget ← NIL;
RETURN;
};
Compute in CAMERA the displacement from hitPoint to origin.
viewerToolData.dragCameraVector ← SVVector3d.Sub[originCamera, hitPointCAMERA];
Draw a coordinate frame at the current spot (as a form of highlighting).
SVViewerUser.Painter[DoEraseSelection, viewerToolData];
}; -- end of StartDrag
DepthFromTarget: PRIVATE PROC [target: Assembly, targetPt: Point3d] RETURNS [depth: REAL, plane: NAT] = {
toolData: ToolData;
toolData ← NARROW[target.toolMasterObject.mainBody];
IF toolData.plane > 3 THEN depth ← targetPt[3]
ELSE depth ← targetPt[toolData.plane];
plane ← toolData.plane;
};
RayMeetsTargetPlane: PRIVATE PROC [cameraPoint: Point2d, planeA: Assembly, depth: REAL, plane: NAT, camera: Camera] RETURNS [planePtCamera: Point3d, parallel: BOOL] = TRUSTED {
targetPlanePt is in CAMERA coords.
rayWorld: Ray;
worldCamera: Matrix4by4;
planePtWorld: Point3d;
rayWorldCSG.GetRayFromPool[];
CSG.StuffWorldRayFromCamera[rayWorld, cameraPoint, camera];
[planePtWorld, parallel] ← CastRays.RayMeetsPlaneOfCoordSystem[planeA.coordSys, rayWorld, plane, depth];
worldCamera ← CoordSys.FindAInTermsOfB[camera.coordSys.parent, camera.coordSys];
planePtCamera ← Matrix3d.Update[worldCamera, planePtWorld];
CSG.ReturnRayToPool[rayWorld];
};
RayMeetsCameraPlane: PRIVATE PROC [cameraPoint: Point2d, depth: REAL, camera: Camera] RETURNS [planePtCamera: Point3d, parallel: BOOL] = TRUSTED {
rayWorld: Ray;
worldCamera: Matrix4by4;
planePtWorld: Point3d;
rayWorldCSG.GetRayFromPool[];
CSG.StuffWorldRayFromCamera[rayWorld, cameraPoint, camera];
[planePtWorld, parallel] ← CastRays.RayMeetsPlaneOfCoordSystem[camera.coordSys, rayWorld, 3, depth];
worldCamera ← CoordSys.FindAInTermsOfB[camera.coordSys.parent, camera.coordSys];
planePtCamera ← Matrix3d.Update[worldCamera, planePtWorld];
CSG.ReturnRayToPool[rayWorld];
};
SetDrag: PUBLIC PROC [viewerToolData: ViewerToolData, cameraPoint: Point2d] = TRUSTED {
Cast a ray at the dragging plane. Move the dragee so as to maintain the displacement between the dragee origin and the ray tracing point.
camera: Camera ← viewerToolData.camera;
scene: Scene ← viewerToolData.scene;
hitPointCAMERA, newOriginPoint: Point3d;
dragee, target: Assembly;
toolData: ToolData;
parallel: BOOL;
DoDrawAssembly: PROC [dc: Imager.Context] = TRUSTED {
SVViewerUser.DrawAssemblyXOR[dc, viewerToolData, dragee];
};
dragee ← viewerToolData.dragAssembly;
IF dragee = NIL THEN RETURN;
target ← viewerToolData.dragTarget;
IF target = NIL THEN RETURN;
toolDataNARROW[target.toolMasterObject.mainBody];
IF toolData = NIL THEN {
SVError.Append["Dragging plane is not defined", oneLiner];
SVError.Blink[];
RETURN;
};
Cast a ray at the dragging plane.
[hitPointCAMERA, parallel] ← RayMeetsTargetPlane[cameraPoint, viewerToolData.dragTarget, viewerToolData.dragPlaneDepth, toolData.plane, camera];
IF parallel THEN {
SVError.Append["SetDrag: Dragging plane is parallel to ray.", oneLiner];
SVError.Blink[];
RETURN;
};
newOriginPoint ← SVVector3d.Add[hitPointCAMERA, viewerToolData.dragCameraVector];
Erase the old assembly coordsys, and body.
SVViewerUser.Painter[DoDrawAssembly, viewerToolData];
Place the assembly's coordinate systems at this new point.
SVTransforms.Abut[dragee.coordSys, camera.coordSys];
SVTransforms.Translate[dragee.coordSys, camera.coordSys, newOriginPoint[1], newOriginPoint[2], newOriginPoint[3]];
SVTransforms.TellAboutParent[dragee.coordSys];
Draw a coordinate frame and assembly at the new spot.
SVViewerUser.Painter[DoDrawAssembly, viewerToolData];
Update the ray tracing tree for this node.
To be implemented.
}; -- end of SetDrag
Cast a ray at the dragging plane.
newRay ← CSG.GetRayFromPool[];
CSG.StuffCameraRay[newRay, cameraPoint, camera];
[cameraWallPoint, parallel] ← CastRays.RayMeetsPlaneOfCoordSystem[newRay, camera.coordSys, 3, viewerToolData.dragPlaneDepth];
CSG.ReturnRayToPool[newRay];
newOriginPoint ← SVVector3d.Add[cameraWallPoint, viewerToolData.dragCameraVector];
IF parallel THEN ERROR;
SetCameraDrag: PUBLIC PROC [viewerToolData: ViewerToolData, cameraPoint: Point2d] = TRUSTED {
Cast a ray at the dragging plane. Move the dragee so as to maintain the displacement between the dragee origin and the ray tracing point.
camera: Camera ← viewerToolData.camera;
scene: Scene ← viewerToolData.scene;
hitPointCAMERA, newOriginPoint: Point3d;
dragee: Assembly;
parallel: BOOL;
DoDrawAssembly: PROC [dc: Imager.Context] = TRUSTED {
SVViewerUser.DrawAssemblyXOR[dc, viewerToolData, dragee];
};
dragee ← viewerToolData.dragAssembly;
IF dragee = NIL THEN RETURN;
Cast a ray at the dragging plane.
[hitPointCAMERA, parallel] ← RayMeetsCameraPlane[cameraPoint, viewerToolData.dragPlaneDepth, camera];
IF parallel THEN {
SVError.Append["SetCameraDrag: Dragging plane is parallel to ray.", oneLiner];
SVError.Blink[];
RETURN;
};
newOriginPoint ← SVVector3d.Add[hitPointCAMERA, viewerToolData.dragCameraVector];
Erase the old assembly, coordsys and body.
SVViewerUser.Painter[DoDrawAssembly, viewerToolData];
Place the assembly's coordinate systems at this new point.
SVTransforms.Abut[dragee.coordSys, camera.coordSys];
SVTransforms.Translate[dragee.coordSys, camera.coordSys, newOriginPoint[1], newOriginPoint[2], newOriginPoint[3]];
SVTransforms.TellAboutParent[dragee.coordSys];
Draw a coordinate frame at the new spot.
SVViewerUser.Painter[DoDrawAssembly, viewerToolData];
Update the ray tracing tree for this node.
To be implemented.
};
EndDrag: PUBLIC PROC [viewerToolData: ViewerToolData, cameraPoint: Point2d] = {
editToolData: EditToolData ← NARROW[viewerToolData.editToolData];
camera: Camera ← viewerToolData.camera;
scene: Scene ← viewerToolData.scene;
drageeSel: Selection;
assembly: Assembly ← NARROW[viewerToolData.dragAssembly];
DoDrawAssembly: PROC [dc: Imager.Context] = TRUSTED {
SVViewerUser.DrawAssemblyXOR[dc, viewerToolData, assembly];
};
DoRedrawSelection: PROC [dc: Imager.Context] = TRUSTED {
SVSelections.ComplementSelectionDC[dc, drageeSel, viewerToolData];
};
assembly ← NARROW[viewerToolData.dragAssembly];
IF assembly = NIL THEN RETURN;
drageeSel ← SVSelections.TopMovee[];
SetDrag[viewerToolData, cameraPoint];
SVViewerUser.Painter[DoDrawAssembly, viewerToolData];
SVViewerUser.Painter[DoRedrawSelection, viewerToolData];
Redraw the scene and show that it has been edited.
SVEditUser.SceneNewVersion[viewerToolData];
SVEditUser.PaintSceneAllViewers[SVViewerUser.EraseAndDrawSceneEtc, editToolData, scene];
};
EndCameraDrag: PUBLIC PROC [viewerToolData: ViewerToolData, cameraPoint: Point2d] = {
editToolData: EditToolData ← NARROW[viewerToolData.editToolData];
camera: Camera ← viewerToolData.camera;
scene: Scene ← viewerToolData.scene;
drageeSel: Selection;
assembly: Assembly;
DoDrawAssembly: PROC [dc: Imager.Context] = TRUSTED {
SVViewerUser.DrawAssemblyXOR[dc, viewerToolData, assembly];
};
DoRedrawSelection: PROC [dc: Imager.Context] = TRUSTED {
SVSelections.ComplementSelectionDC[dc, drageeSel, viewerToolData];
};
assembly ← NARROW[viewerToolData.dragAssembly];
IF assembly = NIL THEN RETURN;
drageeSel ← SVSelections.TopMovee[];
SetCameraDrag[viewerToolData, cameraPoint];
SVViewerUser.Painter[DoDrawAssembly, viewerToolData];
SVViewerUser.Painter[DoRedrawSelection, viewerToolData];
Redraw the scene and show that it has been edited.
SVEditUser.SceneNewVersion[viewerToolData];
SVEditUser.PaintSceneAllViewers[SVViewerUser.EraseAndDrawSceneEtc, editToolData, scene];
};
END.