Project

General

Profile

Download (37.6 KB) Statistics
| Branch: | Revision:

library / src / main / java / org / distorted / library / mesh / MeshBase.java @ 22422a76

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2016 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// Distorted is free software: you can redistribute it and/or modify                             //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Distorted is distributed in the hope that it will be useful,                                  //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.library.mesh;
21

    
22
import android.opengl.GLES30;
23
import android.opengl.Matrix;
24
import android.util.Log;
25

    
26
import org.distorted.library.effect.MatrixEffect;
27
import org.distorted.library.effect.VertexEffect;
28
import org.distorted.library.effectqueue.EffectQueue;
29
import org.distorted.library.main.InternalBuffer;
30
import org.distorted.library.program.DistortedProgram;
31
import org.distorted.library.type.Static4D;
32

    
33
import java.io.IOException;
34
import java.nio.ByteBuffer;
35
import java.nio.ByteOrder;
36
import java.nio.FloatBuffer;
37
import java.nio.channels.FileChannel;
38
import java.util.ArrayList;
39

    
40
///////////////////////////////////////////////////////////////////////////////////////////////////
41
/**
42
 * Abstract class which represents a Mesh, ie an array of vertices (rendered as a TRIANGLE_STRIP).
43
 * <p>
44
 * If you want to render to a particular shape, extend from here, construct a float array
45
 * containing per-vertex attributes, and call back setAttribs().
46
 */
