Project

General

Profile

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

library / src / main / java / org / distorted / library / mesh / MeshBase.java @ 0bd9f644

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.main.InternalBuffer;
29
import org.distorted.library.program.DistortedProgram;
30
import org.distorted.library.type.Static4D;
31

    
32
import java.io.DataOutputStream;
33
import java.io.IOException;
34
import java.io.DataInputStream;
35
import java.nio.ByteBuffer;
36
import java.nio.ByteOrder;
37
import java.nio.FloatBuffer;
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 UBO_BINDING = 1;
50
   private static final int MAX_EFFECT_COMPONENTS= 100;
51
   private static final int DEFAULT_ASSOCIATION = 0xffffffff;
52

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

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

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

    
70
   private static final int BYTES_PER_FLOAT = 4;
71

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

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

    
82
   private static int mAssociationSize = 8*MAX_EFFECT_COMPONENTS;
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 InternalBuffer mUBO;               // Uniform Buffer Object
87
   private int mNumVertices;
88
   private float[] mVertAttribs1;             // packed: PosX,PosY,PosZ, NorX,NorY,NorZ, InfX,InfY,InfZ
89
   private float[] mVertAttribs2;             // packed: TexS,TexT, Component
90
   private float mInflate;
91
   private int[] mAssociations;
92
   private int mAssociationBlock;
93
   private boolean mNeedAdjustAssociation;
94

    
95
   DeferredJobs.JobNode[] mJobNode;
96

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

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

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

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

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

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

    
129
///////////////////////////////////////////////////////////////////////////////////////////////////
130

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

    
138
     mNeedAdjustAssociation = true;
139
     mAssociationBlock = computeAssociationBlockSize();
140
     mAssociations= new int[mAssociationSize/4];
141

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

    
144
     for(int i=0; i<MAX_EFFECT_COMPONENTS; i++)
