DIRECTORY BasicObject3d, CastRays, CoordSys, CSG, DisplayList3d, DisplayListToTree, Graphics, GraphicsColor, Matrix3d, Preprocess3d, Rope, SV2d, SV3d, SVEditUser, SVError, SVInterfaceTypes, SVModelTypes, SVRayTypes, SVSceneTypes, SVSelections, SVTransforms, SVVector3d, SVViewerInput, SVViewerTools, SVViewerUser, TIPUser, ViewerClasses, ViewerTools; SVViewerInputImplC: PROGRAM IMPORTS CastRays, CoordSys, CSG, DisplayList3d, DisplayListToTree, Matrix3d, Preprocess3d, SVEditUser, SVError, SVSelections, SVTransforms, SVVector3d, SVViewerInput, SVViewerTools, SVViewerUser, ViewerTools EXPORTS SVViewerInput = BEGIN Artwork: TYPE = SVModelTypes.Artwork; ArtworkToolData: TYPE = SVInterfaceTypes.ArtworkToolData; Assembly: TYPE = SVSceneTypes.Assembly; AssemblyList: TYPE = SVSceneTypes.AssemblyList; BoundBox: TYPE = SVModelTypes.BoundBox; BoundSphere: TYPE = SVModelTypes.BoundSphere; Camera: TYPE = SVModelTypes.Camera; Classification: TYPE = SVRayTypes.Classification; Color: TYPE = GraphicsColor.Color; CoordSystem: TYPE = SVModelTypes.CoordSystem; CSGTree: TYPE = SVRayTypes.CSGTree; CylinderRec: TYPE = BasicObject3d.CylinderRec; EditToolData: TYPE = SVInterfaceTypes.EditToolData; FileCamera: TYPE = SVSceneTypes.FileCamera; FrameBox: TYPE = SVModelTypes.FrameBox; MasterObject: TYPE = SVSceneTypes.MasterObject; Matrix4by4: TYPE = SV3d.Matrix4by4; Point2d: TYPE = SV2d.Point2d; Point3d: TYPE = SV3d.Point3d; Primitive: TYPE = SVRayTypes.Primitive; Ray: TYPE = SVRayTypes.Ray; Scene: TYPE = SVSceneTypes.Scene; SearchDepth: TYPE = SVInterfaceTypes.SearchDepth; Selection: TYPE = SVInterfaceTypes.Selection; SelectionGenerator: TYPE = SVInterfaceTypes.SelectionGenerator; Shape: TYPE = SVSceneTypes.Shape; SkitterMode: TYPE = SVInterfaceTypes.SkitterMode; ToolData: TYPE = SVSceneTypes.ToolData; TrigLine: TYPE = SV2d.TrigLine; Vector: TYPE = SV3d.Vector; ViewerToolData: TYPE = SVInterfaceTypes.ViewerToolData; JackPivotX: PUBLIC PROC [viewerToolData: ViewerToolData, degrees: REAL] = { editToolData: EditToolData _ viewerToolData.editToolData; scene: Scene _ viewerToolData.scene; targetSel: Selection; coincident: Assembly; targetSel _ SVSelections.TopTarget[]; IF targetSel = NIL THEN RETURN; coincident _ targetSel.coincident; SVSelections.ComplementSelection[viewerToolData, targetSel]; SVTransforms.XRotate[coincident.coordSys, coincident.coordSys, degrees, TRUE]; SVSelections.ComplementSelection[viewerToolData, targetSel]; }; JackPivotY: PUBLIC PROC [viewerToolData: ViewerToolData, degrees: REAL] = { editToolData: EditToolData _ viewerToolData.editToolData; scene: Scene _ viewerToolData.scene; targetSel: Selection; coincident: Assembly; targetSel _ SVSelections.TopTarget[]; IF targetSel = NIL THEN RETURN; coincident _ targetSel.coincident; SVSelections.ComplementSelection[viewerToolData, targetSel]; SVTransforms.YRotate[coincident.coordSys, coincident.coordSys, degrees, TRUE]; SVSelections.ComplementSelection[viewerToolData, targetSel]; }; JackPivotZ: PUBLIC PROC [viewerToolData: ViewerToolData, degrees: REAL] = { editToolData: EditToolData _ viewerToolData.editToolData; scene: Scene _ viewerToolData.scene; targetSel: Selection; coincident: Assembly; targetSel _ SVSelections.TopTarget[]; IF targetSel = NIL THEN RETURN; coincident _ targetSel.coincident; SVSelections.ComplementSelection[viewerToolData, targetSel]; SVTransforms.ZRotate[coincident.coordSys, coincident.coordSys, degrees, TRUE]; SVSelections.ComplementSelection[viewerToolData, targetSel]; }; SourcePivotX: PUBLIC PROC [viewerToolData: ViewerToolData, degrees: REAL] = { editToolData: EditToolData _ viewerToolData.editToolData; scene: Scene _ viewerToolData.scene; sourceSel: Selection; jack, indirect: Assembly; sourceSel _ SVSelections.TopMovee[]; IF sourceSel = NIL THEN RETURN; SELECT sourceSel.referentType FROM hook => { jack _ sourceSel.coincident; indirect _ sourceSel.indirect; }; coordSys => { jack _ sourceSel.coincident; indirect _ sourceSel.coincident; }; ENDCASE => ERROR; SVEditUser.PaintAssemblyAllViewers[SVViewerUser.DrawAssemblyXOR, editToolData, scene, indirect]; SVTransforms.XRotate[indirect.coordSys, jack.coordSys, degrees, TRUE]; SVEditUser.PaintAssemblyAllViewers[SVViewerUser.DrawAssemblyXOR, editToolData, scene, indirect]; }; SourcePivotY: PUBLIC PROC [viewerToolData: ViewerToolData, degrees: REAL] = { editToolData: EditToolData _ viewerToolData.editToolData; scene: Scene _ viewerToolData.scene; sourceSel: Selection; jack, indirect: Assembly; sourceSel _ SVSelections.TopMovee[]; IF sourceSel = NIL THEN RETURN; SELECT sourceSel.referentType FROM hook => { jack _ sourceSel.coincident; indirect _ sourceSel.indirect; }; coordSys => { jack _ sourceSel.coincident; indirect _ sourceSel.coincident; }; ENDCASE => ERROR; SVEditUser.PaintAssemblyAllViewers[SVViewerUser.DrawAssemblyXOR, editToolData, scene, indirect]; SVTransforms.YRotate[indirect.coordSys, jack.coordSys, degrees, TRUE]; SVEditUser.PaintAssemblyAllViewers[SVViewerUser.DrawAssemblyXOR, editToolData, scene, indirect]; }; SourcePivotZ: PUBLIC PROC [viewerToolData: ViewerToolData, degrees: REAL] = { editToolData: EditToolData _ viewerToolData.editToolData; scene: Scene _ viewerToolData.scene; sourceSel: Selection; jack, indirect: Assembly; sourceSel _ SVSelections.TopMovee[]; IF sourceSel = NIL THEN RETURN; SELECT sourceSel.referentType FROM hook => { jack _ sourceSel.coincident; indirect _ sourceSel.indirect; }; coordSys => { jack _ sourceSel.coincident; indirect _ sourceSel.coincident; }; ENDCASE => ERROR; SVEditUser.PaintAssemblyAllViewers[SVViewerUser.DrawAssemblyXOR, editToolData, scene, indirect]; SVTransforms.ZRotate[indirect.coordSys, jack.coordSys, degrees, TRUE]; SVEditUser.PaintAssemblyAllViewers[SVViewerUser.DrawAssemblyXOR, editToolData, scene, indirect]; }; ArrowShoot: PUBLIC PROC [] = { source, target: Assembly; sourceSel, firstTargetSel: Selection; viewerToolData: ViewerToolData; sourceSel _ SVSelections.PopMovee[]; IF sourceSel = NIL THEN RETURN; source _ sourceSel.coincident; viewerToolData _ sourceSel.viewerToolData; firstTargetSel _ SVSelections.PopTarget[]; IF firstTargetSel = NIL THEN RETURN; FOR targetSel: Selection _ firstTargetSel, SVSelections.NextTarget[] UNTIL targetSel = NIL DO IF targetSel.viewerToolData # sourceSel.viewerToolData THEN { SVError.Append["Can't shoot arrows between viewers.", TRUE, TRUE]; SVError.Blink[]; LOOP; }; target _ targetSel.coincident; ArrowShootAux[source.coordSys, target.coordSys, viewerToolData]; ENDLOOP; SVEditUser.PaintSceneAllViewers[SVViewerUser.EraseAndDrawSceneEtc, viewerToolData.editToolData, viewerToolData.scene]; }; ArrowShootAux: PROC [sourceCS, targetCS: CoordSystem, viewerToolData: ViewerToolData] = { sOriginWorld, tOriginWorld: Point3d; tree: CSGTree; ray: Ray; class: Classification; t: REAL; worldDirection, primitiveNormal, worldNormal: Vector; selectionMat: Matrix4by4; surfacePtInWorld: Point3d; primitive: Primitive; assembly: Assembly; scene: Scene; camera: Camera; scene _ viewerToolData.scene; camera _ viewerToolData.camera; tree _ DisplayListToTree.AssemblyToTree[scene.assembly, scene, camera]; [] _ Preprocess3d.PreprocessForSlice[tree, camera]; sOriginWorld _ Matrix3d.OriginOfMatrix[sourceCS.wrtWorld]; tOriginWorld _ Matrix3d.OriginOfMatrix[targetCS.wrtWorld]; ray _ CSG.GetRayFromPool[]; worldDirection _ SVVector3d.Sub[tOriginWorld, sOriginWorld]; CSG.StuffWorldRay[ray, sOriginWorld, worldDirection, camera]; class _ CastRays.RayCastBoundingSpheres[ray, tree.son]; FOR i: NAT IN [1..class.count] DO t _ class.params[i]; -- the parameter of the ray intersection primitiveNormal _ class.normals[i]; primitive _ class.primitives[i]; worldNormal _ Matrix3d.UpdateVectorWithInverse[primitive.worldWRTPrim, primitiveNormal]; surfacePtInWorld[1] _ sOriginWorld[1] + t*worldDirection[1]; surfacePtInWorld[2] _ sOriginWorld[2] + t*worldDirection[2]; surfacePtInWorld[3] _ sOriginWorld[3] + t*worldDirection[3]; assembly _ NARROW[primitive.assembly]; SVViewerInput.ComplementSkitter[]; -- erase any old skitter selectionMat _ MakeAlignedMat[worldNormal, surfacePtInWorld, assembly.coordSys]; SVSelections.UpdateSkitter[assembly, primitive, viewerToolData]; SVSelections.PositionSkitter[[0,0], selectionMat]; SVSelections.SetModeSkitter[surface]; SVViewerInput.ComplementSkitter[]; -- draw new skitter SVViewerInput.SkitterMakes[]; ENDLOOP; CastRays.ReturnClassToPool[class]; CSG.ReturnRayToPool[ray]; }; Sign: PRIVATE PROC [r: REAL] RETURNS [INT] = { IF r = 0.0 THEN RETURN[2]; IF r < 0.0 THEN RETURN[-1] ELSE RETURN[1]; }; AntiParallel: PRIVATE PROC [v1, v2: Vector] RETURNS [BOOL] = { RETURN[Sign[v1[1]] = -Sign[v2[1]] OR Sign[v1[2]] = -Sign[v2[2]] OR Sign[v1[3]] = -Sign[v2[3]] ]; }; MakeAlignedMat: PRIVATE PROC [worldNormal: Vector, surfacePtInWorld: Point3d, cs: CoordSystem] RETURNS [mat: Matrix4by4] = TRUSTED { yAxisOfCS: Vector _ Matrix3d.YAxisOfMatrix[cs.wrtWorld]; xAxis: Vector; IF SVVector3d.Parallel[yAxisOfCS, worldNormal] THEN { xAxis _ Matrix3d.XAxisOfMatrix[cs.wrtWorld]; IF AntiParallel[yAxisOfCS, worldNormal] THEN xAxis _ SVVector3d.Negate[xAxis]; } ELSE xAxis _ SVVector3d.CrossProduct[yAxisOfCS, worldNormal]; mat _ Matrix3d.MakeMatFromZandXAxis[worldNormal, xAxis, surfacePtInWorld]; }; MoveUntilTouch: PUBLIC PROC [] = { source, target: Assembly; sourceSel, targetSel: Selection; viewerToolData: ViewerToolData; sourceSel _ SVSelections.PopMovee[]; IF sourceSel = NIL THEN RETURN; source _ sourceSel.coincident; viewerToolData _ sourceSel.viewerToolData; targetSel _ SVSelections.PopTarget[]; IF targetSel = NIL THEN RETURN; IF targetSel.viewerToolData # sourceSel.viewerToolData THEN { SVError.Append["Can't skewer between viewers.", TRUE, TRUE]; SVError.Blink[]; RETURN; }; target _ targetSel.coincident; MoveUntilTouchAux[source, target, viewerToolData]; SVEditUser.PaintSceneAllViewers[SVViewerUser.EraseAndDrawSceneEtc, viewerToolData.editToolData, viewerToolData.scene]; }; MoveUntilTouchAux: PROC [source, target: Assembly, viewerToolData: ViewerToolData] = { sOriginWorld, tOriginWorld: Point3d; tree, sourceTree: CSGTree; worldDirection: Vector; scene: Scene; camera: Camera; boundSphere: BoundSphere; R: REAL; basisMat: Matrix4by4; scene _ viewerToolData.scene; camera _ viewerToolData.camera; sourceTree _ DisplayListToTree.AssemblyToTree[source, scene, camera]; boundSphere _ Preprocess3d.PreprocessForSlice[sourceTree, camera]; R _ boundSphere.radius; tree _ DisplayListToTree.AssemblyToTree[scene.assembly, scene, camera]; [] _ Preprocess3d.PreprocessForSlice[tree, camera]; sOriginWorld _ Matrix3d.OriginOfMatrix[source.coordSys.wrtWorld]; tOriginWorld _ Matrix3d.OriginOfMatrix[target.coordSys.wrtWorld]; worldDirection _ SVVector3d.Sub[tOriginWorld, sOriginWorld]; basisMat _ Matrix3d.MakeHorizontalMatFromZAxis[worldDirection, sOriginWorld]; MoveUntilTouchAuxAux[source, scene.coordSysRoot, basisMat, worldDirection, R, camera, tree]; }; -- end of MoveUntilTouchAux MoveUntilTouchAuxAux: PROC [source: Assembly, worldCS: CoordSystem, basisMat: Matrix4by4, worldDirection: Vector, R: REAL, camera: Camera, tree: CSGTree] = { ray: Ray; minDeltaT, lastSourceT, firstOtherT: REAL; class: Classification; success, someData: BOOL; basisBasePt, worldBasePt: Point3d; moveVector: Vector; raysPerHalfSide: NAT = 20; raysPerHalfSideF: REAL = 20.0; ray _ CSG.GetRayFromPool[]; someData _ FALSE; FOR i: INT IN [-raysPerHalfSide..raysPerHalfSide-1] DO basisBasePt[1] _ (i+0.5)*R/raysPerHalfSideF; FOR j: INT IN [-raysPerHalfSide..raysPerHalfSide-1] DO basisBasePt[2] _ (j+0.5)*R/raysPerHalfSideF; basisBasePt[3] _ 0.0; worldBasePt _ Matrix3d.Update[basisMat, basisBasePt]; CSG.StuffWorldRay[ray, worldBasePt, worldDirection, camera]; class _ CastRays.RayCastBoundingSpheres[ray, tree.son, FALSE]; [lastSourceT, firstOtherT, success] _ SourceAndOtherT[class, source]; IF NOT success THEN { CastRays.ReturnClassToPool[class]; LOOP; }; IF firstOtherT < lastSourceT THEN { SVError.Append["Source is already touching.",TRUE,TRUE]; SVError.Blink[]; RETURN; }; IF NOT someData THEN { minDeltaT _ firstOtherT-lastSourceT; someData _ TRUE; } ELSE minDeltaT _ MIN[minDeltaT, firstOtherT-lastSourceT]; CastRays.ReturnClassToPool[class]; ENDLOOP; -- j ENDLOOP; -- i IF NOT someData THEN { SVError.Append["No Obstacles Found. Object NOT moved.",TRUE,TRUE]; SVError.Blink[]; RETURN; }; moveVector _ SVVector3d.Scale[worldDirection, minDeltaT]; SVTransforms.Translate[source.coordSys, worldCS, moveVector[1], moveVector[2], moveVector[3]]; CSG.ReturnRayToPool[ray]; }; SourceAndOtherT: PROC [class: Classification, source: Assembly] RETURNS [lastSourceT, firstOtherT: REAL, success: BOOL _ FALSE] = { sourceFound, otherFound: BOOL; thisAssembly: Assembly; sourceFound _ FALSE; otherFound _ FALSE; IF class.count = 0 THEN RETURN [0,0,FALSE]; FOR i: NAT IN [1..class.count] DO thisAssembly _ NARROW[class.primitives[i].assembly]; IF DisplayListToTree.IsSuccessorOf[thisAssembly, source] THEN { lastSourceT _ class.params[i]; sourceFound _ TRUE; } ELSE IF NOT otherFound THEN { firstOtherT _ class.params[i]; otherFound _ TRUE; }; ENDLOOP; success _ sourceFound AND otherFound; }; Skewer: PUBLIC PROC [] = { source, target: Assembly; sourceSel, firstTargetSel: Selection; viewerToolData: ViewerToolData; sourceSel _ SVSelections.PopMovee[]; IF sourceSel = NIL THEN RETURN; source _ sourceSel.coincident; viewerToolData _ sourceSel.viewerToolData; firstTargetSel _ SVSelections.PopTarget[]; IF firstTargetSel = NIL THEN RETURN; IF firstTargetSel.viewerToolData # sourceSel.viewerToolData THEN { SVError.Append["Can't skewer between viewers.", TRUE, TRUE]; SVError.Blink[]; RETURN; }; target _ firstTargetSel.coincident; SkewerAux[source, target, viewerToolData]; SVEditUser.PaintSceneAllViewers[SVViewerUser.EraseAndDrawSceneEtc, viewerToolData.editToolData, viewerToolData.scene]; }; SkewerAux: PROC [source, target: Assembly, viewerToolData: ViewerToolData] = { sOriginWorld, tOriginWorld: Point3d; tree: CSGTree; ray: Ray; class: Classification; t: REAL; directionWorld: Vector; surfacePtInWorld, lastSurfacePtInWorld: Point3d; primitive: Primitive; assembly, lastAssembly: Assembly; moveVector, totalVector, localDiff: Vector; scene: Scene; camera: Camera; sourceCS, targetCS: CoordSystem; sourceCS _ source.coordSys; targetCS _ target.coordSys; scene _ viewerToolData.scene; camera _ viewerToolData.camera; tree _ DisplayListToTree.AssemblyToTree[scene.assembly, scene, camera]; [] _ Preprocess3d.PreprocessForSlice[tree, camera]; sOriginWorld _ Matrix3d.OriginOfMatrix[sourceCS.wrtWorld]; tOriginWorld _ Matrix3d.OriginOfMatrix[targetCS.wrtWorld]; ray _ CSG.GetRayFromPool[]; directionWorld _ SVVector3d.Sub[tOriginWorld, sOriginWorld]; sOriginWorld _ SVVector3d.Sub[sOriginWorld, SVVector3d.Scale[directionWorld, 0.3]]; directionWorld _ SVVector3d.Scale[directionWorld, 1.6]; CSG.StuffWorldRay[ray, sOriginWorld, directionWorld, camera]; class _ CastRays.RayCastBoundingSpheres[ray, tree.son, FALSE]; CastRays.SortClassByPrimitive[class]; IF class.count = 0 THEN { CastRays.ReturnClassToPool[class]; CSG.ReturnRayToPool[ray]; RETURN; }; lastAssembly _ NARROW[class.primitives[1].assembly]; t _ class.params[1]; lastSurfacePtInWorld[1] _ sOriginWorld[1] + t*directionWorld[1]; lastSurfacePtInWorld[2] _ sOriginWorld[2] + t*directionWorld[2]; lastSurfacePtInWorld[3] _ sOriginWorld[3] + t*directionWorld[3]; totalVector _ [0,0,0]; FOR i: NAT IN [2..class.count] DO t _ class.params[i]; -- the parameter of the ray intersection IF t > 1.0 THEN EXIT; -- Compression occurs only BETWEEN source and target. primitive _ class.primitives[i]; surfacePtInWorld[1] _ sOriginWorld[1] + t*directionWorld[1]; surfacePtInWorld[2] _ sOriginWorld[2] + t*directionWorld[2]; surfacePtInWorld[3] _ sOriginWorld[3] + t*directionWorld[3]; assembly _ NARROW[primitive.assembly]; IF lastAssembly # assembly THEN { localDiff _ SVVector3d.Sub[lastSurfacePtInWorld, surfacePtInWorld]; moveVector _ SVVector3d.Add[localDiff, totalVector]; totalVector _ SVVector3d.Add[totalVector, localDiff]; SVTransforms.Translate[assembly.coordSys, scene.coordSysRoot, moveVector[1], moveVector[2], moveVector[3]]; }; lastAssembly _ assembly; lastSurfacePtInWorld _ surfacePtInWorld; ENDLOOP; CastRays.ReturnClassToPool[class]; CSG.ReturnRayToPool[ray]; }; AddCylinder: PUBLIC PROC [] = { sourceSel, firstTargetSel: Selection; sourceCS, targetCS: CoordSystem; viewerToolData: ViewerToolData; editToolData: EditToolData; radius: REAL; scene: Scene; sourceSel _ SVSelections.PopMovee[]; IF sourceSel = NIL THEN RETURN; firstTargetSel _ SVSelections.PopTarget[]; IF firstTargetSel = NIL THEN RETURN; IF sourceSel.viewerToolData # firstTargetSel.viewerToolData THEN { SVError.Append["Can't add cylinder between viewers.", TRUE, TRUE]; SVError.Blink[]; RETURN; }; viewerToolData _ sourceSel.viewerToolData; scene _ viewerToolData.scene; editToolData _ viewerToolData.editToolData; sourceCS _ sourceSel.coincident.coordSys; radius _ SVViewerTools.GetReal[editToolData.cylinderSection.radius, 20]; FOR targetSel: Selection _ firstTargetSel, SVSelections.NextTarget[] UNTIL targetSel = NIL DO targetCS _ targetSel.coincident.coordSys; AddCylinderAux[sourceCS, targetCS, radius, editToolData, scene]; ENDLOOP; SVEditUser.PaintSceneAllViewers[SVViewerUser.EraseAndDrawSceneEtc, editToolData, viewerToolData.scene]; }; AddCylinderAux: PROC [sourceCS, targetCS: CoordSystem, radius: REAL, editToolData: EditToolData, scene: Scene] = { cylMO: MasterObject; moFound: BOOL; cylinderRec: CylinderRec; sOriginWorld, tOriginWorld, midPointWorld: Point3d; cylWorld, superWorld, cylSuper: Matrix4by4; cylinderY: Vector; height: REAL; newAssembly, superAssembly: Assembly; success: BOOL; addSucceeds: BOOL _ TRUE; cylName: Rope.ROPE; [cylMO, moFound] _ DisplayList3d.FindObjectFromName["cylinder", scene]; IF NOT moFound THEN ERROR; cylinderRec _ NARROW[cylMO.mainBody]; sOriginWorld _ Matrix3d.OriginOfMatrix[sourceCS.wrtWorld]; tOriginWorld _ Matrix3d.OriginOfMatrix[targetCS.wrtWorld]; midPointWorld _ SVVector3d.Add[sOriginWorld, tOriginWorld]; midPointWorld _ SVVector3d.Scale[midPointWorld, 0.5]; cylinderY _ SVVector3d.Sub[tOriginWorld, sOriginWorld]; height _ SVVector3d.Magnitude[cylinderY]; cylWorld _ MakeHorizontalMatFromYAxis[cylinderY, midPointWorld]; radius _ radius/cylinderRec.radius; height _ height/cylinderRec.height; cylName _ ViewerTools.GetContents[editToolData.sceneSection.new]; cylName _ CoordSys.UniqueNameFrom[cylName, scene.coordSysRoot]; [superAssembly, success] _ SVEditUser.GetParent[editToolData]; IF NOT success THEN RETURN; superWorld _ superAssembly.coordSys.wrtWorld; cylSuper _ Matrix3d.WorldToLocal[superWorld, cylWorld]; [newAssembly, ----] _ DisplayList3d.CreateAndAddPrimitiveAssembly[cylName, "cylinder", [radius, height, radius], scene, superAssembly, cylSuper ! DisplayList3d.NameAlreadyPresent => TRUSTED { SVError.Append["This cyl name is already registered. Try another.", TRUE, TRUE]; SVError.Blink[]; addSucceeds _ FALSE; CONTINUE}; DisplayList3d.AttemptToAddSubassemblyToPrimitive => { SVError.Append["Attempt To Add Subassembly To Primitive", TRUE, TRUE]; SVError.Blink[]; addSucceeds _ FALSE; CONTINUE} ]; IF NOT addSucceeds THEN RETURN; }; -- end of AddCylinderAux MakeHorizontalMatFromYAxis: PROC [yAxis: Vector, origin: Point3d] RETURNS [mat: Matrix4by4] = { xAxis: Vector; IF yAxis[1] = 0 AND yAxis[3] = 0 THEN xAxis _ [1,0,0] ELSE xAxis _ SVVector3d.CrossProduct[[0,1,0], yAxis]; mat _ Matrix3d.MakeMatFromYandXAxis[yAxis, xAxis, origin]; }; END. PFile: SVViewerInputImplC.mesa Last edited by Bier on January 26, 1985 2:35:54 pm PST Copyright c 1984 by Xerox Corporation. All rights reserved. Contents: Procedures for responding to button clicks made in a solidviewer. Rotate the distinguished target coincident with respect to itself by degrees. This makes sense for both hook and coordsys targets. Erases the target shape. For a jack, this leaves nothing. For another object, this leaves the object. Rotate the distinguished target coincident with respect to itself by degrees. This makes sense for both hook and coordsys targets. Erases the target shape. For a jack, this leaves nothing. For another object, this leaves the object. Rotate the distinguished target coincident with respect to itself by degrees. This makes sense for both hook and coordsys targets. Erases the target shape. For a jack, this leaves nothing. For another object, this leaves the object. Rotate the distinguished source indirect with respect to the distinguished source coincident. If the selection is not a hook jack, then indirect and coincident are identical. Rotate the distinguished source indirect with respect to the distinguished source coincident. If the selection is not a hook jack, then indirect and coincident are identical. Rotate the distinguished source indirect with respect to the distinguished source coincident. If the selection is not a hook jack, then indirect and coincident are identical. Cast a ray from the distinguished source to each of the targets. Create a hook at each intersection point, aligned with the surface normal at that point. Cast a ray from source to target. Create a hook at each intersection point, aligned with the surface normal at that point. Create a Matrix4by4 with origin at surfacePtInWorld whose z axis is parallel to worldNormal and whose x zxis is orthogonal to both worldNormal and the y axis of cs in WORLD coordinates. Assume that cs.wrtWorld is accurate Allows positioning code to distinguish between top surfaces and bottom surfaces. Consider a line from the distinguished source to the distinguished target. Using translation along the ray direction (only) move the distinguish source towards the distinguished target until it touches something other than itself. If the distinguished source already touches something else, leave it alone. Cast a set of rays parallel to the line from source to target and starting on a plane normal to that line a bounding sphere's radius behind source. Using translation along the ray direction (only) move the source until it touches something (anything). Shoot many rays in this direction starting from the plane of points x satisfying (x-sOriginWorld).w = 0. First, let's find two basis vectors for this plane. They are the x and y axes of the basis matrix. Shoot a ray from the distinguished source to the distinguished target. Using translation along the ray direction (only) bring all intersected objects together so they are touching at the ray intersection points. Cast a ray from source to target. Using translation along the ray direction (only) bring all intersected objects together so they are touching at the ray intersection points. The skewer extends from the earliest point hit on the source object (by the infinite line) to the last point hit on the target object. For now, a kludge: Cast a ray from 30% behind the source to 30% after the target. Here comes the kludge End of kludge. Add a cylinder whose radius is taken from the editTool and whose height is just large enough so it stretches from the distinguished source to the distinguished target. Add a cylinder whose radius is taken from the editTool and whose height is just large enough so it stretches from sourceCS to targetCS. Uses yAxis as it is. Finds a horizontal x axis orthogonal to zAxis. If yAxis is vertical, then there are infinitely many. Chooses [1,0,0] in this case. Κ―˜Iheadšœ™Jšœ6™6Jšœ Οmœ1™šžœž˜$Jšœž˜Jšœ˜—J˜J˜—š ŸœžœžœCžœžœ˜„Jšœή™ήJšœ8˜8Jšœ˜šžœ-žœ˜5Jšœ,˜,Jšžœ&žœ"˜NJ™PJ˜—Jšžœ9˜=JšœJ˜JJšœ˜J˜—šŸœž œ˜"J™΄J˜Jšœ ˜ Jšœ˜J˜Jš  œ˜$Jšžœ žœžœžœ˜Jšœ˜Jšœ*˜*J˜Jš  œ˜%Jšžœ žœžœžœ˜šžœ5žœ˜=Jšœ0žœžœ˜‘œ˜MJ˜Jš œ7žœ˜\Jšœ’˜J˜—šŸœžœXžœžœ$˜Jšœ ˜ Jšœ%žœ˜*J˜Jšœžœ˜Jšœ"˜"J˜Jšœžœ˜Jšœžœ˜Jšœžœ˜Jšœ žœ˜šžœžœžœ'ž˜6Jšœžœ˜,šžœžœžœ'ž˜6Jšœžœ˜,Jšœ˜Jšœ5˜5Jšžœ9˜Jšœ& œ˜Ešžœžœ žœ˜Jšœ"˜"Jšžœ˜J˜—šžœžœ˜#Jšœ-žœžœ˜8J˜Jšžœ˜J˜—šžœžœ žœ˜Jšœ$˜$Jšœ žœ˜J˜—Jšžœ žœ%˜9Jšœ"˜"—Jšžœ’˜ —Jšžœ’˜ šžœžœ žœ˜Jšœ8žœžœ˜CJ˜Jšžœ˜J˜—Jšœ9˜9Jšœ^˜^Jšžœ˜J˜J˜—š Ÿœžœ+žœžœ žœžœ˜ƒJšœžœ˜Jšœ˜Jšœžœ˜Jšœ žœ˜Jšžœžœžœžœ˜+šžœžœžœž˜!Jšœžœ˜4šžœ7žœ˜?Jšœ˜Jšœžœ˜J˜—šžœžœžœ žœ˜Jšœ˜Jšœ žœ˜J˜——Jšžœ˜Jšœžœ ˜%J˜J˜—šŸœž œ˜J™ΤJ˜Jšœ%˜%Jšœ˜J˜Jš  œ˜$Jšžœ žœžœžœ˜Jšœ˜Jšœ*˜*J˜Jš œ˜*Jšžœžœžœžœ˜$šžœ:žœ˜BJšœ0žœžœ˜Jšœ Ÿœ˜%šžœžœ˜Jšœ"˜"Jšžœ˜Jšžœ˜J˜—Jšœžœ˜4Jšœ˜Jšœ!‘œ‘œ˜@Jšœ!‘œ‘œ˜@Jšœ!‘œ‘œ˜@Jšœ˜šžœžœžœž˜!Jšœ œ’)˜=Jšžœ žœžœ’5˜KJšœ ˜ Jš œ ‘œ‘œ˜Lšžœžœ žœžœ˜Lšœ‘œ#˜-Lšœ‘œ‘œ‘œ˜7L˜Lšœ’œ˜šœt‘˜yšœ&žœ˜/LšœEžœžœ˜QLšœžœžœ˜0—šœ5˜5Lšœ:žœžœ˜FLšœ˜Lšœžœžœ˜—Lšœ˜—Lšžœžœ žœžœ˜Lšœ’˜L˜J˜—šŸœžœ"žœ˜_Lšœš™šLšœ˜Lšžœžœžœ˜5Lšžœ1˜5Lšœ:˜:Lšœ˜L˜—Jšžœ˜J˜—…—L<p;