47
public abstract class MeshBase
48
   {
49
   private static final int MAX_EFFECT_COMPONENTS= 100;
50
   private static final int DEFAULT_ASSOCIATION = 0xffffffff;
51

    
52
   // sizes of attributes of an individual vertex.
53
   private static final int POS_DATA_SIZE= 3; // vertex coordinates: x,y,z
54
   private static final int NOR_DATA_SIZE= 3; // normal vector: x,y,z
55
   private static final int INF_DATA_SIZE= 3; // 'inflate' vector: x,y,z
56
   private static final int TEX_DATA_SIZE= 2; // texture coordinates: s,t
57
   private static final int COM_DATA_SIZE= 1; // component number, a single float
58

    
59
   static final int POS_ATTRIB   = 0;
60
   static final int NOR_ATTRIB   = POS_DATA_SIZE;
61
   static final int INF_ATTRIB   = POS_DATA_SIZE + NOR_DATA_SIZE;
62
   static final int TEX_ATTRIB   = 0;
63
   static final int COM_ATTRIB   = TEX_DATA_SIZE;
64

    
65
   static final int VERT1_ATTRIBS= POS_DATA_SIZE + NOR_DATA_SIZE + INF_DATA_SIZE;  // number of attributes of a vertex (the part changed by preapply)
66
   static final int VERT2_ATTRIBS= TEX_DATA_SIZE + COM_DATA_SIZE;                  // number of attributes of a vertex (the 'preapply invariant' part)
67
   static final int TRAN_ATTRIBS = POS_DATA_SIZE + NOR_DATA_SIZE + INF_DATA_SIZE;  // number of attributes of a transform feedback vertex
68

    
69
   private static final int BYTES_PER_FLOAT = 4;
70

    
71
   private static final int OFFSET_POS = POS_ATTRIB*BYTES_PER_FLOAT;
72
   private static final int OFFSET_NOR = NOR_ATTRIB*BYTES_PER_FLOAT;
73
   private static final int OFFSET_INF = INF_ATTRIB*BYTES_PER_FLOAT;
74
   private static final int OFFSET_TEX = TEX_ATTRIB*BYTES_PER_FLOAT;
75
   private static final int OFFSET_COM = COM_ATTRIB*BYTES_PER_FLOAT;
76

    
77
   private static final int TRAN_SIZE  = TRAN_ATTRIBS*BYTES_PER_FLOAT;
78
   private static final int VERT1_SIZE = VERT1_ATTRIBS*BYTES_PER_FLOAT;
79
   private static final int VERT2_SIZE = VERT2_ATTRIBS*BYTES_PER_FLOAT;
80

    
81
   private boolean mShowNormals;              // when rendering this mesh, draw normal vectors?
82
   private InternalBuffer mVBO1, mVBO2, mTFO; // main vertex buffer and transform feedback buffer
83
   private int mNumVertices;
84
   private float[] mVertAttribs1;             // packed: PosX,PosY,PosZ, NorX,NorY,NorZ, InfX,InfY,InfZ
85
   private float[] mVertAttribs2;             // packed: TexS,TexT, Component
86
   private float mInflate;
87
   private int[] mEquAssociation;
88
   private int[] mAndAssociation;
89

    
90
   DeferredJobs.JobNode[] mJobNode;
91

    
92
   private static int[] mEquAssociationH = new int[EffectQueue.MAIN_VARIANTS];
93
   private static int[] mAndAssociationH = new int[EffectQueue.MAIN_VARIANTS];
94

    
95
   private static final int TEX_COMP_SIZE = 5; // 5 four-bytes entities inside the component
96

    
97
   private static class TexComponent
98
     {
99
     private int mEndIndex;
100
     private Static4D mTextureMap;
101

    
102
     TexComponent(int end)
103
       {
104
       mEndIndex  = end;
105
       mTextureMap= new Static4D(0,0,1,1);
106
       }
107
     TexComponent(TexComponent original)
108
       {
109
       mEndIndex = original.mEndIndex;
110

    
111
       float x = original.mTextureMap.get0();
112
       float y = original.mTextureMap.get1();
113
       float z = original.mTextureMap.get2();
114
       float w = original.mTextureMap.get3();
115
       mTextureMap = new Static4D(x,y,z,w);
116
       }
117

    
118
     void setMap(Static4D map)
119
       {
120
       mTextureMap.set(map.get0(),map.get1(),map.get2(),map.get3());
121
       }
122
     }
123

    
124
   private ArrayList<TexComponent> mTexComponent;
125
   private ArrayList<Integer> mEffComponent;
126

    
127
///////////////////////////////////////////////////////////////////////////////////////////////////
128

    
129
   MeshBase()
130
     {
131
     mShowNormals  = false;
132
     mInflate      = 0.0f;
133
     mTexComponent = new ArrayList<>();
134
     mEffComponent = new ArrayList<>();
135

    
136
     mEquAssociation= new int[MAX_EFFECT_COMPONENTS];
137
     mAndAssociation= new int[MAX_EFFECT_COMPONENTS];
138

    
139
     mJobNode = new DeferredJobs.JobNode[1];
140

    
141
     for(int i=0; i<MAX_EFFECT_COMPONENTS; i++)
142
       {
143
       mAndAssociation[i] = DEFAULT_ASSOCIATION;
144
       mEquAssociation[i] = i;
145
       }
146

    
147
     mVBO1= new InternalBuffer(GLES30.GL_ARRAY_BUFFER             , GLES30.GL_STATIC_READ);
148
     mVBO2= new InternalBuffer(GLES30.GL_ARRAY_BUFFER             , GLES30.GL_STATIC_READ);
149
     mTFO = new InternalBuffer(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, GLES30.GL_STATIC_READ);
150
     }
151

    
152
///////////////////////////////////////////////////////////////////////////////////////////////////
153
// copy constructor
154

    
155
   MeshBase(MeshBase original, boolean deep)
156
     {
157
     mShowNormals= original.mShowNormals;
158
     mInflate    = original.mInflate;
159
     mNumVertices= original.mNumVertices;
160

    
161
     mAndAssociation= new int[MAX_EFFECT_COMPONENTS];
162
     System.arraycopy(original.mAndAssociation, 0, mAndAssociation, 0, MAX_EFFECT_COMPONENTS);
163
     mEquAssociation= new int[MAX_EFFECT_COMPONENTS];
164
     System.arraycopy(original.mEquAssociation, 0, mEquAssociation, 0, MAX_EFFECT_COMPONENTS);
165

    
166
     if( deep )
167
       {
168
       mJobNode = new DeferredJobs.JobNode[1];
169
       if( original.mJobNode[0]==null ) copy(original);
170
       else mJobNode[0] = DeferredJobs.copy(this,original);
171
       }
172
     else
173
       {
174
       mJobNode      = original.mJobNode;
175
       mVBO1         = original.mVBO1;
176
       mVertAttribs1 = original.mVertAttribs1;
177
       shallowCopy(original);
178
       }
179

    
180
     mTFO = new InternalBuffer(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, GLES30.GL_STATIC_READ);
181
     mTFO.invalidate();
182
     }
183

    
184
///////////////////////////////////////////////////////////////////////////////////////////////////
185

    
186
   void copy(MeshBase original)
187
     {
188
     shallowCopy(original);
189

    
190
     mVBO1= new InternalBuffer(GLES30.GL_ARRAY_BUFFER, GLES30.GL_STATIC_READ);
191
     mVertAttribs1= new float[mNumVertices*VERT1_ATTRIBS];
192
     System.arraycopy(original.mVertAttribs1,0,mVertAttribs1,0,mNumVertices*VERT1_ATTRIBS);
193
     mVBO1.invalidate();
194
     }
195

    
196
///////////////////////////////////////////////////////////////////////////////////////////////////
197

    
198
   private void shallowCopy(MeshBase original)
199
     {
200
     int texComSize = original.mTexComponent.size();
201
     mTexComponent = new ArrayList<>();
202

    
203
     for(int i=0; i<texComSize; i++)
204
       {
205
       TexComponent comp = new TexComponent(original.mTexComponent.get(i));
206
       mTexComponent.add(comp);
207
       }
208

    
209
     mEffComponent = new ArrayList<>();
210
     mEffComponent.addAll(original.mEffComponent);
211

    
212
     mVBO2= new InternalBuffer(GLES30.GL_ARRAY_BUFFER, GLES30.GL_STATIC_READ);
213
     mVertAttribs2= new float[mNumVertices*VERT2_ATTRIBS];
214
     System.arraycopy(original.mVertAttribs2,0,mVertAttribs2,0,mNumVertices*VERT2_ATTRIBS);
215
     mVBO2.invalidate();
216
     }
217

    
218
///////////////////////////////////////////////////////////////////////////////////////////////////
219

    
220
   void mergeTexComponentsNow()
221
     {
222
     int num = mTexComponent.size();
223

    
224
     if( num>1 )
225
       {
226
       mTexComponent.clear();
227
       mTexComponent.add(new TexComponent(mNumVertices-1));
228

    
229
       mVBO2.invalidate();
230
       }
231
     }
232

    
233
///////////////////////////////////////////////////////////////////////////////////////////////////
234

    
235
   void mergeEffComponentsNow()
236
     {
237
     int num = mEffComponent.size();
238

    
239
     if( num>1 )
240
       {
241
       mEffComponent.clear();
242
       mEffComponent.add(mNumVertices-1);
243

    
244
       for(int index=0; index<mNumVertices; index++)
245
         {
246
         mVertAttribs2[VERT2_ATTRIBS*index+COM_ATTRIB] = 0;
247
         }
248

    
249
       mVBO2.invalidate();
250
       }
251
     }
252

    
253
///////////////////////////////////////////////////////////////////////////////////////////////////
254

    
255
   void applyMatrix(MatrixEffect effect, int andAssoc, int equAssoc)
256
     {
257
     float[] matrix   = new float[16];
258
     float[] uniforms = new float[7];
259
     int start, end=-1, numComp = mEffComponent.size();
260

    
261
     Matrix.setIdentityM(matrix,0);
262
     effect.compute(uniforms,0,0,0);
263
     effect.apply(matrix, uniforms, 0);
264

    
265
     for(int i=0; i<numComp; i++)
266
       {
267
       start = end+1;
268
       end   = mEffComponent.get(i);
269

    
270
       if( (andAssoc & mAndAssociation[i]) != 0 || (equAssoc == mEquAssociation[i]) )
271
         {
272
         applyMatrixToComponent(matrix,start,end);
273
         }
274
       }
275

    
276
     mVBO1.invalidate();
277
     }
278

    
279
///////////////////////////////////////////////////////////////////////////////////////////////////
280

    
281
   private void applyMatrixToComponent(float[] matrix, int start, int end)
282
     {
283
     float x,y,z;
284

    
285
     for(int index=start*VERT1_ATTRIBS; index<=end*VERT1_ATTRIBS; index+=VERT1_ATTRIBS )
286
       {
287
       x = mVertAttribs1[index+POS_ATTRIB  ];
288
       y = mVertAttribs1[index+POS_ATTRIB+1];
289
       z = mVertAttribs1[index+POS_ATTRIB+2];
290

    
291
       mVertAttribs1[index+POS_ATTRIB  ] = matrix[0]*x + matrix[4]*y + matrix[ 8]*z + matrix[12];
292
       mVertAttribs1[index+POS_ATTRIB+1] = matrix[1]*x + matrix[5]*y + matrix[ 9]*z + matrix[13];
293
       mVertAttribs1[index+POS_ATTRIB+2] = matrix[2]*x + matrix[6]*y + matrix[10]*z + matrix[14];
294

    
295
       x = mVertAttribs1[index+NOR_ATTRIB  ];
296
       y = mVertAttribs1[index+NOR_ATTRIB+1];
297
       z = mVertAttribs1[index+NOR_ATTRIB+2];
298

    
299
       mVertAttribs1[index+NOR_ATTRIB  ] = matrix[0]*x + matrix[4]*y + matrix[ 8]*z;
300
       mVertAttribs1[index+NOR_ATTRIB+1] = matrix[1]*x + matrix[5]*y + matrix[ 9]*z;
301
       mVertAttribs1[index+NOR_ATTRIB+2] = matrix[2]*x + matrix[6]*y + matrix[10]*z;
302

    
303
       x = mVertAttribs1[index+INF_ATTRIB  ];
304
       y = mVertAttribs1[index+INF_ATTRIB+1];
305
       z = mVertAttribs1[index+INF_ATTRIB+2];
306

    
307
       mVertAttribs1[index+INF_ATTRIB  ] = matrix[0]*x + matrix[4]*y + matrix[ 8]*z;
308
       mVertAttribs1[index+INF_ATTRIB+1] = matrix[1]*x + matrix[5]*y + matrix[ 9]*z;
309
       mVertAttribs1[index+INF_ATTRIB+2] = matrix[2]*x + matrix[6]*y + matrix[10]*z;
310
       }
311
     }
312

    
313
///////////////////////////////////////////////////////////////////////////////////////////////////
314

    
315
   void setEffectAssociationNow(int component, int andAssociation, int equAssociation)
316
     {
317
     mAndAssociation[component] = andAssociation;
318
     mEquAssociation[component] = equAssociation;
319
     }
320

    
321
///////////////////////////////////////////////////////////////////////////////////////////////////
322

    
323
   int numTexComponents()
324
     {
325
     return mTexComponent.size();
326
     }
327

    
328
///////////////////////////////////////////////////////////////////////////////////////////////////
329

    
330
   int numEffComponents()
331
     {
332
     return mEffComponent.size();
333
     }
334

    
335
///////////////////////////////////////////////////////////////////////////////////////////////////
336
// when a derived class is done computing its mesh, it has to call this method.
337

    
338
   void setAttribs(float[] vert1Attribs, float[] vert2Attribs)
339
     {
340
     mNumVertices = vert1Attribs.length/VERT1_ATTRIBS;
341
     mVertAttribs1= vert1Attribs;
342
     mVertAttribs2= vert2Attribs;
343

    
344
     mTexComponent.add(new TexComponent(mNumVertices-1));
345
     mEffComponent.add(mNumVertices-1);
346

    
347
     mVBO1.invalidate();
348
     mVBO2.invalidate();
349
     }
350

    
351
///////////////////////////////////////////////////////////////////////////////////////////////////
352

    
353
   void joinAttribs(MeshBase[] meshes)
354
     {
355
     MeshBase mesh;
356
     TexComponent comp;
357
     int numMeshes = meshes.length;
358
     int numVertices,origVertices = mNumVertices;
359
     int origTexComponents,numTexComponents;
360
     int origEffComponents=0,numEffComponents;
361

    
362
     if( origVertices>0 )
363
       {
364
       origTexComponents = mTexComponent.size();
365
       mNumVertices+= ( mNumVertices%2==1 ? 2:1 );
366
       mTexComponent.get(origTexComponents-1).mEndIndex = mNumVertices-1;
367
       origEffComponents = mEffComponent.size();
368
       mEffComponent.set(origEffComponents-1,mNumVertices-1);
369
       }
370

    
371
     for(int i=0; i<numMeshes; i++)
372
       {
373
       mesh = meshes[i];
374
       numTexComponents = mesh.mTexComponent.size();
375
       numEffComponents = mesh.mEffComponent.size();
376
       numVertices = mesh.mNumVertices;
377

    
378
       int extraVerticesBefore = mNumVertices==0 ? 0:1;
379
       int extraVerticesAfter  = (i==numMeshes-1) ? 0 : (numVertices%2==1 ? 2:1);
380

    
381
       for(int j=0; j<numTexComponents; j++)
382
         {
383
         comp = new TexComponent(mesh.mTexComponent.get(j));
384
         comp.mEndIndex += (extraVerticesBefore+mNumVertices);
385
         if( j==numTexComponents-1) comp.mEndIndex += extraVerticesAfter;
386
         mTexComponent.add(comp);
387
         }
388

    
389
       for(int j=0; j<numEffComponents; j++)
390
         {
391
         int index = mesh.mEffComponent.get(j);
392
         index += (extraVerticesBefore+mNumVertices);
393
         if( j==numEffComponents-1 ) index += extraVerticesAfter;
394
         mEffComponent.add(index);
395

    
396
         if( origEffComponents<MAX_EFFECT_COMPONENTS )
397
           {
398
           mAndAssociation[origEffComponents] = mesh.mAndAssociation[j];
399
           mEquAssociation[origEffComponents] = mesh.mEquAssociation[j];
400
           origEffComponents++;
401
           }
402
         }
403

    
404
       mNumVertices += (extraVerticesBefore+numVertices+extraVerticesAfter);
405
       }
406

    
407
     float[] newAttribs1 = new float[VERT1_ATTRIBS*mNumVertices];
408
     float[] newAttribs2 = new float[VERT2_ATTRIBS*mNumVertices];
409
     numVertices = origVertices;
410

    
411
     if( origVertices>0 )
412
       {
413
       System.arraycopy(mVertAttribs1,                              0, newAttribs1,                          0, VERT1_ATTRIBS*numVertices);
414
       System.arraycopy(mVertAttribs1, VERT1_ATTRIBS*(origVertices-1), newAttribs1, VERT1_ATTRIBS*origVertices, VERT1_ATTRIBS            );
415
       System.arraycopy(mVertAttribs2,                              0, newAttribs2,                          0, VERT2_ATTRIBS*numVertices);
416
       System.arraycopy(mVertAttribs2, VERT2_ATTRIBS*(origVertices-1), newAttribs2, VERT2_ATTRIBS*origVertices, VERT2_ATTRIBS            );
417
       origVertices++;
418

    
419
       if( numVertices%2==1 )
420
         {
421
         System.arraycopy(mVertAttribs1, VERT1_ATTRIBS*(origVertices-1), newAttribs1, VERT1_ATTRIBS*origVertices, VERT1_ATTRIBS);
422
         System.arraycopy(mVertAttribs2, VERT2_ATTRIBS*(origVertices-1), newAttribs2, VERT2_ATTRIBS*origVertices, VERT2_ATTRIBS);
423
         origVertices++;
424
         }
425
       }
426

    
427
     for(int i=0; i<numMeshes; i++)
428
       {
429
       mesh = meshes[i];
430
       numVertices = mesh.mNumVertices;
431

    
432
       if( origVertices>0 )
433
         {
434
         System.arraycopy(mesh.mVertAttribs1, 0, newAttribs1, VERT1_ATTRIBS*origVertices, VERT1_ATTRIBS);
435
         System.arraycopy(mesh.mVertAttribs2, 0, newAttribs2, VERT2_ATTRIBS*origVertices, VERT2_ATTRIBS);
436
         origVertices++;
437
         }
438
       System.arraycopy(mesh.mVertAttribs1, 0, newAttribs1, VERT1_ATTRIBS*origVertices, VERT1_ATTRIBS*numVertices);
439
       System.arraycopy(mesh.mVertAttribs2, 0, newAttribs2, VERT2_ATTRIBS*origVertices, VERT2_ATTRIBS*numVertices);
440
       origVertices+=numVertices;
441

    
442
       if( i<numMeshes-1 )
443
         {
444
         System.arraycopy(mesh.mVertAttribs1, VERT1_ATTRIBS*(numVertices-1), newAttribs1, VERT1_ATTRIBS*origVertices, VERT1_ATTRIBS);
445
         System.arraycopy(mesh.mVertAttribs2, VERT2_ATTRIBS*(numVertices-1), newAttribs2, VERT2_ATTRIBS*origVertices, VERT2_ATTRIBS);
446
         origVertices++;
447

    
448
         if( numVertices%2==1 )
449
           {
450
           System.arraycopy(mesh.mVertAttribs1, VERT1_ATTRIBS*(numVertices-1), newAttribs1, VERT1_ATTRIBS*origVertices, VERT1_ATTRIBS);
451
           System.arraycopy(mesh.mVertAttribs2, VERT2_ATTRIBS*(numVertices-1), newAttribs2, VERT2_ATTRIBS*origVertices, VERT2_ATTRIBS);
452
           origVertices++;
453
           }
454
         }
455
       }
456

    
457
     if( origVertices!=mNumVertices )
458
       {
459
       android.util.Log.e("mesh", "join: origVertices: "+origVertices+" numVertices: "+mNumVertices);
460
       }
461

    
462
     int endIndex, index=0, numEffComp = mEffComponent.size();
463

    
464
     for(int component=0; component<numEffComp; component++)
465
       {
466
       endIndex = mEffComponent.get(component);
467

    
468
       for( ; index<=endIndex; index++) newAttribs2[VERT2_ATTRIBS*index+COM_ATTRIB] = component;
469
       }
470

    
471
     mVertAttribs1 = newAttribs1;
472
     mVertAttribs2 = newAttribs2;
473
     mVBO1.invalidate();
474
     mVBO2.invalidate();
475
     }
476

    
477
///////////////////////////////////////////////////////////////////////////////////////////////////
478
// called from MeshJoined
479

    
480
   void join(MeshBase[] meshes)
481
     {
482
     boolean immediateJoin = true;
483

    
484
     for (MeshBase mesh : meshes)
485
       {
486
       if (mesh.mJobNode[0] != null)
487
         {
488
         immediateJoin = false;
489
         break;
490
         }
491
       }
492

    
493
     if( immediateJoin ) joinAttribs(meshes);
494
     else                mJobNode[0] = DeferredJobs.join(this,meshes);
495
     }
496

    
497
///////////////////////////////////////////////////////////////////////////////////////////////////
498

    
499
   void textureMap(Static4D[] maps, int startComponent)
500
     {
501
     int num_comp = mTexComponent.size();
502
     int num_maps = maps.length;
503
     int min = Math.min(num_comp-startComponent, num_maps);
504
     int vertex = startComponent>0 ? mTexComponent.get(startComponent-1).mEndIndex+1 : 0;
505
     Static4D newMap, oldMap;
506
     TexComponent comp;
507
     float newW, newH, ratW, ratH, movX, movY;
508

    
509
     for(int i=0; i<min; i++)
510
       {
511
       newMap = maps[i];
512
       comp = mTexComponent.get(i+startComponent);
513

    
514
       if( newMap!=null )
515
         {
516
         newW = newMap.get2();
517
         newH = newMap.get3();
518

    
519
         if( newW!=0.0f && newH!=0.0f )
520
           {
521
           oldMap = comp.mTextureMap;
522
           ratW = newW/oldMap.get2();
523
           ratH = newH/oldMap.get3();
524
           movX = newMap.get0() - ratW*oldMap.get0();
525
           movY = newMap.get1() - ratH*oldMap.get1();
526

    
527
           for( int index=vertex*VERT2_ATTRIBS+TEX_ATTRIB ; vertex<=comp.mEndIndex; vertex++, index+=VERT2_ATTRIBS)
528
             {
529
             mVertAttribs2[index  ] = ratW*mVertAttribs2[index  ] + movX;
530
             mVertAttribs2[index+1] = ratH*mVertAttribs2[index+1] + movY;
531
             }
532
           comp.setMap(newMap);
533
           }
534
         }
535

    
536
       vertex= comp.mEndIndex+1;
537
       }
538

    
539
     mVBO2.invalidate();
540
     }
541

    
542
///////////////////////////////////////////////////////////////////////////////////////////////////
543

    
544
   public static int getMaxEffComponents()
545
     {
546
     return MAX_EFFECT_COMPONENTS;
547
     }
548

    
549
///////////////////////////////////////////////////////////////////////////////////////////////////
550

    
551
   public static void getUniforms(int mProgramH, int variant)
552
     {
553
     mEquAssociationH[variant] = GLES30.glGetUniformLocation( mProgramH, "vComEquAssoc");
554
     mAndAssociationH[variant] = GLES30.glGetUniformLocation( mProgramH, "vComAndAssoc");
555
     }
556

    
557
///////////////////////////////////////////////////////////////////////////////////////////////////
558
/**
559
 * Not part of public API, do not document (public only because has to be used from the main package)
560
 *
561
 * @y.exclude
562
 */
563
   public void copyTransformToVertex()
564
     {
565
     ByteBuffer buffer = (ByteBuffer)GLES30.glMapBufferRange( GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0,
566
                                                              TRAN_SIZE*mNumVertices, GLES30.GL_MAP_READ_BIT);
567
     if( buffer!=null )
568
       {
569
       FloatBuffer feedback = buffer.order(ByteOrder.nativeOrder()).asFloatBuffer();
570
       feedback.get(mVertAttribs1,0,VERT1_ATTRIBS*mNumVertices);
571
       mVBO1.update(mVertAttribs1);
572
       }
573
     else
574
       {
575
       int error = GLES30.glGetError();
576
       Log.e("mesh", "failed to map tf buffer, error="+error);
577
       }
578

    
579
     GLES30.glUnmapBuffer(GLES30.GL_TRANSFORM_FEEDBACK);
580
     }
581

    
582
///////////////////////////////////////////////////////////////////////////////////////////////////
583
/**
584
 * Not part of public API, do not document (public only because has to be used from the main package)
585
 *
586
 * @y.exclude
587
 */
588
   public void debug()
589
     {
590
     if( mJobNode[0]!=null )
591
       {
592
       mJobNode[0].print(0);
593
       }
594
     else
595
       {
596
       android.util.Log.e("mesh", "JobNode null");
597
       }
598
     }
599

    
600
///////////////////////////////////////////////////////////////////////////////////////////////////
601
/**
602
 * Not part of public API, do not document (public only because has to be used from the main package)
603
 *
604
 * @y.exclude
605
 */
606
   public void printPos()
607
     {
608
     StringBuilder sb = new StringBuilder();
609

    
610
     for(int i=0; i<mNumVertices; i++)
611
       {
612
       sb.append('(');
613
       sb.append(mVertAttribs1[VERT1_ATTRIBS*i+POS_ATTRIB  ]);
614
       sb.append(',');
615
       sb.append(mVertAttribs1[VERT1_ATTRIBS*i+POS_ATTRIB+1]);
616
       sb.append(',');
617
       sb.append(mVertAttribs1[VERT1_ATTRIBS*i+POS_ATTRIB+2]);
618
       sb.append(") ");
619
       }
620
     Log.d("mesh", sb.toString());
621
     }
622

    
623
///////////////////////////////////////////////////////////////////////////////////////////////////
624
/**
625
 * Not part of public API, do not document (public only because has to be used from the main package)
626
 *
627
 * @y.exclude
628
 */
629
   public void printCom()
630
     {
631
     StringBuilder sb = new StringBuilder();
632

    
633
     for(int i=0; i<mNumVertices; i++)
634
       {
635
       sb.append(mVertAttribs2[VERT2_ATTRIBS*i+COM_ATTRIB]);
636
       sb.append(' ');
637
       }
638

    
639
     Log.d("mesh", sb.toString());
640
     }
641

    
642
///////////////////////////////////////////////////////////////////////////////////////////////////
643
/**
644
 * Not part of public API, do not document (public only because has to be used from the main package)
645
 *
646
 * @y.exclude
647
 */
648
   public void printTex()
649
     {
650
     int vert=0;
651
     int num = numTexComponents();
652
     StringBuilder sb = new StringBuilder();
653
     sb.append("tex components: ").append(num);
654

    
655
     for(int i=0; i<num; i++)
656
       {
657
       int end = mTexComponent.get(i).mEndIndex;
658
       sb.append("\n");
659

    
660
       for( ; vert<=end; vert++)
661
         {
662
         sb.append(' ');
663
         sb.append('(');
664
         sb.append(mVertAttribs2[VERT2_ATTRIBS*vert+TEX_ATTRIB]);
665
         sb.append(',');
666
         sb.append(mVertAttribs2[VERT2_ATTRIBS*vert+TEX_ATTRIB+1]);
667
         sb.append(')');
668
         }
669
       }
670

    
671
     Log.d("mesh", sb.toString());
672
     }
673

    
674
///////////////////////////////////////////////////////////////////////////////////////////////////
675
/**
676
 * Not part of public API, do not document (public only because has to be used from the main package)
677
 *
678
 * @y.exclude
679
 */
680
   public int getTFO()
681
     {
682
     return mTFO.createImmediately(mNumVertices*TRAN_SIZE, null);
683
     }
684

    
685
///////////////////////////////////////////////////////////////////////////////////////////////////
686
/**
687
 * Not part of public API, do not document (public only because has to be used from the main package)
688
 *
689
 * @y.exclude
690
 */
691
   public int getNumVertices()
692
     {
693
     return mNumVertices;
694
     }
695

    
696
///////////////////////////////////////////////////////////////////////////////////////////////////
697
/**
698
 * Not part of public API, do not document (public only because has to be used from the main package)
699
 *
700
 * @y.exclude
701
 */
702
   public void send(int variant)
703
     {
704
     GLES30.glUniform1iv( mEquAssociationH[variant], MAX_EFFECT_COMPONENTS, mEquAssociation, 0);
705
     GLES30.glUniform1iv( mAndAssociationH[variant], MAX_EFFECT_COMPONENTS, mAndAssociation, 0);
706
     }
707

    
708
///////////////////////////////////////////////////////////////////////////////////////////////////
709
/**
710
 * Not part of public API, do not document (public only because has to be used from the main package)
711
 *
712
 * @y.exclude
713
 */
714
   public void bindVertexAttribs(DistortedProgram program)
715
     {
716
     if( mJobNode[0]!=null )
717
       {
718
       mJobNode[0].execute();  // this will set itself to null
719
       }
720

    
721
     int index1 = mVBO1.createImmediately(mNumVertices*VERT1_SIZE, mVertAttribs1);
722
     int index2 = mVBO2.createImmediately(mNumVertices*VERT2_SIZE, mVertAttribs2);
723

    
724
     GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, index1 );
725
     GLES30.glVertexAttribPointer(program.mAttribute[0], POS_DATA_SIZE, GLES30.GL_FLOAT, false, VERT1_SIZE, OFFSET_POS);
726
     GLES30.glVertexAttribPointer(program.mAttribute[1], NOR_DATA_SIZE, GLES30.GL_FLOAT, false, VERT1_SIZE, OFFSET_NOR);
727
     GLES30.glVertexAttribPointer(program.mAttribute[2], INF_DATA_SIZE, GLES30.GL_FLOAT, false, VERT1_SIZE, OFFSET_INF);
728
     GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, index2 );
