Project

General

Profile

Download (27 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / helpers / FactoryCubit.java @ be56193c

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.helpers;
21

    
22
import org.distorted.library.effect.MatrixEffectMove;
23
import org.distorted.library.effect.MatrixEffectQuaternion;
24
import org.distorted.library.effect.MatrixEffectScale;
25
import org.distorted.library.effect.VertexEffect;
26
import org.distorted.library.effect.VertexEffectDeform;
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
public class FactoryCubit
39
  {
40
  private static final Static1D RADIUS = new Static1D(1);
41
  private static FactoryCubit mThis;
42

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

    
49
  private static class StickerCoords
50
    {
51
    double[] vertices;
52
    }
53

    
54
  private static class FaceTransform
55
    {
56
    int sticker;
57
    double vx,vy,vz;
58
    double scale;
59
    double qx,qy,qz,qw;
60
    boolean flip;
61
    }
62

    
63
  private static final ArrayList<FaceTransform> mNewFaceTransf = new ArrayList<>();
64
  private static final ArrayList<FaceTransform> mOldFaceTransf = new ArrayList<>();
65
  private static final ArrayList<StickerCoords> mStickerCoords = new ArrayList<>();
66

    
67
///////////////////////////////////////////////////////////////////////////////////////////////////
68

    
69
  private FactoryCubit()
70
    {
71

    
72
    }
73

    
74
///////////////////////////////////////////////////////////////////////////////////////////////////
75

    
76
  public static FactoryCubit getInstance()
77
    {
78
    if( mThis==null ) mThis = new FactoryCubit();
79

    
80
    return mThis;
81
    }
82

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

    
118
///////////////////////////////////////////////////////////////////////////////////////////////////
119

    
120
  private float f(float D, float B, float x)
121
    {
122
    return ((D-B)*x + B*(1-D))/(1-B);
123
    }
124

    
125
///////////////////////////////////////////////////////////////////////////////////////////////////
126

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

    
133
///////////////////////////////////////////////////////////////////////////////////////////////////
134

    
135
  private float h(float R, float sinAlpha, float x)
136
    {
137
    return R*(sinAlpha-(float)Math.sin(x));
138
    }
139

    
140
///////////////////////////////////////////////////////////////////////////////////////////////////
141

    
142
  private boolean areColinear(double[][] vertices, int index1, int index2, int index3)
143
    {
144
    double x1 = vertices[index1][0];
145
    double y1 = vertices[index1][1];
146
    double z1 = vertices[index1][2];
147
    double x2 = vertices[index2][0];
148
    double y2 = vertices[index2][1];
149
    double z2 = vertices[index2][2];
150
    double x3 = vertices[index3][0];
151
    double y3 = vertices[index3][1];
152
    double z3 = vertices[index3][2];
153

    
154
    double v1x = x2-x1;
155
    double v1y = y2-y1;
156
    double v1z = z2-z1;
157
    double v2x = x3-x1;
158
    double v2y = y3-y1;
159
    double v2z = z3-z1;
160

    
161
    double A = Math.sqrt( (v1x*v1x+v1y*v1y+v1z*v1z) / (v2x*v2x+v2y*v2y+v2z*v2z) );
162

    
163
    return (v1x==A*v2x && v1y==A*v2y && v1z==A*v2z);
164
    }
165

    
166
///////////////////////////////////////////////////////////////////////////////////////////////////
167

    
168
  private void computeNormalVector(double[][] vertices, int index1, int index2, int index3)
169
    {
170
    double x1 = vertices[index1][0];
171
    double y1 = vertices[index1][1];
172
    double z1 = vertices[index1][2];
173
    double x2 = vertices[index2][0];
174
    double y2 = vertices[index2][1];
175
    double z2 = vertices[index2][2];
176
    double x3 = vertices[index3][0];
177
    double y3 = vertices[index3][1];
178
    double z3 = vertices[index3][2];
179

    
180
    double v1x = x2-x1;
181
    double v1y = y2-y1;
182
    double v1z = z2-z1;
183
    double v2x = x3-x1;
184
    double v2y = y3-y1;
185
    double v2z = z3-z1;
186

    
187
    mBuffer[0] = v1y*v2z - v2y*v1z;
188
    mBuffer[1] = v1z*v2x - v2z*v1x;
189
    mBuffer[2] = v1x*v2y - v2x*v1y;
190

    
191
    double len = mBuffer[0]*mBuffer[0] + mBuffer[1]*mBuffer[1] + mBuffer[2]*mBuffer[2];
192
    len = Math.sqrt(len);
193
    mBuffer[0] /= len;
194
    mBuffer[1] /= len;
195
    mBuffer[2] /= len;
196
    }
197

    
198
///////////////////////////////////////////////////////////////////////////////////////////////////
199
// return quat1*quat2
200

    
201
  private static void quatMultiply( double[] quat1, double[] quat2, double[] result )
202
    {
203
    double qx = quat1[0];
204
    double qy = quat1[1];
205
    double qz = quat1[2];
206
    double qw = quat1[3];
207

    
208
    double rx = quat2[0];
209
    double ry = quat2[1];
210
    double rz = quat2[2];
211
    double rw = quat2[3];
212

    
213
    result[0] = rw*qx - rz*qy + ry*qz + rx*qw;
214
    result[1] = rw*qy + rz*qx + ry*qw - rx*qz;
215
    result[2] = rw*qz + rz*qw - ry*qx + rx*qy;
216
    result[3] = rw*qw - rz*qz - ry*qy - rx*qx;
217
    }
218

    
219
///////////////////////////////////////////////////////////////////////////////////////////////////
220

    
221
  private void fitInSquare(FaceTransform info, double[][] vert3D)
222
    {
223
    double minX = Double.MAX_VALUE;
224
    double maxX =-Double.MAX_VALUE;
225
    double minY = Double.MAX_VALUE;
226
    double maxY =-Double.MAX_VALUE;
227

    
228
    for (double[] vert : vert3D)
229
      {
230
      double x = vert[0];
231
      double y = vert[1];
232

    
233
      if (x > maxX) maxX = x;
234
      if (x < minX) minX = x;
235
      if (y > maxY) maxY = y;
236
      if (y < minY) minY = y;
237
      }
238

    
239
    minX = minX<0 ? -minX:minX;
240
    maxX = maxX<0 ? -maxX:maxX;
241
    minY = minY<0 ? -minY:minY;
242
    maxY = maxY<0 ? -maxY:maxY;
243

    
244
    double max1 = Math.max(minX,minY);
245
    double max2 = Math.max(maxX,maxY);
246
    double max3 = Math.max(max1,max2);
247

    
248
    info.scale = max3/0.5;
249

    
250
    int len = vert3D.length;
251
    StickerCoords sInfo = new StickerCoords();
252
    sInfo.vertices = new double[2*len];
253

    
254
    for( int vertex=0; vertex<len; vertex++ )
255
      {
256
      sInfo.vertices[2*vertex  ] = vert3D[vertex][0] / info.scale;
257
      sInfo.vertices[2*vertex+1] = vert3D[vertex][1] / info.scale;
258
      }
259

    
260
    mStickerCoords.add(sInfo);
261

    
262
    info.sticker = mStickerCoords.size() -1;
263
    info.flip = false;
264
    }
265

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

    
268
  private FaceTransform constructNewTransform(final double[][] vert3D)
269
    {
270
    FaceTransform ft = new FaceTransform();
271

    
272
    // compute center of gravity
273
    ft.vx = 0.0f;
274
    ft.vy = 0.0f;
275
    ft.vz = 0.0f;
276
    int len = vert3D.length;
277

    
278
    for (double[] vert : vert3D)
279
      {
280
      ft.vx += vert[0];
281
      ft.vy += vert[1];
282
      ft.vz += vert[2];
283
      }
284

    
285
    ft.vx /= len;
286
    ft.vy /= len;
287
    ft.vz /= len;
288

    
289
    // move all vertices so that their center of gravity is at (0,0,0)
290
    for (int i=0; i<len; i++)
291
      {
292
      vert3D[i][0] -= ft.vx;
293
      vert3D[i][1] -= ft.vy;
294
      vert3D[i][2] -= ft.vz;
295
      }
296

    
297
    // find 3 non-colinear vertices
298
    int foundIndex = -1;
299

    
300
    for(int vertex=2; vertex<len; vertex++)
301
      {
302
      if( !areColinear(vert3D,0,1,vertex) )
303
        {
304
        foundIndex = vertex;
305
        break;
306
        }
307
      }
308

    
309
    // compute the normal vector
310
    if( foundIndex==-1 )
311
      {
312
      throw new RuntimeException("all vertices colinear");
313
      }
314

    
315
    computeNormalVector(vert3D,0,1,foundIndex);
316

    
317
    // rotate so that the normal vector becomes (0,0,1)
318
    double axisX, axisY, axisZ;
319

    
320
    if( mBuffer[0]!=0.0f || mBuffer[1]!=0.0f )
321
      {
322
      axisX = -mBuffer[1];
323
      axisY =  mBuffer[0];
324
      axisZ = 0.0f;
325

    
326
      double axiLen = axisX*axisX + axisY*axisY;
327
      axiLen = Math.sqrt(axiLen);
328
      axisX /= axiLen;
329
      axisY /= axiLen;
330
      axisZ /= axiLen;
331
      }
332
    else
333
      {
334
      axisX = 0.0f;
335
      axisY = 1.0f;
336
      axisZ = 0.0f;
337
      }
338

    
339
    double cosTheta = mBuffer[2];
340
    double sinTheta = Math.sqrt(1-cosTheta*cosTheta);
341
    double sinHalfTheta = computeSinHalf(cosTheta);
342
    double cosHalfTheta = computeCosHalf(sinTheta,cosTheta);
343

    
344
    mQuat1[0] = axisX*sinHalfTheta;
345
    mQuat1[1] = axisY*sinHalfTheta;
346
    mQuat1[2] = axisZ*sinHalfTheta;
347
    mQuat1[3] = cosHalfTheta;
348
    mQuat2[0] =-axisX*sinHalfTheta;
349
    mQuat2[1] =-axisY*sinHalfTheta;
350
    mQuat2[2] =-axisZ*sinHalfTheta;
351
    mQuat2[3] = cosHalfTheta;
352

    
353
    for (double[] vert : vert3D)
354
      {
355
      quatMultiply(mQuat1, vert  , mQuat3);
356
      quatMultiply(mQuat3, mQuat2, vert  );
357
      }
358

    
359
    // fit the whole thing in a square and remember the scale & 2D vertices
360
    fitInSquare(ft, vert3D);
361

    
362
    // remember the rotation
363
    ft.qx =-mQuat1[0];
364
    ft.qy =-mQuat1[1];
365
    ft.qz =-mQuat1[2];
366
    ft.qw = mQuat1[3];
367

    
368
    return ft;
369
    }
370

    
371
///////////////////////////////////////////////////////////////////////////////////////////////////
372

    
373
  private double computeCos(double oldX, double oldY, double newX, double newY, double len1, double len2)
374
    {
375
    double ret= (oldX*newX+oldY*newY) / (len1*len2);
376
    if( ret<-1.0 ) return -1.0;
377
    if( ret> 1.0 ) return  1.0;
378

    
379
    return ret;
380
    }
381

    
382
///////////////////////////////////////////////////////////////////////////////////////////////////
383
// sin of (signed!) angle between vectors 'old' and 'new', counterclockwise!
384

    
385
  private double computeSin(double oldX, double oldY, double newX, double newY, double len1, double len2)
386
    {
387
    double ret= (newX*oldY-oldX*newY) / (len1*len2);
388
    if( ret<-1.0 ) return -1.0;
389
    if( ret> 1.0 ) return  1.0;
390

    
391
    return ret;
392
    }
393

    
394
///////////////////////////////////////////////////////////////////////////////////////////////////
395

    
396
  private void rotateAllVertices(double[] result, int len, double[] vertices, double sin, double cos)
397
    {
398
    for(int i=0; i<len; i++)
399
      {
400
      result[2*i  ] = vertices[2*i  ]*cos - vertices[2*i+1]*sin;
401
      result[2*i+1] = vertices[2*i  ]*sin + vertices[2*i+1]*cos;
402
      }
403
    }
404

    
405
///////////////////////////////////////////////////////////////////////////////////////////////////
406

    
407
  private double computeScale(double[] v1, double[] v2, int v1i, int v2i)
408
    {
409
    double v1x = v1[2*v1i];
410
    double v1y = v1[2*v1i+1];
411
    double v2x = v2[2*v2i];
412
    double v2y = v2[2*v2i+1];
413

    
414
    double lenSq1 = v1x*v1x + v1y*v1y;
415
    double lenSq2 = v2x*v2x + v2y*v2y;
416

    
417
    return Math.sqrt(lenSq2/lenSq1);
418
    }
419

    
420
///////////////////////////////////////////////////////////////////////////////////////////////////
421
// valid for 0<angle<2*PI
422

    
423
  private double computeSinHalf(double cos)
424
    {
425
    return Math.sqrt((1-cos)/2);
426
    }
427

    
428
///////////////////////////////////////////////////////////////////////////////////////////////////
429
// valid for 0<angle<2*PI
430

    
431
  private double computeCosHalf(double sin, double cos)
432
    {
433
    double cosHalf = Math.sqrt((1+cos)/2);
434
    return sin<0 ? -cosHalf : cosHalf;
435
    }
436

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

    
439
  private int computeRotatedIndex(int oldVertex, int len, int rotatedVertex, boolean inverted)
440
    {
441
    int v = (rotatedVertex + (inverted? -oldVertex : oldVertex));
442
    if( v>=len ) v-=len;
443
    if( v< 0   ) v+=len;
444

    
445
    return v;
446
    }
447

    
448
///////////////////////////////////////////////////////////////////////////////////////////////////
449

    
450
  private boolean isScaledVersionOf(double[] newVert, double[] oldVert, int len, int vertex, boolean inverted)
451
    {
452
    int newZeroIndex = computeRotatedIndex(0,len,vertex,inverted);
453
    double EPSILON = 0.001;
454
    double scale = computeScale(newVert,oldVert,newZeroIndex,0);
455

    
456
    for(int i=1; i<len; i++)
457
      {
458
      int index = computeRotatedIndex(i,len,vertex,inverted);
459

    
460
      double horz = oldVert[2*i  ] - scale*newVert[2*index  ];
461
      double vert = oldVert[2*i+1] - scale*newVert[2*index+1];
462

    
463
      if( horz>EPSILON || horz<-EPSILON || vert>EPSILON || vert<-EPSILON ) return false;
464
      }
465

    
466
    return true;
467
    }
468

    
469
///////////////////////////////////////////////////////////////////////////////////////////////////
470

    
471
  private void mirrorAllVertices(double[] output, int len, double[] input)
472
    {
473
    for(int vertex=0; vertex<len; vertex++)
474
      {
475
      output[2*vertex  ] = input[2*vertex  ];
476
      output[2*vertex+1] =-input[2*vertex+1];
477
      }
478
    }
479

    
480
///////////////////////////////////////////////////////////////////////////////////////////////////
481

    
482
  private void correctInfo(FaceTransform info, double scale, double sin, double cos, int oldSticker, boolean flip)
483
    {
484
    mStickerCoords.remove(info.sticker);
485

    
486
    info.flip    = flip;
487
    info.sticker = oldSticker;
488
    info.scale  *= scale;
489

    
490
    mQuat1[0] = info.qx;
491
    mQuat1[1] = info.qy;
492
    mQuat1[2] = info.qz;
493
    mQuat1[3] = info.qw;
494

    
495
    double sinHalf = computeSinHalf(cos);
496
    double cosHalf = computeCosHalf(sin,cos);
497

    
498
    if( flip )
499
      {
500
      mQuat3[0] = 0.0f;
501
      mQuat3[1] = 0.0f;
502
      mQuat3[2] = sinHalf;
503
      mQuat3[3] = cosHalf;
504

    
505
      mQuat4[0] = 1.0;
506
      mQuat4[1] = 0.0;
507
      mQuat4[2] = 0.0;
508
      mQuat4[3] = 0.0;
509

    
510
      quatMultiply( mQuat3, mQuat4, mQuat2 );
511
      }
512
    else
513
      {
514
      mQuat2[0] = 0.0f;
515
      mQuat2[1] = 0.0f;
516
      mQuat2[2] = sinHalf;
517
      mQuat2[3] = cosHalf;
518
      }
519

    
520
    quatMultiply( mQuat1, mQuat2, mQuat3 );
521

    
522
    info.qx = mQuat3[0];
523
    info.qy = mQuat3[1];
524
    info.qz = mQuat3[2];
525
    info.qw = mQuat3[3];
526
    }
527

    
528
///////////////////////////////////////////////////////////////////////////////////////////////////
529

    
530
  private void printVert(double[] buffer)
531
    {
532
    int len = buffer.length/2;
533
    String str = "";
534

    
535
    for(int i=0; i<len; i++)
536
      {
537
      str += (" ("+buffer[2*i]+" , "+buffer[2*i+1]+" ) ");
538
      }
539

    
540
    android.util.Log.d("D", str);
541
    }
542

    
543
///////////////////////////////////////////////////////////////////////////////////////////////////
544

    
545
  private boolean foundVertex(FaceTransform info, double[] buffer, int len, double[] newVert,
546
                              double[] oldVert, double lenFirstOld, int oldSticker, boolean inverted)
547
    {
548
    for(int vertex=0; vertex<len; vertex++)
549
      {
550
      double newX = newVert[2*vertex  ];
551
      double newY = newVert[2*vertex+1];
552
      double lenIthNew = Math.sqrt(newX*newX + newY*newY);
553
      double cos = computeCos( oldVert[0], oldVert[1], newX, newY, lenIthNew, lenFirstOld);
554
      double sin = computeSin( oldVert[0], oldVert[1], newX, newY, lenIthNew, lenFirstOld);
555

    
556
      rotateAllVertices(buffer,len,newVert,sin,cos);
557

    
558
      if( isScaledVersionOf(buffer,oldVert,len,vertex,inverted) )
559
        {
560
        int newZeroIndex = computeRotatedIndex(0,len,vertex,inverted);
561
        double scale = computeScale(oldVert,newVert,0,newZeroIndex);
562
        correctInfo(info,scale,sin,cos,oldSticker,inverted);
563
        return true;
564
        }
565
      }
566

    
567
    return false;
568
    }
569

    
570
///////////////////////////////////////////////////////////////////////////////////////////////////
571

    
572
  private boolean successfullyCollapsedStickers(final FaceTransform newInfo, final FaceTransform oldInfo)
573
    {
574
    StickerCoords sNewInfo = mStickerCoords.get(newInfo.sticker);
575
    StickerCoords sOldInfo = mStickerCoords.get(oldInfo.sticker);
576
    double[] newVert = sNewInfo.vertices;
577
    double[] oldVert = sOldInfo.vertices;
578
    int oldLen = oldVert.length;
579
    int newLen = newVert.length;
580

    
581
    if( oldLen == newLen )
582
      {
583
      int oldSticker = oldInfo.sticker;
584
      double[] buffer1 = new double[oldLen];
585
      double lenFirstOld = Math.sqrt(oldVert[0]*oldVert[0] + oldVert[1]*oldVert[1]);
586
      if( foundVertex(newInfo, buffer1, oldLen/2, newVert, oldVert, lenFirstOld, oldSticker, false) ) return true;
587
      double[] buffer2 = new double[oldLen];
588
      mirrorAllVertices(buffer2, newLen/2, newVert);
589
      if( foundVertex(newInfo, buffer1, oldLen/2, buffer2, oldVert, lenFirstOld, oldSticker, true ) ) return true;
590
      }
591

    
592
    return false;
593
    }
594

    
595
///////////////////////////////////////////////////////////////////////////////////////////////////
596

    
597
  private double[][] constructVert(double[][] vertices, int[] index)
598
    {
599
    int len = index.length;
600
    double[][] ret = new double[len][4];
601

    
602
    for(int i=0; i<len; i++)
603
      {
604
      ret[i][0] = vertices[index[i]][0];
605
      ret[i][1] = vertices[index[i]][1];
606
      ret[i][2] = vertices[index[i]][2];
607
      ret[i][3] = 1.0f;
608
      }
609

    
610
    return ret;
611
    }
612

    
613
///////////////////////////////////////////////////////////////////////////////////////////////////
614

    
615
  private void prepareAndRoundCorners(MeshBase mesh, double[][] vertices,
616
                                      float[][] corners, int[] cornerIndexes,
617
                                      float[][] centers, int[] centerIndexes )
618
    {
619
    int lenV = vertices.length;
620
    Static3D[] staticVert = new Static3D[1];
621
    Static3D center = new Static3D(0,0,0);
622

    
623
    for(int v=0; v<lenV; v++)
624
      {
625
      staticVert[0] = new Static3D( (float)vertices[v][0], (float)vertices[v][1], (float)vertices[v][2]);
626

    
627
      int cent = centerIndexes[v];
628

    
629
      if( cent>=0 )
630
        {
631
        center.set( centers[cent][0], centers[cent][1], centers[cent][2]);
632

    
633
        int corn = cornerIndexes[v];
634
        float strength = corners[corn][0];
635
        float radius   = corners[corn][1];
636

    
637
        roundCorners(mesh, center, staticVert, strength, radius);
638
        }
639
      }
640
    }
641

    
642
///////////////////////////////////////////////////////////////////////////////////////////////////
643

    
644
  private void correctComponents(MeshBase mesh, int numComponents)
645
    {
646
    int numTexToBeAdded = numComponents-mesh.getNumTexComponents();
647

    
648
    mesh.mergeEffComponents();
649

    
650
    for(int i=0; i<numTexToBeAdded; i++ ) mesh.addEmptyTexComponent();
651
    }
652

    
653
///////////////////////////////////////////////////////////////////////////////////////////////////
654

    
655
  private void printTransform(FaceTransform f)
656
    {
657
    android.util.Log.e("D", "q=("+f.qx+", "+f.qy+", "+f.qz+", "+f.qw+") v=("
658
                       +f.vx+", "+f.vy+", "+f.vz+") scale="+f.scale+" sticker="+f.sticker);
659
    }
660

    
661
///////////////////////////////////////////////////////////////////////////////////////////////////
662
// PUBLIC
663

    
664
  public float[] computeBands(float H, int alpha, float dist, float K, int N)
665
    {
666
    float[] bands = new float[2*N];
667

    
668
    bands[0] = 1.0f;
669
    bands[1] = 0.0f;
670

    
671
    float beta = (float)Math.atan(dist*Math.tan(Math.PI*alpha/180));
672
    float sinBeta = (float)Math.sin(beta);
673
    float cosBeta = (float)Math.cos(beta);
674
    float R = cosBeta<1.0f ? H/(1.0f-cosBeta) : 0.0f;
675
    float D = R*sinBeta;
676
    float B = h(R,sinBeta,K*beta);
677

    
678
    if( D>1.0f )
679
      {
680
      for(int i=1; i<N; i++)
681
        {
682
        bands[2*i  ] = (float)(N-1-i)/(N-1);
683
        bands[2*i+1] = H*(1-bands[2*i]);
684
        }
685
      }
686
    else
687
      {
688
      int K2 = (int)((N-3)*K);
689
      int K1 = (N-3)-K2;
690

    
691
      for(int i=0; i<=K1; i++)
692
        {
693
        float angle = K*beta + (1-K)*beta*(K1-i)/(K1+1);
694
        float x = h(R,sinBeta,angle);
695
        bands[2*i+2] = 1.0f - x;
696
        bands[2*i+3] = g(R,D,x,cosBeta);
697
        }
698

    
699
      for(int i=0; i<=K2; i++)
700
        {
701
        float x = (1-B)*(i+1)/(K2+1) + B;
702
        bands[2*K1+2 + 2*i+2] = 1.0f - x;
703
        bands[2*K1+2 + 2*i+3] = g(R,D,f(D,B,x),cosBeta);
704
        }
705
      }
706

    
707
    bands[2*N-2] = 0.0f;
708
    bands[2*N-1] =    H;
709

    
710
    return bands;
711
    }
712

    
713
///////////////////////////////////////////////////////////////////////////////////////////////////
714

    
715
  public void roundCorners(MeshBase mesh, Static3D center, Static3D[] vertices, float strength, float regionRadius)
716
    {
717
    Static4D reg= new Static4D(0,0,0,regionRadius);
718

    
719
    float centX = center.get0();
720
    float centY = center.get1();
721
    float centZ = center.get2();
722

    
723
    for (Static3D vertex : vertices)
724
      {
725
      float x = strength*(centX - vertex.get0());
726
      float y = strength*(centY - vertex.get1());
727
      float z = strength*(centZ - vertex.get2());
728

    
729
      VertexEffect effect = new VertexEffectDeform(new Static3D(x,y,z), RADIUS, vertex, reg);
730
      mesh.apply(effect);
731
      }
732
    }
733

    
734
///////////////////////////////////////////////////////////////////////////////////////////////////
735

    
736
  public void printStickerCoords()
737
    {
738
    int stickers = mStickerCoords.size();
739

    
740
    android.util.Log.d("D", "---- STICKER COORDS ----");
741

    
742
    for(int s=0; s<stickers; s++)
743
      {
744
      String ver = "{ ";
745
      StickerCoords info = mStickerCoords.get(s);
746
      int len = info.vertices.length/2;
747

    
748
      for(int i =0; i<len; i++)
749
        {
750
        if( i!=0 ) ver += ", ";
751
        ver += ( (float)info.vertices[2*i]+"f, "+(float)info.vertices[2*i+1]+"f");
752
        }
753

    
754
      ver += " }";
755
      android.util.Log.d("D", ver);
756
      }
757

    
758
    android.util.Log.d("D", "---- END STICKER COORDS ----");
759
    }
760

    
761
///////////////////////////////////////////////////////////////////////////////////////////////////
762

    
763
  public void printFaceTransform()
764
    {
765
    android.util.Log.d("D", "---- OLD FACE TRANSFORM ---");
766

    
767
    int oldfaces = mOldFaceTransf.size();
768

    
769
    for(int f=0; f<oldfaces; f++)
770
      {
771
      printTransform(mOldFaceTransf.get(f));
772
      }
773

    
774
    android.util.Log.d("D", "---- NEW FACE TRANSFORM ---");
775

    
776
    int newfaces = mNewFaceTransf.size();
777

    
778
    for(int f=0; f<newfaces; f++)
779
      {
780
      printTransform(mNewFaceTransf.get(f));
781
      }
782
    }
783

    
784
///////////////////////////////////////////////////////////////////////////////////////////////////
785

    
786
  public void clear()
787
    {
788
    mStickerCoords.clear();
789
    mNewFaceTransf.clear();
790
    mOldFaceTransf.clear();
791
    }
792

    
793
///////////////////////////////////////////////////////////////////////////////////////////////////
794

    
795
  public void createNewFaceTransform( final double[][] vertices, final int[][] indexes)
796
    {
797
    FaceTransform ft;
798
    int numNew = mNewFaceTransf.size();
799

    
800
    for(int i=0; i<numNew; i++)
801
      {
802
      ft = mNewFaceTransf.remove(0);
803
      mOldFaceTransf.add(ft);
804
      }
805

    
806
    int numFaces = indexes.length;
807
    int numOld = mOldFaceTransf.size();
808

    
809
    for (int face=0; face<numFaces; face++)
810
      {
811
      boolean collapsed = false;
812

    
813
      double[][] vert = constructVert(vertices, indexes[face]);
814
      FaceTransform newT = constructNewTransform(vert);
815

    
816
      for (int old=0; !collapsed && old<numOld; old++)
817
        {
818
        ft = mOldFaceTransf.get(old);
819
        if (successfullyCollapsedStickers(newT, ft)) collapsed = true;
820
        }
821

    
822
      for (int pre=0; !collapsed && pre<face; pre++)
823
        {
824
        ft = mNewFaceTransf.get(pre);
825
        if (successfullyCollapsedStickers(newT, ft)) collapsed = true;
826
        }
827

    
828
      mNewFaceTransf.add(newT);
829
      }
830
    }
831

    
832
///////////////////////////////////////////////////////////////////////////////////////////////////
833

    
834
  public MeshBase createRoundedSolid(final double[][] vertices, final int[][] vertIndexes,
835
                                     final float[][] bands    , final int[]   bandIndexes,
836
                                     final float[][] corners  , final int[]   cornerIndexes,
837
                                     final float[][] centers  , final int[]   centerIndexes,
838
                                     final int numComponents )
839
    {
840
    int numFaces = vertIndexes.length;
841
    float[] band, bandsComputed;
842
    MeshBase[] meshes = new MeshBase[numFaces];
843
    FaceTransform fInfo;
844
    StickerCoords sInfo;
845

    
846
    for(int face=0; face<numFaces; face++)
847
      {
848
      fInfo = mNewFaceTransf.get(face);
849
      sInfo = mStickerCoords.get(fInfo.sticker);
850

    
851
      double[] verts = sInfo.vertices;
852
      int lenVerts = verts.length;
853
      float[] vertsFloat = new float[lenVerts];
854
      for(int i=0; i<lenVerts; i++) vertsFloat[i] = (float)verts[i];
855

    
856
      band = bands[bandIndexes[face]];
857
      bandsComputed = computeBands( band[0], (int)band[1], band[2], band[3], (int)band[4]);
858
      meshes[face] = new MeshPolygon(vertsFloat,bandsComputed,(int)band[5],(int)band[6]);
859
      meshes[face].setEffectAssociation(0,(1<<face),0);
860
      }
861

    
862
    MeshBase mesh = new MeshJoined(meshes);
863
    Static3D center = new Static3D(0,0,0);
864

    
865
    for(int face=0; face<numFaces; face++)
866
      {
867
      int assoc = (1<<face);
868
      fInfo = mNewFaceTransf.get(face);
869

    
870
      float vx = (float)fInfo.vx;
871
      float vy = (float)fInfo.vy;
872
      float vz = (float)fInfo.vz;
873
      float sc = (float)fInfo.scale;
874
      float qx = (float)fInfo.qx;
875
      float qy = (float)fInfo.qy;
876
      float qz = (float)fInfo.qz;
877
      float qw = (float)fInfo.qw;
878

    
879
      Static3D scale = new Static3D(sc,sc, fInfo.flip ? -sc : sc);
880
      Static3D move3D= new Static3D(vx,vy,vz);
881
      Static4D quat  = new Static4D(qx,qy,qz,qw);
882

    
883
      mesh.apply(new MatrixEffectScale(scale)           ,assoc,-1);
884
      mesh.apply(new MatrixEffectQuaternion(quat,center),assoc,-1);
885
      mesh.apply(new MatrixEffectMove(move3D)           ,assoc,-1);
886
      }
887

    
888
    prepareAndRoundCorners(mesh, vertices, corners, cornerIndexes, centers, centerIndexes);
889

    
890
    correctComponents(mesh,numComponents);
891

    
892
    return mesh;
893
    }
894
  }
(3-3/4)