Project

General

Profile

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

examples / src / main / java / org / distorted / examples / meshfile / FactoryCubit.java @ 140f2c4e

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube 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
// Magic Cube 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 Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.examples.meshfile;
21

    
22
import org.distorted.library.effect.VertexEffect;
23
import org.distorted.library.effect.VertexEffectDeform;
24
import org.distorted.library.effect.VertexEffectMove;
25
import org.distorted.library.effect.VertexEffectQuaternion;
26
import org.distorted.library.effect.VertexEffectScale;
27
import org.distorted.library.mesh.MeshBase;
28
import org.distorted.library.mesh.MeshJoined;
29
import org.distorted.library.mesh.MeshPolygon;
30
import org.distorted.library.type.Static1D;
31
import org.distorted.library.type.Static3D;
32
import org.distorted.library.type.Static4D;
33

    
34
import java.util.ArrayList;
35

    
36
///////////////////////////////////////////////////////////////////////////////////////////////////
37

    
38
class FactoryCubit
39
  {
40
  static final float SQ5   = (float)Math.sqrt(5);
41
  static final float SIN18 = (SQ5-1)/4;
42
  static final float COS18 = (float)(0.25f*Math.sqrt(10.0f+2.0f*SQ5));
43

    
44
  private static final float[] mBuffer = new float[3];
45
  private static final float[] mQuat1  = new float[4];
46
  private static final float[] mQuat2  = new float[4];
47
  private static final float[] mQuat3  = new float[4];
48

    
49
  private static final Static1D RADIUS = new Static1D(1);
50

    
51
  private static FactoryCubit mThis;
52

    
53
  private static class FaceInfo
54
    {
55
    float[] vertices;
56
    float vx,vy,vz;
57
    float scale;
58
    float qx,qy,qz,qw;
59
    boolean flip;
60
    }
61

    
62
  private static final ArrayList<FaceInfo> mFaceInfo = new ArrayList<>();
63

    
64
///////////////////////////////////////////////////////////////////////////////////////////////////
65

    
66
  private FactoryCubit()
67
    {
68

    
69
    }
70

    
71
///////////////////////////////////////////////////////////////////////////////////////////////////
72

    
73
  public static FactoryCubit getInstance()
74
    {
75
    if( mThis==null ) mThis = new FactoryCubit();
76

    
77
    return mThis;
78
    }
79

    
80
///////////////////////////////////////////////////////////////////////////////////////////////////
81
// H - height of the band in the middle
82
// alpha - angle of the edge  [0,90]
83
// dist - often in a polygon the distance from edge to center is not 1, but something else.
84
// This is the distance.
85
// K - where to begin the second, much more flat part of the band. [0,1]
86
// N - number of bands. N>=3
87
//
88
// theory: two distinct parts to the band:
89
// 1) (0,B) - steep
90
// 2) (B,1) - flat
91
//
92
// In first part, we have y = g(x) ; in second - y = g(f(x)) where
93
//
94
// g(x) = sqrt( R^2 - (x-D)^2 ) - R*cos(alpha)
95
// f(x) = ((D-B)/(1-B)*x + B*(1-D)/(1-B)
96
// h(x) = R*(sin(alpha) - sin(x))
97
// R = H/(1-cos(alpha))
98
// D = H*sin(alpha)
99
// B = h(K*alpha)
100
//
101
// The N points are taken at:
102
//
103
// 1) in the second part, there are K2 = (N-3)/3 such points
104
// 2) in the first - K1 = (N-3) - K2
105
// 3) also, the 3 points 0,B,1
106
//
107
// so we have the sequence A[i] of N points
108
//
109
// 0
110
// h((i+1)*(1-K)*alpha/(K1+1)) (i=0,1,...,K1-1)
111
// B
112
// (1-B)*(i+1)/(K2+1) + B   (i=0,i,...,K2-1)
113
// 1
114

    
115
///////////////////////////////////////////////////////////////////////////////////////////////////
116

    
117
  private float f(float D, float B, float x)
118
    {
119
    return ((D-B)*x + B*(1-D))/(1-B);
120
    }
121

    
122
///////////////////////////////////////////////////////////////////////////////////////////////////
123

    
124
  private float g(float R, float D, float x, float cosAlpha)
125
    {
126
    float d = x-D;
127
    return (float)(Math.sqrt(R*R-d*d)-R*cosAlpha);
128
    }
129

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

    
132
  private float h(float R, float sinAlpha, float x)
133
    {
134
    return R*(sinAlpha-(float)Math.sin(x));
135
    }
136

    
137
///////////////////////////////////////////////////////////////////////////////////////////////////
138

    
139
  float[] computeBands(float H, int alpha, float dist, float K, int N)
140
    {
141
    float[] bands = new float[2*N];
142

    
143
    bands[0] = 1.0f;
144
    bands[1] = 0.0f;
145

    
146
    float beta = (float)Math.atan(dist*Math.tan(Math.PI*alpha/180));
147
    float sinBeta = (float)Math.sin(beta);
148
    float cosBeta = (float)Math.cos(beta);
149
    float R = cosBeta<1.0f ? H/(1.0f-cosBeta) : 0.0f;
150
    float D = R*sinBeta;
151
    float B = h(R,sinBeta,K*beta);
152

    
153
    if( D>1.0f )
154
      {
155
      for(int i=1; i<N; i++)
156
        {
157
        bands[2*i  ] = (float)(N-1-i)/(N-1);
158
        bands[2*i+1] = H*(1-bands[2*i]);
159
        }
160
      }
161
    else
162
      {
163
      int K2 = (int)((N-3)*K);
164
      int K1 = (N-3)-K2;
165

    
166
      for(int i=0; i<=K1; i++)
167
        {
168
        float angle = K*beta + (1-K)*beta*(K1-i)/(K1+1);
169
        float x = h(R,sinBeta,angle);
170
        bands[2*i+2] = 1.0f - x;
171
        bands[2*i+3] = g(R,D,x,cosBeta);
172
        }
173

    
174
      for(int i=0; i<=K2; i++)
175
        {
176
        float x = (1-B)*(i+1)/(K2+1) + B;
177
        bands[2*K1+2 + 2*i+2] = 1.0f - x;
178
        bands[2*K1+2 + 2*i+3] = g(R,D,f(D,B,x),cosBeta);
179
        }
180
      }
181

    
182
    bands[2*N-2] = 0.0f;
183
    bands[2*N-1] =    H;
184

    
185
    return bands;
186
    }
187

    
188
///////////////////////////////////////////////////////////////////////////////////////////////////
189

    
190
  private void roundCorners(MeshBase mesh, Static3D center, Static3D[] vertices, float strength, float regionRadius)
191
    {
192
    Static4D reg= new Static4D(0,0,0,regionRadius);
193

    
194
    float centX = center.get0();
195
    float centY = center.get1();
196
    float centZ = center.get2();
197

    
198
    for (Static3D vertex : vertices)
199
      {
200
      float x = strength*(centX - vertex.get0());
201
      float y = strength*(centY - vertex.get1());
202
      float z = strength*(centZ - vertex.get2());
203

    
204
      VertexEffect effect = new VertexEffectDeform(new Static3D(x,y,z), RADIUS, vertex, reg);
205
      mesh.apply(effect);
206
      }
207
    }
208

    
209
///////////////////////////////////////////////////////////////////////////////////////////////////
210

    
211
  private boolean areColinear(float[][] vertices, int index1, int index2, int index3)
212
    {
213
    float x1 = vertices[index1][0];
214
    float y1 = vertices[index1][1];
215
    float z1 = vertices[index1][2];
216
    float x2 = vertices[index2][0];
217
    float y2 = vertices[index2][1];
218
    float z2 = vertices[index2][2];
219
    float x3 = vertices[index3][0];
220
    float y3 = vertices[index3][1];
221
    float z3 = vertices[index3][2];
222

    
223
    float v1x = x2-x1;
224
    float v1y = y2-y1;
225
    float v1z = z2-z1;
226
    float v2x = x3-x1;
227
    float v2y = y3-y1;
228
    float v2z = z3-z1;
229

    
230
    float A = (float)Math.sqrt( (v1x*v1x+v1y*v1y+v1z*v1z) / (v2x*v2x+v2y*v2y+v2z*v2z) );
231

    
232
//android.util.Log.e("D", "("+x1+","+y1+","+z1+") , ("+x2+","+y2+","+z2+") , ("+x3+","+y3+","+z3+")" );
233

    
234
//boolean result = (v1x==A*v2x && v1y==A*v2y && v1z==A*v2z);
235

    
236
//android.util.Log.e("D", "are those colinear? : "+result);
237

    
238
    return (v1x==A*v2x && v1y==A*v2y && v1z==A*v2z);
239
    }
240

    
241
///////////////////////////////////////////////////////////////////////////////////////////////////
242

    
243
  private void computeNormalVector(float[][] vertices, int index1, int index2, int index3)
244
    {
245
    float x1 = vertices[index1][0];
246
    float y1 = vertices[index1][1];
247
    float z1 = vertices[index1][2];
248
    float x2 = vertices[index2][0];
249
    float y2 = vertices[index2][1];
250
    float z2 = vertices[index2][2];
251
    float x3 = vertices[index3][0];
252
    float y3 = vertices[index3][1];
253
    float z3 = vertices[index3][2];
254

    
255
    float v1x = x2-x1;
256
    float v1y = y2-y1;
257
    float v1z = z2-z1;
258
    float v2x = x3-x1;
259
    float v2y = y3-y1;
260
    float v2z = z3-z1;
261

    
262
    mBuffer[0] = v1y*v2z - v2y*v1z;
263
    mBuffer[1] = v1z*v2x - v2z*v1x;
264
    mBuffer[2] = v1x*v2y - v2x*v1y;
265

    
266
    float len = mBuffer[0]*mBuffer[0] + mBuffer[1]*mBuffer[1] + mBuffer[2]*mBuffer[2];
267
    len = (float)Math.sqrt(len);
268
    mBuffer[0] /= len;
269
    mBuffer[1] /= len;
270
    mBuffer[2] /= len;
271

    
272
//android.util.Log.e("D", " normal: "+mBuffer[0]+" "+mBuffer[1]+" "+mBuffer[2]);
273
    }
274

    
275
///////////////////////////////////////////////////////////////////////////////////////////////////
276
// return quat1*quat2
277

    
278
  private static void quatMultiply( float[] quat1, float[] quat2, float[] result )
279
    {
280
    float qx = quat1[0];
281
    float qy = quat1[1];
282
    float qz = quat1[2];
283
    float qw = quat1[3];
284

    
285
    float rx = quat2[0];
286
    float ry = quat2[1];
287
    float rz = quat2[2];
288
    float rw = quat2[3];
289

    
290
    result[0] = rw*qx - rz*qy + ry*qz + rx*qw;
291
    result[1] = rw*qy + rz*qx + ry*qw - rx*qz;
292
    result[2] = rw*qz + rz*qw - ry*qx + rx*qy;
293
    result[3] = rw*qw - rz*qz - ry*qy - rx*qx;
294
    }
295

    
296
///////////////////////////////////////////////////////////////////////////////////////////////////
297

    
298
  private void fitInSquare(FaceInfo info, float[][] vert3D)
299
    {
300
    float minX = Float.MAX_VALUE;
301
    float maxX =-Float.MAX_VALUE;
302
    float minY = Float.MAX_VALUE;
303
    float maxY =-Float.MAX_VALUE;
304

    
305
    for (float[] vert : vert3D)
306
      {
307
      float x = vert[0];
308
      float y = vert[1];
309

    
310
      if (x > maxX) maxX = x;
311
      if (x < minX) minX = x;
312
      if (y > maxY) maxY = y;
313
      if (y < minY) minY = y;
314
      }
315

    
316
    info.scale = Math.max(maxX-minX,maxY-minY);
317

    
318
    int len = vert3D.length;
319
    info.vertices = new float[2*len];
320

    
321
    for( int vertex=0; vertex<len; vertex++ )
322
      {
323
      info.vertices[2*vertex  ] = vert3D[vertex][0] / info.scale;
324
      info.vertices[2*vertex+1] = vert3D[vertex][1] / info.scale;
325
      }
326

    
327
    info.flip = false;
328
    }
329

    
330
///////////////////////////////////////////////////////////////////////////////////////////////////
331

    
332
  private void constructNew(FaceInfo info, final float[][] vert3D)
333
    {
334
    // compute center of gravity
335
    info.vx = 0.0f;
336
    info.vy = 0.0f;
337
    info.vz = 0.0f;
338
    int len = vert3D.length;
339

    
340
    for (float[] vert : vert3D)
341
      {
342
      info.vx += vert[0];
343
      info.vy += vert[1];
344
      info.vz += vert[2];
345
      }
346

    
347
    info.vx /= len;
348
    info.vy /= len;
349
    info.vz /= len;
350

    
351
    // move all vertices so that their center of gravity is at (0,0,0)
352
    for (int i=0; i<len; i++)
353
      {
354
      vert3D[i][0] -= info.vx;
355
      vert3D[i][1] -= info.vy;
356
      vert3D[i][2] -= info.vz;
357
      }
358

    
359
    // find 3 non-colinear vertices
360
    int foundIndex = -1;
361

    
362
    for(int vertex=2; vertex<len; vertex++)
363
      {
364
      if( !areColinear(vert3D,0,1,vertex) )
365
        {
366
        foundIndex = vertex;
367
        break;
368
        }
369
      }
370

    
371
    // compute the normal vector
372
    if( foundIndex==-1 )
373
      {
374
      throw new RuntimeException("all vertices colinear");
375
      }
376

    
377
    computeNormalVector(vert3D,0,1,foundIndex);
378

    
379
    // rotate so that the normal vector becomes (0,0,1)
380
    float axisX, axisY, axisZ;
381

    
382
    if( mBuffer[0]!=0.0f || mBuffer[1]!=0.0f )
383
      {
384
      axisX = -mBuffer[1];
385
      axisY =  mBuffer[0];
386
      axisZ = 0.0f;
387

    
388
      float axiLen = axisX*axisX + axisY*axisY + axisZ*axisZ;
389
      axiLen = (float)Math.sqrt(axiLen);
390
      axisX /= axiLen;
391
      axisY /= axiLen;
392
      axisZ /= axiLen;
393
      }
394
    else
395
      {
396
      axisX = 0.0f;
397
      axisY = 1.0f;
398
      axisZ = 0.0f;
399
      }
400

    
401
    float cosTheta = mBuffer[2];
402
  //float sinTheta = axiLen / vecLen;
403

    
404
    float sinHalfTheta = (float)Math.sqrt(0.5f*(1-cosTheta));
405
    float cosHalfTheta = (float)Math.sqrt(0.5f*(1+cosTheta));
406

    
407
    mQuat1[0] = axisX*sinHalfTheta;
408
    mQuat1[1] = axisY*sinHalfTheta;
409
    mQuat1[2] = axisZ*sinHalfTheta;
410
    mQuat1[3] = cosHalfTheta;
411
    mQuat2[0] = axisX*sinHalfTheta;
412
    mQuat2[1] = axisY*sinHalfTheta;
413
    mQuat2[2] = axisZ*sinHalfTheta;
414
    mQuat2[3] = -cosHalfTheta;
415

    
416
    for (float[] vert : vert3D)
417
      {
418
      quatMultiply(mQuat1, vert, mQuat3);
419
      quatMultiply(mQuat3, mQuat2, vert);
420
      }
421

    
422
    // fit the whole thing in a square and remember the scale & 2D vertices
423
    fitInSquare(info, vert3D);
424

    
425
    // remember the rotation
426
    info.qx = mQuat1[0];
427
    info.qy = mQuat1[1];
428
    info.qz = mQuat1[2];
429
    info.qw =-mQuat1[3];
430
    }
431

    
432
///////////////////////////////////////////////////////////////////////////////////////////////////
433

    
434
  private float computeCos(float x1, float y1, float x2, float y2, float len1, float len2)
435
    {
436
    return (x1*x2+y1*y2) / (len1*len2);
437
    }
438

    
439
///////////////////////////////////////////////////////////////////////////////////////////////////
440
// sin of (signed!) angle between vectors (x1,y1) and (x2,y2), counterclockwise!
441

    
442
  private float computeSin(float x1, float y1, float x2, float y2, float len1, float len2)
443
    {
444
    return (x2*y1-x1*y2) / (len1*len2);
445
    }
446

    
447
///////////////////////////////////////////////////////////////////////////////////////////////////
448

    
449
  private void rotateAllVertices(float[] result, int len, float[] vertices, float sin, float cos)
450
    {
451
    for(int i=0; i<len; i++)
452
      {
453
      result[2*i  ] = vertices[2*i  ]*cos - vertices[2*i+1]*sin;
454
      result[2*i+1] = vertices[2*i  ]*sin + vertices[2*i+1]*cos;
455
      }
456
    }
457

    
458
///////////////////////////////////////////////////////////////////////////////////////////////////
459

    
460
  private boolean isScaledVersionOf(float[] v1, float[] v2, int len)
461
    {
462
    float EPSILON = 0.001f;
463
    float scale = v1[0]!=0.0f ? v2[0]/v1[0] : v2[1]/v1[1];
464

    
465
    for(int i=1; i<len; i++)
466
      {
467
      float horz = v2[2*i  ] - scale*v1[2*i  ];
468
      float vert = v2[2*i+1] - scale*v1[2*i+1];
469

    
470
      if( horz>EPSILON || horz<-EPSILON || vert>EPSILON || vert<-EPSILON ) return false;
471
      }
472

    
473
    return true;
474
    }
475

    
476
///////////////////////////////////////////////////////////////////////////////////////////////////
477

    
478
  private void mirrorAllVertices(float[] output, int len, float[] input)
479
    {
480
    for(int vertex=0; vertex<len; vertex++)
481
      {
482
      output[2*vertex  ] = input[2*vertex  ];
483
      output[2*vertex+1] =-input[2*vertex+1];
484
      }
485
    }
486

    
487
///////////////////////////////////////////////////////////////////////////////////////////////////
488

    
489
  private void correctInfo(FaceInfo info, float[] rotatedVertices, int len, float[] originalVertices, float sin, float cos, boolean flip)
490
    {
491
    info.flip = flip;
492

    
493
    System.arraycopy(originalVertices, 0, info.vertices, 0, 2*len);
494

    
495
    float scale = rotatedVertices[0]!=0.0f ? originalVertices[0]/rotatedVertices[0] :
496
                                             originalVertices[1]/rotatedVertices[1];
497
    info.scale *= scale;
498

    
499
    mQuat1[0] = 0.0f;
500
    mQuat1[1] = 0.0f;
501
    mQuat1[2] = sin;
502
    mQuat1[3] = cos;
503

    
504
    mQuat2[0] = info.qx;
505
    mQuat2[1] = info.qy;
506
    mQuat2[2] = info.qz;
507
    mQuat2[3] = info.qw;
508

    
509
    quatMultiply( mQuat1, mQuat2, mQuat3 );
510

    
511
    info.qx = mQuat3[0];
512
    info.qy = mQuat3[1];
513
    info.qz = mQuat3[2];
514
    info.qw = mQuat3[3];
515
    }
516

    
517
///////////////////////////////////////////////////////////////////////////////////////////////////
518

    
519
  private boolean foundVertex(FaceInfo info, float[] buffer, int len, boolean inverted, float[] vertices, float[] vert2D, float lenVert)
520
    {
521
    for(int vertex=0; vertex<len; vertex++)
522
      {
523
      float xR = vertices[2*vertex  ];
524
      float yR = vertices[2*vertex+1];
525
      float lenRotV = (float)Math.sqrt(xR*xR+yR*yR);
526
      float cos = computeCos(xR,yR,vert2D[0],vert2D[1], lenRotV, lenVert);
527
      float sin = computeSin(xR,yR,vert2D[0],vert2D[1], lenRotV, lenVert);
528

    
529
      rotateAllVertices(buffer,len,vertices,sin,cos);
530

    
531
      if( isScaledVersionOf(buffer,vert2D,len) )
532
        {
533
        correctInfo(info,buffer,len,vert2D,sin,cos,inverted);
534
        return true;
535
        }
536
      }
537

    
538
    return false;
539
    }
540

    
541
///////////////////////////////////////////////////////////////////////////////////////////////////
542

    
543
  private boolean tryFindingRotation(final FaceInfo info, final float[] vert2D)
544
    {
545
    int len = vert2D.length/2;
546

    
547
    if( len == info.vertices.length/2 )
548
      {
549
      float[] tmp1 = new float[2*len];
550
      float lenVert = (float)Math.sqrt(vert2D[0]*vert2D[0] + vert2D[1]*vert2D[1]);
551
      if( foundVertex(info,tmp1,len,false,info.vertices,vert2D,lenVert) ) return true;
552
      float[] tmp2 = new float[2*len];
553
      mirrorAllVertices(tmp2,len,info.vertices);
554
      if( foundVertex(info,tmp1,len,true ,tmp2         ,vert2D,lenVert) ) return true;
555
      }
556

    
557
    return false;
558
    }
559

    
560
///////////////////////////////////////////////////////////////////////////////////////////////////
561

    
562
  private float[][] constructVert(float[][] vertices, int[] index)
563
    {
564
    int len = index.length;
565
    float[][] ret = new float[len][4];
566

    
567
    for(int i=0; i<len; i++)
568
      {
569
      ret[i][0] = vertices[index[i]][0];
570
      ret[i][1] = vertices[index[i]][1];
571
      ret[i][2] = vertices[index[i]][2];
572
      ret[i][3] = 1.0f;
573
      }
574

    
575
    return ret;
576
    }
577

    
578
///////////////////////////////////////////////////////////////////////////////////////////////////
579

    
580
  private void prepareFaceInfo( final float[][] vertices, final int[][] indexes)
581
    {
582
    mFaceInfo.clear();
583

    
584
    int numFaces = indexes.length;
585
    FaceInfo info;
586

    
587
    for(int face=0; face<numFaces; face++)
588
      {
589
      FaceInfo newInfo = new FaceInfo();
590
      int[] index = indexes[face];
591
      float[][] vert = constructVert(vertices,index);
592
      constructNew(newInfo,vert);
593

    
594
      for(int previous=0; previous<face; previous++)
595
        {
596
        info = mFaceInfo.get(previous);
597
        if( tryFindingRotation(newInfo,info.vertices) )
598
          {
599
          android.util.Log.e("D", "comparing face "+face+" to "+previous+" SUCCESS!!");
600
          break;
601
          }
602
        }
603

    
604
      mFaceInfo.add(newInfo);
605
      }
606
    }
607

    
608
///////////////////////////////////////////////////////////////////////////////////////////////////
609

    
610
  private void printInfo(FaceInfo info)
611
    {
612
    android.util.Log.e("D", "vx="+info.vx+" vy="+info.vy+" vz="+info.vz);
613
    android.util.Log.e("D", "qx="+info.qx+" qy="+info.qy+" qz="+info.qz+" qw="+info.qw);
614
    android.util.Log.e("D", "scale="+info.scale);
615

    
616
    String ver="";
617

    
618
    int len = info.vertices.length/2;
619

    
620
    for(int i =0; i<len; i++)
621
      {
622
      ver += ("("+info.vertices[2*i]+","+info.vertices[2*i+1]+") ");
623
      }
624

    
625
    android.util.Log.e("D", "vertices= "+ver);
626
    }
627

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

    
630
  MeshBase createRoundedSolid(final float[][] vertices, final int[][] vertIndexes, final float[][] bands, final int[] bandIndexes)
631
    {
632
    int EFFECTS_PER_FACE = 3;
633

    
634
    prepareFaceInfo(vertices,vertIndexes);
635

    
636
    int numFaces = vertIndexes.length;
637
    float[] band, bandsComputed;
638
    MeshBase[] meshes = new MeshBase[numFaces];
639
    FaceInfo info;
640

    
641
    for(int face=0; face<numFaces; face++)
642
      {
643
      info = mFaceInfo.get(face);
644

    
645
      android.util.Log.d("D", "--------------");
646
      printInfo(info);
647

    
648
      band = bands[bandIndexes[face]];
649
      bandsComputed = computeBands( band[0], (int)band[1], band[2], band[3], (int)band[4]);
650
      meshes[face] = new MeshPolygon(info.vertices,bandsComputed,(int)band[5],(int)band[6]);
651
      meshes[face].setEffectAssociation(0,(1<<face),0);
652
      }
653

    
654
    MeshBase mesh = new MeshJoined(meshes);
655
    VertexEffect[] effects = new VertexEffect[EFFECTS_PER_FACE*numFaces];
656
    Static3D center = new Static3D(0,0,0);
657

    
658
    for(int face=0; face<numFaces; face++)
659
      {
660
      int assoc = (1<<face);
661
      info = mFaceInfo.get(face);
662

    
663
      Static3D move3D= new Static3D(info.vx,info.vy,info.vz);
664
      Static3D scale = new Static3D(info.scale,info.scale, info.flip ? -info.scale : info.scale);
665
      Static4D quat  = new Static4D(info.qx,info.qy,info.qz,info.qw);
666

    
667
      effects[EFFECTS_PER_FACE*face  ] = new VertexEffectScale(scale);
668
      effects[EFFECTS_PER_FACE*face+1] = new VertexEffectQuaternion(quat,center);
669
      effects[EFFECTS_PER_FACE*face+2] = new VertexEffectMove(move3D);
670

    
671
      effects[EFFECTS_PER_FACE*face  ].setMeshAssociation(assoc,-1);
672
      effects[EFFECTS_PER_FACE*face+1].setMeshAssociation(assoc,-1);
673
      effects[EFFECTS_PER_FACE*face+2].setMeshAssociation(assoc,-1);
674
      }
675

    
676
    for( VertexEffect effect : effects ) mesh.apply(effect);
677

    
678
    return mesh;
679
    }
680
  }
(1-1/5)