145
       {
146
       mAssociations[getAndIndex(i)] = DEFAULT_ASSOCIATION;
147
       mAssociations[getEquIndex(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
     mUBO = new InternalBuffer(GLES30.GL_UNIFORM_BUFFER           , GLES30.GL_STATIC_READ);
154
     }
155

    
156
///////////////////////////////////////////////////////////////////////////////////////////////////
157
// copy constructor
158

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

    
165
     mNeedAdjustAssociation = original.mNeedAdjustAssociation;
166
     mAssociationBlock = original.mAssociationBlock;
167

    
168
     int size = original.mAssociations.length;
169
     mAssociations= new int[size];
170
     System.arraycopy(original.mAssociations, 0, mAssociations, 0, size);
171

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

    
186
     mTFO = new InternalBuffer(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, GLES30.GL_STATIC_READ);
187
     mUBO = new InternalBuffer(GLES30.GL_UNIFORM_BUFFER           , GLES30.GL_STATIC_READ);
188
     }
189

    
190
///////////////////////////////////////////////////////////////////////////////////////////////////
191
/**
192
 * @y.exclude
193
 */
194
   public static void setAssociationSize(int size)
195
     {
196
     mAssociationSize = size;
197
     }
198

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

    
201
   private int getAndIndex(int component)
202
     {
203
     return mAssociationBlock*component;
204
     }
205

    
206
///////////////////////////////////////////////////////////////////////////////////////////////////
207

    
208
   private int getEquIndex(int component)
209
     {
210
     return mAssociationBlock*(MAX_EFFECT_COMPONENTS+component);
211
     }
212

    
213
///////////////////////////////////////////////////////////////////////////////////////////////////
214

    
215
   private int computeAssociationBlockSize()
216
     {
217
     return 1 + (mAssociationSize/4 - 2*MAX_EFFECT_COMPONENTS) / (2*MAX_EFFECT_COMPONENTS-1);
218
     }
219

    
220
///////////////////////////////////////////////////////////////////////////////////////////////////
221
// The problem here is that at MeshBase object creation time, we might not know the size of the
222
// 'meshAssociation' Uniform Block Object in the vertex shader (the UBO is packed according to the
223
// 'shared' layout, which means the size of the block is known only after linking the shaders).
224
//
225
// We thus, in the constructor, guess that the layout will be tight (so we will need 8*MAX_EFFECT_C
226
// bytes there), allocate mAssociation already, and if later on, as a result of linking the shaders,
227
// we get a call to setAssociationSize() which changes the size to something else, we need to reallocate.
228
//
229
// It can happen that even before the linking the value of mAssociationSize is already 'right' because
230
// this is a static variable and it might persist from an earlier run. All the better then; this should
231
// never be wrong.
232

    
233
   private void adjustAssociation()
234
     {
235
     int oldLen = mAssociations.length;
236

    
237
     if( mAssociationSize != 4*oldLen )
238
       {
239
       int[] tmp = new int[oldLen];
240
       System.arraycopy(mAssociations, 0, tmp, 0, oldLen);
241

    
242
       int newLen = mAssociationSize/4;
243
       mAssociations = new int[newLen];
244
       mAssociationBlock = computeAssociationBlockSize();
245

    
246
       for(int i=0; i<oldLen/2; i++)
247
         {
248
         mAssociations[getAndIndex(i)] = tmp[i];                         // oldLen must be equal to
249
         mAssociations[getEquIndex(i)] = tmp[MAX_EFFECT_COMPONENTS+i];   // 8*MAX_EFFECT_COM
250
         }
251
       }
252
     }
253

    
254
///////////////////////////////////////////////////////////////////////////////////////////////////
255

    
256
   void copy(MeshBase original)
257
     {
258
     shallowCopy(original);
259

    
260
     mVBO1= new InternalBuffer(GLES30.GL_ARRAY_BUFFER, GLES30.GL_STATIC_READ);
261
     mVertAttribs1= new float[mNumVertices*VERT1_ATTRIBS];
262
     System.arraycopy(original.mVertAttribs1,0,mVertAttribs1,0,mNumVertices*VERT1_ATTRIBS);
263
     mVBO1.invalidate();
264
     }
265

    
266
///////////////////////////////////////////////////////////////////////////////////////////////////
267

    
268
   private void shallowCopy(MeshBase original)
269
     {
270
     int texComSize = original.mTexComponent.size();
271
     mTexComponent = new ArrayList<>();
272

    
273
     for(int i=0; i<texComSize; i++)
274
       {
275
       TexComponent comp = new TexComponent(original.mTexComponent.get(i));
276
       mTexComponent.add(comp);
277
       }
278

    
279
     mEffComponent = new ArrayList<>();
280
     mEffComponent.addAll(original.mEffComponent);
281

    
282
     mVBO2= new InternalBuffer(GLES30.GL_ARRAY_BUFFER, GLES30.GL_STATIC_READ);
283
     mVertAttribs2= new float[mNumVertices*VERT2_ATTRIBS];
284
     System.arraycopy(original.mVertAttribs2,0,mVertAttribs2,0,mNumVertices*VERT2_ATTRIBS);
285
     mVBO2.invalidate();
286
     }
287

    
288
///////////////////////////////////////////////////////////////////////////////////////////////////
289

    
290
   void mergeTexComponentsNow()
291
     {
292
     int num = mTexComponent.size();
293

    
294
     if( num>1 )
295
       {
296
       mTexComponent.clear();
297
       mTexComponent.add(new TexComponent(mNumVertices-1));
298

    
299
       mVBO2.invalidate();
300
       }
301
     }
302

    
303
///////////////////////////////////////////////////////////////////////////////////////////////////
304

    
305
   void mergeEffComponentsNow()
306
     {
307
     int num = mEffComponent.size();
308

    
309
     if( num>1 )
310
       {
311
       mEffComponent.clear();
312
       mEffComponent.add(mNumVertices-1);
313

    
314
       for(int index=0; index<mNumVertices; index++)
315
         {
316
         mVertAttribs2[VERT2_ATTRIBS*index+COM_ATTRIB] = 0;
317
         }
318

    
319
       mVBO2.invalidate();
320
       }
321
     }
322

    
323
///////////////////////////////////////////////////////////////////////////////////////////////////
324

    
325
   void applyMatrix(MatrixEffect effect, int andAssoc, int equAssoc)
326
     {
327
     float[] matrixP  = new float[16];
328
     float[] matrixV  = new float[16];
329
     float[] uniforms = new float[7];
330
     int start, end=-1, numComp = mEffComponent.size();
331

    
332
     Matrix.setIdentityM(matrixP,0);
333
     Matrix.setIdentityM(matrixV,0);
334
     effect.compute(uniforms,0,0,0);
335
     effect.apply(matrixP, matrixV, uniforms, 0);
336

    
337
     for(int i=0; i<numComp; i++)
338
       {
339
       start = end+1;
340
       end   = mEffComponent.get(i);
341

    
342
       if( (andAssoc & mAssociations[getAndIndex(i)]) != 0 || (equAssoc == mAssociations[getEquIndex(i)]) )
343
         {
344
         applyMatrixToComponent(matrixP, matrixV, start, end);
345
         }
346
       }
347

    
348
     mVBO1.invalidate();
349
     }
350

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

    
353
   private void applyMatrixToComponent(float[] matrixP, float[] matrixV, int start, int end)
354
     {
355
     float x,y,z;
356

    
357
     for(int index=start*VERT1_ATTRIBS; index<=end*VERT1_ATTRIBS; index+=VERT1_ATTRIBS )
358
       {
359
       x = mVertAttribs1[index+POS_ATTRIB  ];
360
       y = mVertAttribs1[index+POS_ATTRIB+1];
361
       z = mVertAttribs1[index+POS_ATTRIB+2];
362

    
363
       mVertAttribs1[index+POS_ATTRIB  ] = matrixP[0]*x + matrixP[4]*y + matrixP[ 8]*z + matrixP[12];
364
       mVertAttribs1[index+POS_ATTRIB+1] = matrixP[1]*x + matrixP[5]*y + matrixP[ 9]*z + matrixP[13];
365
       mVertAttribs1[index+POS_ATTRIB+2] = matrixP[2]*x + matrixP[6]*y + matrixP[10]*z + matrixP[14];
366

    
367
       x = mVertAttribs1[index+NOR_ATTRIB  ];
368
       y = mVertAttribs1[index+NOR_ATTRIB+1];
369
       z = mVertAttribs1[index+NOR_ATTRIB+2];
370

    
371
       mVertAttribs1[index+NOR_ATTRIB  ] = matrixV[0]*x + matrixV[4]*y + matrixV[ 8]*z;
372
       mVertAttribs1[index+NOR_ATTRIB+1] = matrixV[1]*x + matrixV[5]*y + matrixV[ 9]*z;
373
       mVertAttribs1[index+NOR_ATTRIB+2] = matrixV[2]*x + matrixV[6]*y + matrixV[10]*z;
374

    
375
       x = mVertAttribs1[index+NOR_ATTRIB  ];
376
       y = mVertAttribs1[index+NOR_ATTRIB+1];
377
       z = mVertAttribs1[index+NOR_ATTRIB+2];
378

    
379
       float len1 = (float)Math.sqrt(x*x + y*y + z*z);
380

    
381
       if( len1>0.0f )
382
         {
383
         mVertAttribs1[index+NOR_ATTRIB  ] /= len1;
384
         mVertAttribs1[index+NOR_ATTRIB+1] /= len1;
385
         mVertAttribs1[index+NOR_ATTRIB+2] /= len1;
386
         }
387

    
388
       x = mVertAttribs1[index+INF_ATTRIB  ];
389
       y = mVertAttribs1[index+INF_ATTRIB+1];
390
       z = mVertAttribs1[index+INF_ATTRIB+2];
391

    
392
       mVertAttribs1[index+INF_ATTRIB  ] = matrixV[0]*x + matrixV[4]*y + matrixV[ 8]*z;
393
       mVertAttribs1[index+INF_ATTRIB+1] = matrixV[1]*x + matrixV[5]*y + matrixV[ 9]*z;
394
       mVertAttribs1[index+INF_ATTRIB+2] = matrixV[2]*x + matrixV[6]*y + matrixV[10]*z;
395

    
396
       x = mVertAttribs1[index+INF_ATTRIB  ];
397
       y = mVertAttribs1[index+INF_ATTRIB+1];
398
       z = mVertAttribs1[index+INF_ATTRIB+2];
399

    
400
       float len2 = (float)Math.sqrt(x*x + y*y + z*z);
401

    
402
       if( len2>0.0f )
403
         {
404
         mVertAttribs1[index+INF_ATTRIB  ] /= len2;
405
         mVertAttribs1[index+INF_ATTRIB+1] /= len2;
406
         mVertAttribs1[index+INF_ATTRIB+2] /= len2;
407
         }
408
       }
409
     }
410

    
411
///////////////////////////////////////////////////////////////////////////////////////////////////
412

    
413
   void setEffectAssociationNow(int component, int andAssociation, int equAssociation)
414
     {
415
     mAssociations[getAndIndex(component)] = andAssociation;
416
     mAssociations[getEquIndex(component)] = equAssociation;
417

    
418
     mUBO.invalidate();
419
     }
420

    
421
///////////////////////////////////////////////////////////////////////////////////////////////////
422
// when a derived class is done computing its mesh, it has to call this method.
423

    
424
   void setAttribs(float[] vert1Attribs, float[] vert2Attribs)
425
     {
426
     mNumVertices = vert1Attribs.length/VERT1_ATTRIBS;
427
     mVertAttribs1= vert1Attribs;
428
     mVertAttribs2= vert2Attribs;
429

    
430
     mTexComponent.add(new TexComponent(mNumVertices-1));
431
     mEffComponent.add(mNumVertices-1);
432

    
433
     mVBO1.invalidate();
434
     mVBO2.invalidate();
435
     }
436

    
437
///////////////////////////////////////////////////////////////////////////////////////////////////
438

    
439
   void joinAttribs(MeshBase[] meshes)
440
     {
441
     MeshBase mesh;
442
     TexComponent comp;
443
     int numMeshes = meshes.length;
444
     int numVertices,origVertices = mNumVertices;
445
     int origTexComponents,numTexComponents;
446
     int origEffComponents=0,numEffComponents;
447

    
448
     if( origVertices>0 )
449
       {
450
       origTexComponents = mTexComponent.size();
451
       mNumVertices+= ( mNumVertices%2==1 ? 2:1 );
452
       mTexComponent.get(origTexComponents-1).mEndIndex = mNumVertices-1;
453
       origEffComponents = mEffComponent.size();
454
       mEffComponent.set(origEffComponents-1,mNumVertices-1);
455
       }
456

    
457
     for(int i=0; i<numMeshes; i++)
458
       {
459
       mesh = meshes[i];
460
       numTexComponents = mesh.mTexComponent.size();
461
       numEffComponents = mesh.mEffComponent.size();
462
       numVertices = mesh.mNumVertices;
463

    
464
       int extraVerticesBefore = mNumVertices==0 ? 0:1;
465
       int extraVerticesAfter  = (i==numMeshes-1) ? 0 : (numVertices%2==1 ? 2:1);
466

    
467
       for(int j=0; j<numTexComponents; j++)
468
         {
469
         comp = new TexComponent(mesh.mTexComponent.get(j));
470
         comp.mEndIndex += (extraVerticesBefore+mNumVertices);
471
         if( j==numTexComponents-1) comp.mEndIndex += extraVerticesAfter;
472
         mTexComponent.add(comp);
473
         }
474

    
475
       for(int j=0; j<numEffComponents; j++)
476
         {
477
         int index = mesh.mEffComponent.get(j);
478
         index += (extraVerticesBefore+mNumVertices);
479
         if( j==numEffComponents-1 ) index += extraVerticesAfter;
480
         mEffComponent.add(index);
481

    
482
         if( origEffComponents<MAX_EFFECT_COMPONENTS )
483
           {
484
           mAssociations[getAndIndex(origEffComponents)] = mesh.mAssociations[mesh.getAndIndex(j)];
485
           mAssociations[getEquIndex(origEffComponents)] = mesh.mAssociations[mesh.getEquIndex(j)];
486
           origEffComponents++;
487
           }
488
         }
489

    
490
       mNumVertices += (extraVerticesBefore+numVertices+extraVerticesAfter);
491
       }
492

    
493
     float[] newAttribs1 = new float[VERT1_ATTRIBS*mNumVertices];
494
     float[] newAttribs2 = new float[VERT2_ATTRIBS*mNumVertices];
495
     numVertices = origVertices;
496

    
497
     if( origVertices>0 )
498
       {
499
       System.arraycopy(mVertAttribs1,                              0, newAttribs1,                          0, VERT1_ATTRIBS*numVertices);
500
       System.arraycopy(mVertAttribs1, VERT1_ATTRIBS*(origVertices-1), newAttribs1, VERT1_ATTRIBS*origVertices, VERT1_ATTRIBS            );
501
       System.arraycopy(mVertAttribs2,                              0, newAttribs2,                          0, VERT2_ATTRIBS*numVertices);
502
       System.arraycopy(mVertAttribs2, VERT2_ATTRIBS*(origVertices-1), newAttribs2, VERT2_ATTRIBS*origVertices, VERT2_ATTRIBS            );
503
       origVertices++;
504

    
505
       if( numVertices%2==1 )
506
         {
507
         System.arraycopy(mVertAttribs1, VERT1_ATTRIBS*(origVertices-1), newAttribs1, VERT1_ATTRIBS*origVertices, VERT1_ATTRIBS);
508
         System.arraycopy(mVertAttribs2, VERT2_ATTRIBS*(origVertices-1), newAttribs2, VERT2_ATTRIBS*origVertices, VERT2_ATTRIBS);
509
         origVertices++;
510
         }
511
       }
512

    
513
     for(int i=0; i<numMeshes; i++)
514
       {
515
       mesh = meshes[i];
516
       numVertices = mesh.mNumVertices;
517

    
518
       if( origVertices>0 )
519
         {
520
         System.arraycopy(mesh.mVertAttribs1, 0, newAttribs1, VERT1_ATTRIBS*origVertices, VERT1_ATTRIBS);
521
         System.arraycopy(mesh.mVertAttribs2, 0, newAttribs2, VERT2_ATTRIBS*origVertices, VERT2_ATTRIBS);
522
         origVertices++;
523
         }
524
       System.arraycopy(mesh.mVertAttribs1, 0, newAttribs1, VERT1_ATTRIBS*origVertices, VERT1_ATTRIBS*numVertices);
525
       System.arraycopy(mesh.mVertAttribs2, 0, newAttribs2, VERT2_ATTRIBS*origVertices, VERT2_ATTRIBS*numVertices);
526
       origVertices+=numVertices;
527

    
528
       if( i<numMeshes-1 )
529
         {
530
         System.arraycopy(mesh.mVertAttribs1, VERT1_ATTRIBS*(numVertices-1), newAttribs1, VERT1_ATTRIBS*origVertices, VERT1_ATTRIBS);
531
         System.arraycopy(mesh.mVertAttribs2, VERT2_ATTRIBS*(numVertices-1), newAttribs2, VERT2_ATTRIBS*origVertices, VERT2_ATTRIBS);
532
         origVertices++;
533

    
534
         if( numVertices%2==1 )
535
           {
536
           System.arraycopy(mesh.mVertAttribs1, VERT1_ATTRIBS*(numVertices-1), newAttribs1, VERT1_ATTRIBS*origVertices, VERT1_ATTRIBS);
537
           System.arraycopy(mesh.mVertAttribs2, VERT2_ATTRIBS*(numVertices-1), newAttribs2, VERT2_ATTRIBS*origVertices, VERT2_ATTRIBS);
538
           origVertices++;
539
           }
540
         }
541
       }
542

    
543
     if( origVertices!=mNumVertices )
544
       {
545
       android.util.Log.e("mesh", "join: origVertices: "+origVertices+" numVertices: "+mNumVertices);
546
       }
547

    
548
     int endIndex, index=0, numEffComp = mEffComponent.size();
549

    
550
     for(int component=0; component<numEffComp; component++)
551
       {
552
       endIndex = mEffComponent.get(component);
553

    
554
       for( ; index<=endIndex; index++) newAttribs2[VERT2_ATTRIBS*index+COM_ATTRIB] = component;
555
       }
556

    
557
     mVertAttribs1 = newAttribs1;
558
     mVertAttribs2 = newAttribs2;
559
     mVBO1.invalidate();
560
     mVBO2.invalidate();
561
     }
562

    
563
///////////////////////////////////////////////////////////////////////////////////////////////////
564
// called from MeshJoined
565

    
566
   void join(MeshBase[] meshes)
567
     {
568
     boolean immediateJoin = true;
569

    
570
     for (MeshBase mesh : meshes)
571
       {
572
       if (mesh.mJobNode[0] != null)
573
         {
574
         immediateJoin = false;
575
         break;
576
         }
577
       }
578

    
579
     if( immediateJoin ) joinAttribs(meshes);
580
     else                mJobNode[0] = DeferredJobs.join(this,meshes);
581
     }
582

    
583
///////////////////////////////////////////////////////////////////////////////////////////////////
584

    
585
   void textureMap(Static4D[] maps, int startComponent)
586
     {
587
     int num_comp = mTexComponent.size();
588
     int num_maps = maps.length;
589
     int min = Math.min(num_comp-startComponent, num_maps);
590
     int vertex = startComponent>0 ? mTexComponent.get(startComponent-1).mEndIndex+1 : 0;
591
     Static4D newMap, oldMap;
592
     TexComponent comp;
593
     float newW, newH, ratW, ratH, movX, movY;
594

    
595
     for(int i=0; i<min; i++)
596
       {
597
       newMap = maps[i];
598
       comp = mTexComponent.get(i+startComponent);
599

    
600
       if( newMap!=null )
601
         {
602
         newW = newMap.get2();
603
         newH = newMap.get3();
604

    
605
         if( newW!=0.0f && newH!=0.0f )
606
           {
607
           oldMap = comp.mTextureMap;
608
           ratW = newW/oldMap.get2();
609
           ratH = newH/oldMap.get3();
610
           movX = newMap.get0() - ratW*oldMap.get0();
611
           movY = newMap.get1() - ratH*oldMap.get1();
612

    
613
           for( int index=vertex*VERT2_ATTRIBS+TEX_ATTRIB ; vertex<=comp.mEndIndex; vertex++, index+=VERT2_ATTRIBS)
614
             {
615
             mVertAttribs2[index  ] = ratW*mVertAttribs2[index  ] + movX;
616
             mVertAttribs2[index+1] = ratH*mVertAttribs2[index+1] + movY;
617
             }
618
           comp.setMap(newMap);
619
           }
620
         }
621

    
622
       vertex= comp.mEndIndex+1;
623
       }
624

    
625
     mVBO2.invalidate();
626
     }
627

    
628
///////////////////////////////////////////////////////////////////////////////////////////////////
629

    
630
   public static int getMaxEffComponents()
631
     {
632
     return MAX_EFFECT_COMPONENTS;
633
     }
634

    
635
///////////////////////////////////////////////////////////////////////////////////////////////////
636
/**
637
 * Not part of public API, do not document (public only because has to be used from the main package)
638
 *
639
 * @y.exclude
640
 */
641
   public void copyTransformToVertex()
642
     {
643
     ByteBuffer buffer = (ByteBuffer)GLES30.glMapBufferRange( GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0,
644
                                                              TRAN_SIZE*mNumVertices, GLES30.GL_MAP_READ_BIT);
645
     if( buffer!=null )
646
       {
647
       FloatBuffer feedback = buffer.order(ByteOrder.nativeOrder()).asFloatBuffer();
648
       feedback.get(mVertAttribs1,0,VERT1_ATTRIBS*mNumVertices);
649
       mVBO1.updateFloat(mVertAttribs1);
650
       }
651
     else
652
       {
653
       int error = GLES30.glGetError();
654
       Log.e("mesh", "failed to map tf buffer, error="+error);
655
       }
656

    
657
     GLES30.glUnmapBuffer(GLES30.GL_TRANSFORM_FEEDBACK);
658
     }
659

    
660
///////////////////////////////////////////////////////////////////////////////////////////////////
661
/**
662
 * Not part of public API, do not document (public only because has to be used from the main package)
663
 *
664
 * @y.exclude
665
 */
666
   public void debug()
667
     {
668
     if( mJobNode[0]!=null )
669
       {
670
       mJobNode[0].print(0);
671
       }
672
     else
673
       {
674
       android.util.Log.e("mesh", "JobNode null");
675
       }
676
     }
677

    
678
///////////////////////////////////////////////////////////////////////////////////////////////////
679
/**
680
 * Not part of public API, do not document (public only because has to be used from the main package)
681
 *
682
 * @y.exclude
683
 */
684
   public void printPos()
685
     {
686
     StringBuilder sb = new StringBuilder();
687

    
688
     for(int i=0; i<mNumVertices; i++)
689
       {
690
       sb.append('(');
691
       sb.append(mVertAttribs1[VERT1_ATTRIBS*i+POS_ATTRIB  ]);
692
       sb.append(',');
693
       sb.append(mVertAttribs1[VERT1_ATTRIBS*i+POS_ATTRIB+1]);
694
       sb.append(',');
695
       sb.append(mVertAttribs1[VERT1_ATTRIBS*i+POS_ATTRIB+2]);
696
       sb.append(") ");
697
       }
698
     Log.d("mesh", sb.toString());
699
     }
700

    
701
///////////////////////////////////////////////////////////////////////////////////////////////////
702
/**
703
 * Not part of public API, do not document (public only because has to be used from the main package)
704
 *
705
 * @y.exclude
706
 */
707
   public void printCom()
708
     {
709
     StringBuilder sb = new StringBuilder();
710

    
711
     for(int i=0; i<mNumVertices; i++)
712
       {
713
       sb.append(mVertAttribs2[VERT2_ATTRIBS*i+COM_ATTRIB]);
714
       sb.append(' ');
715
       }
716

    
717
     Log.d("mesh", sb.toString());
718
     }
719

    
720
///////////////////////////////////////////////////////////////////////////////////////////////////
721
/**
722
 * Not part of public API, do not document (public only because has to be used from the main package)
723
 *
724
 * @y.exclude
725
 */
726
   public void printTex()
727
     {
728
     int vert=0;
729
     int num = numTexComponents();
730
     StringBuilder sb = new StringBuilder();
731
     sb.append("tex components: ").append(num);
732

    
733
     for(int i=0; i<num; i++)
734
       {
735
       int end = mTexComponent.get(i).mEndIndex;
736
       sb.append("\n");
737

    
738
       for( ; vert<=end; vert++)
739
         {
740
         sb.append(' ');
741
         sb.append('(');
742
         sb.append(mVertAttribs2[VERT2_ATTRIBS*vert+TEX_ATTRIB]);
743
         sb.append(',');
744
         sb.append(mVertAttribs2[VERT2_ATTRIBS*vert+TEX_ATTRIB+1]);
745
         sb.append(')');
746
         }
747
       }
748

    
749
     Log.d("mesh", sb.toString());
750
     }
751

    
752
///////////////////////////////////////////////////////////////////////////////////////////////////
753
/**
754
 * Not part of public API, do not document (public only because has to be used from the main package)
755
 *
756
 * @y.exclude
757
 */
758
   public int getTFO()
759
     {
760
     return mTFO.createImmediatelyFloat(mNumVertices*TRAN_SIZE, null);
761
     }
762

    
763
///////////////////////////////////////////////////////////////////////////////////////////////////
764
/**
765
 * Not part of public API, do not document (public only because has to be used from the main package)
766
 *
767
 * @y.exclude
768
 */
769
   public int getNumVertices()
770
     {
771
     return mNumVertices;
772
     }
773

    
774
///////////////////////////////////////////////////////////////////////////////////////////////////
775
/**
776
 * Not part of public API, do not document (public only because has to be used from the main package)
777
 *
778
 * @y.exclude
779
 */
780
   public void send(int programH)
781
     {
782
     if( mNeedAdjustAssociation )
783
       {
784
       mNeedAdjustAssociation = false;
785
       adjustAssociation();
786
       }
787

    
788
     int index = mUBO.createImmediatelyInt( mAssociationSize, mAssociations);
789

    
790
     GLES30.glBindBufferBase(GLES30.GL_UNIFORM_BUFFER, UBO_BINDING, index);
791
     GLES30.glUniformBlockBinding(programH, UBO_BINDING, index);
792
     }
793

    
794
///////////////////////////////////////////////////////////////////////////////////////////////////
795
/**
796
 * Not part of public API, do not document (public only because has to be used from the main package)
797
 *
798
 * @y.exclude
799
 */
800
   public void bindVertexAttribs(DistortedProgram program)
801
     {
802
     if( mJobNode[0]!=null )
803
       {
804
       mJobNode[0].execute();  // this will set itself to null
805
/*
806
       try
807
         {
808
         String name = "/sdcard/"+mNumVertices+".dmesh";
809
         DataOutputStream dos = new DataOutputStream(new FileOutputStream(name));
810
         write(dos);
811
         android.util.Log.e("mesh", "file written: "+name);
812
         }
813
       catch(FileNotFoundException ex)
814
         {
815
         android.util.Log.e("mesh", "file not found exception: "+ex.toString());
816
         }
817
 */
818
       }
819

    
820
     int index1 = mVBO1.createImmediatelyFloat(mNumVertices*VERT1_SIZE, mVertAttribs1);
821
     int index2 = mVBO2.createImmediatelyFloat(mNumVertices*VERT2_SIZE, mVertAttribs2);
822

    
823
     GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, index1 );
824
     GLES30.glVertexAttribPointer(program.mAttribute[0], POS_DATA_SIZE, GLES30.GL_FLOAT, false, VERT1_SIZE, OFFSET_POS);
825
     GLES30.glVertexAttribPointer(program.mAttribute[1], NOR_DATA_SIZE, GLES30.GL_FLOAT, false, VERT1_SIZE, OFFSET_NOR);
826
     GLES30.glVertexAttribPointer(program.mAttribute[2], INF_DATA_SIZE, GLES30.GL_FLOAT, false, VERT1_SIZE, OFFSET_INF);
827
     GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, index2 );
