예제 #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
    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);
        }
    }
예제 #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 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));
        }
    }
예제 #5
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);
    }
예제 #6
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);
        }
    }
예제 #7
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);
    }
예제 #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
    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);
        }
    }
예제 #10
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);
    }