729
     GLES30.glVertexAttribPointer(program.mAttribute[3], TEX_DATA_SIZE, GLES30.GL_FLOAT, false, VERT2_SIZE, OFFSET_TEX);
730
     GLES30.glVertexAttribPointer(program.mAttribute[4], COM_DATA_SIZE, GLES30.GL_FLOAT, false, VERT2_SIZE, OFFSET_COM);
731
     GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0);
732
     }
733

    
734
///////////////////////////////////////////////////////////////////////////////////////////////////
735
/**
736
 * Not part of public API, do not document (public only because has to be used from the main package)
737
 *
738
 * @y.exclude
739
 */
740
   public void bindTransformAttribs(DistortedProgram program)
741
     {
742
     int index = mTFO.createImmediately(mNumVertices*TRAN_SIZE, null);
743

    
744
     GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, index );
745
     GLES30.glVertexAttribPointer(program.mAttribute[0], POS_DATA_SIZE, GLES30.GL_FLOAT, false, 0, 0);
746
     GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0);
747
     }
748

    
749
///////////////////////////////////////////////////////////////////////////////////////////////////
750
/**
751
 * Not part of public API, do not document (public only because has to be used from the main package)
752
 *
753
 * @y.exclude
754
 */
755
   public void setInflate(float inflate)
