Subversion Repositories AndroidProjects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1051 chris 1
package com.gebauz.bauzoid.graphics.spritex;
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
        public void drawSprite(AtlasSpriteInstance instance, int frame)
188
        {
189
                drawSprite(instance.getFrame(frame), instance.param);
190
        }
191
 
192
        /** Takes a sprite and uses its own properties to add it to the VBO. */
193
        public void drawSprite(AtlasSpriteFrame sprite)
194
        {
195
                drawSprite(sprite, sprite.param);
196
        }
197
 
198
        /** Takes a sprite and sprite properties and adds it to the VBO. */
199
        public void drawSprite(AtlasSpriteFrame sprite, SpriteParameters param)
200
        {
201
                if (!isDrawing())
202
                        return;
203
 
204
                if (sprite.getSprite().getTexture() != mCurrentTexture)
205
                        flush();
206
 
207
                if ((mNumQuads+1) > mSize)
208
                        flush();
209
 
210
                /*if ((mCurrentVertex + 4) > mSize)
211
                        flush();*/
212
 
213
                mCurrentTexture = sprite.getSprite().getTexture();
214
 
215
                // transform quad vertices based on sprite's properties
216
                SpriteRegion r = sprite.getSprite().getRegion(sprite.getRegionIndex());
217
 
218
                // bottom left and top right corner points relative to origin
219
                final float worldOriginX = param.x + param.pivotX;
220
                final float worldOriginY = param.y + param.pivotY;
221
                float fx = -param.pivotX;
222
                float fy = -param.pivotY;
223
                float fx2 = param.w - param.pivotX;
224
                float fy2 = param.h - param.pivotY;
225
 
226
                // construct corner points, start from top left and go counter clockwise
227
                final float p1x = fx;
228
                final float p1y = fy;
229
                final float p2x = fx;
230
                final float p2y = fy2;
231
                final float p3x = fx2;
232
                final float p3y = fy2;
233
                final float p4x = fx2;
234
                final float p4y = fy;
235
 
236
                float x1;
237
                float y1;
238
                float x2;
239
                float y2;
240
                float x3;
241
                float y3;
242
                float x4;
243
                float y4;
244
 
245
                // rotate
246
                if (param.angle != 0)
247
                {
248
                        final float cos = MathUtil.cos(param.angle);
249
 
250
                        // TODO: changing this sign might require changes elsewhere - currently angle is CCW defined!
251
                        final float sin = -MathUtil.sin(param.angle);
252
 
253
                        x1 = cos * p1x - sin * p1y;
254
                        y1 = sin * p1x + cos * p1y;
255
 
256
                        x2 = cos * p2x - sin * p2y;
257
                        y2 = sin * p2x + cos * p2y;
258
 
259
                        x3 = cos * p3x - sin * p3y;
260
                        y3 = sin * p3x + cos * p3y;
261
 
262
                        x4 = x1 + (x3 - x2);
263
                        y4 = y3 - (y2 - y1);
264
                }
265
                else
266
                {
267
                        x1 = p1x;
268
                        y1 = p1y;
269
 
270
                        x2 = p2x;
271
                        y2 = p2y;
272
 
273
                        x3 = p3x;
274
                        y3 = p3y;
275
 
276
                        x4 = p4x;
277
                        y4 = p4y;
278
                }
279
 
280
                x1 += worldOriginX - param.pivotX;
281
                y1 += worldOriginY - param.pivotY;
282
                x2 += worldOriginX - param.pivotX;
283
                y2 += worldOriginY - param.pivotY;
284
                x3 += worldOriginX - param.pivotX;
285
                y3 += worldOriginY - param.pivotY;
286
                x4 += worldOriginX - param.pivotX;
287
                y4 += worldOriginY - param.pivotY;
288
 
289
/*              float invTexWidth = 1.0f/sprite.getTextureWidth();
290
                float invTexHeight = 1.0f/sprite.getTextureHeight();
291
 
292
                float u = srcX * invTexWidth;
293
                float v = (srcY + srcHeight) * invTexHeight;
294
                float u2 = (srcX + srcWidth) * invTexWidth;
295
                float v2 = srcY * invTexHeight;*/
296
 
297
                float u = r.left;
298
                float v = r.top;
299
                float u2 = r.right;
300
                float v2 = r.bottom;
301
 
302
                if (param.mirrorX)
303
                {
304
                        float tmp = u;
305
                        u = u2;
306
                        u2 = tmp;
307
                }
308
 
309
                if (param.mirrorY)
310
                {
311
                        float tmp = v;
312
                        v = v2;
313
                        v2 = tmp;
314
                }
315
 
316
                // add vertices to buffer
317
 
318
                //int n = mCurrentVertex * (COORDS_PER_ELEMENT);
319
                int n = mNumQuads * 4 * (COORDS_PER_ELEMENT);
320
 
321
                mVertices[n++] = x1;
322
                mVertices[n++] = y1;
323
                mVertices[n++] = 0;
324
                mVertices[n++] = param.color.x;
325
                mVertices[n++] = param.color.y;
326
                mVertices[n++] = param.color.z;
327
                mVertices[n++] = param.color.w;
328
                mVertices[n++] = u;
329
                mVertices[n++] = v;
330
                //mVertices[n++] = texCoords[0];
331
                //mVertices[n++] = texCoords[1];
332
 
333
                mVertices[n++] = x2;
334
                mVertices[n++] = y2;
335
                mVertices[n++] = 0;
336
                mVertices[n++] = param.color.x;
337
                mVertices[n++] = param.color.y;
338
                mVertices[n++] = param.color.z;
339
                mVertices[n++] = param.color.w;
340
                mVertices[n++] = u;
341
                mVertices[n++] = v2;
342
                //mVertices[n++] = texCoords[2];
343
                //mVertices[n++] = texCoords[3];
344
 
345
                mVertices[n++] = x3;
346
                mVertices[n++] = y3;
347
                mVertices[n++] = 0;
348
                mVertices[n++] = param.color.x;
349
                mVertices[n++] = param.color.y;
350
                mVertices[n++] = param.color.z;
351
                mVertices[n++] = param.color.w;
352
                mVertices[n++] = u2;
353
                mVertices[n++] = v2;
354
                //mVertices[n++] = texCoords[4];
355
                //mVertices[n++] = texCoords[5];
356
 
357
                mVertices[n++] = x4;
358
                mVertices[n++] = y4;
359
                mVertices[n++] = 0;
360
                mVertices[n++] = param.color.x;
361
                mVertices[n++] = param.color.y;
362
                mVertices[n++] = param.color.z;
363
                mVertices[n++] = param.color.w;
364
                mVertices[n++] = u2;
365
                mVertices[n++] = v;
366
                //mVertices[n++] = texCoords[6];
367
                //mVertices[n++] = texCoords[7];
368
 
369
                //mCurrentVertex += 4;
370
                mNumQuads++;
371
        }
