Project

General

Profile

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

library / src / main / java / org / distorted / library / mesh / MeshBase.java @ bc2ab8c5

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.DataOutputStream;
34
import java.io.FileNotFoundException;
35
import java.io.FileOutputStream;
36
import java.io.IOException;
37
import java.io.DataInputStream;
38
import java.nio.ByteBuffer;
39
import java.nio.ByteOrder;
40
import java.nio.FloatBuffer;
41
import java.util.ArrayList;
42

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

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

    
62
   static final int POS_ATTRIB   = 0;
63
   static final int NOR_ATTRIB   = POS_DATA_SIZE;
64
   static final int INF_ATTRIB   = POS_DATA_SIZE + NOR_DATA_SIZE;
65
   static final int TEX_ATTRIB   = 0;
66
   static final int COM_ATTRIB   = TEX_DATA_SIZE;
67

    
68
   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)
69
   static final int VERT2_ATTRIBS= TEX_DATA_SIZE + COM_DATA_SIZE;                  // number of attributes of a vertex (the 'preapply invariant' part)
70
   static final int TRAN_ATTRIBS = POS_DATA_SIZE + NOR_DATA_SIZE + INF_DATA_SIZE;  // number of attributes of a transform feedback vertex
71

    
72
   private static final int BYTES_PER_FLOAT = 4;
73

    
74
   private static final int OFFSET_POS = POS_ATTRIB*BYTES_PER_FLOAT;
75
   private static final int OFFSET_NOR = NOR_ATTRIB*BYTES_PER_FLOAT;
76
   private static final int OFFSET_INF = INF_ATTRIB*BYTES_PER_FLOAT;
77
   private static final int OFFSET_TEX = TEX_ATTRIB*BYTES_PER_FLOAT;
78
   private static final int OFFSET_COM = COM_ATTRIB*BYTES_PER_FLOAT;
79

    
80
   private static final int TRAN_SIZE  = TRAN_ATTRIBS*BYTES_PER_FLOAT;
81
   private static final int VERT1_SIZE = VERT1_ATTRIBS*BYTES_PER_FLOAT;
82
   private static final int VERT2_SIZE = VERT2_ATTRIBS*BYTES_PER_FLOAT;
83

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

    
93
   DeferredJobs.JobNode[] mJobNode;
94

    
95
   private static int[] mEquAssociationH = new int[EffectQueue.MAIN_VARIANTS];
96
   private static int[] mAndAssociationH = new int[EffectQueue.MAIN_VARIANTS];
97

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

    
100
   private static class TexComponent
101
     {
102
     private int mEndIndex;
103
     private Static4D mTextureMap;
104

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

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

    
121
     void setMap(Static4D map)
122
       {
123
       mTextureMap.set(map.get0(),map.get1(),map.get2(),map.get3());
124
       }
125
     }
126

    
127
   private ArrayList<TexComponent> mTexComponent;
128
   private ArrayList<Integer> mEffComponent;
129

    
130
///////////////////////////////////////////////////////////////////////////////////////////////////
131

    
132
   MeshBase()
133
     {
134
     mShowNormals  = false;
135
     mInflate      = 0.0f;
136
     mTexComponent = new ArrayList<>();
137
     mEffComponent = new ArrayList<>();
138

    
139
     mEquAssociation= new int[MAX_EFFECT_COMPONENTS];
140
     mAndAssociation= new int[MAX_EFFECT_COMPONENTS];
141

    
142
     mJobNode = new DeferredJobs.JobNode[1];
143

    
144
     for(int i=0; i<MAX_EFFECT_COMPONENTS; i++)
145
       {
146
       mAndAssociation[i] = DEFAULT_ASSOCIATION;
147
       mEquAssociation[i] = i;
148
       }
149

    
150
     mVBO1= new InternalBuffer(GLES30.GL_ARRAY_BUFFER             , GLES30.GL_STATIC_READ);
151
     mVBO2= new InternalBuffer(GLES30.GL_ARRAY_BUFFER             , GLES30.GL_STATIC_READ);
152
     mTFO = new InternalBuffer(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, GLES30.GL_STATIC_READ);
153
     }
154

    
155
///////////////////////////////////////////////////////////////////////////////////////////////////
156
// copy constructor
157

    
158
   MeshBase(MeshBase original, boolean deep)
