Subversion Repositories AndroidProjects

Rev

Rev 300 | Blame | Compare with Previous | Last modification | View Log | RSS feed

package com.gebauz.pingk.entities;

import java.util.Vector;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.gebauz.Bauzoid.graphics.model.AttributeArray;
import com.gebauz.Bauzoid.graphics.model.SimpleGeometry;
import com.gebauz.Bauzoid.graphics.model.Geometry;
import com.gebauz.Bauzoid.graphics.renderstates.RenderStates;
import com.gebauz.Bauzoid.graphics.renderstates.BlendingStates.BlendingMode;
import com.gebauz.Bauzoid.graphics.shader.ShaderProgram;
import com.gebauz.Bauzoid.graphics.shader.ShaderUniform;
import com.gebauz.Bauzoid.graphics.shader.ShaderUtil;
import com.gebauz.Bauzoid.graphics.sprite.SpriteShader;
import com.gebauz.Bauzoid.math.MathUtil;
import com.gebauz.Bauzoid.math.Matrix4;
import com.gebauz.Bauzoid.math.Vector2;
import com.gebauz.pingk.game.GameConsts;
import com.gebauz.pingk.game.GameLogic;

public class BallTrail extends Entity
{
        private class TrailElement
        {
                private Vector2 mPosition;
                private Vector2 mNormal;
                private Vector2 mDirection;
                private Vector2 mPoint1;
                private Vector2 mPoint2;
                private float mLifeTime = 0.0f;
               
                public TrailElement(Vector2 pos, Vector2 prevPos, float angleNormal)
                {
                        mPosition = new Vector2(pos.x, pos.y);
                        mDirection = new Vector2(pos.x - prevPos.x, pos.y - prevPos.y);
                       
                        if (angleNormal < 0.0f)
                        {
                                mNormal = new Vector2(mDirection.y, -mDirection.x);
                        }
                        else
                        {
                                // 0
                                mNormal = new Vector2((float)Math.cos(MathUtil.degToRad(angleNormal)), (float)Math.sin(MathUtil.degToRad(angleNormal)));
                        }
                        mNormal.setLength(GameConsts.BALL_TRAIL_WIDTH);
                       
                        mPoint1 = new Vector2(mPosition.x + mNormal.x, mPosition.y + mNormal.y);
                        mPoint2 = new Vector2(mPosition.x - mNormal.x, mPosition.y - mNormal.y);
                       
                        mLifeTime = 0.0f;
                }
               
                public Vector2 getPosition()
                {
                        return mPosition;
                }
               
                public Vector2 getDirection()
                {
                        return mDirection;
                }
               
                public Vector2 getNormal()
                {
                        return mNormal;
                }
               
                public Vector2 getPoint1()
                {
                        return mPoint1;
                }
               
                public Vector2 getPoint2()
                {
                        return mPoint2;
                }
               
                public void update(float deltaTime)
                {
                        mLifeTime += deltaTime;
                }
               
                public float getAlpha()
                {
                        return (1.0f-MathUtil.clamp(mLifeTime / GameConsts.BALL_TRAIL_ELEMENT_LIFETIME, 0.0f, 1.0f));
                }
        }
       
        private Ball mBall;
//      private Mesh mTrailMesh = new Mesh();
        private SimpleGeometry mTrailMesh = null;
        private ShaderProgram mShaderProgram = null;
        private ShaderUniform mTextureHandle = null;
        private Texture mTexture = null;
        private Vector<TrailElement> mElements = new Vector<TrailElement>();
        private int mNumPrimitives = 0;
        private float mTrailTimer = 0.0f;
       
        public BallTrail(GameLogic gameLogic, Ball ball)
        {
                super(gameLogic);
               
                mBall = ball;          
        }
       