828
     GLES30.glVertexAttribPointer(program.mAttribute[3], TEX_DATA_SIZE, GLES30.GL_FLOAT, false, VERT2_SIZE, OFFSET_TEX);
829
     GLES30.glVertexAttribPointer(program.mAttribute[4], COM_DATA_SIZE, GLES30.GL_FLOAT, false, VERT2_SIZE, OFFSET_COM);
830
     GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0);
831
     }
832

    
833
///////////////////////////////////////////////////////////////////////////////////////////////////
834
/**
835
 * Not part of public API, do not document (public only because has to be used from the main package)
836
 *
837
 * @y.exclude
838
 */
839
   public void bindTransformAttribs(DistortedProgram program)
840
     {
841
     int index = mTFO.createImmediatelyFloat(mNumVertices*TRAN_SIZE, null);
842

    
843
     GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, index );
844
     GLES30.glVertexAttribPointer(program.mAttribute[0], POS_DATA_SIZE, GLES30.GL_FLOAT, false, 0, 0);
845
     GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0);
846
     }
847

    
848
///////////////////////////////////////////////////////////////////////////////////////////////////
849
/**
850
 * Not part of public API, do not document (public only because has to be used from the main package)
851
 *
852
 * @y.exclude
853
 */
854
   public void setInflate(float inflate)
