public void smooth_append(CurvePreview preview, Vector3f newPos, float fDistThresh) { // empty curve, always append if (preview.VertexCount == 0) { preview.AppendVertex(newPos); last_append = newPos; appended_last_update = true; have_temp_append = false; return; } double d = (newPos - last_append).Length; if (d < fDistThresh) { // have not gone far enough for a real new vertex! Vector3f usePos = new Vector3f(newPos); bool bValid = false; // do we have enough vertices to do a good job? if (preview.VertexCount > 3) { int nLast = (have_temp_append) ? preview.VertexCount - 2 : preview.VertexCount - 1; Vector3d tan = preview.Tangent(nLast); double fDot = tan.Dot((usePos - preview[nLast]).Normalized); if (fDot > 0.9f) // cos(25) ~= 0.9f // new vtx is aligned with tangent of last "real" vertex { bValid = true; } else { // not aligned, try projection onto tangent Line3d l = new Line3d(preview[nLast], tan); double t = l.Project(newPos); if (t > 0) { // projection of new vtx is 'ahead' so we can use it usePos = (Vector3f)l.PointAt(t); bValid = true; } } } if (bValid) { if (appended_last_update) { preview.AppendVertex(usePos); have_temp_append = true; } else if (have_temp_append) { preview[preview.VertexCount - 1] = usePos; } } appended_last_update = false; } else { // ok we drew far enough, add this position if (have_temp_append) { // re-use temp vertex preview[preview.VertexCount - 1] = newPos; have_temp_append = false; } else { preview.AppendVertex(newPos); } last_append = newPos; appended_last_update = true; // do smoothing pass smoother.End = preview.VertexCount - 1; smoother.Start = MathUtil.Clamp(smoother.End - 5, 0, smoother.End); smoother.UpdateDeformation(2); } }
public void UpdateDraw_Spatial(Ray3f ray, Frame3f handFrame, int nStep) { // scene xform may have changed during steps (eg view rotation), so we // need to reconstruct our local frame Frame3f primCurW = scene.ToWorldFrame(primStartS); // step 1: find radius in plane if (nStep == 0) { Vector3f forwardDir = ray.Direction; Vector3f plane_hit = VRUtil.SafeRayPlaneIntersection(ray, forwardDir, primCurW.Origin, primCurW.Y); plane_hit_local = primCurW.ToFrameP(plane_hit); } float fX = MathUtil.SignedClamp(plane_hit_local[0], MinDimension, MaxDimension); float fY = MinDimension; float fZ = MathUtil.SignedClamp(plane_hit_local[2], MinDimension, MaxDimension); float fR_plane = MathUtil.Clamp(plane_hit_local.Length, MinDimension / 2, MaxDimension / 2); // step 2: find height from plane if (nStep == 1) { Vector3f plane_hit = primCurW.FromFrameP(plane_hit_local); Line3d l = new Line3d(plane_hit, primCurW.Y); Vector3f handTip = handFrame.Origin + SceneGraphConfig.HandTipOffset * handFrame.Z; float fHandDist = (float)l.DistanceSquared(handTip); if (fHandDist < fR_plane * 1.5f) { fY = (float)l.Project(handTip); } else { fY = (float)DistLine3Ray3.MinDistanceLineParam(ray, l); } } // figure out possible dimensions, clamp to ranges fY = MathUtil.SignedClamp(fY, MinDimension, MaxDimension); // update frame primitive.Frame = primCurW; // update dimensions bool bIsCorner = (primitive.Center == CenterModes.Corner); float fScale = 1.0f; // object is not in scene coordinates! if (primitive.Type == MeshPrimitivePreview.PrimType.Cylinder) { primitive.Width = (bIsCorner) ? fR_plane * fScale : 2 * fR_plane * fScale; primitive.Depth = primitive.Width; //primitive.Depth = Mathf.Sign(fZ) * primitive.Width; //primitive.Width = Mathf.Sign(fX) * primitive.Width; primitive.Height = fY * fScale; } else if (primitive.Type == MeshPrimitivePreview.PrimType.Box) { primitive.Width = (bIsCorner) ? fX : 2 * fX * fScale; primitive.Depth = (bIsCorner) ? fZ : 2 * fZ * fScale; primitive.Height = fY * fScale; } else if (primitive.Type == MeshPrimitivePreview.PrimType.Sphere) { primitive.Width = (bIsCorner) ? fR_plane * fScale : 2 * fR_plane * fScale; primitive.Depth = primitive.Height = primitive.Width; //primitive.Depth = Mathf.Sign(fZ) * primitive.Width; //primitive.Width = Mathf.Sign(fX) * primitive.Width; //primitive.Height = Mathf.Sign(fY) * primitive.Width; } else { throw new NotImplementedException("DrawPrimitivesTool.UpdateDraw_Ray - type not supported"); } }
public void UpdateDraw_Ray(Ray3f ray, int nStep) { // scene xform may have changed during steps (eg view rotation), so we // need to reconstruct our local frame Frame3f primCurW = scene.ToWorldFrame(primStartS); // try snap points SnapResult snap = Snaps.FindHitSnapPoint(ray); bool bHaveSnap = (snap != null); Frame3f snapF = (bHaveSnap) ? scene.ToWorldFrame(snap.FrameS) : Frame3f.Identity; // step 1: find radius in plane // step 2: find height from plane float fY = MinDimension; if (nStep == 0) { if (bHaveSnap) { plane_hit_local = primCurW.ToFrameP( primCurW.ProjectToPlane(snapF.Origin, 1)); } else { Vector3f forwardDir = ray.Direction; Vector3f plane_hit = VRUtil.SafeRayPlaneIntersection(ray, forwardDir, primCurW.Origin, primCurW.Y); plane_hit_local = primCurW.ToFrameP(plane_hit); } } else if (nStep == 1) { Vector3f plane_hit = primCurW.FromFrameP(plane_hit_local); Line3d l = new Line3d(plane_hit, primCurW.Y); if (bHaveSnap) { fY = (float)l.Project(snapF.Origin); } else { fY = (float)DistLine3Ray3.MinDistanceLineParam(ray, l); } } // figure out possible dimensions, clamp to ranges float planeX = MathUtil.SignedClamp(plane_hit_local[0], MinDimension, MaxDimension); float planeZ = MathUtil.SignedClamp(plane_hit_local[2], MinDimension, MaxDimension); float fR_plane = MathUtil.Clamp(plane_hit_local.Length, MinDimension / 2, MaxDimension / 2); fY = MathUtil.SignedClamp(fY, MinDimension, MaxDimension); // update frame primitive.Frame = primCurW; // update dimensions bool bIsCorner = (primitive.Center == CenterModes.Corner); float fScale = 1.0f; // object is not in scene coordinates! if (primitive.Type == MeshPrimitivePreview.PrimType.Cylinder) { primitive.Width = (bIsCorner) ? fR_plane * fScale : 2 * fR_plane * fScale; primitive.Depth = primitive.Width; primitive.Height = fY * fScale; } else if (primitive.Type == MeshPrimitivePreview.PrimType.Box) { primitive.Width = (bIsCorner) ? planeX * fScale : 2 * planeX * fScale; primitive.Depth = (bIsCorner) ? planeZ * fScale : 2 * planeZ * fScale; primitive.Height = fY * fScale; } else if (primitive.Type == MeshPrimitivePreview.PrimType.Sphere) { primitive.Width = (bIsCorner) ? fR_plane * fScale : 2 * fR_plane * fScale; primitive.Depth = primitive.Width; primitive.Height = Mathf.Sign(fY) * primitive.Width; } else { throw new NotImplementedException("SnapDrawPrimitivesTool.UpdateDraw_Ray - type not supported"); } }