示例#1
0
 private void synchronize_velocity_air_to_ground()
 {
     if (observer.exists)
     {
         horizontal_velocity = Vector3.Dot(velocity, Bearing.right(planetaria_transform.position, collision.geometry_visitor.normal()));
         vertical_velocity   = Vector3.Dot(velocity, collision.geometry_visitor.normal());
     }
 }
示例#2
0
        /// <summary>
        /// Inspector - Finds the point at "angle" extruded "extrusion" along "local_angle" direction.
        /// </summary>
        /// <param name="arc">The arc (used to determine positions and relative angles).</param>
        /// <param name="angle">The angle along the arc path. Range: [-arc.angle()/2, +arc.angle()/2]</param>
        /// <param name="local_angle">The secant angle relative to the arc at position("angle"). Range: [0, 2PI]</param>
        /// <param name="extrusion">The distance along "local_angle" to extrude.</param>
        /// <returns>The relative position after extruding the point at "angle" by "extrusion" along "local_angle".</returns>
        public static Vector3 relative_point(Arc arc, float angle, float local_angle, float extrusion)
        {
            Vector3 from            = arc.position(angle);
            Vector3 local_direction = Bearing.bearing(arc.position(angle), arc.normal(angle), local_angle);
            Vector3 to = PlanetariaMath.spherical_linear_interpolation(from, local_direction, extrusion);

            return(to);
        }
示例#3
0
 private void synchronize_velocity_ground_to_air()
 {
     if (observer.exists)
     {
         Vector3 x = horizontal_velocity * Bearing.right(planetaria_transform.position, collision.geometry_visitor.normal());
         Vector3 y = vertical_acceleration * Time.fixedDeltaTime * collision.geometry_visitor.normal();
         velocity = x + y;
     }
 }
示例#4
0
        private void grounded_accelerate(float delta)
        {
            Vector3 normal = collision.geometry_visitor.normal();
            Vector3 right  = Bearing.right(collision.geometry_visitor.position(), normal);

            acceleration            = get_acceleration();
            horizontal_acceleration = Vector3.Dot(acceleration, right);
            vertical_acceleration   = Vector3.Dot(acceleration, normal) - collision.magnetism;
            vertical_velocity      += vertical_acceleration * Time.fixedDeltaTime;
            if (!collision.grounded(internal_velocity))   // TODO: check centripedal force
            {
                derail(0, vertical_acceleration * delta); // Force OnCollisionExit, "un-collision" (and accelerate for a frame)
            }
        }
示例#5
0
        /// <summary>
        /// Inspector - project a point onto the given equator axis (the direction a raindrop would fall along a globe).
        /// </summary>
        /// <param name="point">The point that shall be projected.</param>
        /// <param name="equator_axis">The axis of the equator line (onto which the point shall be projected).</param>
        /// <returns>A projected point along the equator axis.</returns>
        public static Vector3 project_onto_equator(Vector3 point, Vector3 equator_axis)
        {
            if (Vector3.Dot(point, equator_axis) < 0) // make sure you are repelling from the pole closer to the point (so the point moves towards the equator).
            {
                equator_axis *= -1;
            }
            Vector3 gradient = Bearing.repeller(point, equator_axis);                             // push the point away from the axis towards the equator
            float   angle    = Mathf.PI / 2 - Vector3.Angle(point, equator_axis) * Mathf.Deg2Rad; // find the angle to the equator

            Vector3 projected_point = spherical_linear_interpolation(point, gradient, angle);

            Debug.Assert(Vector3.Dot(projected_point, equator_axis) < Precision.threshold);
            return(projected_point);
        }
示例#6
0
        private static bool platform_collision(Arc arc, PlanetariaCollider collider, PlanetariaTransform transformation, PlanetariaRigidbody rigidbody, optional <Vector3> intersection_point)
        {
            Vector3 velocity = Bearing.attractor(rigidbody.get_previous_position(), rigidbody.get_position());

            if (intersection_point.exists)
            {
                float   arc_angle            = arc.position_to_angle(intersection_point.data);
                Vector3 normal               = arc.normal(arc_angle);
                bool    upward_facing_normal = Vector3.Dot(normal, rigidbody.get_acceleration()) <= 0;
                bool    moving_toward        = Vector3.Dot(normal, velocity) <= 0;

                if (upward_facing_normal && moving_toward)
                {
                    return(true);
                }
            }
            return(false);
        }