855
     {
856
     mInflate = inflate;
857
     }
858

    
859
///////////////////////////////////////////////////////////////////////////////////////////////////
860
/**
861
 * Not part of public API, do not document (public only because has to be used from the main package)
862
 *
863
 * @y.exclude
864
 */
865
   public float getInflate()
866
     {
867
     return mInflate;
868
     }
869

    
870
///////////////////////////////////////////////////////////////////////////////////////////////////
871
// Return the number of bytes read.
872

    
873
   int read(DataInputStream stream)
874
     {
875
     byte[] buffer = new byte[BYTES_PER_FLOAT*4];
876
     int version, numEff, numTex;
877

    
878
     try
879
       {
880
       stream.read(buffer);
881
       ByteBuffer byteBuf = ByteBuffer.wrap(buffer);
882

    
883
       version = byteBuf.getInt(0);
884

    
885
       if( version==1 )
886
         {
887
         mNumVertices= byteBuf.getInt(4);
888
         numTex      = byteBuf.getInt(8);
889
         numEff      = byteBuf.getInt(12);
890
         }
891
       else
892
         {
893
         android.util.Log.e("mesh", "Error: unknown mesh file version "+String.format("0x%08X", version));
894
         return 0;
895
         }
896
       }
897
     catch(IOException e)
898
       {
899
       android.util.Log.e("mesh", "IOException1 trying to read file: "+e.toString());
900
       return 0;
901
       }
902

    
903
     if( mNumVertices>0 && numEff>0 && numTex>0 )
904
       {
905
       int size = numEff+TEX_COMP_SIZE*numTex;
906
       float[] tmp = new float[size];
907
       mVertAttribs1 = new float[VERT1_ATTRIBS*mNumVertices];
908
       mVertAttribs2 = new float[VERT2_ATTRIBS*mNumVertices];
909

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

    
912
       try
913
         {
914
         stream.read(buffer);
915
         }
916
       catch(IOException e)
917
         {
918
         android.util.Log.e("mesh", "IOException2 trying to read file: "+e.toString());
919
         return 0;
920
         }
921

    
922
       ByteBuffer byteBuf = ByteBuffer.wrap(buffer);
923
       FloatBuffer floatBuf = byteBuf.asFloatBuffer();
924

    
925
       floatBuf.get(tmp,0,size);
926
       floatBuf.get(mVertAttribs1, 0, VERT1_ATTRIBS*mNumVertices);
927
       floatBuf.get(mVertAttribs2, 0, VERT2_ATTRIBS*mNumVertices);
928

    
929
       TexComponent tex;
930
       int index, texComp;
931
       float x, y, z, w;
932

    
933
       for(texComp=0; texComp<numTex; texComp++)
934
         {
935
         index = (int)tmp[TEX_COMP_SIZE*texComp];
936

    
937
         x= tmp[TEX_COMP_SIZE*texComp+1];
938
         y= tmp[TEX_COMP_SIZE*texComp+2];
939
         z= tmp[TEX_COMP_SIZE*texComp+3];
940
         w= tmp[TEX_COMP_SIZE*texComp+4];
941

    
942
         tex = new TexComponent(index);
943
         tex.setMap(new Static4D(x,y,z,w));
944

    
945
         mTexComponent.add(tex);
946
         }
947

    
948
       for(int effComp=0; effComp<numEff; effComp++)
949
         {
950
         index = (int)tmp[TEX_COMP_SIZE*texComp + effComp ];
951
         mEffComponent.add(index);
952
         }
953
       }
954

    
955
     return BYTES_PER_FLOAT*( 4 + numEff+TEX_COMP_SIZE*numTex + VERT1_ATTRIBS*mNumVertices + VERT2_ATTRIBS*mNumVertices );
956
     }
