示例#1
0
    private static float MaxErrorLocation(ArcOfSphere arc, float begin, float end)
    {
        Vector2 L1 = SpaceConverter.SphereToUV(arc.Evaluate(begin));
        Vector2 L2 = SpaceConverter.SphereToUV(arc.Evaluate(end));

        // 2) use binary / bisection search to find the point of maximal error
        while (end - begin > delta)
        {
            float midpoint = (begin + end) / 2;

            float error_left  = Point_Line_Distance(L1, L2, SpaceConverter.SphereToUV(arc.Evaluate(midpoint - delta)));
            float error_right = Point_Line_Distance(L1, L2, SpaceConverter.SphereToUV(arc.Evaluate(midpoint + delta)));

            if (error_left < error_right) //error begin should be replaced since it has less error
            {
                begin = midpoint;
            }
            else //error end should be replaced since it has less error
            {
                end = midpoint;
            }
        }

        return((begin + end) / 2); // return location of max error
    }
示例#2
0
    public static ConcaveCorner Spawn(ArcOfSphere previous_edge, ArcOfSphere next_edge)
    {
        GameObject prefab = (GameObject)Resources.Load("ConcaveCornerPrefab");

                #if UNITY_EDITOR
        GameObject obj = PrefabUtility.InstantiatePrefab(prefab) as GameObject;
                #else
        GameObject obj = Instantiate(prefab) as GameObject;
                #endif

        #if UNITY_EDITOR
        Undo.RegisterCreatedObjectUndo(obj, "Created concave corner");
                #endif

        obj.name = "Concave corner";

        ConcaveCorner result = obj.GetComponent <ConcaveCorner>();

        result.Initialize(previous_edge, next_edge);

                #if UNITY_EDITOR
        result.Save();
        result.LinkBlock(previous_edge);
                #endif

        return(result);
    }
示例#3
0
    public void GroundedUpdate(CharacterMotor self)
    {
        if (self.input.sqrMagnitude > 1)
        {
            self.input.Normalize();
        }

        Vector3 input3D = new Vector3(self.input.x, self.input.y, 0f);         //FIXME: JANK

        if (input3D.sqrMagnitude > 1)
        {
            input3D.Normalize();
        }

        Quaternion rotation = Quaternion.LookRotation(self.current_position, self.arc.EvaluateNormal(self.angle, self.radius));

        float left_product  = Vector3.Dot(rotation * input3D, self.left);
        float right_product = Vector3.Dot(rotation * input3D, self.right);
        float product       = -Mathf.Abs(left_product);

        if (right_product > left_product)
        {
            product = +Mathf.Abs(right_product);
        }
        if (right_product < 0 && left_product < 0)
        {
            product = 0;
        }

        self.angle += product / self.height / 64; //FIXME: slight math error here-ish

        self.current_position = ArcOfSphere.Evaluate(self.ground.data, self.radius);

        self.transform.rotation = Quaternion.LookRotation(self.current_position, self.arc.EvaluateNormal(self.angle, self.radius));
    }
示例#4
0
    public bool Traverse(ArcOfSphere path, Vector3 desiredPos)     //I don't like these parameters, they can be fixed //I don't like that this is public, it should be private and exposed via a generic move option if possible
    {
        optional <float> interpolation_factor = path.CartesianToRadial(desiredPos);

        if (interpolation_factor.exists)
        {
            ground = new GroundInfo();

            ground.data.angle = interpolation_factor.data;

            ground.data.arc    = path;
            ground.data.block  = path.GetComponentInParent <Block>();
            ground.data.height = path.LengthRadius(radius);
            ground.data.begin  = path.Begin(radius);
            ground.data.end    = path.End(radius);

            current_position = ArcOfSphere.Evaluate(ground.data, radius);
        }
        else
        {
            Debug.Log("Critical Failure: Traverse's interpolation factor doesn't exist!");
        }

        return(interpolation_factor.exists);
    }
    //step 0: Character Controller adds the observed SphericalIsoscelesTriangle to a vector in OnTriggerEnter...
    public void OnTriggerEnter(Collider col)
    {
        ArcOfSphere arc = col.gameObject.GetComponent <ArcOfSphere>();

        if (arc && !colliders.Contains(arc))
        {
            colliders.Add(arc);
        }
    }
    //step 0.5: Character Controller removes the observed SphericalIsoscelesTriangle from a vector in OnTriggerExit...
    public void OnTriggerExit(Collider col) //FIXME: not deleting
    {
        ArcOfSphere arc = col.gameObject.GetComponent <ArcOfSphere>();

        if (arc)
        {
            colliders.Remove(arc);
        }
    }
