AS3- create a loopable random path in 3D space

柔情痞子 提交于 2020-01-06 04:12:05

问题


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.


回答1:


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!



来源:https://stackoverflow.com/questions/19096937/as3-create-a-loopable-random-path-in-3d-space

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!