159
     {
160
     mShowNormals= original.mShowNormals;
161
     mInflate    = original.mInflate;
162
     mNumVertices= original.mNumVertices;
163

    
164
     mAndAssociation= new int[MAX_EFFECT_COMPONENTS];
165
     System.arraycopy(original.mAndAssociation, 0, mAndAssociation, 0, MAX_EFFECT_COMPONENTS);
166
     mEquAssociation= new int[MAX_EFFECT_COMPONENTS];
167
     System.arraycopy(original.mEquAssociation, 0, mEquAssociation, 0, MAX_EFFECT_COMPONENTS);
168

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

    
183
     mTFO = new InternalBuffer(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, GLES30.GL_STATIC_READ);
184
     mTFO.invalidate();
185
     }
186

    
187
///////////////////////////////////////////////////////////////////////////////////////////////////
188

    
189
   void copy(MeshBase original)
190
     {
191
     shallowCopy(original);
192

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

    
199
///////////////////////////////////////////////////////////////////////////////////////////////////
200

    
201
   private void shallowCopy(MeshBase original)
202
     {
203
     int texComSize = original.mTexComponent.size();
204
     mTexComponent = new ArrayList<>();
205

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

    
212
     mEffComponent = new ArrayList<>();
213
     mEffComponent.addAll(original.mEffComponent);
214

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

    
221
///////////////////////////////////////////////////////////////////////////////////////////////////
222

    
223
   void mergeTexComponentsNow()
224
     {
225
     int num = mTexComponent.size();
226

    
227
     if( num>1 )
228
       {
229
       mTexComponent.clear();
230
       mTexComponent.add(new TexComponent(mNumVertices-1));
231

    
232
       mVBO2.invalidate();
233
       }
234
     }
235

    
236
///////////////////////////////////////////////////////////////////////////////////////////////////
237

    
238
   void mergeEffComponentsNow()
239
     {
240
     int num = mEffComponent.size();
241

    
242
     if( num>1 )
243
       {
244
       mEffComponent.clear();
245
       mEffComponent.add(mNumVertices-1);
246

    
247
       for(int index=0; index<mNumVertices; index++)
248
         {
249
         mVertAttribs2[VERT2_ATTRIBS*index+COM_ATTRIB] = 0;
250
         }
251

    
252
       mVBO2.invalidate();
253
       }
254
     }
255

    
256
///////////////////////////////////////////////////////////////////////////////////////////////////
257

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

    
264
     Matrix.setIdentityM(matrix,0);
265
     effect.compute(uniforms,0,0,0);
266
     effect.apply(matrix, uniforms, 0);
267

    
268
     for(int i=0; i<numComp; i++)
269
       {
270
       start = end+1;
271
       end   = mEffComponent.get(i);
272

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

    
279
     mVBO1.invalidate();
280
     }
281

    
282
///////////////////////////////////////////////////////////////////////////////////////////////////
283

    
284
   private void applyMatrixToComponent(float[] matrix, int start, int end)
285
     {
286
     float x,y,z;
287

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

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

    
298
       x = mVertAttribs1[index+NOR_ATTRIB  ];
299
       y = mVertAttribs1[index+NOR_ATTRIB+1];
300
       z = mVertAttribs1[index+NOR_ATTRIB+2];
301

    
302
       mVertAttribs1[index+NOR_ATTRIB  ] = matrix[0]*x + matrix[4]*y + matrix[ 8]*z;
303
       mVertAttribs1[index+NOR_ATTRIB+1] = matrix[1]*x + matrix[5]*y + matrix[ 9]*z;
304
       mVertAttribs1[index+NOR_ATTRIB+2] = matrix[2]*x + matrix[6]*y + matrix[10]*z;
305

    
306
       x = mVertAttribs1[index+INF_ATTRIB  ];
307
       y = mVertAttribs1[index+INF_ATTRIB+1];
308
       z = mVertAttribs1[index+INF_ATTRIB+2];
309

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

    
316
///////////////////////////////////////////////////////////////////////////////////////////////////
317

    
318
   void setEffectAssociationNow(int component, int andAssociation, int equAssociation)
319
     {
320
     mAndAssociation[component] = andAssociation;
321
     mEquAssociation[component] = equAssociation;
322
     }
323

    
324
///////////////////////////////////////////////////////////////////////////////////////////////////
325

    
326
   int numTexComponents()
327
     {
328
     return mTexComponent.size();
329
     }
330

    
331
///////////////////////////////////////////////////////////////////////////////////////////////////
332

    
333
   int numEffComponents()
334
     {
335
     return mEffComponent.size();
336
     }
337

    
338
///////////////////////////////////////////////////////////////////////////////////////////////////
339
// when a derived class is done computing its mesh, it has to call this method.
340

    
341
   void setAttribs(float[] vert1Attribs, float[] vert2Attribs)
342
     {
343
     mNumVertices = vert1Attribs.length/VERT1_ATTRIBS;
344
     mVertAttribs1= vert1Attribs;
345
     mVertAttribs2= vert2Attribs;
346

    
347
     mTexComponent.add(new TexComponent(mNumVertices-1));
348
     mEffComponent.add(mNumVertices-1);
349

    
350
     mVBO1.invalidate();
351
     mVBO2.invalidate();
352
     }
353

    
354
///////////////////////////////////////////////////////////////////////////////////////////////////
355

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

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

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

    
381
       int extraVerticesBefore = mNumVertices==0 ? 0:1;
382
       int extraVerticesAfter  = (i==numMeshes-1) ? 0 : (numVertices%2==1 ? 2:1);
383

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

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

    
399
         if( origEffComponents<MAX_EFFECT_COMPONENTS )
400
           {
401
           mAndAssociation[origEffComponents] = mesh.mAndAssociation[j];
402
           mEquAssociation[origEffComponents] = mesh.mEquAssociation[j];
403
           origEffComponents++;
404
           }
405
         }
406

    
407
       mNumVertices += (extraVerticesBefore+numVertices+extraVerticesAfter);
408
       }
409

    
410
     float[] newAttribs1 = new float[VERT1_ATTRIBS*mNumVertices];
411
     float[] newAttribs2 = new float[VERT2_ATTRIBS*mNumVertices];
412
     numVertices = origVertices;
413

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

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

    
430
     for(int i=0; i<numMeshes; i++)
431
       {
432
       mesh = meshes[i];
433
       numVertices = mesh.mNumVertices;
434

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

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

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

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

    
465
     int endIndex, index=0, numEffComp = mEffComponent.size();
466

    
467
     for(int component=0; component<numEffComp; component++)
468
       {
469
       endIndex = mEffComponent.get(component);
470

    
471
       for( ; index<=endIndex; index++) newAttribs2[VERT2_ATTRIBS*index+COM_ATTRIB] = component;
472
       }
473

    
474
     mVertAttribs1 = newAttribs1;
475
     mVertAttribs2 = newAttribs2;
476
     mVBO1.invalidate();
477
     mVBO2.invalidate();
478
     }
479

    
480
///////////////////////////////////////////////////////////////////////////////////////////////////
481
// called from MeshJoined
482

    
483
   void join(MeshBase[] meshes)
484
     {
485
     boolean immediateJoin = true;
486

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

    
496
     if( immediateJoin ) joinAttribs(meshes);
497
     else                mJobNode[0] = DeferredJobs.join(this,meshes);
498
     }
499

    
500
///////////////////////////////////////////////////////////////////////////////////////////////////
501

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

    
512
     for(int i=0; i<min; i++)
513
       {
514
       newMap = maps[i];
515
       comp = mTexComponent.get(i+startComponent);
516

    
517
       if( newMap!=null )
518
         {
519
         newW = newMap.get2();
520
         newH = newMap.get3();
521

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

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

    
539
       vertex= comp.mEndIndex+1;
540
       }
541

    
542
     mVBO2.invalidate();
543
     }
544

    
545
///////////////////////////////////////////////////////////////////////////////////////////////////
546

    
547
   public static int getMaxEffComponents()
548
     {
549
     return MAX_EFFECT_COMPONENTS;
550
     }
551

    
552
///////////////////////////////////////////////////////////////////////////////////////////////////
553

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

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

    
582
     GLES30.glUnmapBuffer(GLES30.GL_TRANSFORM_FEEDBACK);
583
     }