示例#7
0
        /// <summary>
        /// Inspector - Determine the type of corner connecting the left-hand-side and right-hand-side Arcs (concave/convex/straight).
        /// </summary>
        /// <param name="left">Arc that will connect to beginning.</param>
        /// <param name="right">Arc that will connect to end.</param>
        /// <returns>
        /// GeometryType.ConvexCorner if the corner arc is convex.
        /// GeometryType.ConcaveCorner if the corner arc is concave.
        /// GeometryType.StraightCorner if the corner arc is a straight angle.
        /// </returns>
        public static ArcType corner_type(Arc left, Arc right)
        {
            // Both cases
            Vector3 normal_for_left = left.end_normal();
            // Straight angle check
            Vector3 normal_for_right = right.begin_normal();
            // Convex/Concave check
            Vector3 rightward_for_right = Bearing.right(right.begin(), right.begin_normal());

            if (Vector3.Dot(normal_for_left, normal_for_right) > 1 - Precision.tolerance)
            {
                return(ArcType.StraightCorner);
            }
            else
            {
                return(Vector3.Dot(normal_for_left, rightward_for_right) < Precision.tolerance ?
                       ArcType.ConvexCorner : ArcType.ConcaveCorner);
            }
        }
示例#8
0
        public void derail(float x_velocity, float y_velocity)
        {
            if (observer.exists && observer.data.colliding())
            {
                BlockCollision collision = observer.data.collisions()[0];

                collision.geometry_visitor.move_position(0, transform.scale / 2 * (1 + 1e-3f)); // extrude the player so they do not accidentally re-collide (immediately) // FIXME: magic number, move to Precision.*
                x_velocity += horizontal_velocity;
                //y_velocity += vertical_velocity;
                planetaria_transform.position = collision.geometry_visitor.position();
                Vector3 normal = collision.geometry_visitor.normal();
                Vector3 right  = Bearing.right(planetaria_transform.position, normal);
                velocity = right * x_velocity + normal * y_velocity;
                Debug.DrawRay(planetaria_transform.position, velocity, Color.yellow, 1f);
                acceleration = get_acceleration();
                // TODO: accelerate vertically

                observer.data.clear_block_collision();
                observer = new optional <CollisionObserver>();
            }
        }
示例#9
0
        public bool collide(BlockCollision collision, CollisionObserver observer)
        {
            if (this.observer.exists)
            {
                this.observer.data.clear_block_collision();
            }

            aerial_move(-collision.overshoot); // this only (truly) works with perpendicular vectors?

            this.observer  = observer;
            this.collision = collision;

            horizontal_velocity = Vector3.Dot(velocity, Bearing.right(planetaria_transform.position, collision.geometry_visitor.normal()));
            vertical_velocity   = Vector3.Dot(velocity, collision.geometry_visitor.normal());
            if (vertical_velocity < 0)
            {
                vertical_velocity *= -collision.elasticity;
            }

            grounded_accelerate(0);

            return(this.observer.exists);
        }
