public HitRegion Pick(Matrix4F world, Matrix4F view, Ray3F rayL, Ray3F rayV, float s) { m_hitRegion = HitRegion.None; m_hitRayV = rayV; m_hitMatrix.Set(world); m_hitWorldView = world * view; float sl = s * SquareLength; // test xy square. Vec3F p1 = new Vec3F(0, 0, 0); Vec3F p2 = new Vec3F(sl, 0, 0); Vec3F p3 = new Vec3F(sl, sl, 0); Vec3F p4 = new Vec3F(0, sl, 0); Plane3F plane = new Plane3F(p1, p2, p3); Vec3F p; if (rayL.IntersectPlane(plane, out p)) { // test point in 2d rectangle. if (p.X > p1.X && p.X < p2.X && p.Y > p1.Y && p.Y < p4.Y) { m_hitRegion = HitRegion.XYSquare; return m_hitRegion; } } // test xz square p1 = new Vec3F(0, 0, 0); p2 = new Vec3F(sl, 0, 0); p3 = new Vec3F(sl, 0, sl); p4 = new Vec3F(0, 0, sl); plane = new Plane3F(p1, p2, p3); if (rayL.IntersectPlane(plane, out p)) { // test point in 2d rectangle. if (p.X > p1.X && p.X < p2.X && p.Z > p1.Z && p.Z < p4.Z) { m_hitRegion = HitRegion.XZSquare; return m_hitRegion; } } // test yz square p1 = new Vec3F(0, 0, 0); p2 = new Vec3F(0, 0, sl); p3 = new Vec3F(0, sl, sl); p4 = new Vec3F(0, sl, 0); plane = new Plane3F(p1, p2, p3); if (rayL.IntersectPlane(plane, out p)) { // test point in 2d rectangle. if (p.Z > p1.Z && p.Z < p2.Z && p.Y > p1.Z && p.Y < p4.Y) { m_hitRegion = HitRegion.YZSquare; return m_hitRegion; } } Vec3F min = new Vec3F(-0.5f, -0.5f, -0.5f); Vec3F max = new Vec3F(0.5f, 0.5f, 0.5f); AABB box = new AABB(min, max); Matrix4F boxScale = new Matrix4F(); Matrix4F boxTrans = new Matrix4F(); Matrix4F BoxMtrx = new Matrix4F(); // X axis boxScale.Scale(new Vec3F(s, s * br, s * br)); boxTrans.Translation = new Vec3F(s / 2, 0, 0); BoxMtrx = boxScale * boxTrans; Ray3F ray = rayL; BoxMtrx.Invert(BoxMtrx); ray.Transform(BoxMtrx); if (box.Intersect(ray)) { m_hitRegion = HitRegion.XAxis; return m_hitRegion; } // y axis boxScale.Scale(new Vec3F(s * br, s, s * br)); boxTrans.Translation = new Vec3F(0, s / 2, 0); BoxMtrx = boxScale * boxTrans; ray = rayL; BoxMtrx.Invert(BoxMtrx); ray.Transform(BoxMtrx); if (box.Intersect(ray)) { m_hitRegion = HitRegion.YAxis; return m_hitRegion; } // z axis boxScale.Scale(new Vec3F(s * br, s * br, s)); boxTrans.Translation = new Vec3F(0, 0, s / 2); BoxMtrx = boxScale * boxTrans; ray = rayL; BoxMtrx.Invert(BoxMtrx); ray.Transform(BoxMtrx); if (box.Intersect(ray)) { m_hitRegion = HitRegion.ZAxis; } return m_hitRegion; }
private static float CalcAngle(Vec3F origin, Plane3F plane, Ray3F ray0, Ray3F ray1, float snapAngle) { float theta = 0; Vec3F p0; Vec3F p1; if( ray0.IntersectPlane(plane, out p0) && ray1.IntersectPlane(plane, out p1)) { Vec3F v0 = Vec3F.Normalize(p0 - origin); Vec3F v1 = Vec3F.Normalize(p1 - origin); theta = CalcAngle(v0, v1, plane.Normal, snapAngle); } return theta; }
public Vec3F OnDragging(Ray3F rayV) { if (m_hitRegion == HitRegion.None) return Vec3F.ZeroVector; Vec3F xLocal = m_hitMatrix.XAxis; Vec3F yLocal = m_hitMatrix.YAxis; Vec3F zLocal = m_hitMatrix.ZAxis; Vec3F xAxis = m_hitWorldView.XAxis; Vec3F yAxis = m_hitWorldView.YAxis; Vec3F zAxis = m_hitWorldView.ZAxis; Vec3F origin = m_hitWorldView.Translation; Vec3F translate; float a1, a2; switch (m_hitRegion) { case HitRegion.XAxis: { a1 = Math.Abs(Vec3F.Dot(m_hitRayV.Direction, yAxis)); a2 = Math.Abs(Vec3F.Dot(m_hitRayV.Direction, zAxis)); Vec3F axis = (a1 > a2 ? yAxis : zAxis); Vec3F p0 = m_hitRayV.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); Vec3F p1 = rayV.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); float dragAmount = Vec3F.Dot((p1 - p0), xAxis); translate = dragAmount * xLocal; } break; case HitRegion.YAxis: { a1 = Math.Abs(Vec3F.Dot(m_hitRayV.Direction, zAxis)); a2 = Math.Abs(Vec3F.Dot(m_hitRayV.Direction, xAxis)); Vec3F axis = (a1 > a2 ? zAxis : xAxis); Vec3F p0 = m_hitRayV.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); Vec3F p1 = rayV.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); float dragAmount = Vec3F.Dot((p1 - p0), yAxis); translate = dragAmount * yLocal; } break; case HitRegion.ZAxis: { a1 = Math.Abs(Vec3F.Dot(m_hitRayV.Direction, xAxis)); a2 = Math.Abs(Vec3F.Dot(m_hitRayV.Direction, yAxis)); Vec3F axis = (a1 > a2 ? xAxis : yAxis); Vec3F p0 = m_hitRayV.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); Vec3F p1 = rayV.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); float dragAmount = Vec3F.Dot((p1 - p0), zAxis); translate = dragAmount * zLocal; } break; case HitRegion.XYSquare: { Vec3F p0 = m_hitRayV.IntersectPlane(zAxis, -Vec3F.Dot(zAxis, origin)); Vec3F p1 = rayV.IntersectPlane(zAxis, -Vec3F.Dot(zAxis, origin)); Vec3F deltaLocal = p1 - p0; float dragX = Vec3F.Dot(xAxis, deltaLocal); float dragY = Vec3F.Dot(yAxis, deltaLocal); translate = dragX * xLocal + dragY * yLocal; } break; case HitRegion.YZSquare: { Vec3F p0 = m_hitRayV.IntersectPlane(xAxis, -Vec3F.Dot(xAxis, origin)); Vec3F p1 = rayV.IntersectPlane(xAxis, -Vec3F.Dot(xAxis, origin)); Vec3F deltaLocal = p1 - p0; float dragY = Vec3F.Dot(yAxis, deltaLocal); float dragZ = Vec3F.Dot(zAxis, deltaLocal); translate = dragY * yLocal + dragZ * zLocal; } break; case HitRegion.XZSquare: { Vec3F p0 = m_hitRayV.IntersectPlane(yAxis, -Vec3F.Dot(yAxis, origin)); Vec3F p1 = rayV.IntersectPlane(yAxis, -Vec3F.Dot(yAxis, origin)); Vec3F deltaLocal = p1 - p0; float dragX = Vec3F.Dot(xAxis, deltaLocal); float dragZ = Vec3F.Dot(zAxis, deltaLocal); translate = dragX * xLocal + dragZ * zLocal; } break; default: throw new ArgumentOutOfRangeException(); } return translate; }