584

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

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

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

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

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

    
642
     Log.d("mesh", sb.toString());
643
     }
644

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

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

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

    
674
     Log.d("mesh", sb.toString());
675
     }
676

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

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

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

    
711
///////////////////////////////////////////////////////////////////////////////////////////////////
712
/**
713
 * Not part of public API, do not document (public only because has to be used from the main package)
714
 *
715
 * @y.exclude
716
 */
717
   public void bindVertexAttribs(DistortedProgram program)
718
     {
719
     if( mJobNode[0]!=null )
720
       {
721
       mJobNode[0].execute();  // this will set itself to null
722
/*
723
       try
724
         {
725
         String name = "/sdcard/"+mNumVertices+".dmesh";
726
         DataOutputStream dos = new DataOutputStream(new FileOutputStream(name));
727
         write(dos);
728
         android.util.Log.e("mesh", "file wrritten: "+name);
729
         }
730
       catch(FileNotFoundException ex)
731
         {
732
         android.util.Log.e("mesh", "file not found exception: "+ex.toString());
733
         }
734
 */
735
       }
736

    
737
     int index1 = mVBO1.createImmediately(mNumVertices*VERT1_SIZE, mVertAttribs1);
738
     int index2 = mVBO2.createImmediately(mNumVertices*VERT2_SIZE, mVertAttribs2);
739

    
740
     GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, index1 );
