Subversion Repositories AndroidProjects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1051 chris 1
package com.gebauz.bauzoid.graphics.sprite;
2
 
3
import com.badlogic.gdx.Gdx;
4
import com.badlogic.gdx.graphics.GL20;
5
import com.badlogic.gdx.graphics.Texture;
6
import com.gebauz.bauzoid.app.Consts;
7
import com.gebauz.bauzoid.graphics.Graphics;
8
import com.gebauz.bauzoid.graphics.GraphicsObject;
9
import com.gebauz.bauzoid.graphics.model.IndexStream;
10
import com.gebauz.bauzoid.graphics.model.VertexAttribute;
11
import com.gebauz.bauzoid.graphics.model.VertexStream;
12
import com.gebauz.bauzoid.graphics.renderstates.RenderStates;
13
import com.gebauz.bauzoid.graphics.sprite.SpriteShader;
14
import com.gebauz.bauzoid.math.MathUtil;
15
import com.gebauz.bauzoid.math.Vector4;
16
 
17
/** Batcher that collects Texture draw calls and batches them into a single VBO.
18
 * A possibly faster alternative to Sprite and AtlasSprite which have rather
19
 * small geometry objects.
20
 *
21
 * It is designed to be easy to convert code that used AtlasSprite and Sprite
22
 * to use TileBatch instead.
23
 *
24
 * Also contains convenience functions to import Sprite and AtlasSprite info.
25
 *
26
 * @author chiu
27
 *
28
 */
