Subversion Repositories AndroidProjects

Rev

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;

using BauzoidNET.math;
using BauzoidNET.graphics.renderstates;
using BauzoidNET.graphics.texture;
using BauzoidNET.graphics.model;

using Tao.OpenGl;

namespace BauzoidNET.graphics.sprite
{
    public class Sprite : GraphicsObject
    {
        public const int NUM_INDICES_PER_REGION = 6;
        public const int NUM_ATTRIBUTES_PER_REGION = 4;

            protected Texture mTexture = null;

        private SpriteRegion[] mRegions = null;

            protected SimpleGeometry mMesh = null;

            protected String mTextureFilename = null;
        protected Bitmap mTextureBitmap = null;

        protected String mRegionDefFilename = null;
       
            /** Constructor. Does not load anything yet
             */

            public Sprite(Graphics graphics, String filename)
            : base(graphics)
            {
                    mTextureFilename = filename;
            }

        public Sprite(Graphics graphics, Bitmap bm)
            : base(graphics)
        {
            mTextureBitmap = bm;
        }

        public Sprite(Graphics graphics, String textureFile, String atlasFile)
            : this(graphics, textureFile)
        {
            mRegionDefFilename = atlasFile;
        }

        public Sprite(Graphics graphics, Bitmap bm, String atlasFile)
            : this(graphics, bm)
        {
            mRegionDefFilename = atlasFile;
        }
       
            public void init()
            {
            if ((mTextureFilename == null) && (mTextureBitmap == null))
                return;

            // load texture synchronously
            if (mTextureFilename != null)
                mTexture = new Texture(getGraphics(), mTextureFilename);
            else if (mTextureBitmap != null)
                mTexture = new Texture(getGraphics(), mTextureBitmap);

            if (mRegionDefFilename != null)
            {
                List<SpriteUtil.SpriteRegionInfo> atlas = SpriteUtil.readSpriteRegionInfo(mRegionDefFilename);

                SpriteRegion[] regions = new SpriteRegion[atlas.Count];
                for (int i = 0; i < atlas.Count; i++)
                {
                    regions[i] = new SpriteRegion(this, i, atlas[i].x, atlas[i].y, atlas[i].w, atlas[i].h, true);
                }

                setRegions(regions);
            }
            else
            {
                // create default geometry for entire sprite (make 1 region)
                SpriteRegion[] regions = new SpriteRegion[1];
                regions[0] = new SpriteRegion(this, 0, 0, 0, getTextureWidth(), getTextureHeight(), true);

                setRegions(regions);
            }
            }

        public void dispose()
        {
            if (mRegions != null)
                mRegions = null;

            if (mTexture != null)
            {
                mTexture.dispose();
                mTexture = null;
            }
        }

        public void setRegions(SpriteRegion[] regions)
        {
            if (mMesh != null)
            {
                mMesh.dispose();
                mMesh = null;
            }

            mRegions = regions;
            mMesh = createGeometry();
        }

        public SimpleGeometry createGeometry()
            {
                    float[] vertices = new float[NUM_ATTRIBUTES_PER_REGION * SimpleGeometry.POSITION_COORD_PER_ELEMENT * mRegions.Length];
                    float[] texCoords = new float[NUM_ATTRIBUTES_PER_REGION * SimpleGeometry.TEXCOORD_COORD_PER_ELEMENT * mRegions.Length];
                    float[] colors = new float[NUM_ATTRIBUTES_PER_REGION * SimpleGeometry.COLOR_COORD_PER_ELEMENT * mRegions.Length];
               
                    // two triangles per region
                    short[] indices = new short[NUM_INDICES_PER_REGION * mRegions.Length];
               
                    for (int i = 0; i < mRegions.Length; i++)
                    {
                            SpriteRegion r = getRegion(i);
                       
                            float[] v =
                            {
                                    -1.0f, -1.0f, 0.0f,
                                     1.0f, -1.0f, 0.0f,
                                     1.0f,  1.0f, 0.0f,
                                    -1.0f,  1.0f, 0.0f
                            };
                       
                            float[] t =
                            {
                                    r.left, r.top,
                                    r.right, r.top,
                                    r.right, r.bottom,
                                    r.left, r.bottom
                            };
                       
                            float[] c =
                            {
                                    1, 1, 1, 1,
                                    1, 1, 1, 1,
                                    1, 1, 1, 1,
                                    1, 1, 1, 1
                            };
                       
                            Array.Copy(v, 0, vertices, NUM_ATTRIBUTES_PER_REGION * SimpleGeometry.POSITION_COORD_PER_ELEMENT * i, v.Length);
                            Array.Copy(t, 0, texCoords, NUM_ATTRIBUTES_PER_REGION * SimpleGeometry.TEXCOORD_COORD_PER_ELEMENT * i, t.Length);
                            Array.Copy(c, 0, colors, NUM_ATTRIBUTES_PER_REGION * SimpleGeometry.COLOR_COORD_PER_ELEMENT * i, c.Length);

                            int n = i*NUM_INDICES_PER_REGION;                  
                            short baseIndex = (short)(i * NUM_ATTRIBUTES_PER_REGION);
                indices[n++] = baseIndex; indices[n++] = (short)(baseIndex + 1); indices[n++] = (short)(baseIndex + 2);
                indices[n++] = baseIndex; indices[n++] = (short)(baseIndex + 2); indices[n++] = (short)(baseIndex + 3);
                    }

                    SimpleGeometry mesh = new SimpleGeometry(getGraphics(), Geometry.PrimitiveType.TRIANGLES);
                    mesh.setPositions(vertices);
                    mesh.setTexCoords(texCoords);
                    mesh.setColors(colors);
                    mesh.setIndices(indices);
               
                    return mesh;
            }

