public Ray(Vec3 origin, Vec3 dir) { Debug.Assert(Num.AlmostEqual(dir.Abs(), 1.0)); this.origin = origin; this.dir = dir; }
public static Vec3 Cross(Vec3 lhs, Vec3 rhs) { return new Vec3( lhs.Y * rhs.Z - lhs.Z * rhs.Y, lhs.Z * rhs.X - lhs.X * rhs.Z, lhs.X * rhs.Y - lhs.Y * rhs.X); }
public Plane(Vec3 normal, double distance) { Debug.Assert(Num.AlmostEqual(normal.Abs(), 1.0)); this.normal = normal; this.distance = distance; }
/// <summary> /// Draw a glowing laser beam. /// </summary> public static void DrawBeam( Vec3 start, Vec3 end, double size, Color inner, Color outer) { // TODO: Push translation and rotation to get the result point from start to end. Vec3 dir = end - start; Vec3 axis; double angle; Geom.OrientTowards(new Vec3(1, 0, 0), dir, out axis, out angle); float length = (float)dir.Abs(); float unit = (float)size / 4; Gl.glPushMatrix(); Gl.glTranslated(start.X, start.Y, start.Z); Gl.glRotated(Geom.Rad2Deg(angle), axis.X, axis.Y, axis.Z); Gl.glPushAttrib(Gl.GL_LIGHTING_BIT | Gl.GL_ENABLE_BIT); Gl.glBlendFunc(Gl.GL_ONE, Gl.GL_ONE); Gfx.GlEmissionColor(inner); Gfx.DrawCube(unit, -unit, -unit, length - 2 * unit, 2 * unit, 2 * unit); Gfx.GlEmissionColor(outer); Gfx.DrawCube(0, -2 * unit, -2 * unit, length, 4 * unit, 4 * unit); Gl.glBlendFunc(Gl.GL_ONE, Gl.GL_ZERO); Gl.glPopAttrib(); Gl.glPopMatrix(); }
/// <summary> /// Make a random unit vector. /// </summary> /// <remarks> /// Samples points in [-1, -1, -1] - [1, 1, 1] until one that's neither at /// the origin or outside the unit sphere is found. Returns this vector /// normalized to unit length. /// </remarks> public Vec3 UnitVec() { double len; Vec3 result; do { result = new Vec3( RandDouble(-1.0, 1.0), RandDouble(-1.0, 1.0), RandDouble(-1.0, 1.0)); len = result.Abs(); } while (len < Num.Epsilon || len > 1.0); return result.Unit(); }
public static double Dot(Vec3 lhs, Vec3 rhs) { return lhs.X * rhs.X + lhs.Y * rhs.Y + lhs.Z * rhs.Z; }
/// <summary> /// The smallest angle in radians between two vectors. /// </summary> public static double Angle(Vec3 lhs, Vec3 rhs) { return Math.Acos(Dot(lhs.Unit(), rhs.Unit())); }
public Vec3(Vec3 other) { this.X = other.X; this.Y = other.Y; this.Z = other.Z; }
/// <summary> /// Return the dir8 a vector's XY projection points to. /// </summary> public static int VecToDir8(Vec3 vec) { var result = ((Hexadecant(vec.X, vec.Y) + 1) % 16) / 2; return result; }
/// <summary> /// Determine the point where a ray hits a plane if it does. Return /// whether the ray hits the plane or not. /// </summary> public static bool RayPlaneIntersection( Ray ray, Plane plane, out Vec3 intersection) { double rayPlaneDot = Vec3.Dot(ray.Dir, plane.Normal); if (Num.AlmostEqual(rayPlaneDot, 0.0)) { // Ray is practically parallel to the plane. intersection = new Vec3(0, 0, 0); return false; } // How far along the ray is the intersection? double t = (plane.Distance - Vec3.Dot(plane.Normal, ray.Origin)) / rayPlaneDot; if (t >= 0.0) { intersection = ray.Origin + ray.Dir * t; return true; } else { intersection = new Vec3(0, 0, 0); return false; } }
/// <summary> /// If two vectors are on the same Z plane, return a dir8 pointing from /// the first to the second. /// </summary> public static bool PointTo(Vec3 origin, Vec3 target, out int dir8) { dir8 = -1; if (origin.Z == target.Z) { dir8 = VecToDir8(target - origin); return true; } else { return false; } }
/// <summary> /// Generate an axis + angle rotation that aligns a vector with /// the given direction vector. /// </summary> public static void OrientTowards(Vec3 init, Vec3 dir, out Vec3 axis, out double angle) { axis = Vec3.Cross(init, dir).Unit(); angle = Vec3.Angle(init, dir); }