741
     GLES30.glVertexAttribPointer(program.mAttribute[0], POS_DATA_SIZE, GLES30.GL_FLOAT, false, VERT1_SIZE, OFFSET_POS);
742
     GLES30.glVertexAttribPointer(program.mAttribute[1], NOR_DATA_SIZE, GLES30.GL_FLOAT, false, VERT1_SIZE, OFFSET_NOR);
743
     GLES30.glVertexAttribPointer(program.mAttribute[2], INF_DATA_SIZE, GLES30.GL_FLOAT, false, VERT1_SIZE, OFFSET_INF);
744
     GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, index2 );
745
     GLES30.glVertexAttribPointer(program.mAttribute[3], TEX_DATA_SIZE, GLES30.GL_FLOAT, false, VERT2_SIZE, OFFSET_TEX);
746
     GLES30.glVertexAttribPointer(program.mAttribute[4], COM_DATA_SIZE, GLES30.GL_FLOAT, false, VERT2_SIZE, OFFSET_COM);
747
     GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0);
748
     }
749

    
750
///////////////////////////////////////////////////////////////////////////////////////////////////
751
/**
752
 * Not part of public API, do not document (public only because has to be used from the main package)
753
 *
754
 * @y.exclude
755
 */
756
   public void bindTransformAttribs(DistortedProgram program)
757
     {
758
     int index = mTFO.createImmediately(mNumVertices*TRAN_SIZE, null);
759

    
760
     GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, index );
761
     GLES30.glVertexAttribPointer(program.mAttribute[0], POS_DATA_SIZE, GLES30.GL_FLOAT, false, 0, 0);
762
     GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0);
763
     }
764

    
765
///////////////////////////////////////////////////////////////////////////////////////////////////
766
/**
767
 * Not part of public API, do not document (public only because has to be used from the main package)
768
 *
769
 * @y.exclude
770
 */
771
   public void setInflate(float inflate)
772
     {
773
     mInflate = inflate;
774
     }
775

    
776
///////////////////////////////////////////////////////////////////////////////////////////////////
777
/**
778
 * Not part of public API, do not document (public only because has to be used from the main package)
779
 *
780
 * @y.exclude
781
 */
782
   public float getInflate()
783
     {
784
     return mInflate;
785
     }
786

    
787
///////////////////////////////////////////////////////////////////////////////////////////////////
788

    
789
   void read(DataInputStream stream)
