private Vec4D RandomShine(Vec4D dir, double shininess) { double z = shininess == double.PositiveInfinity ? 1 : Math.Pow(Rand.NextDouble(), 1 / shininess); double theta = Rand.NextDouble() * Math.PI * 2; return(Vec4D.CreateHorizon(dir, z, theta)); }
public static AABB Combine(IBoundedObject a, IBoundedObject b) { AABB aBB = a is AABB aAsBox ? aAsBox : CreateFromBounded(a); AABB bBB = b is AABB bAsBox ? bAsBox : CreateFromBounded(b); return(new AABB(Vec4D.Min(aBB.Minimum, bBB.Minimum), Vec4D.Max(aBB.Maximum, bBB.Maximum))); }
public static Vec4D Normalize(Vec4D v) { var result = v; result.Normalize(); return(result); }
private Triangle CreateRect(Vec4D pos, Vec4D up, Vec4D norm, double dist, double width, double height) { Triangle prim = Triangle.CreateRectangle(Ray.Directional(pos + (norm * (dist / 2)), up), norm, width, height); prim.Parent = this; return(prim); }
protected override Vec4D CalculateMotionData4D(Particle particle) { //normal displacement var cr = particle.CollisionRadius * particle.Scale; var r = Vec2D.GetFromPool(particle.X - X, particle.Y - Y); //no collision detected var len = r.Length - cr; if (len > Radius) { Vec2D.RecycleToPool(r); return(null); } //collision detected r.Length = Radius + cr; var v = Vec2D.GetFromPool(particle.Vx, particle.Vy); v.ProjectThis(r); var factor = 1 + Bounce; Vec2D.RecycleToPool(r); Vec2D.RecycleToPool(v); return(Vec4D.GetFromPool(X + r.X, Y + r.Y, (particle.Vx - v.X * factor) * Slipperiness, (particle.Vy - v.Y * factor) * Slipperiness)); }
public override void Transform(Mat4x4D forward, Mat4x4D inverse) { Vec4D center = forward * GetCenter(); Normal = (inverse.Transpose3x3() * Normal).Normalize(); OriginDistance = center.Dot(Normal); }
public double GetMaxCenterDistance(Vec4D direction) { double dist = 0; if (direction == Vec4D.Zero) { dist = Math.Max((new Vec4D(Minimum.X, Minimum.Y, Minimum.Z, 1) - Center).Length, dist); dist = Math.Max((new Vec4D(Minimum.X, Minimum.Y, Maximum.Z, 1) - Center).Length, dist); dist = Math.Max((new Vec4D(Minimum.X, Maximum.Y, Minimum.Z, 1) - Center).Length, dist); dist = Math.Max((new Vec4D(Minimum.X, Maximum.Y, Maximum.Z, 1) - Center).Length, dist); dist = Math.Max((new Vec4D(Maximum.X, Minimum.Y, Minimum.Z, 1) - Center).Length, dist); dist = Math.Max((new Vec4D(Maximum.X, Minimum.Y, Maximum.Z, 1) - Center).Length, dist); dist = Math.Max((new Vec4D(Maximum.X, Maximum.Y, Minimum.Z, 1) - Center).Length, dist); dist = Math.Max((new Vec4D(Maximum.X, Maximum.Y, Maximum.Z, 1) - Center).Length, dist); } else { dist = Math.Max((new Vec4D(Minimum.X, Minimum.Y, Minimum.Z, 1) - Center).Dot(direction), dist); dist = Math.Max((new Vec4D(Minimum.X, Minimum.Y, Maximum.Z, 1) - Center).Dot(direction), dist); dist = Math.Max((new Vec4D(Minimum.X, Maximum.Y, Minimum.Z, 1) - Center).Dot(direction), dist); dist = Math.Max((new Vec4D(Minimum.X, Maximum.Y, Maximum.Z, 1) - Center).Dot(direction), dist); dist = Math.Max((new Vec4D(Maximum.X, Minimum.Y, Minimum.Z, 1) - Center).Dot(direction), dist); dist = Math.Max((new Vec4D(Maximum.X, Minimum.Y, Maximum.Z, 1) - Center).Dot(direction), dist); dist = Math.Max((new Vec4D(Maximum.X, Maximum.Y, Minimum.Z, 1) - Center).Dot(direction), dist); dist = Math.Max((new Vec4D(Maximum.X, Maximum.Y, Maximum.Z, 1) - Center).Dot(direction), dist); } return(dist); }
private static Vec4D SelectFromSign(Vec4D positive, Vec4D negative, Vec4D mask) { return(new Vec4D( mask.X < 0 ? negative.X : positive.X, mask.Y < 0 ? negative.Y : positive.Y, mask.Z < 0 ? negative.Z : positive.Z, positive.W)); }
/// <summary>Rotates the camera around the specified <paramref name="axis"/> vector by <paramref name="angle"/> degrees.</summary> /// <param name="angle">The angle to rotate by.</param> /// <param name="axis">The axis to rotate around.</param> public void Rotate(double angle, Vec4D axis) { Mat4x4D rotMat = MatrixTransforms.Rotate(angle, axis); position = rotMat * position; look = rotMat * look; up = rotMat * up; }
public Camera(Vec4D pos, Vec4D lookAt, Vec4D up) { initPosition = pos; initLookAt = lookAt; initUp = up; Reset(); }
public override Ray GetRay(double x, double y) { double offX = tanFOVX2 * ((x - w2) / w2); double offY = tanFOVY2 * ((y - h2) / h2); Vec4D dir = look + (side * offX) + (up * offY); return(Ray.Directional(position, dir)); }
public Triangle(Vec4D p0, Vec4D p1, Vec4D p2, bool mirror) { Vert0 = new Vertex(p0); Vert1 = new Vertex(p1); Vert2 = new Vertex(p2); Recalculate(); Mirror = mirror; }
public static Triangle CreateRectangle(Ray up, Vec4D normal, double width, double height) { Vec4D side = up.Direction.Cross(normal).Normalize(); Vec4D v0 = up.Origin + (up.Direction * (-height / 2)) + (side * (-width / 2)); Vec4D v1 = v0 + (side * width); Vec4D v2 = v0 + (up.Direction * height); return(new Triangle(v0, v1, v2, true)); }
/// <summary>Initializes the camera for a frame render.</summary> /// <param name="width">The width of the viewport in pixels</param> /// <param name="height">The height of the viewport in pixels</param> public virtual void InitRender(int width, int height) { w2 = width / 2D; h2 = height / 2D; // This code is a bit screwy to avoid flipping the camera, not sure if there's a better way to do this (yet) look = (lookAt - position).Normalize(); side = look.Cross(-up).Normalize(); up = look.Cross(side).Normalize(); side = -side; }
public override void Transform(Mat4x4D forward, Mat4x4D inverse) { if (forward != Mat4x4D.Identity4x4) { Transformed = true; } MatrixToObject *= forward; MatrixToWorld = inverse * MatrixToWorld; MatrixToNormal = MatrixToWorld.Transpose3x3(); CenterObj = MatrixToWorld * Center; }
public Hit(Primitive primitive, Vec4D position, double distance, Vec4D normal, bool inside) { Util.Assert(primitive != null, "Cannot initialize Hit primitive to null."); Primitive = primitive; Position = position; Distance = distance; Normal = normal; Inside = inside; }
private void Recalculate() { Edge0to1 = Vert1.Position - Vert0.Position; Edge0to2 = Vert2.Position - Vert0.Position; if (!HasNormals) { Normal = Edge0to1.Cross(Edge0to2).Normalize(); Vert0 = Vert0.WithNormal(Normal); Vert1 = Vert1.WithNormal(Normal); Vert2 = Vert2.WithNormal(Normal); } }
public static TreeNode CreateVector(Vec4D vector, string name) { TreeNode node = Create($"{name} (Vector {vector}):", name); node.Tag = vector; node.Nodes.Add($"x: {vector.X}"); node.Nodes.Add($"y: {vector.Y}"); node.Nodes.Add($"z: {vector.Z}"); node.Nodes.Add($"w: {vector.W}"); node.Nodes.Add($"Length: {vector.Length}"); return(node); }
public (double near, double far) Intersect(Ray ray) { if (SIMDHelpers.Enabled) { return(IntersectAVX(ray)); } Vec4D d = ray.Direction; Vec4D min = Minimum; Vec4D max = Maximum; Vec4D temp = min; min = SelectFromSign(min, max, d); max = SelectFromSign(max, temp, d); min = (min - ray.Origin) / d; max = (max - ray.Origin) / d; // Fix cases of zeroed direction axes if (ray.Direction.Z == 0 | ray.Direction.Y == 0 | ray.Direction.Z == 0) { min = new Vec4D( (double.IsNaN(min.X) && Util.ValueInRange(ray.Origin.X, Minimum.X, Maximum.X)) ? double.NegativeInfinity : min.X, (double.IsNaN(min.Y) && Util.ValueInRange(ray.Origin.Y, Minimum.Y, Maximum.Y)) ? double.NegativeInfinity : min.Y, (double.IsNaN(min.Z) && Util.ValueInRange(ray.Origin.Z, Minimum.Z, Maximum.Z)) ? double.NegativeInfinity : min.Z, min.W); max = new Vec4D( (double.IsNaN(max.X) && Util.ValueInRange(ray.Origin.X, Minimum.X, Maximum.X)) ? double.PositiveInfinity : max.X, (double.IsNaN(max.Y) && Util.ValueInRange(ray.Origin.Y, Minimum.Y, Maximum.Y)) ? double.PositiveInfinity : max.Y, (double.IsNaN(max.Z) && Util.ValueInRange(ray.Origin.Z, Minimum.Z, Maximum.Z)) ? double.PositiveInfinity : max.Z, min.W); } double near = min.X; double far = max.X; near = Math.Max(min.Y, near); near = Math.Max(min.Z, near); far = Math.Min(max.Y, far); far = Math.Min(max.Z, far); if (near >= far | !(far >= 0)) { return(double.NaN, double.NaN); } return(near, far); }
public AABB(Vec4D minimum, Vec4D maximum) { Minimum = minimum; Maximum = maximum; Size = Maximum - Minimum; // Replace NaN with 0 for cases where infinity Center = (Minimum + (Size / 2)).WithDefault(0); #if TRACE Util.Assert(!Minimum.HasNaN(), $"Attempted to create a bounding box with an invalid minimum: ({Minimum})"); Util.Assert(!Maximum.HasNaN(), $"Attempted to create a bounding box with an invalid maximum: ({Maximum})"); Util.Assert(!Size.HasNaN(), $"Creating a bounding box resulted in an invalid size: ({Size})"); Util.Assert(!Center.HasNaN(), $"Creating a bounding box resulted in an invalid center: ({Center})"); #endif }
public static AABB CreateFromBounded(IBoundedObject bounded) { Vec4D center = bounded.GetCenter(); return(new AABB( center - new Vec4D( bounded.GetMaxCenterDistance(new Vec4D(-1, 0, 0, 0)), bounded.GetMaxCenterDistance(new Vec4D(0, -1, 0, 0)), bounded.GetMaxCenterDistance(new Vec4D(0, 0, -1, 0)), 0), center + new Vec4D( bounded.GetMaxCenterDistance(new Vec4D(1, 0, 0, 0)), bounded.GetMaxCenterDistance(new Vec4D(0, 1, 0, 0)), bounded.GetMaxCenterDistance(new Vec4D(0, 0, 1, 0)), 0))); }
internal override Hit[] DoRayTrace(Ray ray) { Vec4D d = ray.Direction; Vec4D min = Minimum; Vec4D max = Maximum; Vec4D temp = min; min = new Vec4D(d.X < 0 ? max.X : min.X, d.Y < 0 ? max.Y : min.Y, d.Z < 0 ? max.Z : min.Z, min.W); max = new Vec4D(d.X < 0 ? temp.X : max.X, d.Y < 0 ? temp.Y : max.Y, d.Z < 0 ? temp.Z : max.Z, max.W); min = (min - ray.Origin) / d; max = (max - ray.Origin) / d; double near = min.X; int nearSide = 0; double far = max.X; int farSide = 0; if (min.Y > near) { near = min.Y; nearSide = 1; } if (max.Y < far) { far = max.Y; farSide = 1; } if (min.Z > near) { near = min.Z; nearSide = 2; } if (max.Z < far) { far = max.Z; farSide = 2; } if (near > far | !(far >= 0)) { return(default);
public override void Update(Emitter emitter, Particle particle, float timeDelta, float currentTime) { foreach (Deflector deflector in Deflectors) { var md4D = deflector.GetMotionData4D(particle); if (md4D != null) { particle.IsDeflected = true; particle.X = md4D.X; particle.Y = md4D.Y; particle.Vx = md4D.Vx; particle.Vy = md4D.Vy; Vec4D.RecycleToPool(md4D); } else { particle.IsDeflected = false; } } }
public static Ray GetCameraRay(Camera camera, Random rand, int x, int y) { double dofAmt = camera.dofAmount; double subX = x + rand.NextDouble(); double subY = y + rand.NextDouble(); Ray ray = camera.GetRay(subX, subY).Offset(camera.imagePlane); if (dofAmt != 0) { Vec4D focusPoint = ray.GetPoint(camera.focalLength - camera.imagePlane); double dist = Math.Sqrt(rand.NextDouble()) * dofAmt; double angle = rand.NextDouble() * Math.PI * 2; double offX = Math.Cos(angle) * dist; double offY = Math.Sin(angle) * dist; ray = camera.GetRay(subX + offX, subY + offY).Offset(camera.imagePlane).PointingTowards(focusPoint); } return(ray); }
public Sphere(Vec4D center, double radius) { Center = center; Radius = radius; }
public Vertex(Vec4D pos, Vec4D normal) { Position = pos; Normal = normal.Normalize(); }
public Vertex WithNormal(Vec4D normal) { return(new Vertex(Position, normal)); }
public Vertex(Vec4D pos) : this(pos, new Vec4D(0, 0, 1, 0)) { }
public Plane(double origin, Vec4D normal) { OriginDistance = origin; Normal = normal.Normalize(); }
public CubePrimitive(Vec4D center, Vec4D size) { size /= 2; Minimum = center - size; Maximum = center + size; }