957

    
958
///////////////////////////////////////////////////////////////////////////////////////////////////
959
/**
960
 * @y.exclude
961
 */
962
   public int getLastVertexEff(int effComponent)
963
     {
964
     if( effComponent>=0 && effComponent<mTexComponent.size() )
965
       {
966
       return mEffComponent.get(effComponent);
967
       }
968

    
969
     return 0;
970
     }
971

    
972
///////////////////////////////////////////////////////////////////////////////////////////////////
973
/**
974
 * @y.exclude
975
 */
976
   public int getLastVertexTex(int texComponent)
977
     {
978
     if( texComponent>=0 && texComponent<mTexComponent.size() )
979
       {
980
       return mTexComponent.get(texComponent).mEndIndex;
981
       }
982

    
983
     return 0;
984
     }
985

    
986
///////////////////////////////////////////////////////////////////////////////////////////////////
987
// PUBLIC API
988
///////////////////////////////////////////////////////////////////////////////////////////////////
989
/**
990
 * Write the Mesh to a File.
991
 */
992
   public void write(DataOutputStream stream)
993
     {
994
     TexComponent tex;
995

    
996
     int numTex = mTexComponent.size();
997
     int numEff = mEffComponent.size();
998

    
999
     try
1000
       {
1001
       stream.writeInt(1);  // version
1002
       stream.writeInt(mNumVertices);
1003
       stream.writeInt(numTex);
1004
       stream.writeInt(numEff);
1005

    
1006
       for(int i=0; i<numTex; i++)
1007
         {
1008
         tex = mTexComponent.get(i);
1009

    
1010
         stream.writeFloat((float)tex.mEndIndex);
1011
         stream.writeFloat(tex.mTextureMap.get0());
1012
         stream.writeFloat(tex.mTextureMap.get1());
1013
         stream.writeFloat(tex.mTextureMap.get2());
1014
         stream.writeFloat(tex.mTextureMap.get3());
1015
         }
1016

    
1017
       for(int i=0; i<numEff; i++)
1018
         {
1019
         stream.writeFloat((float)mEffComponent.get(i));
1020
         }
1021

    
1022
       ByteBuffer vertBuf1 = ByteBuffer.allocate(VERT1_SIZE*mNumVertices);
1023
       vertBuf1.asFloatBuffer().put(mVertAttribs1);
1024
       ByteBuffer vertBuf2 = ByteBuffer.allocate(VERT2_SIZE*mNumVertices);
1025
       vertBuf2.asFloatBuffer().put(mVertAttribs2);
1026

    
1027
       stream.write(vertBuf1.array());
1028
       stream.write(vertBuf2.array());
1029
       }
1030
     catch(IOException ex)
1031
       {
1032
       android.util.Log.e("mesh", "IOException trying to write a mesh: "+ex.toString());
1033
       }
1034
     }