29
public class TileBatch extends GraphicsObject
30
{
31
 
32
        // Constants========================================================================================
33
 
34
        public static final int POSITION_COORD_PER_ELEMENT = 3;
35
        public static final int NORMAL_COORD_PER_ELEMENT = 3;
36
        public static final int COLOR_COORD_PER_ELEMENT = 4;
37
        public static final int TEXCOORD_COORD_PER_ELEMENT = 2;
38
 
39
        public static final Vector4 WHITE_COLOR = new Vector4(1, 1, 1, 1);
40
 
41
        public static final int COORDS_PER_ELEMENT = POSITION_COORD_PER_ELEMENT + COLOR_COORD_PER_ELEMENT + TEXCOORD_COORD_PER_ELEMENT;
42
 
43
        // Embedded Types===================================================================================
44
 
45
        // Fields===========================================================================================
46
 
47
        /** Number of vertices. */
48
        private int mSize = 0;
49
        private float mVertices[] = null;
50
        private int mNumQuads = 0;
51
 
52
//      private SimpleGeometry mMesh = null;
53
        private Texture mCurrentTexture = null;
54
        private boolean mIsDrawing = false;
55
 
56
        private VertexStream mVertexStream= null;
57
        private IndexStream mIndexStream = null;
58
 
59
 
60
        // Methods==========================================================================================
61
 
62
        public TileBatch(Graphics graphics)
63
        {
64
                this(graphics, 250);
65
        }
66
 
67
        public TileBatch(Graphics graphics, int size)
68
        {
69
                super(graphics);
70
                mSize = size;
71
 
72
                mVertexStream = new VertexStream(
73
                                getGraphics(),
74
                                VertexStream.StreamType.INTERLEAVED,
75
                                "Vertices",
76
                                new VertexAttribute[]
77
                                        {
78
                                                new VertexAttribute(VertexAttribute.POSITION, POSITION_COORD_PER_ELEMENT, 0),
79
                                                new VertexAttribute(VertexAttribute.COLOR, COLOR_COORD_PER_ELEMENT, POSITION_COORD_PER_ELEMENT*Consts.SIZEOF_FLOAT),
80
                                                new VertexAttribute(VertexAttribute.TEXCOORD0, TEXCOORD_COORD_PER_ELEMENT, (POSITION_COORD_PER_ELEMENT+COLOR_COORD_PER_ELEMENT)*Consts.SIZEOF_FLOAT)
81
                                        },
82
                                false);
83
 
84
                mIndexStream = new IndexStream(getGraphics());
85
 
86
                mVertices = new float[size * 4 * (COORDS_PER_ELEMENT)];
87
                //mCurrentVertex = 0;
88
                mNumQuads = 0;
89
 
90
                // create indices as those will stay the same
91
                int len = size * 6;
92
                short[] indices = new short[len];
93
                short j = 0;
94
                for (int i = 0; i < len; i += 6, j += 4)
95
                {
96
                        indices[i + 0] = (short)(j + 0);
97
                        indices[i + 1] = (short)(j + 1);
98
                        indices[i + 2] = (short)(j + 2);
99
                        indices[i + 3] = (short)(j + 0);
100
                        indices[i + 4] = (short)(j + 2);
101
                        indices[i + 5] = (short)(j + 3);
102
                }
103
                mIndexStream.setData(indices);
104
                mIndexStream.upload();
105
        }
106
 
107
        public void dispose()
108
        {
109
                if (mVertexStream != null)
110
                {
111
                        mVertexStream.dispose();
112
                        mVertexStream = null;
113
                }
114
 
115
                if (mIndexStream != null)
116
                {
117
                        mIndexStream.dispose();
118
                        mIndexStream = null;
119
                }
120
        }
121
 
122
        /** Initialize internal variables for a new batch. */
123
        public void begin()
124
        {
125
                if (mIsDrawing)
126
                        return;
127
 
128
                mIsDrawing = true;
129
                //mCurrentVertex = 0;
130
                mNumQuads = 0;
131
        }
132
 
133
        /** Stops collecting and renders what's left on the screen. */
134
        public void end()
135
        {
136
                if (!mIsDrawing)
137
                        return;
138
 
139
                if (mNumQuads == 0)
140
                        return;
141
 
142
                flush();
143
        }
144
 
145
        /** Flush everything collected so far to screen and clear everything for new collection. */
146
        public void flush()
147
        {
148
                if (mCurrentTexture == null)
149
                        return;
150
 
151
                SpriteShader shader = getGraphics().getSpriteShader();
152
                RenderStates rs = getRenderStates();
153
 
154
                // bind VBO and upload geometry
155
 
156
                mVertexStream.setData(mVertices, COORDS_PER_ELEMENT, COORDS_PER_ELEMENT * Consts.SIZEOF_FLOAT);
157
                mVertexStream.reupload();              
158
 
159
                // bind texture and render
160
                rs.pushModelMatrix();
161
                {
162
                        rs.model.identity();
163
 
164
                        // draw sprite
165
                        shader.activate(mCurrentTexture, 1.0f, WHITE_COLOR);
166
                        {
167
                                rs.blending.setEnabled(true);
168
                                rs.culling.setEnabled(false);
169
                                rs.activate();
170
                                {
171
                                        mVertexStream.activate();
172
                                        mIndexStream.activate();
173
                                        Gdx.gl20.glDrawElements(GL20.GL_TRIANGLES, mNumQuads*6, GL20.GL_UNSIGNED_SHORT, 0);
174
                                        mVertexStream.deactivate();
175
                                        mIndexStream.deactivate();
176
                                }
177
                                rs.deactivate();
178
                        }
179
                        shader.deactivate();
180
                }
181
                rs.popModelMatrix();
182
 
183
                //mCurrentVertex = 0;
184
                mNumQuads = 0;
185
        }
186
 
187
        /** Takes a sprite and uses its own properties to add it to the VBO. */
188
        public void drawSprite(SpriteInstance sprite)
189
        {
190
                drawSprite(sprite, sprite.transform);
191
        }
192
 
193
        /** Takes a sprite and sprite properties and adds it to the VBO. */
194
        public void drawSprite(SpriteInstance sprite, SpriteTransform param)
195
        {
196
                if (!isDrawing())
197
                        return;
198
 
199
                if (sprite.getSprite().getTexture() != mCurrentTexture)
200
                        flush();
201
 
202
                if ((mNumQuads+1) > mSize)
203
                        flush();
204
 
205
                mCurrentTexture = sprite.getSprite().getTexture();
206
 
207
                // transform quad vertices based on sprite's properties
208
                SpriteRegion r = sprite.getSpriteRegion(); //sprite.getSprite().getRegion(sprite.getRegionIndex());
209
 
210
                // bottom left and top right corner points relative to origin
211
                final float worldOriginX = param.x + param.pivotX;
212
                final float worldOriginY = param.y + param.pivotY;
213
                float fx = -param.pivotX;
214
                float fy = -param.pivotY;
215
                float fx2 = param.w - param.pivotX;
216
                float fy2 = param.h - param.pivotY;
217
 
218
                // construct corner points, start from top left and go counter clockwise
219
                final float p1x = fx;
220
                final float p1y = fy;
221
                final float p2x = fx;
222
                final float p2y = fy2;
223
                final float p3x = fx2;
224
                final float p3y = fy2;
225
                final float p4x = fx2;
226
                final float p4y = fy;
227
 
228
                float x1;
229
                float y1;
230
                float x2;
231
                float y2;
232
                float x3;
233
                float y3;
234
                float x4;
235
                float y4;
236
 
237
                // rotate
238
                if (param.angle != 0)
239
                {
240
                        final float cos = MathUtil.cos(param.angle);
241
 
242
                        // Angle is CCW
243
                        final float sin = -MathUtil.sin(param.angle);
244
 
245
                        x1 = cos * p1x - sin * p1y;
246
                        y1 = sin * p1x + cos * p1y;
247
 
248
                        x2 = cos * p2x - sin * p2y;
249
                        y2 = sin * p2x + cos * p2y;
250
 
251
                        x3 = cos * p3x - sin * p3y;
252
                        y3 = sin * p3x + cos * p3y;
253
 
254
                        x4 = x1 + (x3 - x2);
255
                        y4 = y3 - (y2 - y1);
256
                }
257
                else
258
                {
259
                        x1 = p1x;
260
                        y1 = p1y;
261
 
262
                        x2 = p2x;
263
                        y2 = p2y;
264
 
265
                        x3 = p3x;
266
                        y3 = p3y;
267
 
268
                        x4 = p4x;
269
                        y4 = p4y;
270
                }
271
 
272
                x1 += worldOriginX - param.pivotX;
273
                y1 += worldOriginY - param.pivotY;
274
                x2 += worldOriginX - param.pivotX;
275
                y2 += worldOriginY - param.pivotY;
276
                x3 += worldOriginX - param.pivotX;
277
                y3 += worldOriginY - param.pivotY;
278
                x4 += worldOriginX - param.pivotX;
279
                y4 += worldOriginY - param.pivotY;
280
 
281
                float u = r.left;
282
                float v = r.top;
283
                float u2 = r.right;
284
                float v2 = r.bottom;
285
 
286
                if (param.mirrorX)
287
                {
288
                        float tmp = u;
289
                        u = u2;
290
                        u2 = tmp;
291
                }
292
 
293
                if (param.mirrorY)
294
                {
295
                        float tmp = v;
296
                        v = v2;
297
                        v2 = tmp;
298
                }
299
 
300
                // add vertices to buffer
301
                int n = mNumQuads * 4 * (COORDS_PER_ELEMENT);
302
 
303
                mVertices[n++] = x1;
304
                mVertices[n++] = y1;
305
                mVertices[n++] = 0;
306
                mVertices[n++] = sprite.color.x;
307
                mVertices[n++] = sprite.color.y;
308
                mVertices[n++] = sprite.color.z;
309
                mVertices[n++] = sprite.color.w;
310
                mVertices[n++] = u;
311
                mVertices[n++] = v;
312
                //mVertices[n++] = texCoords[0];
313
                //mVertices[n++] = texCoords[1];
314
 
315
                mVertices[n++] = x2;
316
                mVertices[n++] = y2;
317
                mVertices[n++] = 0;
318
                mVertices[n++] = sprite.color.x;
319
                mVertices[n++] = sprite.color.y;
320
                mVertices[n++] = sprite.color.z;
321
                mVertices[n++] = sprite.color.w;
322
                mVertices[n++] = u;
323
                mVertices[n++] = v2;
324
                //mVertices[n++] = texCoords[2];
325
                //mVertices[n++] = texCoords[3];
326
 
327
                mVertices[n++] = x3;
328
                mVertices[n++] = y3;
329
                mVertices[n++] = 0;
330
                mVertices[n++] = sprite.color.x;
331
                mVertices[n++] = sprite.color.y;
332
                mVertices[n++] = sprite.color.z;
333
                mVertices[n++] = sprite.color.w;
334
                mVertices[n++] = u2;
335
                mVertices[n++] = v2;
336
                //mVertices[n++] = texCoords[4];
337
                //mVertices[n++] = texCoords[5];
338
 
339
                mVertices[n++] = x4;
340
                mVertices[n++] = y4;
341
                mVertices[n++] = 0;
342
                mVertices[n++] = sprite.color.x;
343
                mVertices[n++] = sprite.color.y;
344
                mVertices[n++] = sprite.color.z;
345
                mVertices[n++] = sprite.color.w;
346
                mVertices[n++] = u2;
347
                mVertices[n++] = v;
348
                //mVertices[n++] = texCoords[6];
349
                //mVertices[n++] = texCoords[7];
350
 
351
                //mCurrentVertex += 4;
352
                mNumQuads++;
353
        }
354
 
355
        // Getters/Setters==================================================================================
356
 
357
 
358
        private boolean isDrawing() { return mIsDrawing; }
359
 
360
}
361
 
362
 
363
 
364