示例#7
0
    public QuadraticBezier(ArcOfSphere a, Vector2 b, Vector2 c, Vector2 e, float bt, float et)
    {
        begin_UV      = b;
        control_point = c;
        end_UV        = e;

        arc   = a;
        begin = bt;
        end   = et;
    }
示例#8
0
    public static Edge LinkRight(ArcOfSphere left, Vector3 position)
    {
        Vector3 right = left.Evaluate(left.End());

        Edge obj = Edge.StartEdge(left.transform.parent.transform, right, position);

        obj.Relink(left, left.next);

        return(obj);
    }
示例#9
0
    protected static Vector3 MaxGradient(ArcOfSphere arc, Vector3 desired)
    {
        Vector3 max_gradient = Vector3.zero;
        float   max_product  = Mathf.NegativeInfinity;

        /** if we don't calculate per quadrant, calculations for an arc with angle 2*PI become ambiguous because left == right
         */
        float quadrants = Mathf.Ceil(arc.End() / (Mathf.PI / 2f)); //maximum of 4, always integral, float for casting "left" and "right"

        for (float quadrant = 0; quadrant < quadrants; ++quadrant)
        {
            float left  = arc.End() * (quadrant / quadrants);               //get beginning of quadrant i.e. 0.00,0.25,0.50,0.75
            float right = arc.End() * ((quadrant + 1) / quadrants);         //get    end    of quadrant i.e. 0.25,0.50,0.75,1.00

            float left_product  = Vector3.Dot(arc.Evaluate(left), desired); //find the correlation factor between left and the desired direction
            float right_product = Vector3.Dot(arc.Evaluate(right), desired);

            /** this is basically a binary search
             *
             *  1) take the left and right vectors and compute their dot products with the desired direction.
             *  2) take the lesser dot product and ignore that half of the remaining arc
             */
            for (int iteration = 0; iteration < 8 * sizeof(float); ++iteration) //because we are dealing with floats, more precision could help (or hurt?)
            {
                float midpoint = (left + right) / 2;
                if (left_product < right_product) //is the right vector closer to the desired direction?
                {
                    left         = midpoint;      //throw out the left half if the right vector is closer
                    left_product = Vector3.Dot(arc.Evaluate(left), desired);
                }
                else
                {
                    right         = midpoint; //throw out the right half if the left vector is closer
                    right_product = Vector3.Dot(arc.Evaluate(right), desired);
                }
            }

            /** figure out if this quadrant contains a larger gradient
             */
            if (max_product < right_product)
            {
                max_gradient = arc.Evaluate(right);
                max_product  = right_product;
            }
            if (max_product < left_product)
            {
                max_gradient = arc.Evaluate(left);
                max_product  = left_product;
            }
        }
        return(max_gradient);
    }
示例#10
0
    private static void UpdateSigns(ArcOfSphere arc, ref int[,] data, float location, float delta)
    {
        //assert data's size is [2, 3]

        for (int dimension = 0; dimension < 3; ++dimension)
        {
            data[0, dimension] = System.Math.Sign(arc.Evaluate(location)[dimension]);
        }
        for (int dimension = 0; dimension < 3; ++dimension)
        {
            data[1, dimension] = System.Math.Sign(arc.Evaluate(location + delta)[dimension] - arc.Evaluate(location)[dimension]) * System.Math.Sign(delta);
        }
    }