756
     {
757
     mInflate = inflate;
758
     }
759

    
760
///////////////////////////////////////////////////////////////////////////////////////////////////
761
/**
762
 * Not part of public API, do not document (public only because has to be used from the main package)
763
 *
764
 * @y.exclude
765
 */
766
   public float getInflate()
767
     {
768
     return mInflate;
769
     }
770

    
771
///////////////////////////////////////////////////////////////////////////////////////////////////
772

    
773
   void read(FileChannel file) throws IOException
774
     {
775
     ByteBuffer buffer = ByteBuffer.allocate(BYTES_PER_FLOAT*4);
776
     int version, numVertices=0, numEff=0, numTex=0;
777

    
778
     try
779
       {
780
       file.read(buffer);
781

    
782
       version = buffer.getInt(0);
783

    
784
       if( version==1 )
785
         {
786
         numVertices = buffer.getInt(4);
787
         numTex      = buffer.getInt(8);
788
         numEff      = buffer.getInt(12);
789
         }
790
       else
791
         {
792
         android.util.Log.e("mesh", "Error: unknown mesh file version "+version);
793
         file.close();
794
         return;
795
         }
796
       }
797
     catch(IOException e)
798
       {
799
       file.close();
800
       throw e;
801
       }
802

    
803
     if( numVertices>0 && numEff>0 && numTex>0 )
804
       {
805
       int size = numEff+TEX_COMP_SIZE*numTex;
806
       float[] tmp = new float[size];
807
       mVertAttribs1 = new float[VERT1_SIZE*mNumVertices];
808
       mVertAttribs2 = new float[VERT2_SIZE*mNumVertices];
809

    
810
       buffer = ByteBuffer.allocate(BYTES_PER_FLOAT*size + mNumVertices*(VERT1_SIZE+VERT2_SIZE));
811

    
812
       file.read(buffer);
813

    
814
       buffer.asFloatBuffer().get(tmp,0,size);
815
       buffer.asFloatBuffer().get(mVertAttribs1, 0, VERT1_SIZE*mNumVertices);
816
       buffer.asFloatBuffer().get(mVertAttribs2, 0, VERT2_SIZE*mNumVertices);
817

    
818
       TexComponent tex;
819
       int index, texComp;
820
       float x, y, z, w;
821

    
822
       for(texComp=0; texComp<numTex; texComp++)
823
         {
824
         index = (int)tmp[TEX_COMP_SIZE*texComp];
825

    
826
         x= tmp[TEX_COMP_SIZE*texComp+1];
827
         y= tmp[TEX_COMP_SIZE*texComp+2];
828
         z= tmp[TEX_COMP_SIZE*texComp+3];
829
         w= tmp[TEX_COMP_SIZE*texComp+4];
830

    
831
         tex = new TexComponent(index);
832
         tex.setMap(new Static4D(x,y,z,w));
833

    
834
         mTexComponent.add(tex);
835
         }
836

    
837
       for(int effComp=0; effComp<numEff; effComp++)
838
         {
839
         index = (int)tmp[TEX_COMP_SIZE*texComp + effComp ];
840
         mEffComponent.add(index);
841
         }
842
       }
843

    
844
     file.close();
845
     }