372
 
373
        /** Takes the sprite instance with its current properties and adds it to the VBO. */
374
        public void drawSprite(SpriteInstance instance)
375
        {
376
                drawSprite(instance.getSprite(), instance.param);
377
        }
378
 
379
 
380
        /** Takes the sprite with its current properties and adds it to the VBO. */
381
        public void drawSprite(Sprite sprite)
382
        {
383
                drawSprite(sprite, sprite.param);
384
        }
385
 
386
        /** Takes a sprite and sprite properties and adds it to the VBO. */
387
        public void drawSprite(Sprite sprite, SpriteParameters param)
388
        {
389
                if (!isDrawing())
390
                        return;
391
 
392
                if (sprite.getTexture() != mCurrentTexture)
393
                        flush();
394
 
395
                if ((mNumQuads+1) > mSize)
396
                        flush();
397
 
398
                /*if ((mCurrentVertex + 4) > mSize)
399
                        flush();*/
400
 
401
                mCurrentTexture = sprite.getTexture();
402
 
403
                // transform quad vertices based on sprite's properties
404
 
405
                // bottom left and top right corner points relative to origin
406
                final float worldOriginX = param.x + param.pivotX;
407
                final float worldOriginY = param.y + param.pivotY;
408
                float fx = -param.pivotX;
409
                float fy = -param.pivotY;
410
                float fx2 = param.w - param.pivotX;
411
                float fy2 = param.h - param.pivotY;
412
 
413
                // construct corner points, start from top left and go counter clockwise
414
                final float p1x = fx;
415
                final float p1y = fy;
416
                final float p2x = fx;
417
                final float p2y = fy2;
418
                final float p3x = fx2;
419
                final float p3y = fy2;
420
                final float p4x = fx2;
421
                final float p4y = fy;
422
 
423
                float x1;
424
                float y1;
425
                float x2;
426
                float y2;
427
                float x3;
428
                float y3;
429
                float x4;
430
                float y4;
431
 
432
                // rotate
433
                if (param.angle != 0) {
434
                        final float cos = MathUtil.cos(param.angle);
435
                        final float sin = -MathUtil.sin(param.angle);
436
 
437
                        x1 = cos * p1x - sin * p1y;
438
                        y1 = sin * p1x + cos * p1y;
439
 
440
                        x2 = cos * p2x - sin * p2y;
441
                        y2 = sin * p2x + cos * p2y;
442
 
443
                        x3 = cos * p3x - sin * p3y;
444
                        y3 = sin * p3x + cos * p3y;
445
 
446
                        x4 = x1 + (x3 - x2);
447
                        y4 = y3 - (y2 - y1);
448
                } else {
449
                        x1 = p1x;
450
                        y1 = p1y;
451
 
452
                        x2 = p2x;
453
                        y2 = p2y;
454
 
455
                        x3 = p3x;
456
                        y3 = p3y;
457
 
458
                        x4 = p4x;
459
                        y4 = p4y;
460
                }
461
 
462
                x1 += worldOriginX - param.pivotX;
463
                y1 += worldOriginY - param.pivotY;
464
                x2 += worldOriginX - param.pivotX;
465
                y2 += worldOriginY - param.pivotY;
466
                x3 += worldOriginX - param.pivotX;
467
                y3 += worldOriginY - param.pivotY;
468
                x4 += worldOriginX - param.pivotX;
469
                y4 += worldOriginY - param.pivotY;
470
 
471
/*              float invTexWidth = 1.0f/sprite.getTextureWidth();
472
                float invTexHeight = 1.0f/sprite.getTextureHeight();
473
 
474
                float u = srcX * invTexWidth;
475
                float v = (srcY + srcHeight) * invTexHeight;
476
                float u2 = (srcX + srcWidth) * invTexWidth;
477
                float v2 = srcY * invTexHeight;*/
478
 
479
                float u = 0;
480
                float v = 0;
481
                float u2 = 1;
482
                float v2 = 1;
483
 
484
                if (param.mirrorX)
485
                {
486
                        float tmp = u;
487
                        u = u2;
488
                        u2 = tmp;
489
                }
490
 
491
                if (param.mirrorY)
492
                {
493
                        float tmp = v;
494
                        v = v2;
495
                        v2 = tmp;
496
                }
497
 
498
                // add vertices to buffer
499
 
500
                //int n = mCurrentVertex * (COORDS_PER_ELEMENT);
501
                int n = mNumQuads * 4 * COORDS_PER_ELEMENT;
502
 
503
                mVertices[n++] = x1;
504
                mVertices[n++] = y1;
505
                mVertices[n++] = 0;
506
                mVertices[n++] = param.color.x;
507
                mVertices[n++] = param.color.y;
508
                mVertices[n++] = param.color.z;
509
                mVertices[n++] = param.color.w * param.alpha;
510
                mVertices[n++] = 0;
511
                mVertices[n++] = 0;
512
 
513
                mVertices[n++] = x2;
514
                mVertices[n++] = y2;
515
                mVertices[n++] = 0;
516
                mVertices[n++] = param.color.x;
517
                mVertices[n++] = param.color.y;
518
                mVertices[n++] = param.color.z;
519
                mVertices[n++] = param.color.w * param.alpha;
520
                mVertices[n++] = 0;
521
                mVertices[n++] = 1;
522
 
523
                mVertices[n++] = x3;
524
                mVertices[n++] = y3;
525
                mVertices[n++] = 0;
526
                mVertices[n++] = param.color.x;
527
                mVertices[n++] = param.color.y;
528
                mVertices[n++] = param.color.z;
529
                mVertices[n++] = param.color.w * param.alpha;
530
                mVertices[n++] = 1;
531
                mVertices[n++] = 1;
532
 
533
                mVertices[n++] = x4;
534
                mVertices[n++] = y4;
535
                mVertices[n++] = 0;
536
                mVertices[n++] = param.color.x;
537
                mVertices[n++] = param.color.y;
538
                mVertices[n++] = param.color.z;
539
                mVertices[n++] = param.color.w * param.alpha;
540
                mVertices[n++] = 1;
541
                mVertices[n++] = 0;
542
 
543
                //mCurrentVertex += 4;          
544
                mNumQuads++;
545
        }
546
 
547
        // Getters/Setters==================================================================================
548
 
549
 
550
        private boolean isDrawing() { return mIsDrawing; }
551
 
552
}
553
 
554
 
555
 
556