Exemple #1
0
        /// <summary>
        /// Inspector - move a position by its velocity.
        /// </summary>
        /// <param name="position">The position.</param>
        /// <param name="velocity">A velocity vector perpendicular to the position. The magnitude is the radians to rotate (can be zero or greater).</param>
        /// <returns>The mext position after adjusting by velocity.</returns>
        public static Vector3 move(Vector3 position, Vector3 velocity)
        {
            float   speed_in_radians = velocity.magnitude;
            Vector3 direction        = velocity.normalized;

            return(PlanetariaMath.spherical_linear_interpolation(position, direction, speed_in_radians));
        }
Exemple #2
0
        /// <summary>
        /// Inspector - Get the normal at a particular angle.
        /// </summary>
        /// <param name="angle">The angle in radians along the arc.</param>
        /// <param name="extrusion">The radius to extrude.</param>
        /// <returns>A normal on the arc.</returns>
        public Vector3 normal(float angle, float extrusion = 0f) // TODO: delegate to position() [bug-prone when adding PI/2]
        {
            if (curvature == ArcType.ConcaveCorner)              // Concave corners are "inside-out"
            {
                extrusion *= -1;
            }

            float actual_elevation = arc_latitude + extrusion;

            if (actual_elevation >= -Mathf.PI / 2)
            {
                Vector3 equator_position = PlanetariaMath.spherical_linear_interpolation(forward_axis, right_axis, angle);
                Vector3 result           = PlanetariaMath.spherical_linear_interpolation(equator_position, center_axis, actual_elevation + Mathf.PI / 2);
                return(curvature == ArcType.ConcaveCorner ? -result : result);
            }
            else // if (actual_elevation < -Mathf.PI/2) // Primarily used for concave corners
            {
                actual_elevation += Mathf.PI / 2;
                actual_elevation /= Mathf.Cos(half_angle);
                actual_elevation -= Mathf.PI / 2;

                if (curvature == ArcType.ConcaveCorner || curvature == ArcType.ConvexCorner) // Concave corners are "inside-out"
                {
                    angle *= -1;
                }

                Vector3 normal_position = PlanetariaMath.spherical_linear_interpolation(forward_axis, center_axis, actual_elevation - Mathf.PI / 2);
                Vector3 result          = PlanetariaMath.spherical_linear_interpolation(normal_position, right_axis, angle);
                return(curvature == ArcType.ConvexCorner ? -result : result);
            }
        }
        // Preview rendering of this function is non-trivial, since ephemeral edges only work for the most recent edge.
        public static PlanetariaShape create_equilateral(PlanetariaShape shape, Vector3 center, Vector3 vertex, int faces,
                                                         PlanetariaShape.AppendMode permanence = PlanetariaShape.AppendMode.OverwriteWithPermanent)
        {
            if (faces > 0 && center != vertex)
            {
                if (faces >= 2)
                {
                    Vector3 forward = center.normalized;
                    Vector3 right   = Vector3.ProjectOnPlane(vertex, forward).normalized;
                    Vector3 up      = Vector3.Cross(forward, right).normalized;

                    float phi = Vector3.Angle(vertex, center) * Mathf.Deg2Rad;

                    List <Vector3> vertices = new List <Vector3>();
                    for (float face_index = 0; face_index < faces; ++face_index)
                    {
                        Vector3 equatorial_position = PlanetariaMath.spherical_linear_interpolation(right, up, -(face_index / faces) * (Mathf.PI * 2));
                        Vector3 final_position      = PlanetariaMath.spherical_linear_interpolation(forward, equatorial_position, phi);
                        vertices.Add(final_position);
                    }

                    List <SerializedArc> polygon = new List <SerializedArc>();
                    for (int face_index = 0; face_index < faces; ++face_index)
                    {
                        Vector3 start_point = vertices[face_index];
                        Vector3 end_point   = vertices[(face_index + 1) % faces];
                        polygon.Add(ArcFactory.line(start_point, end_point));
                    }
                    shape.append(polygon, permanence);
                    return(shape);
                }
                else // create a circle with given radius
                {
                    // first_vertex is circle start
                    Vector3 right         = Vector3.Cross(center, vertex).normalized;
                    Vector3 mirror        = Vector3.Cross(center, right).normalized;
                    Vector3 hidden_vertex = Vector3.Reflect(vertex, mirror).normalized; // opposite end of circle start

                    Vector3 first_up      = Vector3.Cross(vertex, right).normalized;
                    Vector3 first_tangent = -Vector3.Cross(first_up, vertex).normalized;

                    Vector3 second_up      = -Vector3.Cross(hidden_vertex, right).normalized;
                    Vector3 second_tangent = -Vector3.Cross(second_up, hidden_vertex).normalized;

                    SerializedArc upper_circle = ArcFactory.curve(vertex, first_tangent, hidden_vertex);
                    SerializedArc lower_circle = ArcFactory.curve(hidden_vertex, second_tangent, vertex);


                    // TODO: this entire function can be replaced now (with the circle generator)
                    shape.append(new List <SerializedArc>()
                    {
                        upper_circle, lower_circle
                    }, permanence);
                    return(shape);
                }
            }
            shape.append(new List <SerializedArc>(), permanence);
            return(shape);
        }