846

    
847
///////////////////////////////////////////////////////////////////////////////////////////////////
848
// PUBLIC API
849
///////////////////////////////////////////////////////////////////////////////////////////////////
850
/**
851
 * Write the Mesh to a File.
852
 */
853
   public void write(FileChannel file) throws IOException
854
     {
855
     TexComponent tex;
856

    
857
     int numTex = mTexComponent.size();
858
     int numEff = mEffComponent.size();
859

    
860
     ByteBuffer buffer = ByteBuffer.allocate(BYTES_PER_FLOAT*(numEff+TEX_COMP_SIZE*numTex+4));
861
     FloatBuffer buf  = buffer.asFloatBuffer();
862

    
863
     buf.put(1);             // version
864
     buf.put(mNumVertices);
865
     buf.put(numTex);
866
     buf.put(numEff);
867

    
868
     for(int i=0; i<numTex; i++)
869
       {
870
       tex = mTexComponent.get(i);
871

    
872
       buf.put(tex.mEndIndex);
873
       buf.put(tex.mTextureMap.get0());
874
       buf.put(tex.mTextureMap.get1());
875
       buf.put(tex.mTextureMap.get2());
876
       buf.put(tex.mTextureMap.get3());
877
       }
878

    
879
     for(int i=0; i<numEff; i++)
880
       {
881
       buf.put(mEffComponent.get(i));
882
       }
883

    
884
     ByteBuffer vertBuf1 = ByteBuffer.allocate(VERT1_SIZE*mNumVertices);
885
     vertBuf1.asFloatBuffer().put(mVertAttribs1);
886
     ByteBuffer vertBuf2 = ByteBuffer.allocate(VERT2_SIZE*mNumVertices);
887
     vertBuf2.asFloatBuffer().put(mVertAttribs2);
888

    
889
     try
890
       {
891
       file.write(buffer);
892
       file.write(vertBuf1);
893
       file.write(vertBuf2);
894
       }
895
     catch(IOException e)
896
       {
897
       file.close();
898
       throw e;
899
       }
900

    
901
     file.close();
902
     }
