سؤال

I'm trying to optimize a 3d demo by populating a lookup table with 3d points(Vector 3D http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/geom/Vector3D.html) which I will then access later on.

These 3D points will define a random and loopable path in 3D space.

Does anyone know a way of achieving this?

I was thinking modifying the Greensock Bezier tween to create a bezier in 3d space, and then somehow grabbing the xyz values of the resulting tween.

هل كانت مفيدة؟

المحلول

Ok, you'll need to do two things:

  1. Create a looped 3D cubic bezier curve from several fragments

  2. Create a custom tween function that will take your object as a target, your bezier loop as a path and your total loop time.

One fragment of your cubic bezier curve will always take 4 vertices, a full loop must contain at least 2 segments, so you will need to randomly create at least 7 vertices. The number of vertices will always be 3 * NumberOfSegments + 1, but we will store just 3 * NumberOfSegments as the first vertex will be equal to the last one

Most simple case (2 segments, 6 vertices):

...
private function generateRandomPoints():Vector<Vector3D>
{
    var resultingVector:Vector<Vector3D> = new Vector<Vector3D>();
    for(var i:int = 0; i < 6; i++)
    {
        var x:Number = Math.random() * 10;
        var y:Number = Math.random() * 10;
        var z:Number = Math.random() * 10;
        var currentPoint3D:Vector3D = new Vector3D(x, y, z);
        resultingVector.push(currentPoint3D);
    }
    return resultingVector;
}
...

Now when we have our path, we can parse it to get this tweening effect. You can either call this function every time you'll need new coordinates (but you'll need to store your initial time somewhere), or create a tweener object that will handle everything for you. I'll show the most basic example - autonomous function:

public static function getNextCoordinates(loopStartTime:int, totalLoopTime:int, path:Vector.<Vector3D>):Vector3D
    {
        var resultingPoint:Vector3D = new Vector3D();
        var passedTime:int = getTimer() - loopStartTime;

        //Total passed ratio
        var passedRatio:Number = passedTime / totalLoopTime;
        var totalSegments:int = path.length / 3;

        var totalTimePerSegment:Number = totalLoopTime / totalSegments;

        //So it can loop forever
        while (passedRatio > 1)
        {
            passedRatio -= 1;
        }
        //Let's find our current bezier curve segment number
        var currentSegment:int = Math.floor( passedRatio * totalSegments);
        var currentSegmentRatio:Number = (passedTime - currentSegment * totalTimePerSegment) / totalTimePerSegment;
        //It can be optimized here
        while (currentSegmentRatio > 1)
        {
            currentSegmentRatio -= 1;
        }

        var startingIndex:int = currentSegment * 3;
        //our four path vertices
        var point0:Vector3D = path[startingIndex];
        var point1:Vector3D = path[startingIndex + 1];
        var point2:Vector3D = path[startingIndex + 2];

        //if it's a last segment, we need to "connect" to the first vertex
        if (startingIndex + 3 >= path.length)
        {
            var point3:Vector3D = path[0];
        }
        else
        {
            point3 = path[startingIndex + 3];
        }
        //At last, we find our coordinates
        var tempRatio:Number = 1 - currentSegmentRatio;
        resultingPoint.x = tempRatio * tempRatio * tempRatio * point0.x + 3 * tempRatio * tempRatio * currentSegmentRatio * point1.x + 3 * tempRatio * currentSegmentRatio * currentSegmentRatio * point2.x + currentSegmentRatio * currentSegmentRatio * currentSegmentRatio * point3.x;
        resultingPoint.y = tempRatio * tempRatio * tempRatio * point0.y + 3 * tempRatio * tempRatio * currentSegmentRatio * point1.y + 3 * tempRatio * currentSegmentRatio * currentSegmentRatio * point2.y + currentSegmentRatio * currentSegmentRatio * currentSegmentRatio * point3.y;
        resultingPoint.z = tempRatio * tempRatio * tempRatio * point0.z + 3 * tempRatio * tempRatio * currentSegmentRatio * point1.z + 3 * tempRatio * currentSegmentRatio * currentSegmentRatio * point2.z + currentSegmentRatio * currentSegmentRatio * currentSegmentRatio * point3.z;

        return resultingPoint;
    }

You can extend this function to be a part of the tweening object. I've tested it in 2D space and it perfectly loops sprite's movement along a random multi-segment bezier curve

Cheers!

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top