790
     {
791
     byte[] buffer = new byte[BYTES_PER_FLOAT*4];
792
     int version, numEff, numTex;
793

    
794
     try
795
       {
796
       stream.read(buffer);
797
       ByteBuffer byteBuf = ByteBuffer.wrap(buffer);
798

    
799
       version = byteBuf.getInt(0);
800

    
801
       if( version==1 )
802
         {
803
         mNumVertices= byteBuf.getInt(4);
804
         numTex      = byteBuf.getInt(8);
805
         numEff      = byteBuf.getInt(12);
806

    
807
    //     android.util.Log.e("mesh", "version: "+version+" vert: "+mNumVertices+" numTex: "+numTex+" numEff: "+numEff);
808
         }
809
       else
810
         {
811
         android.util.Log.e("mesh", "Error: unknown mesh file version "+String.format("0x%08X", version));
812
         return;
813
         }
814
       }
815
     catch(IOException e)
816
       {
817
       android.util.Log.e("mesh", "IOException1 trying to read file: "+e.toString());
818
       return;
819
       }
820

    
821
     if( mNumVertices>0 && numEff>0 && numTex>0 )
822
       {
823
       int size = numEff+TEX_COMP_SIZE*numTex;
824
       float[] tmp = new float[size];
825
       mVertAttribs1 = new float[VERT1_ATTRIBS*mNumVertices];
826
       mVertAttribs2 = new float[VERT2_ATTRIBS*mNumVertices];
827

    
828
       buffer = new byte[BYTES_PER_FLOAT*(size + mNumVertices*(VERT1_ATTRIBS+VERT2_ATTRIBS))];
829

    
830
       try
831
         {
832
         stream.read(buffer);
833
         }
834
       catch(IOException e)
835
         {
836
         android.util.Log.e("mesh", "IOException2 trying to read file: "+e.toString());
837
         return;
838
         }
839

    
840

    
841
       ByteBuffer byteBuf = ByteBuffer.wrap(buffer);
842
       FloatBuffer floatBuf = byteBuf.asFloatBuffer();
843

    
844
       floatBuf.get(tmp,0,size);
845

    
846
/*
847
for(int f=0; f<size; f++)
848
  {
849
  android.util.Log.e("mesh", "tmp "+f+": "+tmp[f]);
850
  }
851
*/
852

    
853
       floatBuf.get(mVertAttribs1, 0, VERT1_ATTRIBS*mNumVertices);
854
       floatBuf.get(mVertAttribs2, 0, VERT2_ATTRIBS*mNumVertices);
855
/*
856
for(int f=0; f<mNumVertices; f++)
857
  {
858
  android.util.Log.e("mesh", "vert "+f+": "+mVertAttribs1[9*f]+" "+mVertAttribs1[9*f+1]+" "+mVertAttribs1[9*f+2]+"   "+mVertAttribs1[9*f+3]+" "+mVertAttribs1[9*f+4]+" "+mVertAttribs1[9*f+5]+"   "+mVertAttribs1[9*f+6]+" "+mVertAttribs1[9*f+7]+" "+mVertAttribs1[9*f+8]);
859
  }
860
*/
861
       TexComponent tex;
862
       int index, texComp;
863
       float x, y, z, w;
864

    
865
       for(texComp=0; texComp<numTex; texComp++)
866
         {
867
         index = (int)tmp[TEX_COMP_SIZE*texComp];
868

    
869
         x= tmp[TEX_COMP_SIZE*texComp+1];
870
         y= tmp[TEX_COMP_SIZE*texComp+2];
871
         z= tmp[TEX_COMP_SIZE*texComp+3];
872
         w= tmp[TEX_COMP_SIZE*texComp+4];
873

    
874
//android.util.Log.e("mesh", "tex comp "+texComp+" index="+index+" x="+x+" y="+y+" z="+z+" w="+w);
875

    
876
         tex = new TexComponent(index);
877
         tex.setMap(new Static4D(x,y,z,w));
878

    
879
         mTexComponent.add(tex);
880
         }
881

    
882
       for(int effComp=0; effComp<numEff; effComp++)
883
         {
884
         index = (int)tmp[TEX_COMP_SIZE*texComp + effComp ];
885
         mEffComponent.add(index);
886

    
887

    
888
//android.util.Log.e("mesh", "eff comp "+effComp+" index="+index);
889

    
890
         }
891
       }
892
     }
893

    
894
///////////////////////////////////////////////////////////////////////////////////////////////////
895
// PUBLIC API
896
///////////////////////////////////////////////////////////////////////////////////////////////////
897
/**
898
 * Write the Mesh to a File.
899
 */
900
   public void write(DataOutputStream stream)
