protected virtual void update_value(double newValue, bool bSendEvent) { double prev = current_value; current_value = newValue; snapped_value = current_value; if (TickSnapMode != TickSnapModes.NoSnapping && TickCount > 0) { if (TickSnapMode == TickSnapModes.AlwaysSnapToNearest) { double fTickSpan = 1.0 / (TickCount - 1); double fSnapped = Snapping.SnapToIncrement(snapped_value, fTickSpan); fSnapped = MathUtil.Clamp(fSnapped, 0, 1); snapped_value = fSnapped; } else { double fTickSpan = 1.0 / (TickCount - 1); double fSnapped = Snapping.SnapToIncrement(snapped_value, fTickSpan); if (Math.Abs(fSnapped - snapped_value) < TickSnapThreshold) { snapped_value = fSnapped; } } } update_handle_position(); if (bSendEvent) { FUtil.SafeSendEvent(OnValueChanged, this, prev, snapped_value); } }
protected virtual void update_value(double newValue, bool bSendEvent) { double prev = current_value; current_value = newValue; snapped_value = current_value; if (EnableSnapToTicks && TickCount > 0) { double fTickSpan = 1.0 / (TickCount - 1); double fSnapped = Snapping.SnapToIncrement(snapped_value, fTickSpan); fSnapped = MathUtil.Clamp(fSnapped, 0, 1); // [RMS] only snap when close enough to tick? //double fSnapT = fTickSpan * 0.25; //if (Math.Abs(fSnapped - snapped_value) < fSnapT) snapped_value = fSnapped; } update_handle_position(); if (bSendEvent) { FUtil.SafeSendEvent(OnValueChanged, this, prev, snapped_value); } }
public override bool UpdateCapture(ITransformable target, Ray3f worldRay) { // ray-hit with plane perpendicular to rotateAxisW Vector3f planeHitW = raycastFrame.RayPlaneIntersection(worldRay.Origin, worldRay.Direction, 2); // find angle of hitpos in 2D plane perp to rotateAxis, and compute delta-angle Vector3f dv = planeHitW - rotateFrameW.Origin; int iX = (nRotationAxis + 1) % 3; int iY = (nRotationAxis + 2) % 3; float fX = Vector3.Dot(dv, rotateFrameW.GetAxis(iX)); float fY = Vector3.Dot(dv, rotateFrameW.GetAxis(iY)); float fNewAngle = (float)Math.Atan2(fY, fX); if (AbsoluteAngleConstraintF != null) { fNewAngle = AbsoluteAngleConstraintF(rotateFrameL, nRotationAxis, fNewAngle); } float fDeltaAngle = (fNewAngle - fRotateStartAngle); if (DeltaAngleConstraintF != null) { fDeltaAngle = DeltaAngleConstraintF(rotateFrameL, nRotationAxis, fDeltaAngle); } bool on_snap = false; if (EnableSnapping) { double dist = (planeHitW - rotateFrameW.Origin).Length; on_snap = Math.Abs(dist - gizmoRadiusW) < gizmoRadiusW * 0.15f; if (on_snap) { fDeltaAngle = (float)Snapping.SnapToIncrement(fDeltaAngle, SnapIncrementDeg * MathUtil.Deg2Radf); } enable_snap_indicator(true); update_snap_indicator(-fDeltaAngle, on_snap); } // construct new frame for target that is rotated around axis Vector3f rotateAxisL = rotateFrameL.GetAxis(nRotationAxis); Quaternionf q = Quaternion.AngleAxis(fDeltaAngle * Mathf.Rad2Deg, rotateAxisL); Frame3f newFrame = rotateFrameL; newFrame.Rotation = q * newFrame.Rotation; // order matters here! // update target target.SetLocalFrame(newFrame, CoordSpace.ObjectCoords); if (EnableSnapping) { update_circle_indicator(on_snap); } return(true); }
void Update() { if (Context == null) { return; } // [TODO] need to consider camera distane here? Frame3f sceneFrameW = Context.Scene.SceneFrame; if (sceneFrameW.EpsilonEqual(lastSceneFrameW, 0.001f)) { return; } lastSceneFrameW = sceneFrameW; if (AdjustShadowDistance) { // use vertical height of light to figure out appropriate shadow distance. // distance changes if we scale scene, and if we don't do this, shadow // map res gets very blurry. Vector3f thisW = lights[0].transform.position; float fHeight = Vector3f.Dot((thisW - sceneFrameW.Origin), sceneFrameW.Y); float fShadowDist = fHeight * 1.5f; // lights need to be in-range if (fShadowDist < LightDistance) { fShadowDist = LightDistance * 1.5f; } // need to be a multiple of eye distance float fEyeDist = sceneFrameW.Origin.Distance(Camera.main.transform.position); fShadowDist = Mathf.Max(fShadowDist, 1.5f * fEyeDist); int nShadowDist = (int)Snapping.SnapToIncrement(fShadowDist, 50); if (cur_shadow_dist != nShadowDist) { QualitySettings.shadowDistance = nShadowDist; cur_shadow_dist = nShadowDist; } } }
/// <summary> /// shoot parallel set of 2D rays at input polygon, and find portions /// of rays that are inside the polygon (we call these "spans"). These /// are inserted into the polygon, resulting in a non-manifold 2D graph. /// </summary> protected DGraph2 ComputeSpanGraph(GeneralPolygon2d poly) { double angleRad = AngleDeg * MathUtil.Deg2Rad; Vector2d dir = new Vector2d(Math.Cos(angleRad), Math.Sin(angleRad)); // compute projection span along axis Vector2d axis = dir.Perp; Interval1d axisInterval = Interval1d.Empty; Interval1d dirInterval = Interval1d.Empty; foreach (Vector2d v in poly.Outer.Vertices) { dirInterval.Contain(v.Dot(dir)); axisInterval.Contain(v.Dot(axis)); } // [TODO] also check holes? or assume they are contained? should be // classified as outside by winding check anyway... // construct interval we will step along to shoot parallel rays dirInterval.a -= 10 * ToolWidth; dirInterval.b += 10 * ToolWidth; double extent = dirInterval.Length; // nudge in a very tiny amount so that if poly is a rectangle, first // line is not directly on boundary axisInterval.a += ToolWidth * 0.01; axisInterval.b -= ToolWidth * 0.01; axisInterval.a -= PathShift; if (axisInterval.b < axisInterval.a) { return(null); // [RMS] is this right? I guess so. interval is too small to fill? } // If we are doing a dense fill, we want to pack as tightly as possible. // But if we are doing a sparse fill, then we want layers to stack. // So in that case, snap the interval to increments of the spacing // (does this work?) bool bIsSparse = (PathSpacing > ToolWidth * 2); if (bIsSparse) { // snap axisInterval.a to grid so that layers are aligned double snapped_a = Snapping.SnapToIncrement(axisInterval.a, PathSpacing); if (snapped_a > axisInterval.a) { snapped_a -= PathSpacing; } axisInterval.a = snapped_a; } Vector2d startCorner = axisInterval.a * axis + dirInterval.a * dir; double range = axisInterval.Length; int N = (int)(range / PathSpacing) + 1; // nudge spacing so that we exactly fill the available space double use_spacing = PathSpacing; if (bIsSparse == false && AdjustSpacingToMaximizeFill) { int nn = (int)(range / use_spacing); use_spacing = range / (double)nn; N = (int)(range / use_spacing) + 1; } DGraph2 graph = new DGraph2(); graph.AppendPolygon(poly); GraphSplitter2d splitter = new GraphSplitter2d(graph); splitter.InsideTestF = poly.Contains; // insert sequential rays for (int ti = 0; ti <= N; ++ti) { Vector2d o = startCorner + (double)ti * use_spacing * axis; Line2d ray = new Line2d(o, dir); splitter.InsertLine(ray, ti); } return(graph); }