903

    
904
///////////////////////////////////////////////////////////////////////////////////////////////////
905
/**
906
 * When rendering this Mesh, do we want to render the Normal vectors as well?
907
 * <p>
908
 * Will work only on OpenGL ES >= 3.0 devices.
909
 *
910
 * @param show Controls if we render the Normal vectors or not.
911
 */
912
   public void setShowNormals(boolean show)
913
     {
914
     mShowNormals = show;
915
     }
916

    
917
///////////////////////////////////////////////////////////////////////////////////////////////////
918
/**
919
 * When rendering this mesh, should we also draw the normal vectors?
920
 *
921
 * @return <i>true</i> if we do render normal vectors
922
 */
923
   public boolean getShowNormals()
924
     {
925
     return mShowNormals;
926
     }
927

    
928
///////////////////////////////////////////////////////////////////////////////////////////////////
929
/**
930
 * Merge all texture components of this Mesh into a single one.
931
 */
932
   public void mergeTexComponents()
933
     {
934
     if( mJobNode[0]==null )
935
       {
936
       mergeTexComponentsNow();
937
       }
938
     else
939
       {
940
       mJobNode[0] = DeferredJobs.mergeTex(this);
941
       }
942
     }
943

    
944
///////////////////////////////////////////////////////////////////////////////////////////////////
945
/**
946
 * Merge all effect components of this Mesh into a single one.
947
 */