        @Override
        public void init()
        {
                mTexture = new Texture(Gdx.files.internal("data/textures/trail.png"));
                mTrailMesh = new SimpleGeometry(getGraphics(), Geometry.PrimitiveType.TRIANGLE_STRIP);
               
                mShaderProgram = ShaderUtil.createShaderFromFile(getGraphics(), Gdx.files.internal("data/shaders/trailshader.vert"),
                                Gdx.files.internal("data/shaders/trailshader.frag"));
               
                if (mShaderProgram != null)
                {
                        mTextureHandle = mShaderProgram.getUniform("uDiffuse");
                }
        }
       
        @Override
        public void exit()
        {
                if (mShaderProgram != null)
                {
                        mTextureHandle = null;
                        mShaderProgram.dispose();
                        mShaderProgram = null;
                }
                if (mTrailMesh != null)
                {
                        mTrailMesh.dispose();
                        mTrailMesh = null;
                }
                if (mTexture != null)
                {
                        mTexture.dispose();
                        mTexture = null;
                }
                mBall = null;
        }
       
        public void reset()
        {
                mElements.clear();
                //mTrailMesh.setVertices(null);
                mNumPrimitives = 0;
        }
       
        /**
         * Add new trail point
         * @param x X-axis coordinate
         * @param y Y-axis coordinate
         * @param angleNormal if >= 0.0f, specifies the angle of the normal to be used
         */

        public void addTrailPoint(float x, float y, float angleNormal)
        {
                mTrailTimer -= GameConsts.BALL_TRAIL_INTERVAL;
                Vector2 lastPos = new Vector2(x, y);
               
                if (mElements.size() > 0)
                {
                        lastPos = mElements.get(mElements.size()-1).getPosition();
                       
                        // do not add point if positions are the same
                        if (Vector2.distance(lastPos, new Vector2(x, y)) < MathUtil.EPSILON)
                        {
                                return;                                                        
                        }
                }
               
                mElements.add(new TrailElement(new Vector2(x, y), lastPos, angleNormal));

                // trim if larger than wanted
                while (mElements.size() > GameConsts.BALL_TRAIL_LENGTH)
                {
                        mElements.remove(0);
                }
               
                //mTrailFadeTimer = 0.0f;
                buildGeometry();
        }
       
        public void buildGeometry()
        {              
                // prepare geometry
                if (mElements.size() >= 2)
                {
                        //float life = 1.0f - MathUtil.clamp(mTrailFadeTimer / 2.0f, 0.0f, 1.0f);
                       
                        // two vertices per trail element
                        AttributeArray vertices = new AttributeArray(mElements.size() * SimpleGeometry.POSITION_COORD_PER_ELEMENT * 2 * 2);
                        AttributeArray texCoords = new AttributeArray(mElements.size() * SimpleGeometry.TEXCOORD_COORD_PER_ELEMENT * 2 * 2);
                        AttributeArray colors = new AttributeArray(mElements.size() * SimpleGeometry.COLOR_COORD_PER_ELEMENT * 2 * 2);
                       
                        int index = 0;
                       
                        for (int i = mElements.size() - 1; i >= 0; i--)
                        {
                                TrailElement element1 = mElements.get(i);
                               
                                vertices.fill(element1.getPoint1().x, element1.getPoint1().y, 0.0f);
                                vertices.fill(element1.getPoint2().x, element1.getPoint2().y, 0.0f);
                               
                                texCoords.fill(0.0f, 1.0f);
                                texCoords.fill(0.0f, 0.0f);
                               
                                float lifeTime = element1.getAlpha();
                               
                                if (i == 0)
                                        lifeTime = 0.0f;
                               
                                colors.fill(GameConsts.PINGK_COLOR.x, GameConsts.PINGK_COLOR.y, GameConsts.PINGK_COLOR.z, lifeTime);
                                colors.fill(GameConsts.PINGK_COLOR.x, GameConsts.PINGK_COLOR.y, GameConsts.PINGK_COLOR.z, lifeTime);
                               
                                if (i > 0)
                                {
                                       
                                        TrailElement element2 = mElements.get(i-1);
                                        if (Vector2.dotProduct(element1.getNormal(), element2.getNormal()) < 0.0f)
                                        {
                                                // facing away -> twist
                                                vertices.fill(element1.getPoint2().x, element1.getPoint2().y, 0.0f);
                                                vertices.fill(element1.getPoint1().x, element1.getPoint1().y, 0.0f);
                                               
                                                texCoords.fill(0.0f, 1.0f);
                                                texCoords.fill(0.0f, 0.0f);
                                               
                                                colors.fill(GameConsts.PINGK_COLOR.x, GameConsts.PINGK_COLOR.y, GameConsts.PINGK_COLOR.z, lifeTime);
                                                colors.fill(GameConsts.PINGK_COLOR.x, GameConsts.PINGK_COLOR.y, GameConsts.PINGK_COLOR.z, lifeTime);
                                        }
                                }
                        }
                       
                        mNumPrimitives = vertices.getUsedCount() / SimpleGeometry.POSITION_COORD_PER_ELEMENT;
                        mTrailMesh.setPositions(vertices.getAttributeArray());
                        mTrailMesh.setTexCoords(texCoords.getAttributeArray());
                        mTrailMesh.setColors(colors.getAttributeArray());                      
                       
                        /*mTrailMesh.setPrimitiveType(GL10.GL_TRIANGLE_STRIP);
                        mTrailMesh.setVertices(vertices.getAttributeArray());
                        mTrailMesh.setTexCoords(texCoords.getAttributeArray());
                        mTrailMesh.setColors(colors.getAttributeArray());*/

                }
        }
       
