Subversion Repositories AndroidProjects

Rev

Rev 1247 | Rev 1260 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

package com.gebauz.bauzoid.math.collision;

import java.util.Vector;

import com.gebauz.bauzoid.game.Game;
import com.gebauz.bauzoid.game.GameObject;
import com.gebauz.bauzoid.graphics.Graphics;
import com.gebauz.bauzoid.graphics.sprite.SpriteTransform;
import com.gebauz.bauzoid.math.Vector2;

/** Collection of shape elements that form a complex shape. */
public class Shape extends GameObject
{

        // Constants========================================================================================
       
        // Embedded Types===================================================================================

        // Fields===========================================================================================
       
        private Vector<BaseShapeElement> mShapes = new Vector<BaseShapeElement>();
       
        private String mShapeFile = null;
        private boolean mIsAsync = false;
       
        public SpriteTransform transform = new SpriteTransform();
       
        private PolyElement mConvexHull = null;
       
        private AABoundingBox mBoundingBox = null;
        private AABoundingBox mTransformedBoundingBox = null;
       
        // Methods==========================================================================================

        public Shape(Game game, String shapeFile)
        {
                super(game);
                mShapeFile = shapeFile;
        }

        /** Clone a shape and its shape elements to new shape. */
        public Shape(Shape clone)
        {
                super(clone.getGame());
               
                for (int i = 0; i < clone.getShapeElementCount(); i++)
                {
                        mShapes.add(clone.getShapeElement(i).copy(this));
                }
        }
       
        public void initAsync()
        {
                mIsAsync = true;
               
                if (mShapeFile != null)
                {
                        getAssetManager().load(mShapeFile, ShapeData.class, new ShapeDataAsyncLoader.ShapeDataParameter(this));
                }
        }
       
        public void init()
        {
                if (mShapeFile != null)
                {
                        ShapeData shapeData = null;
                        if (!mIsAsync)
                        {
                                shapeData = ShapeUtil.createShapeFromFile(this, mShapeFile);
                        }
                        else
                        {
                                shapeData = getAssetManager().get(mShapeFile, ShapeData.class);
                        }
                       
                        for (int i = 0; i < shapeData.getShapeElementCount(); i++)
                        {
                                mShapes.add(shapeData.getShapeElement(i).copy(this));
                        }
                }
               
                calculateConvexHull();
        }
       
        /** Calculate the untransformed convex hull and the axis aligned bounding box of the shape element group. */
        public void calculateConvexHull()
        {
                Vector<Vector2> pointCloud = new Vector<Vector2>();
                Vector<Vector2> hull = new Vector<Vector2>();
               
                for (int i = 0; i < getShapeElementCount(); i++)
                {
                        BaseShapeElement e = getShapeElement(i);
                       
                        Vector2[] pt = e.getUntransformedPoints();
                       
                        for (int j = 0; j < pt.length; j++)
                        {
                                pointCloud.add(pt[j]);
                        }
                }
               
                // find leftmost point
                int leftMostIndex = 0;
                for (int i = 1; i < pointCloud.size(); i++)
                {
                        if (pointCloud.get(i).x < pointCloud.get(leftMostIndex).x)
                                leftMostIndex = i;
                }
               
                // start from leftmost point
                int p = leftMostIndex;
                int q;
                do
                {
                        // search for point q such that orientation(p, i, q) is counterclockwise for all points i
                        q = (p + 1) % pointCloud.size();
                        for (int i = 0; i < pointCloud.size(); i++)
                        {
                                if (orientation(pointCloud.get(p), pointCloud.get(i), pointCloud.get(q)) == 2)
                                        q = i;
                        }
                       
                        hull.add(pointCloud.get(q).copy());
                        p = q; // set p as q for next iteration
                }
                while (p != leftMostIndex);
               
                mBoundingBox = new AABoundingBox(hull);
               
                mTransformedBoundingBox = mBoundingBox.transform(transform);
               
                mConvexHull = new PolyElement(this, hull);
        }
       
        /** To find orientation of ordered triplet (p, q, r).
         * The function returns following values
         * 0 --> p, q and r are colinear
         * 1 --> Clockwise
         * 2 --> Counterclockwise
         */

        private static int orientation(final Vector2 p, final Vector2 q, final Vector2 r)
        {
                final float x1 = (q.x - p.x) * (r.y - p.y);
        final float x2 = (r.x - p.x) * (q.y - p.y);
        final float val = x1 - x2;
       
        if (val == 0) return 0;
       
        return (val > 0) ? 1 : 2;
        }
       
        /** Render debug output. */
        public void renderDebug(Graphics graphics, SpriteTransform t)
        {
                for (int i = 0; i < getShapeElementCount(); i++)
                {
                        getShapeElement(i).renderDebug(graphics, t);
                }
               
                mConvexHull.renderDebug(graphics, t);
        }
       
        public void addElement(BaseShapeElement shapeElement)
        {
                mShapes.add(shapeElement);
        }
       
        // Getters/Setters==================================================================================
       
        public final BaseShapeElement getShapeElement(int i)
        {
                return mShapes.get(i);
        }
       
        public final int getShapeElementCount()
        {
                return mShapes.size();
        }
       
        public final PolyElement getConvexHull()
        {
                return mConvexHull;
        }
       
        public final AABoundingBox getBoundingBox()
        {
                return mBoundingBox;
        }
       
        public final AABoundingBox getTransformedBoundingBox()
        {
                return mBoundingBox.transform(transform);
               
                /*mBoundingBox.transform(transform, mTransformedBoundingBox);
               
                return mTransformedBoundingBox;*/
     
        }

       
}