948
   public void mergeEffComponents()
949
     {
950
     if( mJobNode[0]==null )
951
       {
952
       mergeEffComponentsNow();
953
       }
954
     else
955
       {
956
       mJobNode[0] = DeferredJobs.mergeEff(this);
957
       }
958
     }
959

    
960
///////////////////////////////////////////////////////////////////////////////////////////////////
961
/**
962
 * Release all internal resources.
963
 */
964
   public void markForDeletion()
965
     {
966
     mVertAttribs1 = null;
967
     mVertAttribs2 = null;
968

    
969
     mVBO1.markForDeletion();
970
     mVBO2.markForDeletion();
971
     mTFO.markForDeletion();
972
     }
973

    
974
///////////////////////////////////////////////////////////////////////////////////////////////////
975
/**
976
 * Apply a Matrix Effect to the components which match the (addAssoc,equAssoc) association.
977
 * <p>
978
 * This is a static, permanent modification of the vertices contained in this Mesh. If the effect
979
 * contains any Dynamics, they will be evaluated at 0.
980
 *
981
 * @param effect List of Matrix Effects to apply to the Mesh.
982
 * @param andAssoc 'Logical AND' association which defines which components will be affected.
983
 * @param equAssoc 'equality' association which defines which components will be affected.
984
 */