        @Override
        public void update(float deltaTime)
        {
                mTrailTimer += deltaTime;
                //mTrailFadeTimer += deltaTime;
                if (mTrailTimer > GameConsts.BALL_TRAIL_INTERVAL)
                {
                        addTrailPoint(mBall.getX(), mBall.getY(), -1.0f);
                }
               
                for (int i = 0; i < mElements.size(); i++)
                {
                        mElements.get(i).update(deltaTime);
                }
        }
       
        public void updateFade(float deltaTime)
        {
                //mTrailFadeTimer += deltaTime;
               
                for (int i = 0; i < mElements.size(); i++)
                {
                        mElements.get(i).update(deltaTime);
                }
               
                // rebuild geometry for color fading...
                buildGeometry();               
        }
       
        @Override
        public void render()
        {
                RenderStates rs = getGraphics().renderStates;
               
                Matrix4 modelMatrix = Matrix4.createIdentity();
               
                rs.pushModelMatrix();
                {
                        rs.model = modelMatrix;
                       
                        mShaderProgram.activate();
                        {
                                mTextureHandle.set(0);
                                rs.getTextureStage(0).bindTexture(mTexture);
                               
                                rs.blending.setEnabled(true);
                                rs.blending.setBlendingMode(BlendingMode.ALPHABLEND);
                                rs.culling.setEnabled(false);
                                rs.depthTest.setEnabled(false);
                                rs.activate();
                                {
                                        mTrailMesh.render();
                                }
                                rs.deactivate();
                        }
                        mShaderProgram.deactivate();
                }
                rs.popModelMatrix();
               
/*              GL10 gl = GLUtil.getGL();
               
                // transform
                gl.glMatrixMode(GL10.GL_MODELVIEW);
                gl.glPushMatrix();
                {
                        gl.glLoadIdentity();
                        RenderStates renderStates = GLUtil.getRenderStates();
                        renderStates.depthTest.setEnabled(false);
                        renderStates.culling.setEnabled(false);
                        renderStates.blending.setEnabled(true);
                        renderStates.blending.setBlendingMode(BlendingMode.ALPHABLEND);
                        renderStates.getTextureStage(0).bindTexture(mTexture);
                        renderStates.activate();
                        mTrailMesh.render(mNumPrimitives);
                        //mTrailMesh.render();
                        renderStates.deactivate();
                        renderStates.getTextureStage(0).bindTexture(null);
                }
                gl.glPopMatrix();*/

        }

}