        /** Create a single SpriteInstance for a single region. */
            public SpriteInstance createSpriteInstance(int regionIndex)
            {
                    return new SpriteInstance(getRegion(regionIndex));
            }

        /** Create a multiple SpriteInstances, each for a single region. */
        public void createSpriteInstances(SpriteInstance[] instances)
        {
            if (instances.Length < mRegions.Length)
                return;

            for (int i = 0; i < instances.Length; i++)
            {
                instances[i] = createSpriteInstance(i);
            }
        }

        /** Create a multiple SpriteInstances, each for a single region. */
        public SpriteInstance[] createSpriteInstances()
        {
                SpriteInstance[] frames = new SpriteInstance[mRegions.Length];
                createSpriteInstances(frames);
                    return frames;
            }

        /** Create a single SpriteInstance for all regions. */
        public SpriteInstance createSpriteInstanceForAll()
        {
            SpriteInstance instance = new SpriteInstance(mRegions);
            return instance;
        }

        /** Peforms the actual render without any model matrix handling. */
        public void performRender(int region, float alpha, Vector4 color, Vector4 fogColor)
        {
            RenderStates rs = getRenderStates();
            SpriteShader shader = getGraphics().getSpriteShader();

            // draw sprite
            shader.activate(getTexture(), alpha, color, fogColor);
            {
                rs.blending.setEnabled(true);
                rs.culling.setEnabled(false);
                rs.activate();
                rs.blending.activate(true);
                {
                    mMesh.render(getMeshStartIndex(region), NUM_INDICES_PER_REGION);
                }
                rs.deactivate();
            }
            shader.deactivate();
        }

            /** Get the sprite texture's total width. */
            public int getTextureWidth()
            {
                    if (mTexture == null)
                            return 0;
                    return mTexture.getWidth();
            }
       
            /** Get the sprite texture's total height. */
            public int getTextureHeight()
            {
                    if (mTexture == null)
                            return 0;
                    return mTexture.getHeight();
            }
       
            /** Get a reference to the texture. */
            public Texture getTexture()
            {
                    return mTexture;
            }
       
            /** Set a new texture, with the old one (if any) getting destroyed. */
            public void setTexture(Texture texture)
            {
                    if (mTexture != null)
                            mTexture.dispose();
               
                    mTexture = texture;
            }
       
            /** Get number of defined regions. */
            public int getRegionCount()
            {
                    if (mRegions == null)
                            return 0;
               
                    return mRegions.Length;
            }
       
            /** Get region. */
            public SpriteRegion getRegion(int i)
            {
                    if (mRegions == null)
                            return null;
               
                    return mRegions[i];
            }
       
            /** Get regions array.*/
            public SpriteRegion[] getRegions()
            {
                    return mRegions;
            }
       
            /** Get starting index for region mesh rendering. */
            private int getMeshStartIndex(int regionIndex)
            {
                    return (regionIndex * NUM_INDICES_PER_REGION);
            }
    }
}