1035

    
1036
///////////////////////////////////////////////////////////////////////////////////////////////////
1037
/**
1038
 * When rendering this Mesh, do we want to render the Normal vectors as well?
1039
 * <p>
1040
 * Will work only on OpenGL ES >= 3.0 devices.
1041
 *
1042
 * @param show Controls if we render the Normal vectors or not.
1043
 */
1044
   public void setShowNormals(boolean show)
1045
     {
1046
     mShowNormals = show;
1047
     }
1048

    
1049
///////////////////////////////////////////////////////////////////////////////////////////////////
1050
/**
1051
 * When rendering this mesh, should we also draw the normal vectors?
1052
 *
1053
 * @return <i>true</i> if we do render normal vectors
1054
 */
1055
   public boolean getShowNormals()
1056
     {
1057
     return mShowNormals;
1058
     }
1059

    
1060
///////////////////////////////////////////////////////////////////////////////////////////////////
1061
/**
1062
 * Merge all texture components of this Mesh into a single one.
1063
 */
1064
   public void mergeTexComponents()
1065
     {
1066
     if( mJobNode[0]==null )
1067
       {
1068
       mergeTexComponentsNow();
1069
       }
1070
     else
1071
       {
1072
       mJobNode[0] = DeferredJobs.mergeTex(this);
1073
       }
1074
     }