示例#10
0
        /// <summary>
        /// Inspector (Cache Mutator) - Updates the cache so that spherical rectangle calculations avoid recomputing old values.
        /// </summary>
        /// <param name="canvas">A Rect (measuring radians) representing the start and stop angles relative to Quaternion.identity. X/Y Range: (-2PI, +2PI).</param>
        public static void cache_spherical_rectangle(Rect canvas)
        {
            if (cached_canvas != canvas)
            {
                Vector3 lower_left   = intersection(canvas.xMin, canvas.yMin);
                Vector3 lower_center = intersection(canvas.center.x, canvas.yMin);
                Vector3 lower_right  = intersection(canvas.xMax, canvas.yMin);

                Vector3 middle_left   = intersection(canvas.xMin, canvas.center.y);
                Vector3 middle_center = intersection(canvas.center.x, canvas.center.y);
                Vector3 middle_right  = intersection(canvas.xMax, canvas.center.y);

                Vector3 upper_left   = intersection(canvas.xMin, canvas.yMax);
                Vector3 upper_center = intersection(canvas.center.x, canvas.yMax);
                Vector3 upper_right  = intersection(canvas.xMax, canvas.yMax);

                Arc biangle_segment1 = ArcFactory.curve(upper_center, upper_right, -upper_center);
                Arc biangle_segment2 = ArcFactory.curve(lower_center, lower_right, -lower_center);
                cached_left_biangle_focus      = PlanetariaIntersection.arc_arc_intersection(biangle_segment1, biangle_segment2, 0).data;
                cached_left_positive_partition = Bearing.attractor(cached_left_biangle_focus, middle_left); // used for a dot product to determine if the angle applied for UV is +/-
                if (Vector3.Dot(cached_left_positive_partition, middle_center) >= 0)
                {
                    cached_left_start_angle = Vector3.Angle(cached_left_biangle_focus, middle_center) * Mathf.Deg2Rad;
                    cached_left_end_angle   = Vector3.Angle(cached_left_biangle_focus, middle_left) * Mathf.Deg2Rad;
                }
                else
                {
                    cached_left_start_angle = Vector3.Angle(-cached_left_biangle_focus, middle_center) * Mathf.Deg2Rad + Mathf.PI;
                    cached_left_end_angle   = Vector3.Angle(-cached_left_biangle_focus, middle_left) * Mathf.Deg2Rad + Mathf.PI;
                }

                biangle_segment1                = ArcFactory.curve(upper_center, upper_left, -upper_center);
                biangle_segment2                = ArcFactory.curve(lower_center, lower_left, -lower_center);
                cached_right_biangle_focus      = PlanetariaIntersection.arc_arc_intersection(biangle_segment1, biangle_segment2, 0).data;
                cached_right_positive_partition = Bearing.attractor(cached_right_biangle_focus, middle_right); // used for a dot product to determine if the angle applied for UV is +/-
                if (Vector3.Dot(cached_right_positive_partition, middle_center) >= 0)
                {
                    cached_right_start_angle = Vector3.Angle(cached_right_biangle_focus, middle_center) * Mathf.Deg2Rad;
                    cached_right_end_angle   = Vector3.Angle(cached_right_biangle_focus, middle_right) * Mathf.Deg2Rad;
                }
                else
                {
                    cached_right_start_angle = Vector3.Angle(-cached_right_biangle_focus, middle_center) * Mathf.Deg2Rad + Mathf.PI;
                    cached_right_end_angle   = Vector3.Angle(-cached_right_biangle_focus, middle_right) * Mathf.Deg2Rad + Mathf.PI;
                }

                biangle_segment1                = ArcFactory.curve(middle_left, upper_left, -middle_left);
                biangle_segment2                = ArcFactory.curve(middle_right, upper_right, -middle_right);
                cached_lower_biangle_focus      = PlanetariaIntersection.arc_arc_intersection(biangle_segment1, biangle_segment2, 0).data;
                cached_lower_positive_partition = Bearing.attractor(cached_lower_biangle_focus, lower_center); // used for a dot product to determine if the angle applied for UV is +/-
                if (Vector3.Dot(cached_lower_positive_partition, middle_center) >= 0)
                {
                    cached_lower_start_angle = Vector3.Angle(cached_lower_biangle_focus, middle_center) * Mathf.Deg2Rad;
                    cached_lower_end_angle   = Vector3.Angle(cached_lower_biangle_focus, lower_center) * Mathf.Deg2Rad;
                }
                else
                {
                    cached_lower_start_angle = Vector3.Angle(-cached_lower_biangle_focus, middle_center) * Mathf.Deg2Rad + Mathf.PI;
                    cached_lower_end_angle   = Vector3.Angle(-cached_lower_biangle_focus, lower_center) * Mathf.Deg2Rad + Mathf.PI;
                }

                biangle_segment1                = ArcFactory.curve(middle_left, lower_left, -middle_left);
                biangle_segment2                = ArcFactory.curve(middle_right, lower_right, -middle_right);
                cached_upper_biangle_focus      = PlanetariaIntersection.arc_arc_intersection(biangle_segment1, biangle_segment2, 0).data;
                cached_upper_positive_partition = Bearing.attractor(cached_upper_biangle_focus, upper_center); // used for a dot product to determine if the angle applied for UV is +/-
                if (Vector3.Dot(cached_upper_positive_partition, middle_center) >= 0)
                {
                    cached_upper_start_angle = Vector3.Angle(cached_upper_biangle_focus, middle_center) * Mathf.Deg2Rad;
                    cached_upper_end_angle   = Vector3.Angle(cached_upper_biangle_focus, upper_center) * Mathf.Deg2Rad;
                }
                else
                {
                    cached_upper_start_angle = Vector3.Angle(-cached_upper_biangle_focus, middle_center) * Mathf.Deg2Rad + Mathf.PI;
                    cached_upper_end_angle   = Vector3.Angle(-cached_upper_biangle_focus, upper_center) * Mathf.Deg2Rad + Mathf.PI;
                }

                cached_north_hemisphere = Bearing.attractor(middle_center, upper_center);
                cached_east_hemisphere  = Bearing.attractor(middle_center, middle_right);

                cached_canvas = canvas;
            }
        }
示例#11
0
 public Vector3 get_acceleration()
 {
     return(Bearing.attractor(get_position(), gravity.normalized) * gravity.magnitude);
 }