示例#1
0
        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));
        }
示例#2
0
        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)));
        }
示例#3
0
            public static Vec4D Normalize(Vec4D v)
            {
                var result = v;

                result.Normalize();
                return(result);
            }
示例#4
0
        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));
        }
示例#6
0
        public override void Transform(Mat4x4D forward, Mat4x4D inverse)
        {
            Vec4D center = forward * GetCenter();

            Normal         = (inverse.Transpose3x3() * Normal).Normalize();
            OriginDistance = center.Dot(Normal);
        }
示例#7
0
        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);
        }
示例#8
0
 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));
 }
示例#9
0
        /// <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;
        }
示例#10
0
        public Camera(Vec4D pos, Vec4D lookAt, Vec4D up)
        {
            initPosition = pos;
            initLookAt   = lookAt;
            initUp       = up;

            Reset();
        }
示例#11
0
        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));
        }
示例#12
0
        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;
        }
示例#13
0
        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));
        }
示例#14
0
 /// <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;
 }
示例#15
0
 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;
 }
示例#16
0
        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;
        }
示例#17
0
        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);
            }
        }
示例#18
0
        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);
        }
示例#19
0
        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);
        }
示例#20
0
        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
        }
示例#21
0
        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)));
        }
示例#22
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);
示例#23
0
 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;
         }
     }
 }
示例#24
0
        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);
        }
示例#25
0
 public Sphere(Vec4D center, double radius)
 {
     Center = center;
     Radius = radius;
 }
示例#26
0
 public Vertex(Vec4D pos, Vec4D normal)
 {
     Position = pos;
     Normal   = normal.Normalize();
 }
示例#27
0
 public Vertex WithNormal(Vec4D normal)
 {
     return(new Vertex(Position, normal));
 }
示例#28
0
 public Vertex(Vec4D pos) : this(pos, new Vec4D(0, 0, 1, 0))
 {
 }
示例#29
0
 public Plane(double origin, Vec4D normal)
 {
     OriginDistance = origin;
     Normal         = normal.Normalize();
 }
示例#30
0
 public CubePrimitive(Vec4D center, Vec4D size)
 {
     size   /= 2;
     Minimum = center - size;
     Maximum = center + size;
 }