public override bool UpdateCapture(ITransformable target, Ray3f worldRay) { // ray-hit with world-space translation plane Vector3f planeHit = translateFrameW.RayPlaneIntersection(worldRay.Origin, worldRay.Direction, nTranslationPlaneNormal); int e0 = (nTranslationPlaneNormal + 1) % 3; int e1 = (nTranslationPlaneNormal + 2) % 3; // construct delta in world space and project into frame coordinates Vector3f delta = (planeHit - vInitialHitPos); delta *= TranslationScaleF(); float dx = Vector3f.Dot(delta, translateFrameW.GetAxis(e0)); float dy = Vector3f.Dot(delta, translateFrameW.GetAxis(e1)); if (DeltaDistanceConstraintF != null) { dx = DeltaDistanceConstraintF(translateFrameL, e0, dx); dy = DeltaDistanceConstraintF(translateFrameL, e1, dy); } // construct new local frame translated along plane axes Frame3f newFrame = translateFrameL; newFrame.Origin += dx * translateFrameL.GetAxis(e0) + dy * translateFrameL.GetAxis(e1); // update target target.SetLocalFrame(newFrame, CoordSpace.ObjectCoords); return(true); }
public override bool BeginCapture(ITransformable target, Ray3f worldRay, UIRayHit hit) { // save local and world frames rotateFrameL = target.GetLocalFrame(CoordSpace.ObjectCoords); rotateFrameW = target.GetLocalFrame(CoordSpace.WorldCoords); rotateAxisW = rotateFrameW.GetAxis(nRotationAxis); // save angle of hitpos in 2D plane perp to rotateAxis, so we can find delta-angle later Vector3f vWorldHitPos = hit.hitPos; Vector3f dv = vWorldHitPos - rotateFrameW.Origin; int iX = (nRotationAxis + 1) % 3; int iY = (nRotationAxis + 2) % 3; float fX = Vector3f.Dot(dv, rotateFrameW.GetAxis(iX)); float fY = Vector3f.Dot(dv, rotateFrameW.GetAxis(iY)); fRotateStartAngle = (float)Math.Atan2(fY, fX); // construct plane we will ray-intersect with in UpdateCapture() raycastFrame = new Frame3f(vWorldHitPos, rotateAxisW); if (EnableSnapping) { enable_circle_indicator(true); } return(true); }
public override bool UpdateCapture(ITransformable target, Ray worldRay) { // ray-hit with plane perpendicular to rotateAxisW Vector3f planeHit = raycastFrame.RayPlaneIntersection(worldRay.origin, worldRay.direction, 2); // find angle of hitpos in 2D plane perp to rotateAxis, and compute delta-angle Vector3f dv = planeHit - 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); float fDeltaAngle = (fNewAngle - fRotateStartAngle); // 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); return(true); }
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); }
public Circle3d(Frame3f frame, double radius, int nNormalAxis = 1) { IsReversed = false; Center = frame.Origin; Normal = frame.GetAxis(nNormalAxis); PlaneX = frame.GetAxis((nNormalAxis + 1) % 3); PlaneY = frame.GetAxis((nNormalAxis + 2) % 3); Radius = radius; }
public override bool UpdateCapture(ITransformable target, Ray3f worldRay) { // ray-hit with plane that contains translation axis Vector3f planeHit = raycastFrame.RayPlaneIntersection(worldRay.Origin, worldRay.Direction, 2); // figure out new T-value along axis, then our translation update is delta-t float fNewT = Distance.ClosestPointOnLineT(translateFrameW.Origin, translateAxisW, planeHit); float fDeltaT = (fNewT - fTranslateStartT); fDeltaT *= TranslationScaleF(); if (DeltaDistanceConstraintF != null) { fDeltaT = DeltaDistanceConstraintF(translateFrameL, nTranslationAxis, fDeltaT); } // construct new frame translated along axis (in local space) Frame3f newFrame = translateFrameL; newFrame.Origin += fDeltaT * translateFrameL.GetAxis(nTranslationAxis); // update target target.SetLocalFrame(newFrame, CoordSpace.ObjectCoords); return(true); }
public override bool CheckVisibility(ref Frame3f curFrameW, ref Vector3d eyePosW) { Vector3d axis = curFrameW.GetAxis(nRotationAxis); Vector3d eyevec = (eyePosW - curFrameW.Origin).Normalized; double dot = axis.Dot(eyevec); return(Math.Abs(dot) > VisibilityThresh); }
public override bool CheckVisibility(ref Frame3f curFrameW, ref Vector3d eyePosW) { Vector3d axis = curFrameW.GetAxis(nTranslationAxis); Vector3d eyevec = (eyePosW - curFrameW.Origin).Normalized; double dot = axis.Dot(eyevec); return(CosVisibilityRange.Contains(dot)); }
void update_position(AnyRayHit hit) { int nNormalAxis = 1; int nUpAxis = 2; // as we drag object we will align Y with hit surface normal, but // we also want to constrain rotation so it is stable. Hence, we are // going to use world or local frame of target object to stabilize // rotation around normal. Frame3f hitF = TargetScene.SceneFrame; Vector3 targetAxis = hitF.GetAxis(1); if (hit.hitSO is SceneObject) { hitF = (hit.hitSO as SceneObject).GetLocalFrame(CoordSpace.WorldCoords); } bool bUseLocal = (TargetScene.Context.TransformManager.ActiveFrameType == FrameType.LocalFrame); if (bUseLocal && hit.hitSO is SceneObject) { hitF = (hit.hitSO as SceneObject).GetLocalFrame(CoordSpace.WorldCoords); targetAxis = hitF.GetAxis(1); } // if normal is parallel to target, this would become unstable, so use another axis if (Vector3.Dot(targetAxis, hit.hitNormal) > 0.99f) { targetAxis = hitF.GetAxis(0); } if (lastHitObject == null || hit.hitSO != lastHitObject) { lastHitF = new Frame3f(hit.hitPos, hit.hitNormal, nNormalAxis); lastHitF.ConstrainedAlignAxis(nUpAxis, targetAxis, lastHitF.GetAxis(nNormalAxis)); } else { lastHitF.Origin = hit.hitPos; lastHitF.AlignAxis(nNormalAxis, hit.hitNormal); lastHitF.ConstrainedAlignAxis(nUpAxis, targetAxis, lastHitF.GetAxis(nNormalAxis)); } lastHitObject = hit.hitSO; }
public void BeginDraw_Ray(Ray3f ray, AnyRayHit rayHit, int nStep) { CreateNewPrimitive(); Vector3f hitPos = rayHit.hitPos; // try snap points SnapResult snap = Snaps.FindHitSnapPoint(ray); if (snap != null) { Frame3f snapF = scene.ToWorldFrame(snap.FrameS); hitPos = snapF.Origin; } Frame3f sceneW = scene.SceneFrame; if (rayHit.hitSO == null) { primStartW = sceneW; primStartW.Origin = hitPos; } else { if (scene.Context.TransformManager.ActiveFrameType == FrameType.WorldFrame) { primStartW = sceneW; primStartW.Origin = hitPos; } else if (rayHit.hitSO is PivotSO) { primStartW = (rayHit.hitSO as PivotSO).GetLocalFrame(CoordSpace.WorldCoords); primStartW.Origin = hitPos; } else if (rayHit.hitSO is PrimitiveSO) { // align with object frame as much as possible, given that we still want // to use hit normal... Frame3f objFrame = (rayHit.hitSO as PrimitiveSO).GetLocalFrame(CoordSpace.WorldCoords); int nBestAxis = MathUtil.MostParallelAxis(objFrame, rayHit.hitNormal); int nPerp = (nBestAxis + 1) % 3; primStartW = new Frame3f(hitPos, rayHit.hitNormal, 1); primStartW.ConstrainedAlignAxis(0, objFrame.GetAxis(nPerp), primStartW.Y); } else { primStartW = new Frame3f(hitPos, rayHit.hitNormal, 1); primStartW.ConstrainedAlignAxis(1, sceneW.Y, primStartW.Y); } } primitive.Frame = primStartW; primStartS = scene.ToSceneFrame(primStartW); }
public static void test_normals() { // check that frames are ok DMesh3 mesh = TestUtil.LoadTestInputMesh("bunny_solid.obj"); foreach (int tid in mesh.TriangleIndices()) { Vector3f n = (Vector3f)mesh.GetTriNormal(tid); for (int j = 0; j < 3; ++j) { Frame3f f = mesh.GetTriFrame(tid, j); if (Math.Abs(f.X.Dot(f.Y)) > MathUtil.ZeroTolerancef || Math.Abs(f.X.Dot(f.Z)) > MathUtil.ZeroTolerancef || Math.Abs(f.Y.Dot(f.Z)) > MathUtil.ZeroTolerancef) { throw new Exception("argh"); } Vector3f fn = f.Z; if (fn.Dot(n) < 0.99) { throw new Exception("shit"); } } } MeshNormals.QuickCompute(mesh); foreach (int vid in mesh.VertexIndices()) { Vector3f n = mesh.GetVertexNormal(vid); for (int j = 1; j <= 2; ++j) { Frame3f f = mesh.GetVertexFrame(vid, (j == 1) ? true : false); Vector3f fn = f.GetAxis(j); if (Math.Abs(f.X.Dot(f.Y)) > MathUtil.ZeroTolerancef || Math.Abs(f.X.Dot(f.Z)) > MathUtil.ZeroTolerancef || Math.Abs(f.Y.Dot(f.Z)) > MathUtil.ZeroTolerancef) { throw new Exception("argh"); } if (fn.Dot(n) < 0.99) { throw new Exception("shit2"); } } } }
public bool Compute() { DMesh3 copy = new DMesh3(Mesh); //Frame3f PlaneO = SceneTransforms.SceneToObject(TargetSO, PlaneS); Vector3f PlaneNormal = Plane.GetAxis(nPlaneAxis); MeshPlaneCut cut = new MeshPlaneCut(copy, Plane.Origin, PlaneNormal); cut.Cut(); Loops = new DCurve3[cut.CutLoops.Count]; for (int li = 0; li < cut.CutLoops.Count; ++li) { EdgeLoop edgeloop = cut.CutLoops[li]; DCurve3 loop = MeshUtil.ExtractLoopV(copy, edgeloop.Vertices); // [TODO] collapse degenerate points... if (NormalOffset > 0) { for (int i = 0; i < loop.VertexCount; ++i) { Vector3f n = Vector3f.Zero; if (copy.HasVertexNormals) { n = (Vector3f)copy.GetVertexNormal(edgeloop.Vertices[i]); } else { n = (Vector3f)MeshNormals.QuickCompute(Mesh, edgeloop.Vertices[i]); } n -= n.Dot(PlaneNormal) * PlaneNormal; n.Normalize(); loop[i] += NormalOffset * (Vector3d)n; } } Loops[li] = loop; } return(Loops.Length > 0); }
public override bool UpdateCapture(ITransformable target, Ray3f worldRay) { // ray-hit with world-space translation plane Vector3f planeHit = cameraFrameW.RayPlaneIntersection(worldRay.Origin, worldRay.Direction, 2); // construct delta in world space and project into frame coordinates Vector3f delta = (planeHit - vInitialHitPos); delta *= ScaleMultiplierF(); //float dx = Vector3f.Dot(delta, cameraFrameW.GetAxis(0)); float dy = Vector3f.Dot(delta, cameraFrameW.GetAxis(1)); float scaleDelta = 1.0f + dy; float scaleFactor = Mathf.Clamp(scaleDelta, 0.1f, 1000.0f); // update target target.SetLocalScale(startScale * scaleFactor); return(true); }
public bool BeginCapture(MMDModel target, HitResult hit) { // save local and world frames translateFrameL = target.GetGameObjectFrame(CoordSpace.ObjectCoords); translateFrameW = target.GetGameObjectFrame(CoordSpace.WorldCoords); translateAxisW = translateFrameW.GetAxis(nTranslationAxis); // save t-value of closest point on translation axis, so we can find delta-t Vector3 vWorldHitPos = hit.HitPosition; fTranslateStartT = ClosestPointOnLineT( translateFrameW.Origin, translateAxisW, vWorldHitPos); // construct plane we will ray-intersect with in UpdateCapture() Vector3 makeUp = Vector3.Cross(Platform.Program.Camera.Forward, translateAxisW).GetNormalized( ); Vector3 vPlaneNormal = Vector3.Cross(makeUp, translateAxisW).GetNormalized( ); raycastFrame = new Frame3f(vWorldHitPos, vPlaneNormal); return(true); }
float fTranslateStartT; // start T-value along translateAxisW public override bool BeginCapture(ITransformable target, Ray3f worldRay, UIRayHit hit) { // save local and world frames translateFrameL = target.GetLocalFrame(CoordSpace.ObjectCoords); translateFrameW = target.GetLocalFrame(CoordSpace.WorldCoords); translateAxisW = translateFrameW.GetAxis(nTranslationAxis); // save t-value of closest point on translation axis, so we can find delta-t Vector3f vWorldHitPos = hit.hitPos; fTranslateStartT = Distance.ClosestPointOnLineT( translateFrameW.Origin, translateAxisW, vWorldHitPos); // construct plane we will ray-intersect with in UpdateCapture() Vector3f makeUp = Vector3f.Cross(Camera.main.transform.forward, translateAxisW).Normalized; Vector3f vPlaneNormal = Vector3f.Cross(makeUp, translateAxisW).Normalized; raycastFrame = new Frame3f(vWorldHitPos, vPlaneNormal); return(true); }
public bool UpdateCapture(MMDModel target, RayWrap worldRay) { int normalAxis = 2; if (nTranslationAxis == 2) { normalAxis = 1; } // ray-hit with plane that contains translation axis var planeHitOpt = raycastFrame.RayPlaneIntersection(worldRay.From, worldRay.Dir, normalAxis); if (!planeHitOpt.HasValue) { return(false); } Vector3 planeHit = planeHitOpt.Value; // figure out new T-value along axis, then our translation update is delta-t float fNewT = ClosestPointOnLineT(translateFrameW.Origin, translateAxisW, planeHit); float fDeltaT = (fNewT - fTranslateStartT); fDeltaT *= TranslationScaleF( ); if (DeltaDistanceConstraintF != null) { fDeltaT = DeltaDistanceConstraintF(translateFrameL, nTranslationAxis, fDeltaT); } // construct new frame translated along axis (in local space) Frame3f newFrame = translateFrameL; newFrame.Origin += fDeltaT * translateFrameL.GetAxis(nTranslationAxis); // update target //target.SetLocalFrame (newFrame, CoordSpace.ObjectCoords); target.Position = newFrame.Origin; return(true); }
public Cylinder3d(Frame3f frame, double radius, double height, int nNormalAxis = 1) { Axis = new Line3d(frame.Origin, frame.GetAxis(nNormalAxis)); Radius = radius; Height = height; }
public bool UpdateCapture(MMDModel target, RayWrap worldRay) { int normalAxis = 2; if (nRotationAxis == 2) { normalAxis = 1; } // ray-hit with plane perpendicular to rotateAxisW var planeHitWOpt = raycastFrame.RayPlaneIntersection(worldRay.From, worldRay.Dir, normalAxis); if (!planeHitWOpt.HasValue) { return(false); } var planeHitW = planeHitWOpt.Value; // 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)); Util.DebugWrite("dv " + dv.ToString( )); Util.DebugWrite("planeHitW " + planeHitW.ToString( )); Util.DebugWrite("rotateFrameW " + rotateFrameW.Origin.ToString( )); 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); Util.DebugWrite("fDeltaAngle " + fDeltaAngle); fDeltaAngle *= 0.03f; 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); } // 軸を中心に回るターゲットのための新しいフレームを作る Vector3f rotateAxisL = rotateFrameL.GetAxis(nRotationAxis); Quaternion q = Quaternion.RotationAxis(rotateAxisL, fDeltaAngle.Deg()); 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); }