985
   public void apply(MatrixEffect effect, int andAssoc, int equAssoc)
986
     {
987
     if( mJobNode[0]==null )
988
       {
989
       applyMatrix(effect,andAssoc,equAssoc);
990
       }
991
     else
992
       {
993
       mJobNode[0] = DeferredJobs.matrix(this,effect,andAssoc,equAssoc);
994
       }
995
     }
996

    
997
///////////////////////////////////////////////////////////////////////////////////////////////////
998
/**
999
 * Apply a Vertex Effect to the vertex mesh.
1000
 * <p>
1001
 * This is a static, permanent modification of the vertices contained in this Mesh. If the effects
1002
 * contain any Dynamics, the Dynamics will be evaluated at 0.
1003
 *
1004
 * We would call this several times building up a list of Effects to do. This list of effects gets
1005
 * lazily executed only when the Mesh is used for rendering for the first time.
1006
 *
1007
 * @param effect Vertex Effect to apply to the Mesh.
1008
 */
1009
   public void apply(VertexEffect effect)
1010
     {
1011
     mJobNode[0] = DeferredJobs.vertex(this,effect);
1012
     }
1013

    
1014
///////////////////////////////////////////////////////////////////////////////////////////////////
1015
/**
1016
 * Sets texture maps for (some of) the components of this mesh.
1017
 * <p>
1018
 * Format: ( x of lower-left corner, y of lower-left corner, width, height ).
1019
 * For example maps[0] = new Static4D( 0.0, 0.5, 0.5, 0.5 ) sets the 0th component texture map to the
1020
 * upper-left quadrant of the texture.
1021
 * <p>
1022
 * Probably the most common user case would be sending as many maps as there are components in this
1023
 * Mesh. One can also send less, or more (the extraneous ones will be ignored) and set some of them
1024
 * to null (those will be ignored as well). So if there are 5 components, and we want to set the map
1025
 * of the 2nd and 4rd one, call this with
1026
 * maps = new Static4D[4]
1027
 * maps[0] = null
1028
 * maps[1] = the map for the 2nd component
1029
 * maps[2] = null
1030
 * maps[3] = the map for the 4th component
1031
 *
1032
 * A map's width and height have to be non-zero (but can be negative!)
1033
 *
1034
 * @param maps            List of texture maps to apply to the texture's components.
1035
 * @param startComponent  the component the first of the maps refers to.
1036
 */
1037
   public void setTextureMap(Static4D[] maps, int startComponent)
1038
     {
1039
     if( mJobNode[0]==null )
1040
       {
1041
       textureMap(maps,startComponent);
1042
       }
1043
     else
1044
       {
1045
       mJobNode[0] = DeferredJobs.textureMap(this,maps,startComponent);
1046
       }
1047
     }
1048

    
1049
///////////////////////////////////////////////////////////////////////////////////////////////////
1050
/**
1051
 * Return the texture map of one of the components.
1052
 *
1053
 * @param component The component number whose texture map we want to retrieve.
1054
 */
1055
   public Static4D getTextureMap(int component)
1056
     {
1057
     return (component>=0 && component<mTexComponent.size()) ? mTexComponent.get(component).mTextureMap : null;
1058
     }
1059

    
1060
///////////////////////////////////////////////////////////////////////////////////////////////////
1061
/**
1062
 * Set Effect association.
1063
 *
1064
 * This creates an association between a Component of this Mesh and a Vertex Effect.
1065
 * One can set two types of associations - an 'logical and' and a 'equal' associations and the Effect
1066
 * will only be active on vertices of Components such that
1067
 *
1068
 * (effect andAssoc) & (component andAssoc) != 0 || (effect equAssoc) == (mesh equAssoc)
1069
 *
1070
 * (see main_vertex_shader)
1071
 *
1072
 * The point: this way we can configure the system so that each Vertex Effect acts only on a certain
1073
 * subset of a Mesh, thus potentially significantly reducing the number of render calls.
1074
 */
1075
   public void setEffectAssociation(int component, int andAssociation, int equAssociation)
1076
     {
1077
     if( component>=0 && component<MAX_EFFECT_COMPONENTS )
1078
       {
1079
       if( mJobNode[0]==null )
1080
         {
1081
         setEffectAssociationNow(component, andAssociation, equAssociation);
1082
         }
1083
       else
1084
         {
1085
         mJobNode[0] = DeferredJobs.effectAssoc(this,component,andAssociation,equAssociation);
1086
         }
1087
       }
1088
     }
1089

    
1090
///////////////////////////////////////////////////////////////////////////////////////////////////
1091
/**
1092
 * Copy the Mesh.
1093
 *
1094
 * @param deep If to be a deep or shallow copy of mVertAttribs1, i.e. the array holding vertices,
1095
 *             normals and inflates (the rest, in particular the mVertAttribs2 containing texture
1096
 *             coordinates and effect associations, is always deep copied)
1097
 */
1098
   public abstract MeshBase copy(boolean deep);
1099
   }
(2-2/9)