Exemple #4
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);
        }
Exemple #5
0
        private void aerial_move(float delta)
        {
            Vector3 next_position = PlanetariaMath.spherical_linear_interpolation(get_position(), velocity.normalized, delta); // Note: when velocity = Vector3.zero, it luckily still returns "position" intact.
            Vector3 next_velocity = PlanetariaMath.spherical_linear_interpolation(get_position(), velocity.normalized, delta + Mathf.PI / 2);

            transform.position = next_position;
            velocity           = next_velocity.normalized * velocity.magnitude; // FIXME: I thought this was numerically stable, but it seems to create more energy.
            //velocity = Vector3.ProjectOnPlane(velocity, get_position()); // TODO: CONSIDER: ensure velocity and position are orthogonal - they seem to desynchronize
            //Debug.DrawRay(get_position(), velocity, Color.green); // draw new velocity (not old one)
        }
Exemple #6
0
        public static void draw_grid()
        {
            UnityEditor.Handles.color = Color.white;

            for (float row = 1; row <= EditorGlobal.self.rows; ++row) // equator lines
            {
                float   angle  = Mathf.PI * row / (EditorGlobal.self.rows + 1);
                float   radius = Mathf.Sin(angle);
                Vector3 center = Vector3.down * Mathf.Cos(angle);
                UnityEditor.Handles.DrawWireDisc(center, Vector3.up, radius);
            }

            for (float column = 0; column < EditorGlobal.self.columns; ++column) // time zone lines
            {
                float   angle  = Mathf.PI * column / EditorGlobal.self.columns;
                Vector3 normal = PlanetariaMath.spherical_linear_interpolation(Vector3.forward, Vector3.right, angle);
                UnityEditor.Handles.DrawWireDisc(Vector3.zero, normal, 1);
            }
        }
Exemple #7
0
        /// <summary>
        /// Inspector - Get the position at a particular angle.
        /// </summary>
        /// <param name="angle">The angle in radians along the arc.</param>
        /// <param name="extrusion">The radius to extrude.</param>
        /// <returns>A position on the arc.</returns>
        public Vector3 position(float angle, float extrusion = 0f)
        {
            if (curvature == ArcType.ConcaveCorner) // Concave corners are "inside-out"
            {
                extrusion *= -1;
            }

            float actual_elevation = arc_latitude + extrusion;

            if (actual_elevation >= -Mathf.PI / 2)
            {
                Vector3 equator_position = PlanetariaMath.spherical_linear_interpolation(forward_axis, right_axis, angle);
                return(PlanetariaMath.spherical_linear_interpolation(equator_position, center_axis, actual_elevation));
            }
            else // if (actual_elevation < -Mathf.PI/2) // Primarily used for concave corners
            {
                actual_elevation += Mathf.PI / 2;
                actual_elevation /= Mathf.Cos(half_angle);
                actual_elevation -= Mathf.PI / 2;
                return(PlanetariaMath.spherical_linear_interpolation(forward_axis, center_axis, actual_elevation));
            }
        }