901
     {
902
     TexComponent tex;
903

    
904
     int numTex = mTexComponent.size();
905
     int numEff = mEffComponent.size();
906

    
907
     try
908
       {
909
       stream.writeInt(1);  // version
910
       stream.writeInt(mNumVertices);
911
       stream.writeInt(numTex);
912
       stream.writeInt(numEff);
913

    
914
       for(int i=0; i<numTex; i++)
915
         {
916
         tex = mTexComponent.get(i);
917

    
918
         stream.writeFloat((float)tex.mEndIndex);
919
         stream.writeFloat(tex.mTextureMap.get0());
920
         stream.writeFloat(tex.mTextureMap.get1());
921
         stream.writeFloat(tex.mTextureMap.get2());
922
         stream.writeFloat(tex.mTextureMap.get3());
923
         }
924

    
925
       for(int i=0; i<numEff; i++)
926
         {
927
         stream.writeFloat((float)mEffComponent.get(i));
928
         }
929

    
930
       ByteBuffer vertBuf1 = ByteBuffer.allocate(VERT1_SIZE*mNumVertices);
931
       vertBuf1.asFloatBuffer().put(mVertAttribs1);
932
       ByteBuffer vertBuf2 = ByteBuffer.allocate(VERT2_SIZE*mNumVertices);
933
       vertBuf2.asFloatBuffer().put(mVertAttribs2);
934

    
935
       stream.write(vertBuf1.array());
936
       stream.write(vertBuf2.array());
937
       }
938
     catch(IOException ex)
939
       {
940
       android.util.Log.e("mesh", "IOException trying to write a mesh: "+ex.toString());
941
       }
942
     }
943

    
944
///////////////////////////////////////////////////////////////////////////////////////////////////
945
/**
946
 * When rendering this Mesh, do we want to render the Normal vectors as well?
947
 * <p>
948
 * Will work only on OpenGL ES >= 3.0 devices.
949
 *
950
 * @param show Controls if we render the Normal vectors or not.
951
 */
952
   public void setShowNormals(boolean show)
953
     {
954
     mShowNormals = show;
955
     }
956

    
957
///////////////////////////////////////////////////////////////////////////////////////////////////
958
/**
959
 * When rendering this mesh, should we also draw the normal vectors?
960
 *
961
 * @return <i>true</i> if we do render normal vectors
962
 */
963
   public boolean getShowNormals()
964
     {
965
     return mShowNormals;
966
     }
967

    
968
///////////////////////////////////////////////////////////////////////////////////////////////////
969
/**
970
 * Merge all texture components of this Mesh into a single one.
971
 */
972
   public void mergeTexComponents()
973
     {
974
     if( mJobNode[0]==null )
975
       {
976
       mergeTexComponentsNow();
977
       }
978
     else
979
       {
980
       mJobNode[0] = DeferredJobs.mergeTex(this);
981
       }
982
     }
983

    
984
///////////////////////////////////////////////////////////////////////////////////////////////////
985
/**
986
 * Merge all effect components of this Mesh into a single one.
987
 */
988
   public void mergeEffComponents()
989
     {
990
     if( mJobNode[0]==null )
991
       {
992
       mergeEffComponentsNow();
993
       }
994
     else
995
       {
996
       mJobNode[0] = DeferredJobs.mergeEff(this);
997
       }
998
     }
999

    
1000
///////////////////////////////////////////////////////////////////////////////////////////////////
1001
/**
1002
 * Release all internal resources.
1003
 */
1004
   public void markForDeletion()
1005
     {
1006
     mVertAttribs1 = null;
1007
     mVertAttribs2 = null;
1008

    
1009
     mVBO1.markForDeletion();
1010
     mVBO2.markForDeletion();
1011
     mTFO.markForDeletion();
1012
     }
1013

    
1014
///////////////////////////////////////////////////////////////////////////////////////////////////
1015
/**
1016
 * Apply a Matrix Effect to the components which match the (addAssoc,equAssoc) association.
1017
 * <p>
1018
 * This is a static, permanent modification of the vertices contained in this Mesh. If the effect
1019
 * contains any Dynamics, they will be evaluated at 0.
1020
 *
1021
 * @param effect List of Matrix Effects to apply to the Mesh.
1022
 * @param andAssoc 'Logical AND' association which defines which components will be affected.
1023
 * @param equAssoc 'equality' association which defines which components will be affected.
1024
 */
1025
   public void apply(MatrixEffect effect, int andAssoc, int equAssoc)
1026
     {
1027
     if( mJobNode[0]==null )
1028
       {
1029
       applyMatrix(effect,andAssoc,equAssoc);
1030
       }
1031
     else
1032
       {
1033
       mJobNode[0] = DeferredJobs.matrix(this,effect,andAssoc,equAssoc);
1034
       }
1035
     }