示例#11
0
    public static void AddLine(ArcOfSphere edge, float begin, float end)
    {
        Vector2 begin_UV = SpaceConverter.SphereToUV(edge.Evaluate(begin));
        Vector2 end_UV   = SpaceConverter.SphereToUV(edge.Evaluate(end));

        if (Vector2.Distance(begin_UV, end_UV) > threshold)
        {
            Vector2 delta_begin_UV = SpaceConverter.SphereToUV(edge.Evaluate(begin + 64 * delta));
            Vector2 delta_end_UV   = SpaceConverter.SphereToUV(edge.Evaluate(end - 64 * delta));
            Vector2 control_point  = Intersection(begin_UV, delta_begin_UV, delta_end_UV, end_UV);

            DebugUtility.Log("AddLine:", begin_UV, end_UV);

            lines.Add(new QuadraticBezier(edge, begin_UV, control_point, end_UV, begin, end));
        }
    }
示例#12
0
    public ArcOfSphere Relink(ArcOfSphere left, ArcOfSphere right)
    {
        #if UNITY_EDITOR
        this.Save();
        left.Save();
        right.Save();
        #endif

        this.next = right;
        this.prev = left;

        left.next  = this;
        right.prev = this;

        return(this);
    }
示例#13
0
    public void Activate()
    {
        SphereCollider region = GetComponent <SphereCollider>();

        Collider[] arc_objects = Physics.OverlapSphere(region.transform.position + region.center, region.transform.localScale.x * region.radius);

        region.enabled = true;

        foreach (Collider arc_object in arc_objects)
        {
            ArcOfSphere arc = arc_object.gameObject.GetComponent <ArcOfSphere>();
            if (arc)
            {
                colliders.Add(arc);
            }
        }
    }
示例#14
0
    public void Move(Vector2 input)
    {
        if (between_levels) //FEATURE: enable movement (grounded and aerial) in between_levels
        {
            connection.data.Move(Input.GetAxis("Vertical"), this);
        }
        else if (grounded) //FIXME: this entire block if it is JANK //spelling -_-'
        {
            if (input.sqrMagnitude > 1)
            {
                input.Normalize();
            }

            Transform camera_transform = GameObject.Find("MainCamera").transform; //FIXME: JANK

            Vector3 input3D = new Vector3(input.x, input.y, 0f);                  //FIXME: JANK
            if (input3D.sqrMagnitude > 1)
            {
                input3D.Normalize();
            }

            float left_product  = Vector3.Dot(camera_transform.rotation * input3D, left);
            float right_product = Vector3.Dot(camera_transform.rotation * input3D, right);
            float product       = -Mathf.Abs(left_product);
            if (right_product > left_product)
            {
                product = +Mathf.Abs(right_product);
            }
            if (right_product < 0 && left_product < 0)
            {
                product = 0;
            }
            angle += product / height / 64; //FIXME: slight math error here-ish

            current_position = ArcOfSphere.Evaluate(ground.data, radius);

            transform.rotation = Quaternion.LookRotation(current_position, arc.EvaluateNormal(angle, radius));
        }
        else
        {
            SphereUtility.Accelerate(ref phi, ref theta, ref vertical_velocity, ref horizontal_velocity, 0.03f, -input.x / 10, Time.fixedDeltaTime);

            current_position   = SphereUtility.SphereToCartesian(new Vector2(phi, theta));
            transform.rotation = Quaternion.LookRotation(current_position, North);
        }
    }
示例#15
0
    private static void Subdivide(ArcOfSphere arc, float begin, float end)
    {
        float midpoint = MaxErrorLocation(arc, begin, end);

        Vector2 L1 = SpaceConverter.SphereToUV(arc.Evaluate(begin));
        Vector2 L2 = SpaceConverter.SphereToUV(arc.Evaluate(end));
        Vector2 P  = SpaceConverter.SphereToUV(arc.Evaluate(midpoint));

        if (Point_Line_Distance(L1, L2, P) > threshold) // if the max error is greater than a threshold, recursively add the left and right halves into the list of lines
        {
            Subdivide(arc, begin, midpoint);
            Subdivide(arc, midpoint, end);
        }
        else
        {
            AddLine(arc, begin, end);
        }
    }
