StarlingGraphics / Starling-Extension-Graphics

flash.display.Graphics style extension for the Starling Flash GPU rendering framework
https://github.com/StarlingGraphics/Starling-Extension-Graphics/wiki
MIT License
285 stars 88 forks source link

new class based on plane #18

Closed vjroger closed 11 years ago

vjroger commented 11 years ago

Hi Jonathan,

here's a new class based on the plane:

package starling.display.graphics { import flash.geom.Rectangle;

import starling.core.RenderSupport;
import starling.core.Starling;
import starling.display.DisplayObject;

public class Ball extends Graphic
{
    private static const VERTEX_STRIDE:int = 9;

    private var vertices:Vector.<Number>;
    public var _Speed:Number
    private var indices:Vector.<uint>;
    public var _width:Number;
    public var _height:Number;
    private var _numVerticesX:uint;
    private var _numVerticesY:uint;
    public var offset:Number = 0
    public var _Shading:Number = 0

    private var isInvalid:Boolean;

    public function Ball( radius:Number = 100, numVerticesX:uint = 2, numVerticesY:uint = 2 ,Speed:Number = 0.005,Shading:Number=0.7)
    {
        _width = radius;
        _height = radius;
        _numVerticesX = numVerticesX+1;
        _numVerticesY = numVerticesY;
        _Speed = Speed
        _Shading = Shading
        isInvalid = true;
        validate()
        isInvalid = false;

    }

    public function validate():void
    {

        if (vertexBuffer)
        {
            vertexBuffer.dispose();
            if(isInvalid){indexBuffer.dispose();}
        }

        // Generate vertices
        var numVertices:int = _numVerticesX * (_numVerticesY-1)+1
        vertices = new Vector.<Number>();

        for (var j:int=1; j < _numVerticesY; j++){

            const temp:Number =  Math.sin(Math.PI*((j)/(_numVerticesY))/2)

            for (var i:int = 0; i < _numVerticesX; i++){

                var u:Number = Math.cos(i*Math.PI*2 / (_numVerticesX - 1))*(j/ (_numVerticesY - 1))/4 + offset
                var v:Number = Math.sin(i*Math.PI*2 / (_numVerticesX - 1))*(j/ (_numVerticesY - 1))/2 +0.5
                var x:Number = (_width+(_width*Math.cos(i*Math.PI*2 / (_numVerticesX - 1)))*(temp))/2
                var y:Number = (_height+(_height*Math.sin(i*Math.PI*2 / (_numVerticesX - 1)))*(temp))/2
                const shading = Math.pow(1-temp,_Shading)
                vertices.push( x, y, 0,shading, shading, shading, 1, u, v );
        }
        }

        vertices.push( _width/2,_height/2 , 0,1, 1, 1, 1, 0+offset, 0.5 );

        if(isInvalid){
            // Generate indices
            indices = new Vector.<uint>();
            var qn:int = 0; //quad number
            for (var m:int = 0; m <_numVerticesY-1; m++) //create quads out of the vertices
            {               
                for (var n:int = 0; n <_numVerticesX - 1; n++)
                {

                  if(m<_numVerticesY - 2){
                  indices.push(qn, qn + 1, qn + _numVerticesX ); //upper face
                  indices.push(qn + _numVerticesX, qn + _numVerticesX  + 1, qn+1); //lower face
                  }else{

                  indices.push(n, n +  1, numVertices-1) 
                  }

                  qn++; //jumps to next quad
                }
                qn++; // jumps to next row
            }
        }
        // Upload vertex/index buffers.
        vertexBuffer = Starling.context.createVertexBuffer(numVertices,VERTEX_STRIDE);
        vertexBuffer.uploadFromVector( vertices, 0, numVertices );

        if(isInvalid){
            indexBuffer = Starling.context.createIndexBuffer(indices.length);
            indexBuffer.uploadFromVector( indices, 0, indices.length );
        }
        offset += _Speed

    }

    public override function getBounds(targetSpace:DisplayObject, resultRect:Rectangle=null):Rectangle
    {
        minBounds.x = 0;
        minBounds.y = 0;
        maxBounds.x = _width;
        maxBounds.y = _height;
        return super.getBounds(targetSpace, resultRect);
    }

    override public function render( renderSupport:RenderSupport, alpha:Number ):void
    {
        if(isInvalid || _Speed != 0){
        validate()}

        super.render( renderSupport, alpha );
    }
}

}

greetings Rogier

PS, funny if you replace the uv's with:

var u:Number = Math.cos(i_Math.PI_2 / (_numVerticesX - 1)+0.4_j_Math.sin(offset10))(j/ (_numVerticesY - 1))/4 + offset; var v:Number = Math.sin(i_Math.PI_2 / (_numVerticesX - 1)+0.4_j_Math.sin(offset10))(j/ (_numVerticesY - 1))/2 +0.5;

jonathanrpace commented 11 years ago

That's cool!

I've got a suggestion for an optimisation. Instead of calling 'validate()' each frame and regenerating the uv's (which is kinda expensive), you could get rid of the 'offset' and instead use an animated UV vertex shader. Like this

var ball:Ball = new Ball(100,20,20,0.005,0.5);
ball.material = new StandardMaterial(new AnimateUVVertexShader(-0.2,0), new   TextureVertexColorFragmentShader());
ball.material.textures[0] = someTexture;
addChild(ball)

This will keep all your processing on the GPU, and will save a lot of bandwidth as you're no longer creating/destroying vertex and index buffers each frame.

vjroger commented 11 years ago

Thanx, you rule!

On Tue, Dec 4, 2012 at 10:23 PM, Jonathan Pace notifications@github.comwrote:

ew AnimateUVVertexShader(