1036

    
1037
///////////////////////////////////////////////////////////////////////////////////////////////////
1038
/**
1039
 * Apply a Vertex Effect to the vertex mesh.
1040
 * <p>
1041
 * This is a static, permanent modification of the vertices contained in this Mesh. If the effects
1042
 * contain any Dynamics, the Dynamics will be evaluated at 0.
1043
 *
1044
 * We would call this several times building up a list of Effects to do. This list of effects gets
1045
 * lazily executed only when the Mesh is used for rendering for the first time.
1046
 *
1047
 * @param effect Vertex Effect to apply to the Mesh.
1048
 */
1049
   public void apply(VertexEffect effect)
1050
     {
1051
     mJobNode[0] = DeferredJobs.vertex(this,effect);
1052
     }
1053

    
1054
///////////////////////////////////////////////////////////////////////////////////////////////////
1055
/**
1056
 * Sets texture maps for (some of) the components of this mesh.
1057
 * <p>
1058
 * Format: ( x of lower-left corner, y of lower-left corner, width, height ).
1059
 * For example maps[0] = new Static4D( 0.0, 0.5, 0.5, 0.5 ) sets the 0th component texture map to the
1060
 * upper-left quadrant of the texture.
1061
 * <p>
1062
 * Probably the most common user case would be sending as many maps as there are components in this
1063
 * Mesh. One can also send less, or more (the extraneous ones will be ignored) and set some of them
1064
 * to null (those will be ignored as well). So if there are 5 components, and we want to set the map
1065
 * of the 2nd and 4rd one, call this with
1066
 * maps = new Static4D[4]
1067
 * maps[0] = null
1068
 * maps[1] = the map for the 2nd component
1069
 * maps[2] = null
1070
 * maps[3] = the map for the 4th component
1071
 *
1072
 * A map's width and height have to be non-zero (but can be negative!)
1073
 *
1074
 * @param maps            List of texture maps to apply to the texture's components.
1075
 * @param startComponent  the component the first of the maps refers to.
1076
 */
1077
   public void setTextureMap(Static4D[] maps, int startComponent)
1078
     {
1079
     if( mJobNode[0]==null )
1080
       {
1081
       textureMap(maps,startComponent);
1082
       }
1083
     else
1084
       {
1085
       mJobNode[0] = DeferredJobs.textureMap(this,maps,startComponent);
1086
       }
1087
     }
1088

    
1089
///////////////////////////////////////////////////////////////////////////////////////////////////
1090
/**
1091
 * Return the texture map of one of the components.
1092
 *
1093
 * @param component The component number whose texture map we want to retrieve.
1094
 */
1095
   public Static4D getTextureMap(int component)
1096
     {
1097
     return (component>=0 && component<mTexComponent.size()) ? mTexComponent.get(component).mTextureMap : null;
1098
     }
1099

    
1100
///////////////////////////////////////////////////////////////////////////////////////////////////
1101
/**
1102
 * Set Effect association.
1103
 *
1104
 * This creates an association between a Component of this Mesh and a Vertex Effect.
1105
 * One can set two types of associations - an 'logical and' and a 'equal' associations and the Effect
1106
 * will only be active on vertices of Components such that
1107
 *
1108
 * (effect andAssoc) & (component andAssoc) != 0 || (effect equAssoc) == (mesh equAssoc)
1109
 *
1110
 * (see main_vertex_shader)
1111
 *
1112
 * The point: this way we can configure the system so that each Vertex Effect acts only on a certain
1113
 * subset of a Mesh, thus potentially significantly reducing the number of render calls.
1114
 */
1115
   public void setEffectAssociation(int component, int andAssociation, int equAssociation)
1116
     {
1117
     if( component>=0 && component<MAX_EFFECT_COMPONENTS )
1118
       {
1119
       if( mJobNode[0]==null )
1120
         {
1121
         setEffectAssociationNow(component, andAssociation, equAssociation);
1122
         }
1123
       else
1124
         {
1125
         mJobNode[0] = DeferredJobs.effectAssoc(this,component,andAssociation,equAssociation);
1126
         }
1127
       }
1128
     }
1129

    
1130
///////////////////////////////////////////////////////////////////////////////////////////////////
1131
/**
1132
 * Copy the Mesh.
1133
 *
1134
 * @param deep If to be a deep or shallow copy of mVertAttribs1, i.e. the array holding vertices,
1135
 *             normals and inflates (the rest, in particular the mVertAttribs2 containing texture
1136
 *             coordinates and effect associations, is always deep copied)
1137
 */
1138
   public abstract MeshBase copy(boolean deep);
1139
   }
(2-2/9)