示例#16
0
    /** Create a AABB that perfectly contains a circular arc
     *
     *  TODO: detailed description and math link
     *
     *  TODO: Ex.
     *
     *  @param collider the box collider that will be altered to contain the ArcOfSphere
     */
    protected static void RecalculateAABB(ArcOfSphere arc)
    {
        float x_min = MaxGradient(arc, Vector3.left).x;
        float x_max = MaxGradient(arc, Vector3.right).x;
        float y_min = MaxGradient(arc, Vector3.down).y;
        float y_max = MaxGradient(arc, Vector3.up).y;
        float z_min = MaxGradient(arc, Vector3.back).z;
        float z_max = MaxGradient(arc, Vector3.forward).z;

        arc.transform.position = new Vector3((x_max + x_min) / 2,
                                             (y_max + y_min) / 2,
                                             (z_max + z_min) / 2);

        BoxCollider collider = arc.GetComponent <BoxCollider>();

        collider.size = new Vector3(x_max - x_min,
                                    y_max - y_min,
                                    z_max - z_min);
    }
示例#17
0
    public override void Initialize(ArcOfSphere left, ArcOfSphere right)
    {
        #if UNITY_EDITOR
        this.Save();
        #endif

        Vector3 path_center = right.Evaluate(right.Begin());

        //Debug.DrawRay(path_center, Vector3.up, Color.yellow);

        path_normal = right.Evaluate(right.Begin());

        arc_left  = left.EvaluateNormal(left.End());
        arc_right = right.EvaluateNormal(right.Begin());

        Initialize(path_center);

        this.Relink(left, right);
    }
示例#18
0
    public static void Append(GameObject shape)
    {
        lines = new List <QuadraticBezier>();

        ArcOfSphere first_edge = shape.GetComponentInChildren <Edge>();
        ArcOfSphere arc        = first_edge;

        do
        {
            float begin       = arc.Begin();
            float end         = arc.End();
            float range_begin = arc.Begin();
            float range_end   = arc.End();
            float range_mid   = arc.End() / 2;

            int[,] xyz_signs_begin       = new int[2, 3]; //positional, derivative; x, y, z
            int[,] xyz_signs_end         = new int[2, 3];
            int[,] xyz_signs_range_begin = new int[2, 3]; //immediately before the first detected change in sign
            int[,] xyz_signs_range_end   = new int[2, 3]; //the first detected change in any sign
            int[,] xyz_signs_range_mid   = new int[2, 3]; //middle of begin and range_end

            // get signs for beginning and end
            UpdateSigns(arc, ref xyz_signs_begin, arc.Begin(), delta);
            UpdateSigns(arc, ref xyz_signs_end, arc.End(), -delta);

            // process new lines until the signs match
            while (!SameSigns(ref xyz_signs_begin, ref xyz_signs_end))
            {
                xyz_signs_range_begin = xyz_signs_begin;
                xyz_signs_range_end   = xyz_signs_end;

                // binary search and discard ranges with matching slope signs and position signs at ends; and then update the slope signs.
                while (range_end - range_begin > delta)
                {
                    range_mid = (range_begin + range_end) / 2; //guaranteed not to overflow since numbers are in range [0, 2pi]
                    UpdateSigns(arc, ref xyz_signs_range_mid, range_mid, delta);
                    if (SameSigns(ref xyz_signs_range_begin, ref xyz_signs_range_mid))
                    {
                        range_begin = range_mid;
                        //xyz_signs_begin = xyz_signs_range_mid; //not necessary, the signs are the same
                    }
                    else
                    {
                        range_end           = range_mid;
                        xyz_signs_range_end = xyz_signs_range_mid;
                    }
                }
                // when you find a sign that switches, log the exact position of the switch with as much precision as possible

                Subdivide(arc, begin, range_begin);
                // when you find that position, you must then switch the x, y, z signs at the new beginning of the arc and the slope signs xyz at the beginning of the arc
                begin           = range_end;
                xyz_signs_begin = xyz_signs_range_end;
            }
            // draw the last line
            Subdivide(arc, begin, end);

            arc = arc.next;                                    // move to next arc
            while (arc.GetType().IsSubclassOf(typeof(Corner))) // skip corners //XXX: Corner is abstract... for now
            {
                arc = arc.next;
            }
        } while (arc != first_edge);
        ClampToEdges();
        OverlapSharedEdges();
        BuildShape();
    }
示例#19
0
 public virtual void Initialize(ArcOfSphere left, ArcOfSphere right)
 {
 }
示例#20
0
 public void LinkBlock(ArcOfSphere other)
 {
     LinkBlock(other.gameObject.transform.parent);
 }