1075

    
1076
///////////////////////////////////////////////////////////////////////////////////////////////////
1077
/**
1078
 * Merge all effect components of this Mesh into a single one.
1079
 */
1080
   public void mergeEffComponents()
1081
     {
1082
     if( mJobNode[0]==null )
1083
       {
1084
       mergeEffComponentsNow();
1085
       }
1086
     else
1087
       {
1088
       mJobNode[0] = DeferredJobs.mergeEff(this);
1089
       }
1090
     }
1091

    
1092
///////////////////////////////////////////////////////////////////////////////////////////////////
1093
/**
1094
 * Release all internal resources.
1095
 */
1096
   public void markForDeletion()
1097
     {
1098
     mVertAttribs1 = null;
1099
     mVertAttribs2 = null;
1100

    
1101
     mVBO1.markForDeletion();
1102
     mVBO2.markForDeletion();
1103
     mTFO.markForDeletion();
1104
     }
1105

    
1106
///////////////////////////////////////////////////////////////////////////////////////////////////
1107
/**
1108
 * Apply a Matrix Effect to the components which match the (addAssoc,equAssoc) association.
1109
 * <p>
1110
 * This is a static, permanent modification of the vertices contained in this Mesh. If the effect
1111
 * contains any Dynamics, they will be evaluated at 0.
1112
 *
1113
 * @param effect List of Matrix Effects to apply to the Mesh.
1114
 * @param andAssoc 'Logical AND' association which defines which components will be affected.
1115
 * @param equAssoc 'equality' association which defines which components will be affected.
1116
 */
1117
   public void apply(MatrixEffect effect, int andAssoc, int equAssoc)
1118
     {
1119
     if( mJobNode[0]==null )
1120
       {
1121
       applyMatrix(effect,andAssoc,equAssoc);
1122
       }
1123
     else
1124
       {
1125
       mJobNode[0] = DeferredJobs.matrix(this,effect,andAssoc,equAssoc);
1126
       }
1127
     }
1128

    
1129
///////////////////////////////////////////////////////////////////////////////////////////////////
1130
/**
1131
 * Apply a Vertex Effect to the vertex mesh.
1132
 * <p>
1133
 * This is a static, permanent modification of the vertices contained in this Mesh. If the effects
1134
 * contain any Dynamics, the Dynamics will be evaluated at 0.
1135
 *
1136
 * We would call this several times building up a list of Effects to do. This list of effects gets
1137
 * lazily executed only when the Mesh is used for rendering for the first time.
1138
 *
1139
 * @param effect Vertex Effect to apply to the Mesh.
1140
 */
1141
   public void apply(VertexEffect effect)
1142
     {
1143
     mJobNode[0] = DeferredJobs.vertex(this,effect);
1144
     }
1145

    
1146
///////////////////////////////////////////////////////////////////////////////////////////////////
1147
/**
1148
 * Sets texture maps for (some of) the components of this mesh.
1149
 * <p>
1150
 * Format: ( x of lower-left corner, y of lower-left corner, width, height ).
1151
 * For example maps[0] = new Static4D( 0.0, 0.5, 0.5, 0.5 ) sets the 0th component texture map to the
1152
 * upper-left quadrant of the texture.
1153
 * <p>
1154
 * Probably the most common user case would be sending as many maps as there are components in this
1155
 * Mesh. One can also send less, or more (the extraneous ones will be ignored) and set some of them
1156
 * to null (those will be ignored as well). So if there are 5 components, and we want to set the map
1157
 * of the 2nd and 4rd one, call this with
1158
 * maps = new Static4D[4]
1159
 * maps[0] = null
1160
 * maps[1] = the map for the 2nd component
1161
 * maps[2] = null
1162
 * maps[3] = the map for the 4th component
1163
 *
1164
 * A map's width and height have to be non-zero (but can be negative!)
1165
 *
1166
 * @param maps            List of texture maps to apply to the texture's components.
1167
 * @param startComponent  the component the first of the maps refers to.
1168
 */
1169
   public void setTextureMap(Static4D[] maps, int startComponent)
1170
     {
1171
     if( mJobNode[0]==null )
1172
       {
1173
       textureMap(maps,startComponent);
1174
       }
1175
     else
1176
       {
1177
       mJobNode[0] = DeferredJobs.textureMap(this,maps,startComponent);
1178
       }
1179
     }
1180

    
1181
///////////////////////////////////////////////////////////////////////////////////////////////////
1182
/**
1183
 * Return the texture map of one of the components.
1184
 *
1185
 * @param component The component number whose texture map we want to retrieve.
1186
 */
1187
   public Static4D getTextureMap(int component)
1188
     {
1189
     return (component>=0 && component<mTexComponent.size()) ? mTexComponent.get(component).mTextureMap : null;
1190
     }
1191

    
1192
///////////////////////////////////////////////////////////////////////////////////////////////////
1193
/**
1194
 * Set Effect association.
1195
 *
1196
 * This creates an association between a Component of this Mesh and a Vertex Effect.
1197
 * One can set two types of associations - an 'logical and' and a 'equal' associations and the Effect
1198
 * will only be active on vertices of Components such that
1199
 *
1200
 * (effect andAssoc) & (component andAssoc) != 0 || (effect equAssoc) == (mesh equAssoc)
1201
 *
1202
 * (see main_vertex_shader)
1203
 *
1204
 * The point: this way we can configure the system so that each Vertex Effect acts only on a certain
1205
 * subset of a Mesh, thus potentially significantly reducing the number of render calls.
1206
 */
1207
   public void setEffectAssociation(int component, int andAssociation, int equAssociation)
1208
     {
1209
     if( component>=0 && component<MAX_EFFECT_COMPONENTS )
1210
       {
1211
       if( mJobNode[0]==null )
1212
         {
1213
         setEffectAssociationNow(component, andAssociation, equAssociation);
1214
         }
1215
       else
1216
         {
1217
         mJobNode[0] = DeferredJobs.effectAssoc(this,component,andAssociation,equAssociation);
1218
         }
1219
       }
1220
     }
1221

    
1222
///////////////////////////////////////////////////////////////////////////////////////////////////
1223
/**
1224
 * Return the number of texture components, i.e. individual subsets of the whole set of vertices
1225
 * which can be independently textured.
1226
 *
1227
 * @return The number of Texture Components of this Mesh.
1228
 */
1229
   public int numTexComponents()
1230
     {
1231
     return mTexComponent.size();
1232
     }
1233

    
1234
///////////////////////////////////////////////////////////////////////////////////////////////////
1235
/**
1236
 * Return the number of 'effect' components, i.e. individual subsets of the whole set of vertices
1237
 * to which a VertexEffect can be addressed, independently of other vertices.
1238
 *
1239
 * @return The number of Effect Components of this Mesh.
1240
 */
1241
   public int numEffComponents()
1242
     {
1243
     return mEffComponent.size();
1244
     }
1245

    
1246
///////////////////////////////////////////////////////////////////////////////////////////////////
1247
/**
1248
 * Copy the Mesh.
1249
 *
1250
 * @param deep If to be a deep or shallow copy of mVertAttribs1, i.e. the array holding vertices,
1251
 *             normals and inflates (the rest, in particular the mVertAttribs2 containing texture
1252
 *             coordinates and effect associations, is always deep copied)
1253
 */
1254
   public abstract MeshBase copy(boolean deep);
1255
   }
(2-2/9)