Project

General

Profile

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

magiccube / src / main / java / org / distorted / helpers / FactoryCubit.java @ 0919eba7

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.effect.VertexEffectMove;
28
import org.distorted.library.effect.VertexEffectRotate;
29
import org.distorted.library.effect.VertexEffectScale;
30
import org.distorted.library.mesh.MeshBase;
31
import org.distorted.library.mesh.MeshJoined;
32
import org.distorted.library.mesh.MeshPolygon;
33
import org.distorted.library.type.Static1D;
34
import org.distorted.library.type.Static3D;
35
import org.distorted.library.type.Static4D;
36

    
37
import java.util.ArrayList;
38

    
39
///////////////////////////////////////////////////////////////////////////////////////////////////
40

    
41
public class FactoryCubit
42
  {
43
  private static final float SQ2 = (float)Math.sqrt(2);
44
  private static final float SQ3 = (float)Math.sqrt(3);
45
  private static final float SQ5 = (float)Math.sqrt(5);
46
  private static final float SQ6 = (float)Math.sqrt(6);
47

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

    
51
  // IVY
52
  static final float IVY_D = 0.003f;
53
  static final float IVY_C = 0.59f;
54
  static final float IVY_M = 0.35f;
55
  private static final int IVY_N = 8;
56

    
57
  // REX
58
  public static final float REX_D = 0.2f;
59

    
60
  // KILO / MEGAMINX
61
  public static final float SIN54    = (SQ5+1)/4;
62
  public static final float COS54    = (float)(Math.sqrt(10-2*SQ5)/4);
63
  public static final float SIN18    = (SQ5-1)/4;
64
  public static final float COS18    = (float)(0.25f*Math.sqrt(10.0f+2.0f*SQ5));
65
  public static final float COS_HALFD= (float)(Math.sqrt(0.5f-0.1f*SQ5)); // cos(half the dihedral angle)
66
  public static final float SIN_HALFD= (float)(Math.sqrt(0.5f+0.1f*SQ5)); // sin(half the dihedral angle)
67
  public static final float DIHEDRAL1= (float)(Math.acos(-SQ5/5)*180/Math.PI);
68
  public static final float DIHEDRAL2= (float)((180/Math.PI)*Math.asin((2*SIN54*SIN54-1)/COS54) - 90);
69
  public static final float MINX_SC  = 0.5f;
70

    
71

    
72
  private static final double[] mBuffer = new double[3];
73
  private static final double[] mQuat1  = new double[4];
74
  private static final double[] mQuat2  = new double[4];
75
  private static final double[] mQuat3  = new double[4];
76
  private static final double[] mQuat4  = new double[4];
77

    
78
  private static class StickerCoords
79
    {
80
    double[] vertices;
81
    }
82

    
83
  private static class FaceTransform
84
    {
85
    int sticker;
86
    double vx,vy,vz;
87
    double scale;
88
    double qx,qy,qz,qw;
89
    boolean flip;
90
    }
91

    
92
  private static final ArrayList<FaceTransform> mNewFaceTransf = new ArrayList<>();
93
  private static final ArrayList<FaceTransform> mOldFaceTransf = new ArrayList<>();
94
  private static final ArrayList<StickerCoords> mStickerCoords = new ArrayList<>();
95

    
96
///////////////////////////////////////////////////////////////////////////////////////////////////
97

    
98
  private FactoryCubit()
99
    {
100

    
101
    }
102

    
103
///////////////////////////////////////////////////////////////////////////////////////////////////
104

    
105
  public static FactoryCubit getInstance()
106
    {
107
    if( mThis==null ) mThis = new FactoryCubit();
108

    
109
    return mThis;
110
    }
111

    
112
///////////////////////////////////////////////////////////////////////////////////////////////////
113
// H - height of the band in the middle
114
// alpha - angle of the edge  [0,90]
115
// dist - often in a polygon the distance from edge to center is not 1, but something else.
116
// This is the distance.
117
// K - where to begin the second, much more flat part of the band. [0,1]
118
// N - number of bands. N>=3
119
//
120
// theory: two distinct parts to the band:
121
// 1) (0,B) - steep
122
// 2) (B,1) - flat
123
//
124
// In first part, we have y = g(x) ; in second - y = g(f(x)) where
125
//
126
// g(x) = sqrt( R^2 - (x-D)^2 ) - R*cos(alpha)
127
// f(x) = ((D-B)/(1-B)*x + B*(1-D)/(1-B)
128
// h(x) = R*(sin(alpha) - sin(x))
129
// R = H/(1-cos(alpha))
130
// D = H*sin(alpha)
131
// B = h(K*alpha)
132
//
133
// The N points are taken at:
134
//
135
// 1) in the second part, there are K2 = (N-3)/3 such points
136
// 2) in the first - K1 = (N-3) - K2
137
// 3) also, the 3 points 0,B,1
138
//
139
// so we have the sequence A[i] of N points
140
//
141
// 0
142
// h((i+1)*(1-K)*alpha/(K1+1)) (i=0,1,...,K1-1)
143
// B
144
// (1-B)*(i+1)/(K2+1) + B   (i=0,i,...,K2-1)
145
// 1
146

    
147
///////////////////////////////////////////////////////////////////////////////////////////////////
148

    
149
  private float f(float D, float B, float x)
150
    {
151
    return ((D-B)*x + B*(1-D))/(1-B);
152
    }
153

    
154
///////////////////////////////////////////////////////////////////////////////////////////////////
155

    
156
  private float g(float R, float D, float x, float cosAlpha)
157
    {
158
    float d = x-D;
159
    return (float)(Math.sqrt(R*R-d*d)-R*cosAlpha);
160
    }
161

    
162
///////////////////////////////////////////////////////////////////////////////////////////////////
163

    
164
  private float h(float R, float sinAlpha, float x)
165
    {
166
    return R*(sinAlpha-(float)Math.sin(x));
167
    }
168

    
169
///////////////////////////////////////////////////////////////////////////////////////////////////
170

    
171
  private float[] computeBands(float H, int alpha, float dist, float K, int N)
172
    {
173
    float[] bands = new float[2*N];
174

    
175
    bands[0] = 1.0f;
176
    bands[1] = 0.0f;
177

    
178
    float beta = (float)Math.atan(dist*Math.tan(Math.PI*alpha/180));
179
    float sinBeta = (float)Math.sin(beta);
180
    float cosBeta = (float)Math.cos(beta);
181
    float R = cosBeta<1.0f ? H/(1.0f-cosBeta) : 0.0f;
182
    float D = R*sinBeta;
183
    float B = h(R,sinBeta,K*beta);
184

    
185
    if( D>1.0f )
186
      {
187
      for(int i=1; i<N; i++)
188
        {
189
        bands[2*i  ] = (float)(N-1-i)/(N-1);
190
        bands[2*i+1] = H*(1-bands[2*i]);
191
        }
192
      }
193
    else
194
      {
195
      int K2 = (int)((N-3)*K);
196
      int K1 = (N-3)-K2;
197

    
198
      for(int i=0; i<=K1; i++)
199
        {
200
        float angle = K*beta + (1-K)*beta*(K1-i)/(K1+1);
201
        float x = h(R,sinBeta,angle);
202
        bands[2*i+2] = 1.0f - x;
203
        bands[2*i+3] = g(R,D,x,cosBeta);
204
        }
205

    
206
      for(int i=0; i<=K2; i++)
207
        {
208
        float x = (1-B)*(i+1)/(K2+1) + B;
209
        bands[2*K1+2 + 2*i+2] = 1.0f - x;
210
        bands[2*K1+2 + 2*i+3] = g(R,D,f(D,B,x),cosBeta);
211
        }
212
      }
213

    
214
    bands[2*N-2] = 0.0f;
215
    bands[2*N-1] =    H;
216

    
217
    return bands;
218
    }
219

    
220
///////////////////////////////////////////////////////////////////////////////////////////////////
221

    
222
  private void roundCorners(MeshBase mesh, Static3D center, Static3D[] vertices, float strength, float regionRadius)
223
    {
224
    Static4D reg= new Static4D(0,0,0,regionRadius);
225

    
226
    float centX = center.get0();
227
    float centY = center.get1();
228
    float centZ = center.get2();
229

    
230
    for (Static3D vertex : vertices)
231
      {
232
      float x = strength*(centX - vertex.get0());
233
      float y = strength*(centY - vertex.get1());
234
      float z = strength*(centZ - vertex.get2());
235

    
236
      VertexEffect effect = new VertexEffectDeform(new Static3D(x,y,z), RADIUS, vertex, reg);
237
      mesh.apply(effect);
238
      }
239
    }
240

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

    
243
  MeshBase createFacesHelicopterFace()
244
    {
245
    MeshBase[] meshes = new MeshBase[4];
246

    
247
    float E = 0.5f;
248
    float F = SQ2/4;
249
    float G = 1.0f/12;
250
    float[] vertices0 = { -E+E/4,E/4, E/4,-E+E/4, E/4,E/4};
251
    float[] bands0 = computeBands(0.028f,35,E/4,0.7f,7);
252

    
253
    meshes[0] = new MeshPolygon(vertices0, bands0, 3, 3);
254
    meshes[0].setEffectAssociation(0,1,0);
255

    
256
    float[] vertices1 = { -F,-G, +F,-G, 0,2*G};
257
    float[] bands1 = computeBands(0.01f,45,F,0.0f,3);
258

    
259
    meshes[1] = new MeshPolygon(vertices1, bands1, 1, 3);
260
    meshes[1].setEffectAssociation(0,2,0);
261

    
262
    float[] vertices2 = { -E/2,-F/3, +E/2,-F/3, 0,2*F/3};
263

    
264
    meshes[2] = new MeshPolygon(vertices2, bands1, 1, 3);
265
    meshes[2].setEffectAssociation(0,4,0);
266
    meshes[3] = meshes[2].copy(true);
267
    meshes[3].setEffectAssociation(0,8,0);
268

    
269
    return new MeshJoined(meshes);
270
    }
271

    
272
///////////////////////////////////////////////////////////////////////////////////////////////////
273

    
274
  MeshBase createFacesRediEdge()
275
    {
276
    MeshBase[] meshes = new MeshPolygon[6];
277

    
278
    float F = 0.25f;
279
    float[] vertices0 = { -F,+F, -F,-F, 0, -2*F, +F,-F, +F,+F };
280
    float[] bands0 = computeBands(0.038f,35,F,0.7f,7);
281

    
282
    meshes[0] = new MeshPolygon(vertices0, bands0, 2, 2);
283
    meshes[0].setEffectAssociation(0,1,0);
284
    meshes[1] = meshes[0].copy(true);
285
    meshes[1].setEffectAssociation(0,2,0);
286

    
287
    float[] bands1 = computeBands(0.02f,35,F/2,0.2f,3);
288
    float[] vertices1 = { -F/2, +F/2, -F/2, -1.5f*F, 1.5f*F, +F/2 };
289

    
290
    meshes[2] = new MeshPolygon(vertices1, bands1, 1, 2);
291
    meshes[2].setEffectAssociation(0,4,0);
292
    meshes[3] = meshes[2].copy(true);
293
    meshes[3].setEffectAssociation(0,8,0);
294

    
295
    float X = 0.25f*SQ2;
296
    float Y = SQ6/16;
297
    float[] vertices2 = { -X, Y, -1.5f*X, -Y, +1.5f*X, -Y, +X, Y };
298

    
299
    meshes[4] = new MeshPolygon(vertices2, bands1, 1, 1);
300
    meshes[4].setEffectAssociation(0,16,0);
301
    meshes[5] = meshes[4].copy(true);
302
    meshes[5].setEffectAssociation(0,32,0);
303

    
304
    return new MeshJoined(meshes);
305
    }
306

    
307
///////////////////////////////////////////////////////////////////////////////////////////////////
308

    
309
  MeshBase createFacesRediCorner()
310
    {
311
    MeshBase[] meshes = new MeshBase[6];
312

    
313
    float E = 0.5f;
314
    float[] vertices0 = { -E,-E, +E,-E, +E,+E, -E,+E };
315
    float[] bands0 = computeBands(0.06f,35,E,0.7f,6);
316

    
317
    meshes[0] = new MeshPolygon(vertices0,bands0,2,2);
318
    meshes[0].setEffectAssociation(0,1,0);
319
    meshes[1] = meshes[0].copy(true);
320
    meshes[1].setEffectAssociation(0,2,0);
321
    meshes[2] = meshes[0].copy(true);
322
    meshes[2].setEffectAssociation(0,4,0);
323

    
324
    float F = 0.5f;
325
    float X = 0.5f;
326
    float G = 0.72f;
327
    float[] vertices1 = { -E,+F, -E+X,0, -E,-F, -E*G,-F, +E*G,-F, +E,-F, +E-X,0, +E,+F, +E*G,+F, -E*G,+F };
328
    float[] bands1 = computeBands(0.0f,0,1.0f,0.0f,2);
329

    
330
    meshes[3] = new MeshPolygon(vertices1,bands1,0,0);
331
    meshes[3].setEffectAssociation(0,8,0);
332
    meshes[4] = meshes[3].copy(true);
333
    meshes[4].setEffectAssociation(0,16,0);
334
    meshes[5] = meshes[3].copy(true);
335
    meshes[5].setEffectAssociation(0,32,0);
336

    
337
    return new MeshJoined(meshes);
338
    }
339

    
340
///////////////////////////////////////////////////////////////////////////////////////////////////
341

    
342
  MeshBase createFacesIvyCorner()
343
    {
344
    MeshBase[] meshes = new MeshBase[6];
345

    
346
    final float angle = (float)Math.PI/(2*IVY_N);
347
    final float CORR  = 1.0f - 2*IVY_D;
348
    final float DIST  = -0.5f*CORR + IVY_D;
349
    float[] vertices  = new float[2*(IVY_N+1)+6];
350

    
351
    vertices[0] = (0.5f-IVY_M) * IVY_C;
352
    vertices[1] = (DIST-IVY_M) * IVY_C;
353
    vertices[2] = (0.5f-IVY_M) * IVY_C;
354
    vertices[3] = (0.5f-IVY_M) * IVY_C;
355
    vertices[4] = (DIST-IVY_M) * IVY_C;
356
    vertices[5] = (0.5f-IVY_M) * IVY_C;
357

    
358
    for(int i=0; i<=IVY_N; i++)
359
      {
360
      float ang = (IVY_N-i)*angle;
361
      float sin = (float)Math.sin(ang);
362
      float cos = (float)Math.cos(ang);
363

    
364
      vertices[2*i+6] = (CORR*(cos-0.5f)-IVY_M)*IVY_C;
365
      vertices[2*i+7] = (CORR*(sin-0.5f)-IVY_M)*IVY_C;
366
      }
367

    
368
    float[] bands0 = computeBands(+0.012f,20,0.2f,0.5f,7);
369
    float[] bands1 = computeBands(-0.100f,20,0.2f,0.0f,2);
370

    
371
    meshes[0] = new MeshPolygon(vertices,bands0,1,2);
372
    meshes[0].setEffectAssociation(0,1,0);
373
    meshes[1] = meshes[0].copy(true);
374
    meshes[1].setEffectAssociation(0,2,0);
375
    meshes[2] = meshes[0].copy(true);
376
    meshes[2].setEffectAssociation(0,4,0);
377
    meshes[3] = new MeshPolygon(vertices,bands1,1,2);
378
    meshes[3].setEffectAssociation(0,8,0);
379
    meshes[4] = meshes[3].copy(true);
380
    meshes[4].setEffectAssociation(0,16,0);
381
    meshes[5] = meshes[3].copy(true);
382
    meshes[5].setEffectAssociation(0,32,0);
383

    
384
    return new MeshJoined(meshes);
385
    }
386

    
387
///////////////////////////////////////////////////////////////////////////////////////////////////
388

    
389
  MeshBase createFacesIvyFace()
390
    {
391
    MeshBase[] meshes = new MeshBase[2];
392

    
393
    final float angle = (float)Math.PI/(2*IVY_N);
394
    final float CORR  = 1.0f - 2*IVY_D;
395
    float[] vertices = new float[4*IVY_N];
396

    
397
    for(int i=0; i<IVY_N; i++)
398
      {
399
      float sin = (float)Math.sin(i*angle);
400
      float cos = (float)Math.cos(i*angle);
401

    
402
      vertices[2*i          ] = CORR*(0.5f-cos);
403
      vertices[2*i+1        ] = CORR*(0.5f-sin);
404
      vertices[2*i  +2*IVY_N] = CORR*(cos-0.5f);
405
      vertices[2*i+1+2*IVY_N] = CORR*(sin-0.5f);
406
      }
407

    
408
    float[] bands0 = computeBands(+0.03f,35,0.5f,0.5f,5);
409
    float[] bands1 = computeBands(-0.10f,45,0.5f,0.0f,2);
410

    
411
    meshes[0] = new MeshPolygon(vertices,bands0,0,0);
412
    meshes[0].setEffectAssociation(0,1,0);
413
    meshes[1] = new MeshPolygon(vertices,bands1,0,0);
414
    meshes[1].setEffectAssociation(0,2,0);
415

    
416
    return new MeshJoined(meshes);
417
    }
418

    
419
///////////////////////////////////////////////////////////////////////////////////////////////////
420

    
421
  MeshBase createFacesRexCorner()
422
    {
423
    MeshBase[] meshes = new MeshBase[2];
424

    
425
    float F = REX_D*SQ2;
426
    float G = (1-REX_D)*SQ2/2;
427
    float H = 0.1f;
428
    float J = +2*G/3 - H*G;
429

    
430
    float[] vertices = { -F/2, -G/3, +F/2, -G/3, H*F/2, J, -H*F/2, J};
431

    
432
    float[] bands0 = computeBands(+0.016f,10,G/3,0.5f,5);
433
    float[] bands1 = computeBands(-0.230f,45,G/3,0.0f,2);
434

    
435
    meshes[0] = new MeshPolygon(vertices,bands0,1,1);
436
    meshes[0].setEffectAssociation(0,1,0);
437
    meshes[1] = new MeshPolygon(vertices,bands1,0,0);
438
    meshes[1].setEffectAssociation(0,2,0);
439

    
440
    return new MeshJoined(meshes);
441
    }
442

    
443
///////////////////////////////////////////////////////////////////////////////////////////////////
444

    
445
  MeshBase createFacesRexFace()
446
    {
447
    MeshBase[] meshes = new MeshBase[2];
448

    
449
    float[] vertices = { -REX_D,0.0f, 0.0f, -REX_D, +REX_D, 0.0f, 0.0f, +REX_D};
450

    
451
    float[] bands0 = computeBands(0.016f,10,REX_D/2,0.5f,5);
452
    float[] bands1 = computeBands(0.000f,45,REX_D/2,0.0f,2);
453

    
454
    meshes[0] = new MeshPolygon(vertices,bands0,0,0);
455
    meshes[0].setEffectAssociation(0,1,0);
456
    meshes[1] = new MeshPolygon(vertices,bands1,0,0);
457
    meshes[1].setEffectAssociation(0,2,0);
458

    
459
    return new MeshJoined(meshes);
460
    }
461

    
462
///////////////////////////////////////////////////////////////////////////////////////////////////
463

    
464
  MeshBase createFacesRexEdge()
465
    {
466
    MeshBase[] meshes = new MeshPolygon[6];
467

    
468
    float E = 0.5f - REX_D;
469
    float F = 0.5f;
470
    float[] vertices0 = { -F,E/3, 0,-2*E/3, +F,E/3 };
471
    float[] bands0 = computeBands(0.03f,27,F/3,0.8f,5);
472

    
473
    meshes[0] = new MeshPolygon(vertices0, bands0, 2, 3);
474
    meshes[0].setEffectAssociation(0,1,0);
475
    meshes[1] = meshes[0].copy(true);
476
    meshes[1].setEffectAssociation(0,2,0);
477

    
478
    float G = (float)Math.sqrt(E*E+F*F);
479
    float[] vertices1 = { -2*G/3, -E/3, G/3, -E/3, G/3, 2*E/3 };
480
    float[] bands1 = computeBands(0.00f,45,G/3,0.2f,3);
481

    
482
    meshes[2] = new MeshPolygon(vertices1, bands1, 1, 2);
483
    meshes[2].setEffectAssociation(0,4,0);
484
    meshes[3] = meshes[2].copy(true);
485
    meshes[3].setEffectAssociation(0,8,0);
486
    meshes[4] = meshes[2].copy(true);
487
    meshes[4].setEffectAssociation(0,16,0);
488
    meshes[5] = meshes[2].copy(true);
489
    meshes[5].setEffectAssociation(0,32,0);
490

    
491
    return new MeshJoined(meshes);
492
    }
493

    
494
///////////////////////////////////////////////////////////////////////////////////////////////////
495

    
496
  MeshBase createFacesKilominxCenter()
497
    {
498
    MeshBase[] meshes = new MeshPolygon[6];
499

    
500
    float X1= 0.5f*SIN54;
501
    float Y1= 0.5f*SIN_HALFD;
502
    float Y2= Y1 - 0.5f*COS54;
503
    float H = 0.5f* SIN54 /COS54  ;
504
    float X2= MINX_SC*H* SIN_HALFD;
505
    float Y3= MINX_SC*H/(2*COS_HALFD);
506
    float Y4= MINX_SC*H*(1/(2*COS_HALFD) - COS_HALFD);
507

    
508
    float[] vertices0 = { -X1, Y2, 0, -Y1, X1, Y2, 0, Y1 };
509
    float[] bands0 = computeBands(0.04f,17,0.3f,0.2f,5);
510
    float[] vertices1 = { -X2, Y4, 0, -Y3, X2, Y4, 0, Y3 };
511
    float[] bands1 = computeBands(0.00f, 0,0.25f,0.5f,2);
512

    
513
    meshes[0] = new MeshPolygon(vertices0, bands0, 1, 1);
514
    meshes[0].setEffectAssociation(0, 1,0);
515
    meshes[1] = meshes[0].copy(true);
516
    meshes[1].setEffectAssociation(0, 2,0);
517
    meshes[2] = meshes[0].copy(true);
518
    meshes[2].setEffectAssociation(0, 4,0);
519
    meshes[3] = new MeshPolygon(vertices1, bands1, 0, 0);
520
    meshes[3].setEffectAssociation(0, 8,0);
521
    meshes[4] = meshes[3].copy(true);
522
    meshes[4].setEffectAssociation(0,16,0);
523
    meshes[5] = meshes[3].copy(true);
524
    meshes[5].setEffectAssociation(0,32,0);
525

    
526
    return new MeshJoined(meshes);
527
    }
528

    
529
///////////////////////////////////////////////////////////////////////////////////////////////////
530

    
531
  MeshBase createFacesMinxCorner(int numLayers)
532
    {
533
    MeshBase[] meshes = new MeshPolygon[6];
534

    
535
    float Y = COS54/(2*SIN54);
536

    
537
    float[] vertices0 = { -0.5f, 0.0f, 0.0f, -Y, 0.5f, 0.0f, 0.0f, Y };
538

    
539
    int numBands0 = numLayers==3 ? 5 : 3;
540
    int numBands1 = numLayers==3 ? 2 : 2;
541
    float h       = numLayers==3 ? 0.04f : 0.03f;
542
    int   e       = numLayers==3 ? 4 : 1;
543

    
544
    float[] bands0 = computeBands(h    ,34,0.3f,0.2f, numBands0);
545
    float[] bands1 = computeBands(0.00f,34,0.3f,0.2f, numBands1);
546

    
547
    meshes[0] = new MeshPolygon(vertices0, bands0, 1, 1);
548
    meshes[0].setEffectAssociation(0, 1,0);
549
    meshes[1] = meshes[0].copy(true);
550
    meshes[1].setEffectAssociation(0, 2,0);
551
    meshes[2] = meshes[0].copy(true);
552
    meshes[2].setEffectAssociation(0, 4,0);
553
    meshes[3] = new MeshPolygon(vertices0, bands1, 1, e);
554
    meshes[3].setEffectAssociation(0, 8,0);
555
    meshes[4] = meshes[3].copy(true);
556
    meshes[4].setEffectAssociation(0,16,0);
557
    meshes[5] = meshes[3].copy(true);
558
    meshes[5].setEffectAssociation(0,32,0);
559

    
560
    return new MeshJoined(meshes);
561
    }
562

    
563
///////////////////////////////////////////////////////////////////////////////////////////////////
564

    
565
  MeshBase createFacesKilominxEdge(int numLayers, float width, float height)
566
    {
567
     MeshBase[] meshes = new MeshPolygon[6];
568

    
569
    float D = height/COS18;
570
    float W = D*SIN18;
571
    float X1 = height/2;
572
    float Y1 = width/2;
573
    float Y2 = (width+W)/2;
574
    float X3 = D*SIN54;
575
    float Y3 = D*COS54;
576
    float X4 = height*SIN_HALFD;
577
    float Y4 = height*COS_HALFD;
578

    
579
    float[] vertices0 = { -X1,-Y1, X1, -Y1, X1, Y1+W,-X1, Y1 };
580
    float[] vertices1 = { -X1,-Y2, X1, -Y2, X1, Y2+W,-X1, Y2 };
581
    float[] vertices2 = { -X3, 0.0f, 0.0f, -Y3, X3, 0.0f, 0.0f, Y3 };
582
    float[] vertices3 = { -X4, 0.0f, 0.0f, -Y4, X4, 0.0f, 0.0f, Y4 };
583

    
584
    int numBands0 = numLayers<=5 ? 5 : 3;
585
    int numBands1 = numLayers<=5 ? 3 : 2;
586
    float h       = numLayers<=5 ? 0.03f : 0.03f;
587

    
588
    float[] bands0 = computeBands(h    ,34,0.2f,0.2f,numBands0);
589
    float[] bands1 = computeBands(0.01f,34,0.3f,0.2f,numBands1);
590

    
591
    meshes[0] = new MeshPolygon(vertices0, bands0, 1, 1);
592
    meshes[0].setEffectAssociation(0, 1,0);
593
    meshes[1] = meshes[0].copy(true);
594
    meshes[1].setEffectAssociation(0, 2,0);
595
    meshes[2] = new MeshPolygon(vertices1, bands1, 0, 0);
596
    meshes[2].setEffectAssociation(0, 4,0);
597
    meshes[3] = meshes[2].copy(true);
598
    meshes[3].setEffectAssociation(0, 8,0);
599
    meshes[4] = new MeshPolygon(vertices2, bands1, 0, 0);
600
    meshes[4].setEffectAssociation(0,16,0);
601
    meshes[5] = new MeshPolygon(vertices3, bands1, 0, 0);
602
    meshes[5].setEffectAssociation(0,32,0);
603

    
604
    return new MeshJoined(meshes);
605
    }
606

    
607
///////////////////////////////////////////////////////////////////////////////////////////////////
608

    
609
  MeshBase createFacesMegaminxEdge(int numLayers, float width, float height)
610
    {
611
    MeshBase[] meshes = new MeshPolygon[6];
612

    
613
    float D = height/COS18;
614
    float W = D*SIN18;
615

    
616
    float Y1 = 0.5f*width;
617
    float Y2 = 0.5f*width + W;
618
    float Y3 = 0.5f*width + 2*W;
619
    float X2 = D*SIN54;
620
    float X1 = 0.5f*height;
621
    float Y4 = D*COS54;
622

    
623
    float[] vertices0 = { -X1, Y1, -X1, -Y1, X1, -Y2, X1, Y2 };
624
    float[] vertices1 = { -X1, Y3, -X1, -Y3, X1, -Y2, X1, Y2 };
625
    float[] vertices2 = { -X2, 0.0f, 0.0f, -Y4, X2, 0.0f, 0.0f, Y4 };
626

    
627
    int numBands0 = numLayers==3 ? 5 : 3;
628
    int numBands1 = numLayers==3 ? 2 : 2;
629
    float h       = numLayers==3 ? 0.03f : 0.03f;
630

    
631
    float[] bands0 = computeBands(h    ,34,0.2f,0.2f,numBands0);
632
    float[] bands1 = computeBands(0.00f,34,0.3f,0.2f,numBands1);
633

    
634
    meshes[0] = new MeshPolygon(vertices0, bands0, 0, 0);
635
    meshes[0].setEffectAssociation(0, 1,0);
636
    meshes[1] = meshes[0].copy(true);
637
    meshes[1].setEffectAssociation(0, 2,0);
638
    meshes[2] = new MeshPolygon(vertices1, bands1, 0, 0);
639
    meshes[2].setEffectAssociation(0, 4,0);
640
    meshes[3] = meshes[2].copy(true);
641
    meshes[3].setEffectAssociation(0, 8,0);
642
    meshes[4] = new MeshPolygon(vertices2, bands1, 0, 0);
643
    meshes[4].setEffectAssociation(0,16,0);
644
    meshes[5] = meshes[4].copy(true);
645
    meshes[5].setEffectAssociation(0,32,0);
646

    
647
    return new MeshJoined(meshes);
648
    }
649

    
650
///////////////////////////////////////////////////////////////////////////////////////////////////
651

    
652
  MeshBase createFacesMegaminxCenter(int numLayers)
653
    {
654
    MeshBase[] meshes = new MeshPolygon[2];
655

    
656
    float R  = 0.5f;
657
    float X1 = R*COS54;
658
    float Y1 = R*SIN54;
659
    float X2 = R*COS18;
660
    float Y2 = R*SIN18;
661

    
662
    float[] vertices0 = { -X1,+Y1, -X2,-Y2, 0.0f,-R, +X2,-Y2, +X1,+Y1 };
663

    
664
    int numBands0 = numLayers==3 ? 4 : 3;
665
    int numBands1 = numLayers==3 ? 2 : 2;
666
    float h       = numLayers==3 ? 0.04f : 0.04f;
667

    
668
    float[] bands0 = computeBands( h    ,45, R/3,0.2f, numBands0);
669
    float[] bands1 = computeBands( 0.00f,34, R/3,0.2f, numBands1);
670

    
671
    meshes[0] = new MeshPolygon(vertices0, bands0, 0, 0);
672
    meshes[0].setEffectAssociation(0,1,0);
673
    meshes[1] = new MeshPolygon(vertices0, bands1, 0, 0);
674
    meshes[1].setEffectAssociation(0,2,0);
675

    
676
    return new MeshJoined(meshes);
677
    }
678

    
679
///////////////////////////////////////////////////////////////////////////////////////////////////
680

    
681
  private float[] createVertices(int A, int B)
682
    {
683
    float E = 0.5f / Math.max(A,B);
684
    return new float[] { -A*E,-B*E, +A*E,-B*E, +A*E,+B*E, -A*E,+B*E };
685
    }
686

    
687
///////////////////////////////////////////////////////////////////////////////////////////////////
688

    
689
  MeshBase createCuboid(int[] dimensions)
690
    {
691
    int X = dimensions[0];
692
    int Y = dimensions[1];
693
    int Z = dimensions[2];
694

    
695
    float[] verticesXY = createVertices(X,Y);
696
    float[] verticesXZ = createVertices(X,Z);
697
    float[] verticesYZ = createVertices(Z,Y);
698

    
699
    float defHeight = 0.048f;
700

    
701
    float[] bandsX = computeBands( defHeight/X,65,0.25f,0.5f,5);
702
    float[] bandsY = computeBands( defHeight/Y,65,0.25f,0.5f,5);
703
    float[] bandsZ = computeBands( defHeight/Z,65,0.25f,0.5f,5);
704

    
705
    MeshBase[] meshes = new MeshPolygon[6];
706

    
707
    meshes[0] = new MeshPolygon(verticesYZ,bandsX,1,2);
708
    meshes[0].setEffectAssociation(0,1,0);
709
    meshes[1] = meshes[0].copy(true);
710
    meshes[1].setEffectAssociation(0,2,0);
711
    meshes[2] = new MeshPolygon(verticesXZ,bandsY,1,2);
712
    meshes[2].setEffectAssociation(0,4,0);
713
    meshes[3] = meshes[2].copy(true);
714
    meshes[3].setEffectAssociation(0,8,0);
715
    meshes[4] = new MeshPolygon(verticesXY,bandsZ,1,2);
716
    meshes[4].setEffectAssociation(0,16,0);
717
    meshes[5] = meshes[4].copy(true);
718
    meshes[5].setEffectAssociation(0,32,0);
719

    
720
    return new MeshJoined(meshes);
721
    }
722

    
723
///////////////////////////////////////////////////////////////////////////////////////////////////
724
// EFFECTS
725
///////////////////////////////////////////////////////////////////////////////////////////////////
726

    
727
  VertexEffect[] createVertexEffectsHelicopterFace()
728
    {
729
    float E = 0.5f;
730
    float F = SQ2/4;
731

    
732
    Static3D move0  = new Static3D(-E/4, -E/4, 0);
733
    Static3D move1  = new Static3D(-(SQ2/24)-E/2, -(SQ2/24)-E/2, 0);
734
    Static3D move2  = new Static3D(-E/2, F/3, 0);
735
    Static3D move3  = new Static3D(+E/2, F/3, 0);
736
    Static3D move4  = new Static3D(+E/3,+E/3, 0);
737
    Static1D angle1 = new Static1D(135);
738
    Static1D angle2 = new Static1D(90);
739
    Static1D angle3 = new Static1D(-90);
740
    Static1D angle4 = new Static1D(-135);
741
    Static3D axisX  = new Static3D(1,0,0);
742
    Static3D axisY  = new Static3D(0,1,0);
743
    Static3D axisZ  = new Static3D(0,0,1);
744
    Static3D axis1  = new Static3D(1,-1,0);
745
    Static3D center = new Static3D(0,0,0);
746
    Static3D center1= new Static3D(-E/2,-E/2,0);
747

    
748
    VertexEffect[] effect = new VertexEffect[10];
749

    
750
    effect[0] = new VertexEffectMove(move0);
751
    effect[1] = new VertexEffectRotate(angle1, axisZ, center);
752
    effect[2] = new VertexEffectMove(move1);
753
    effect[3] = new VertexEffectRotate(angle2, axis1, center1);
754
    effect[4] = new VertexEffectMove(move2);
755
    effect[5] = new VertexEffectMove(move3);
756
    effect[6] = new VertexEffectRotate(angle3, axisZ, center);
757
    effect[7] = new VertexEffectRotate(angle4, axisX, center);
758
    effect[8] = new VertexEffectRotate(angle1, axisY, center);
759
    effect[9] = new VertexEffectMove(move4);
760

    
761
    effect[0].setMeshAssociation( 1,-1);  // mesh 0
762
    effect[1].setMeshAssociation( 2,-1);  // mesh 1
763
    effect[2].setMeshAssociation( 2,-1);  // mesh 1
764
    effect[3].setMeshAssociation( 2,-1);  // mesh 1
765
    effect[4].setMeshAssociation( 4,-1);  // mesh 2
766
    effect[5].setMeshAssociation( 8,-1);  // mesh 3
767
    effect[6].setMeshAssociation( 8,-1);  // mesh 3
768
    effect[7].setMeshAssociation( 4,-1);  // mesh 2
769
    effect[8].setMeshAssociation( 8,-1);  // mesh 3
770
    effect[9].setMeshAssociation(15,-1);  // meshes 0,1,2,3
771

    
772
    return effect;
773
    }
774

    
775
///////////////////////////////////////////////////////////////////////////////////////////////////
776

    
777
  VertexEffect[] createVertexEffectsRediEdge()
778
    {
779
    Static3D move0 = new Static3D(0.0f, -0.5f, 0.0f);
780
    Static3D move1 = new Static3D(0.25f, -0.25f, 0.0f);
781
    Static3D move2 = new Static3D(0.5f, 0.0f, 0.0f);
782
    Static3D move3 = new Static3D(0.0f, (SQ3-6)/8, (SQ3-6)/8);
783
    Static3D flipZ = new Static3D(1,1,-1);
784
    Static3D flipX = new Static3D(-1,1,1);
785
    Static3D scale = new Static3D(2,2,2);
786
    Static3D cent0 = new Static3D(0,0, 0);
787
    Static3D cent1 = new Static3D(0,0, -1.5f);
788
    Static3D axisX = new Static3D(1,0, 0);
789
    Static3D axisY = new Static3D(0,1, 0);
790
    Static3D axis  = new Static3D(0,SQ2/2,-SQ2/2);
791
    Static1D angle1= new Static1D(90);
792
    Static1D angle2= new Static1D(45);
793
    Static1D angle3= new Static1D( (float)(180/Math.PI*Math.acos(SQ3/3)) );
794

    
795
    VertexEffect[] effect = new VertexEffect[12];
796

    
797
    effect[0] = new VertexEffectScale(scale);
798
    effect[1] = new VertexEffectMove(move0);
799
    effect[2] = new VertexEffectScale(flipZ);
800
    effect[3] = new VertexEffectRotate(angle1,axisX,cent0);
801
    effect[4] = new VertexEffectMove(move1);
802
    effect[5] = new VertexEffectRotate(angle1,axisY,cent0);
803
    effect[6] = new VertexEffectMove(move2);
804
    effect[7] = new VertexEffectScale(flipX);
805
    effect[8] = new VertexEffectRotate(angle2,axisX,cent0);
806
    effect[9] = new VertexEffectMove(move3);
807
    effect[10]= new VertexEffectRotate(angle3,axis ,cent1);
808
    effect[11]= new VertexEffectScale(flipX);
809

    
810
    effect[0].setMeshAssociation(63,-1);  // meshes 0,1,2,3,4,5
811
    effect[1].setMeshAssociation( 3,-1);  // meshes 0,1
812
    effect[2].setMeshAssociation( 2,-1);  // mesh 1
813
    effect[3].setMeshAssociation( 2,-1);  // mesh 1
814
    effect[4].setMeshAssociation(12,-1);  // meshes 2,3
815
    effect[5].setMeshAssociation(60,-1);  // meshes 2,3,4,5
816
    effect[6].setMeshAssociation(12,-1);  // meshes 2,3
817
    effect[7].setMeshAssociation( 8,-1);  // mesh 3
818
    effect[8].setMeshAssociation(48,-1);  // meshes 4,5
819
    effect[9].setMeshAssociation(48,-1);  // meshes 4,5
820
    effect[10].setMeshAssociation(48,-1); // meshes 4,5
821
    effect[11].setMeshAssociation(32,-1); // mesh 5
822

    
823
    return effect;
824
    }
825

    
826
///////////////////////////////////////////////////////////////////////////////////////////////////
827

    
828
  VertexEffect[] createVertexEffectsRediCorner()
829
    {
830
    Static3D axisY   = new Static3D(0,1,0);
831
    Static3D axisX   = new Static3D(1,0,0);
832
    Static3D axisZ   = new Static3D(0,0,1);
833
    Static3D center  = new Static3D(0,0,0);
834
    Static1D angle90 = new Static1D(90);
835
    Static1D angle270= new Static1D(270);
836
    Static1D angle45 = new Static1D(-45);
837
    Static3D scale   = new Static3D(1.0f, SQ2, 1.0f);
838

    
839
    VertexEffect[] effect = new VertexEffect[7];
840

    
841
    effect[0] = new VertexEffectMove(new Static3D(0,0,+0.5f));
842
    effect[1] = new VertexEffectRotate( angle270, axisX, center );
843
    effect[2] = new VertexEffectRotate( angle90 , axisY, center );
844
    effect[3] = new VertexEffectScale(scale);
845
    effect[4] = new VertexEffectRotate( angle45 , axisX, center );
846
    effect[5] = new VertexEffectRotate( angle90 , axisY, center );
847
    effect[6] = new VertexEffectRotate( angle270, axisZ, center );
848

    
849
    effect[0].setMeshAssociation( 7,-1);  // 0,1,2
850
    effect[1].setMeshAssociation( 2,-1);  // 1
851
    effect[2].setMeshAssociation( 4,-1);  // 2
852
    effect[3].setMeshAssociation(56,-1);  // 3,4,5
853
    effect[4].setMeshAssociation(56,-1);  // 3,4,5
854
    effect[5].setMeshAssociation(16,-1);  // 4
855
    effect[6].setMeshAssociation(32,-1);  // 5
856

    
857
    return effect;
858
    }
859

    
860
///////////////////////////////////////////////////////////////////////////////////////////////////
861

    
862
  VertexEffect[] createVertexEffectsIvyCorner()
863
    {
864
    Static3D axisX  = new Static3D(1,0,0);
865
    Static3D axisY  = new Static3D(0,1,0);
866
    Static1D angle1 = new Static1D(+90);
867
    Static1D angle2 = new Static1D(-90);
868
    Static3D center = new Static3D(0,0,0);
869
    Static3D move1  = new Static3D(IVY_M-0.5f,IVY_M-0.5f,0);
870

    
871
    VertexEffect[] effect = new VertexEffect[5];
872

    
873
    effect[0] = new VertexEffectScale(1/IVY_C);
874
    effect[1] = new VertexEffectMove(move1);
875
    effect[2] = new VertexEffectScale(new Static3D(1,1,-1));
876
    effect[3] = new VertexEffectRotate(angle1,axisX,center);
877
    effect[4] = new VertexEffectRotate(angle2,axisY,center);
878

    
879
    effect[2].setMeshAssociation(54,-1);  // meshes 1,2,4,5
880
    effect[3].setMeshAssociation(18,-1);  // meshes 1,4
881
    effect[4].setMeshAssociation(36,-1);  // meshes 2,5
882

    
883
    return effect;
884
    }
885

    
886
///////////////////////////////////////////////////////////////////////////////////////////////////
887

    
888
  VertexEffect[] createVertexEffectsRexEdge()
889
    {
890
    float E = 0.5f - REX_D;
891
    float F = 0.5f;
892
    float G = (float)Math.sqrt(E*E+F*F);
893
    float A = (float)((180/Math.PI)*Math.asin(E/G));
894

    
895
    Static3D move1 = new Static3D(    0.0f, -E/3, 0.0f);
896
    Static3D move2 = new Static3D(2*G/3 -F, +E/3, 0.0f);
897

    
898
    Static3D center0= new Static3D(0.0f, 0.0f, 0.0f);
899
    Static3D center1= new Static3D(  -F, 0.0f, 0.0f);
900
    Static3D center2= new Static3D(  +F, 0.0f, 0.0f);
901
    Static3D axisX  = new Static3D(1.0f, 0.0f, 0.0f);
902
    Static3D axisY  = new Static3D(0.0f, 1.0f, 0.0f);
903
    Static3D axisZ  = new Static3D(0.0f, 0.0f, 1.0f);
904

    
905
    Static1D angle180 = new Static1D(180);
906
    Static1D angle90  = new Static1D( 90);
907
    Static1D angle270 = new Static1D(270);
908
    Static1D angle1   = new Static1D(+A);
909
    Static1D angle2   = new Static1D(-A);
910

    
911
    VertexEffect[] effect = new VertexEffect[12];
912

    
913
    effect[0] = new VertexEffectMove(move1);
914
    effect[1] = new VertexEffectMove(move2);
915
    effect[2] = new VertexEffectRotate(  angle90, axisX, center0 );
916
    effect[3] = new VertexEffectRotate( angle270, axisX, center0 );
917
    effect[4] = new VertexEffectRotate( angle180, axisX, center0 );
918
    effect[5] = new VertexEffectRotate( angle180, axisY, center0 );
919
    effect[6] = new VertexEffectScale ( new Static3D(-1, 1, 1) );
920
    effect[7] = new VertexEffectScale ( new Static3D( 1,-1, 1) );
921
    effect[8] = new VertexEffectRotate(   angle1, axisY, center1);
922
    effect[9] = new VertexEffectRotate(   angle2, axisY, center2);
923
    effect[10]= new VertexEffectRotate(   angle2, axisZ, center1);
924
    effect[11]= new VertexEffectRotate(   angle1, axisZ, center2);
925

    
926
    effect[0].setMeshAssociation( 3,-1);  // meshes 0 & 1
927
    effect[1].setMeshAssociation(60,-1);  // meshes 2,3,4,5
928
    effect[2].setMeshAssociation( 2,-1);  // meshes 1
929
    effect[3].setMeshAssociation(12,-1);  // meshes 2,3
930
    effect[4].setMeshAssociation(48,-1);  // meshes 4,5
931
    effect[5].setMeshAssociation(32,-1);  // mesh 5
932
    effect[6].setMeshAssociation( 8,-1);  // apply to mesh 3
933
    effect[7].setMeshAssociation( 2,-1);  // apply to mesh 1
934
    effect[8].setMeshAssociation(16,-1);  // apply to mesh 4
935
    effect[9].setMeshAssociation(32,-1);  // apply to mesh 5
936
    effect[10].setMeshAssociation(4,-1);  // apply to mesh 2
937
    effect[11].setMeshAssociation(8,-1);  // apply to mesh 3
938

    
939
    return effect;
940
    }
941

    
942
///////////////////////////////////////////////////////////////////////////////////////////////////
943

    
944
  VertexEffect[] createVertexEffectsRexCorner()
945
    {
946
    Static3D center= new Static3D(0.0f, 0.0f, 0.0f);
947
    Static3D axisZ = new Static3D(0.0f, 0.0f, 1.0f);
948
    Static1D angle = new Static1D(225);
949

    
950
    VertexEffect[] effect = new VertexEffect[1];
951
    effect[0] = new VertexEffectRotate(angle, axisZ, center);
952

    
953
    return effect;
954
    }
955

    
956
///////////////////////////////////////////////////////////////////////////////////////////////////
957

    
958
  VertexEffect[] createVertexEffectsKilominxCenter(float width)
959
    {
960
    VertexEffect[] effect = new VertexEffect[11];
961

    
962
    float H = 0.5f*(SIN54/COS54);
963
    float Y1= 0.5f*SIN_HALFD;
964
    float Y2= H/(2*COS_HALFD);
965
    float cos18 = (float)(Math.sqrt(1- SIN18 * SIN18));
966
    float LEN   = (float)Math.sqrt(H*H/(COS_HALFD*COS_HALFD) + 0.25f);
967

    
968
    Static3D axisZ = new Static3D(0.0f  , 0.0f , 1.0f);
969
    Static3D axisY = new Static3D(0.0f  , 1.0f , 0.0f);
970
    Static3D axisA = new Static3D(-SIN18, cos18, 0.0f);
971
    Static3D axisC = new Static3D( H/LEN, -0.5f/LEN,-H* SIN_HALFD /(COS_HALFD*LEN));
972

    
973
    Static3D move1 = new Static3D(0,-Y1,0);
974
    Static3D move2 = new Static3D(0,-Y2,0);
975
    Static3D move3 = new Static3D(0.5f*cos18,0.5f*SIN18,0);
976
    Static3D center= new Static3D(0.0f, 0.0f, 0.0f);
977

    
978
    Static1D angle1 = new Static1D(54);
979
    Static1D angle2 = new Static1D(DIHEDRAL1/2+18);
980
    Static1D angle3 = new Static1D(90);
981
    Static1D angle4 = new Static1D(120);
982
    Static1D angle5 = new Static1D(240);
983
    Static1D angle6 = new Static1D(90-DIHEDRAL1/2);
984

    
985
    effect[0] = new VertexEffectMove(move1);
986
    effect[1] = new VertexEffectScale(1/MINX_SC);
987
    effect[2] = new VertexEffectMove(move2);
988
    effect[3] = new VertexEffectRotate(angle1, axisZ, center);
989
    effect[4] = new VertexEffectRotate(angle2, axisZ, center);
990
    effect[5] = new VertexEffectRotate(angle3, axisA, center);
991
    effect[6] = new VertexEffectMove(move3);
992
    effect[7] = new VertexEffectRotate(angle4, axisC, center);
993
    effect[8] = new VertexEffectRotate(angle5, axisC, center);
994
    effect[9] = new VertexEffectRotate(angle6, axisY, center);
995
    effect[10]= new VertexEffectScale(width/0.5f);
996

    
997
    effect[0].setMeshAssociation( 7,-1);  // meshes 0,1,2
998
    effect[1].setMeshAssociation(56,-1);  // meshes 3,4,5
999
    effect[2].setMeshAssociation(56,-1);  // meshes 3,4,5
1000
    effect[3].setMeshAssociation( 7,-1);  // meshes 0,1,2
1001
    effect[4].setMeshAssociation(56,-1);  // meshes 3,4,5
1002
    effect[5].setMeshAssociation(56,-1);  // meshes 3,4,5
1003
    effect[6].setMeshAssociation(56,-1);  // meshes 3,4,5
1004
    effect[7].setMeshAssociation(18,-1);  // meshes 1,4
1005
    effect[8].setMeshAssociation(36,-1);  // meshes 2,5
1006

    
1007
    return effect;
1008
    }
1009

    
1010
///////////////////////////////////////////////////////////////////////////////////////////////////
1011

    
1012
  VertexEffect[] createVertexEffectsMinxCorner(float width)
1013
    {
1014
    VertexEffect[] effect = new VertexEffect[9];
1015

    
1016
    float Y = COS54/(2*SIN54);
1017

    
1018
    float sinA = (2*SIN54*SIN54-1)/COS54;
1019
    float cosA = (float)Math.sqrt(1-sinA*sinA);
1020
    float LEN  = 0.5f/SIN54;
1021
    float scale= width/LEN;
1022

    
1023
    Static3D axisA = new Static3D( SIN54, COS54, 0.0f);
1024
    Static3D axisB = new Static3D(-SIN54, COS54, 0.0f);
1025
    Static3D axisX = new Static3D(  1.0f,  0.0f, 0.0f);
1026

    
1027
    Static3D centerU = new Static3D( 0.0f, Y, 0.0f);
1028
    Static3D centerD = new Static3D( 0.0f,-Y, 0.0f);
1029

    
1030
    Static3D move1= new Static3D(0.0f, -sinA*LEN, -cosA*LEN );
1031
    Static3D move2= new Static3D(0.0f, Y , 0.0f );
1032

    
1033
    Static1D angleD = new Static1D(DIHEDRAL1);
1034
    Static1D angleE = new Static1D(360-DIHEDRAL1);
1035
    Static1D angleF = new Static1D(DIHEDRAL2);
1036

    
1037
    effect[0] = new VertexEffectScale ( new Static3D( 1, 1,-1) );
1038
    effect[1] = new VertexEffectRotate(angleE, axisA, centerU);
1039
    effect[2] = new VertexEffectRotate(angleD, axisB, centerU);
1040
    effect[3] = new VertexEffectMove(move1);
1041
    effect[4] = new VertexEffectRotate(angleE, axisA, centerD);
1042
    effect[5] = new VertexEffectRotate(angleD, axisB, centerD);
1043
    effect[6] = new VertexEffectRotate(angleF, axisX, centerD);
1044
    effect[7] = new VertexEffectMove(move2);
1045
    effect[8] = new VertexEffectScale(scale);
1046

    
1047
    effect[0].setMeshAssociation(  3,-1);  // meshes 0,1
1048
    effect[1].setMeshAssociation( 16,-1);  // mesh 4
1049
    effect[2].setMeshAssociation( 32,-1);  // mesh 5
1050
    effect[3].setMeshAssociation( 56,-1);  // meshes 3,4,5
1051
    effect[4].setMeshAssociation(  1,-1);  // mesh 0
1052
    effect[5].setMeshAssociation(  2,-1);  // mesh 1
1053

    
1054
    return effect;
1055
    }
1056

    
1057
///////////////////////////////////////////////////////////////////////////////////////////////////
1058

    
1059
  VertexEffect[] createVertexEffectsKilominxEdge(float width, float height, boolean left)
1060
    {
1061
    VertexEffect[] effect = new VertexEffect[11 + (left ? 0:1)];
1062

    
1063
    float D = height/COS18;
1064
    float W = D*SIN18;
1065
    float X1 = height/2;
1066
    float Y1 = width/2;
1067
    float Y2 = (width+W)/2;
1068
    float Y3 = D*COS54;
1069
    float Y4 = height*COS_HALFD;
1070
    float Z = 2*height*COS_HALFD;
1071
    float alpha = 90-DIHEDRAL1/2;
1072

    
1073
    Static1D angle1 = new Static1D(alpha);
1074
    Static1D angle2 = new Static1D(180-alpha);
1075
    Static1D angle3 = new Static1D(DIHEDRAL2);
1076
    Static1D angle4 = new Static1D(90);
1077

    
1078
    Static3D move1 = new Static3D(+X1,-Y1,0);
1079
    Static3D move2 = new Static3D(-X1,-Y2+W,-Z);
1080
    Static3D move3 = new Static3D(0,+Y3,0);
1081
    Static3D move4 = new Static3D(0,-Y4-width,0);
1082
    Static3D scale = new Static3D(+1,+1,-1);
1083

    
1084
    Static3D axisXplus = new Static3D(+1, 0, 0);
1085
    Static3D axisYplus = new Static3D( 0,+1, 0);
1086

    
1087
    Static3D center1= new Static3D( 0, 0, 0);
1088
    Static3D center2= new Static3D( 0, 0,-Z);
1089
    Static3D center3= new Static3D( 0,-width, 0);
1090

    
1091
    effect[ 0] = new VertexEffectMove(move1);
1092
    effect[ 1] = new VertexEffectMove(move2);
1093
    effect[ 2] = new VertexEffectMove(move3);
1094
    effect[ 3] = new VertexEffectMove(move4);
1095
    effect[ 4] = new VertexEffectScale(scale);
1096
    effect[ 5] = new VertexEffectRotate(angle1, axisYplus , center1);
1097
    effect[ 6] = new VertexEffectRotate(angle2, axisYplus , center1);
1098
    effect[ 7] = new VertexEffectRotate(angle1, axisYplus , center2);
1099
    effect[ 8] = new VertexEffectRotate(angle2, axisYplus , center2);
1100
    effect[ 9] = new VertexEffectRotate(angle3, axisXplus , center1);
1101
    effect[10] = new VertexEffectRotate(angle4, axisXplus , center3);
1102

    
1103
    if( !left )
1104
      {
1105
      Static3D scale1 = new Static3D(+1,-1,+1);
1106
      effect[11] = new VertexEffectScale(scale1);
1107
      }
1108

    
1109
    effect[ 0].setMeshAssociation( 3,-1);  // meshes 0,1
1110
    effect[ 1].setMeshAssociation(12,-1);  // meshes 2,3
1111
    effect[ 2].setMeshAssociation(16,-1);  // mesh 4
1112
    effect[ 3].setMeshAssociation(32,-1);  // mesh 5
1113
    effect[ 4].setMeshAssociation( 2,-1);  // mesh 1
1114
    effect[ 5].setMeshAssociation( 1,-1);  // mesh 0
1115
    effect[ 6].setMeshAssociation( 2,-1);  // mesh 1
1116
    effect[ 7].setMeshAssociation( 4,-1);  // mesh 2
1117
    effect[ 8].setMeshAssociation( 8,-1);  // mesh 3
1118
    effect[ 9].setMeshAssociation(16,-1);  // mesh 4
1119
    effect[10].setMeshAssociation(32,-1);  // mesh 5
1120

    
1121
    return effect;
1122
    }
1123

    
1124
///////////////////////////////////////////////////////////////////////////////////////////////////
1125

    
1126
  VertexEffect[] createVertexEffectsMegaminxEdge(float width, float height)
1127
    {
1128
    VertexEffect[] effect = new VertexEffect[11];
1129

    
1130
    float X = 0.5f*height;
1131
    float Y = height*(COS54/COS18) + width*0.5f;
1132
    float Z = 2*height*COS_HALFD;
1133

    
1134
    float alpha = 90-DIHEDRAL1/2;
1135
    float beta  = DIHEDRAL2;
1136

    
1137
    Static1D angle1 = new Static1D(alpha);
1138
    Static1D angle2 = new Static1D(180-alpha);
1139
    Static1D angle3 = new Static1D(beta);
1140

    
1141
    Static3D move1 = new Static3D(X,0,0);
1142
    Static3D move2 = new Static3D(X,0,-Z);
1143
    Static3D move3 = new Static3D(0,+Y,0);
1144
    Static3D move4 = new Static3D(0,-Y,0);
1145
    Static3D scale = new Static3D(+1,+1,-1);
1146

    
1147
    Static3D axisXplus = new Static3D(+1, 0, 0);
1148
    Static3D axisXminus= new Static3D(-1, 0, 0);
1149
    Static3D axisYplus = new Static3D( 0,+1, 0);
1150
    Static3D axisYminus= new Static3D( 0,-1, 0);
1151

    
1152
    Static3D center1= new Static3D( 0, 0, 0);
1153
    Static3D center2= new Static3D( 0, 0,-Z);
1154
    Static3D center3= new Static3D( 0,+width*0.5f, 0);
1155
    Static3D center4= new Static3D( 0,-width*0.5f, 0);
1156

    
1157
    effect[ 0] = new VertexEffectMove(move1);
1158
    effect[ 1] = new VertexEffectMove(move2);
1159
    effect[ 2] = new VertexEffectMove(move3);
1160
    effect[ 3] = new VertexEffectMove(move4);
1161
    effect[ 4] = new VertexEffectScale(scale);
1162
    effect[ 5] = new VertexEffectRotate(angle1, axisYplus , center1);
1163
    effect[ 6] = new VertexEffectRotate(angle2, axisYplus , center1);
1164
    effect[ 7] = new VertexEffectRotate(angle1, axisYminus, center2);
1165
    effect[ 8] = new VertexEffectRotate(angle2, axisYminus, center2);
1166
    effect[ 9] = new VertexEffectRotate(angle3, axisXplus , center3);
1167
    effect[10] = new VertexEffectRotate(angle3, axisXminus, center4);
1168

    
1169
    effect[ 0].setMeshAssociation( 3,-1);  // meshes 0,1
1170
    effect[ 1].setMeshAssociation(12,-1);  // meshes 2,3
1171
    effect[ 2].setMeshAssociation(16,-1);  // mesh 4
1172
    effect[ 3].setMeshAssociation(32,-1);  // mesh 5
1173
    effect[ 4].setMeshAssociation( 2,-1);  // mesh 1
1174
    effect[ 5].setMeshAssociation( 1,-1);  // mesh 0
1175
    effect[ 6].setMeshAssociation( 2,-1);  // mesh 1
1176
    effect[ 7].setMeshAssociation( 4,-1);  // mesh 2
1177
    effect[ 8].setMeshAssociation( 8,-1);  // mesh 3
1178
    effect[ 9].setMeshAssociation(16,-1);  // mesh 4
1179
    effect[10].setMeshAssociation(32,-1);  // mesh 5
1180

    
1181
    return effect;
1182
    }
1183

    
1184
///////////////////////////////////////////////////////////////////////////////////////////////////
1185

    
1186
  VertexEffect[] createVertexEffectsMegaminxCenter(float width)
1187
    {
1188
    VertexEffect[] effect = new VertexEffect[2];
1189

    
1190
    Static1D angle = new Static1D(DIHEDRAL2);
1191
    Static3D axisX = new Static3D( 1.0f, 0.0f, 0.0f);
1192
    Static3D center= new Static3D( 0, 0, 0);
1193

    
1194
    effect[0] = new VertexEffectScale(width/COS54);
1195
    effect[1] = new VertexEffectRotate(angle, axisX, center);
1196

    
1197
    return effect;
1198
    }
1199

    
1200
///////////////////////////////////////////////////////////////////////////////////////////////////
1201

    
1202
  VertexEffect[] createCuboidEffects(int[] dimensions)
1203
    {
1204
    float X = dimensions[0];
1205
    float Y = dimensions[1];
1206
    float Z = dimensions[2];
1207

    
1208
    float MAX_XY = Math.max(X,Y);
1209
    float MAX_XZ = Math.max(X,Z);
1210
    float MAX_YZ = Math.max(Z,Y);
1211

    
1212
    Static1D angle = new Static1D(90);
1213
    Static3D move  = new Static3D( 0.0f, 0.0f, 0.5f);
1214
    Static3D axisX = new Static3D( 1.0f, 0.0f, 0.0f);
1215
    Static3D axisY = new Static3D( 0.0f, 1.0f, 0.0f);
1216
    Static3D center= new Static3D( 0.0f, 0.0f, 0.0f);
1217

    
1218
    Static3D scale3 = new Static3D(MAX_XY,MAX_XY,+Z);
1219
    Static3D scale4 = new Static3D(MAX_XY,MAX_XY,-Z);
1220
    Static3D scale5 = new Static3D(MAX_XZ,+Y,MAX_XZ);
1221
    Static3D scale6 = new Static3D(MAX_XZ,-Y,MAX_XZ);
1222
    Static3D scale7 = new Static3D(+X,MAX_YZ,MAX_YZ);
1223
    Static3D scale8 = new Static3D(-X,MAX_YZ,MAX_YZ);
1224

    
1225
    VertexEffect[] effect = new VertexEffect[9];
1226

    
1227
    effect[0] = new VertexEffectMove(move);
1228
    effect[1] = new VertexEffectRotate(angle, axisX, center);
1229
    effect[2] = new VertexEffectRotate(angle, axisY, center);
1230
    effect[3] = new VertexEffectScale(scale3);
1231
    effect[4] = new VertexEffectScale(scale4);
1232
    effect[5] = new VertexEffectScale(scale5);
1233
    effect[6] = new VertexEffectScale(scale6);
1234
    effect[7] = new VertexEffectScale(scale7);
1235
    effect[8] = new VertexEffectScale(scale8);
1236

    
1237
    effect[1].setMeshAssociation(12,-1);  // meshes 2,3
1238
    effect[2].setMeshAssociation( 3,-1);  // meshes 0,1
1239
    effect[3].setMeshAssociation(16,-1);  // mesh 4
1240
    effect[4].setMeshAssociation(32,-1);  // mesh 5
1241
    effect[5].setMeshAssociation( 8,-1);  // mesh 3
1242
    effect[6].setMeshAssociation( 4,-1);  // mesh 2
1243
    effect[7].setMeshAssociation( 1,-1);  // mesh 0
1244
    effect[8].setMeshAssociation( 2,-1);  // mesh 1
1245

    
1246
    return effect;
1247
    }
1248

    
1249
///////////////////////////////////////////////////////////////////////////////////////////////////
1250
// OBJECTS
1251
///////////////////////////////////////////////////////////////////////////////////////////////////
1252

    
1253
  public MeshBase createHelicopterFaceMesh()
1254
    {
1255
    MeshBase mesh = createFacesHelicopterFace();
1256
    VertexEffect[] effects = createVertexEffectsHelicopterFace();
1257
    for( VertexEffect effect : effects ) mesh.apply(effect);
1258

    
1259
    float E = 0.5f;
1260
    Static3D roundingCenter = new Static3D(-E/2 + E/3,-E/2 + E/3,-E/2);
1261

    
1262
    Static3D[] verticesType1 = new Static3D[1];
1263
    verticesType1[0] = new Static3D(E/3,E/3,0.0f);
1264
    roundCorners(mesh,roundingCenter,verticesType1,0.06f,0.15f);
1265

    
1266
    Static3D[] verticesType2 = new Static3D[2];
1267
    verticesType2[0] = new Static3D(-E+E/3, E/3  , 0);
1268
    verticesType2[1] = new Static3D( E/3  ,-E+E/3, 0);
1269
    roundCorners(mesh,roundingCenter,verticesType2,0.08f,0.20f);
1270

    
1271
    mesh.mergeEffComponents();
1272
    mesh.addEmptyTexComponent();
1273
    mesh.addEmptyTexComponent();
1274

    
1275
    return mesh;
1276
    }
1277

    
1278
///////////////////////////////////////////////////////////////////////////////////////////////////
1279
// Redi cube
1280

    
1281
  public MeshBase createRediEdgeMesh()
1282
    {
1283
    MeshBase mesh = createFacesRediEdge();
1284
    VertexEffect[] effects = createVertexEffectsRediEdge();
1285
    for( VertexEffect effect : effects ) mesh.apply(effect);
1286

    
1287
    Static3D center = new Static3D(0.0f,-0.75f,-0.75f);
1288
    Static3D[] vertices = new Static3D[2];
1289
    vertices[0] = new Static3D( 0.5f, 0.0f, 0.0f);
1290
    vertices[1] = new Static3D(-0.5f, 0.0f, 0.0f);
1291
    roundCorners(mesh,center,vertices,0.06f,0.20f);
1292

    
1293
    mesh.mergeEffComponents();
1294

    
1295
    return mesh;
1296
    }
1297

    
1298
///////////////////////////////////////////////////////////////////////////////////////////////////
1299

    
1300
  public MeshBase createRediCornerMesh()
1301
    {
1302
    MeshBase mesh = createFacesRediCorner();
1303
    VertexEffect[] effects = createVertexEffectsRediCorner();
1304
    for( VertexEffect effect : effects ) mesh.apply(effect);
1305

    
1306
    Static3D center = new Static3D(0,0,0);
1307
    Static3D[] vertices = new Static3D[8];
1308
    vertices[0] = new Static3D(+0.5f,+0.5f,+0.5f);
1309
    vertices[1] = new Static3D(+0.5f,+0.5f,-0.5f);
1310
    vertices[2] = new Static3D(+0.5f,-0.5f,+0.5f);
1311
    vertices[3] = new Static3D(+0.5f,-0.5f,-0.5f);
1312
    vertices[4] = new Static3D(-0.5f,+0.5f,+0.5f);
1313
    vertices[5] = new Static3D(-0.5f,+0.5f,-0.5f);
1314
    vertices[6] = new Static3D(-0.5f,-0.5f,+0.5f);
1315
    vertices[7] = new Static3D(-0.5f,-0.5f,-0.5f);
1316

    
1317
    roundCorners(mesh,center,vertices,0.06f,0.12f);
1318

    
1319
    mesh.mergeEffComponents();
1320

    
1321
    return mesh;
1322
    }
1323

    
1324
///////////////////////////////////////////////////////////////////////////////////////////////////
1325

    
1326
  public MeshBase createIvyCornerMesh()
1327
    {
1328
    MeshBase mesh = createFacesIvyCorner();
1329
    VertexEffect[] effects = createVertexEffectsIvyCorner();
1330
    for( VertexEffect effect : effects ) mesh.apply(effect);
1331

    
1332
    Static3D center = new Static3D(-0.5f,-0.5f,-0.5f);
1333
    Static3D[] vertices = new Static3D[4];
1334
    vertices[0] = new Static3D(+0.0f,+0.0f,+0.0f);
1335
    vertices[1] = new Static3D(-1.0f,+0.0f,+0.0f);
1336
    vertices[2] = new Static3D(+0.0f,-1.0f,+0.0f);
1337
    vertices[3] = new Static3D(+0.0f,+0.0f,-1.0f);
1338

    
1339
    roundCorners(mesh,center,vertices,0.03f,0.10f);
1340

    
1341
    mesh.mergeEffComponents();
1342

    
1343
    return mesh;
1344
    }
1345

    
1346
///////////////////////////////////////////////////////////////////////////////////////////////////
1347

    
1348
  public MeshBase createIvyFaceMesh()
1349
    {
1350
    MeshBase mesh = createFacesIvyFace();
1351

    
1352
    Static3D center = new Static3D(-0.0f,-0.0f,-0.5f);
1353
    Static3D[] vertices = new Static3D[2];
1354
    vertices[0] = new Static3D(-0.5f,+0.5f,+0.0f);
1355
    vertices[1] = new Static3D(+0.5f,-0.5f,+0.0f);
1356

    
1357
    roundCorners(mesh,center,vertices,0.03f,0.10f);
1358

    
1359
    mesh.mergeEffComponents();
1360
    mesh.addEmptyTexComponent();
1361
    mesh.addEmptyTexComponent();
1362
    mesh.addEmptyTexComponent();
1363
    mesh.addEmptyTexComponent();
1364

    
1365
    return mesh;
1366
    }
1367

    
1368
///////////////////////////////////////////////////////////////////////////////////////////////////
1369

    
1370
  public MeshBase createRexCornerMesh()
1371
    {
1372
    MeshBase mesh = createFacesRexCorner();
1373
    VertexEffect[] effects = createVertexEffectsRexCorner();
1374
    for( VertexEffect effect : effects ) mesh.apply(effect);
1375

    
1376
    final float G = (1-REX_D)/3;
1377
    Static3D center = new Static3D(0.0f,0.0f,-G*SQ2/2);
1378
    Static3D[] vertices = new Static3D[1];
1379
    vertices[0] = new Static3D(+G,-G,+0.0f);
1380
    roundCorners(mesh,center,vertices,0.10f,0.10f);
1381

    
1382
    mesh.mergeEffComponents();
1383
    mesh.addEmptyTexComponent();
1384
    mesh.addEmptyTexComponent();
1385
    mesh.addEmptyTexComponent();
1386
    mesh.addEmptyTexComponent();
1387

    
1388
    return mesh;
1389
    }
1390

    
1391
///////////////////////////////////////////////////////////////////////////////////////////////////
1392

    
1393
  public MeshBase createRexFaceMesh()
1394
    {
1395
    MeshBase mesh = createFacesRexFace();
1396

    
1397
    mesh.mergeEffComponents();
1398
    mesh.addEmptyTexComponent();
1399
    mesh.addEmptyTexComponent();
1400
    mesh.addEmptyTexComponent();
1401
    mesh.addEmptyTexComponent();
1402

    
1403
    return mesh;
1404
    }
1405

    
1406
///////////////////////////////////////////////////////////////////////////////////////////////////
1407

    
1408
  public MeshBase createRexEdgeMesh()
1409
    {
1410
    MeshBase mesh = createFacesRexEdge();
1411
    VertexEffect[] effects = createVertexEffectsRexEdge();
1412
    for( VertexEffect effect : effects ) mesh.apply(effect);
1413

    
1414
    Static3D center = new Static3D(0.0f,-0.5f,-0.5f);
1415
    Static3D[] vertices = new Static3D[2];
1416
    vertices[0] = new Static3D(+0.5f,+0.0f,+0.0f);
1417
    vertices[1] = new Static3D(-0.5f,+0.0f,+0.0f);
1418
    roundCorners(mesh,center,vertices,0.06f,0.10f);
1419

    
1420
    mesh.mergeEffComponents();
1421

    
1422
    return mesh;
1423
    }
1424

    
1425
///////////////////////////////////////////////////////////////////////////////////////////////////
1426

    
1427
  public MeshBase createKilominxCenterMesh(float width)
1428
    {
1429
    MeshBase mesh = createFacesKilominxCenter();
1430
    VertexEffect[] effects = createVertexEffectsKilominxCenter(width);
1431
    for( VertexEffect effect : effects ) mesh.apply(effect);
1432

    
1433
    float A = (2*SQ3/3)* SIN54;
1434
    float B = 0.4f;
1435
    float X = SIN_HALFD * SIN54 *COS54  ;
1436
    float Y = SIN54 * SIN54 - 0.5f;
1437
    float Z = COS_HALFD* SIN54 *COS54  ;
1438

    
1439
    Static3D center = new Static3D(0.0f, -(float)Math.sqrt(1-A*A)*B,-A*B);
1440

    
1441
    Static3D[] vertices = new Static3D[4];
1442
    vertices[0] = new Static3D( 0.0f, 0.0f, 0.0f);
1443
    vertices[1] = new Static3D( 0.0f,-0.5f, 0.0f);
1444
    vertices[2] = new Static3D(-X   , Y   ,-Z   );
1445
    vertices[3] = new Static3D(+X   , Y   ,-Z   );
1446

    
1447
    roundCorners(mesh,center,vertices,0.03f,0.10f);
1448

    
1449
    mesh.mergeEffComponents();
1450

    
1451
    return mesh;
1452
    }
1453

    
1454
///////////////////////////////////////////////////////////////////////////////////////////////////
1455
// numLayers==3 --> index=0; numLayers=5 --> index=1 ...
1456
// type: 0,1,... 0 --> edge, 1 --> 1 layer deeper, etc
1457

    
1458
  public MeshBase createKilominxEdgeMesh(int numLayers, float width, float height, boolean left)
1459
    {
1460
    MeshBase mesh = createFacesKilominxEdge(numLayers,width,height);
1461
    VertexEffect[] effects = createVertexEffectsKilominxEdge(width,height,left);
1462
    for( VertexEffect effect : effects ) mesh.apply(effect);
1463

    
1464
// round...
1465

    
1466
    mesh.mergeEffComponents();
1467

    
1468
    return mesh;
1469
    }
1470

    
1471
///////////////////////////////////////////////////////////////////////////////////////////////////
1472

    
1473
  public MeshBase createMinxCornerMesh(int numLayers, float width)
1474
    {
1475
    MeshBase mesh = createFacesMinxCorner(numLayers);
1476
    VertexEffect[] effects = createVertexEffectsMinxCorner(width);
1477
    for( VertexEffect effect : effects ) mesh.apply(effect);
1478

    
1479
    float A = (2*SQ3/3)* SIN54;
1480
    float B = 0.4f;
1481
/*
1482
    float X = SIN_HALFD* SIN54 * COS54;
1483
    float Y = SIN54 * SIN54 - 0.5f;
1484
    float Z = COS_HALFD* SIN54 * COS54;
1485
    float S = 2*width;
1486
*/
1487
    Static3D center = new Static3D(0.0f, -(float)Math.sqrt(1-A*A)*B,-A*B);
1488
    Static3D[] vertices = new Static3D[1];
1489
    vertices[0] = new Static3D( 0.0f, 0.0f  , 0.0f);
1490
/*
1491
    vertices[1] = new Static3D( 0.0f,-0.5f*S, 0.0f);
1492
    vertices[2] = new Static3D(-X*S , Y*S   ,-Z*S );
1493
    vertices[3] = new Static3D(+X*S , Y*S   ,-Z*S );
1494
*/
1495
    roundCorners(mesh,center,vertices,0.04f,0.10f);
1496

    
1497
    mesh.mergeEffComponents();
1498

    
1499
    return mesh;
1500
    }
1501

    
1502
///////////////////////////////////////////////////////////////////////////////////////////////////
1503
// numLayers==3 --> index=0; numLayers=5 --> index=1 ...
1504
// type: 0,1,... 0 --> edge, 1 --> 1 layer deeper, etc
1505

    
1506
  public MeshBase createMegaminxEdgeMesh(int numLayers, float width, float height)
1507
    {
1508
    MeshBase mesh = createFacesMegaminxEdge(numLayers,width,height);
1509
    VertexEffect[] effects = createVertexEffectsMegaminxEdge(width,height);
1510
    for( VertexEffect effect : effects ) mesh.apply(effect);
1511

    
1512
    mesh.mergeEffComponents();
1513

    
1514
    return mesh;
1515
    }
1516

    
1517
///////////////////////////////////////////////////////////////////////////////////////////////////
1518

    
1519
  public MeshBase createMegaminxCenterMesh(int numLayers, float width)
1520
    {
1521
    MeshBase mesh = createFacesMegaminxCenter(numLayers);
1522
    VertexEffect[] effects = createVertexEffectsMegaminxCenter(width);
1523
    for( VertexEffect effect : effects ) mesh.apply(effect);
1524

    
1525
    mesh.mergeEffComponents();
1526
    mesh.addEmptyTexComponent();
1527
    mesh.addEmptyTexComponent();
1528
    mesh.addEmptyTexComponent();
1529
    mesh.addEmptyTexComponent();
1530

    
1531
    return mesh;
1532
    }
1533

    
1534
///////////////////////////////////////////////////////////////////////////////////////////////////
1535

    
1536
  public MeshBase createCuboidMesh(int[] dimensions)
1537
    {
1538
    MeshBase mesh = createCuboid(dimensions);
1539
    VertexEffect[] effects = createCuboidEffects(dimensions);
1540
    for( VertexEffect effect : effects ) mesh.apply(effect);
1541

    
1542
    int X = dimensions[0];
1543
    int Y = dimensions[1];
1544
    int Z = dimensions[2];
1545

    
1546
    float strength = 0.04f;
1547
    float radius   = 0.15f;
1548

    
1549
    Static3D[] vertices = new Static3D[1];
1550
    Static3D center;
1551

    
1552
    vertices[0] = new Static3D(+0.5f*X,+0.5f*Y,+0.5f*Z);
1553
    center = new Static3D(+0.5f*(X-1),+0.5f*(Y-1),+0.5f*(Z-1));
1554
    roundCorners(mesh, center, vertices, strength, radius);
1555

    
1556
    vertices[0] = new Static3D(+0.5f*X,+0.5f*Y,-0.5f*Z);
1557
    center = new Static3D(+0.5f*(X-1),+0.5f*(Y-1),-0.5f*(Z-1));
1558
    roundCorners(mesh, center, vertices, strength, radius);
1559

    
1560
    vertices[0] = new Static3D(+0.5f*X,-0.5f*Y,+0.5f*Z);
1561
    center = new Static3D(+0.5f*(X-1),-0.5f*(Y-1),+0.5f*(Z-1));
1562
    roundCorners(mesh, center, vertices, strength, radius);
1563

    
1564
    vertices[0] = new Static3D(+0.5f*X,-0.5f*Y,-0.5f*Z);
1565
    center = new Static3D(+0.5f*(X-1),-0.5f*(Y-1),-0.5f*(Z-1));
1566
    roundCorners(mesh, center, vertices, strength, radius);
1567

    
1568
    vertices[0] = new Static3D(-0.5f*X,+0.5f*Y,+0.5f*Z);
1569
    center = new Static3D(-0.5f*(X-1),+0.5f*(Y-1),+0.5f*(Z-1));
1570
    roundCorners(mesh, center, vertices, strength, radius);
1571

    
1572
    vertices[0] = new Static3D(-0.5f*X,+0.5f*Y,-0.5f*Z);
1573
    center = new Static3D(-0.5f*(X-1),+0.5f*(Y-1),-0.5f*(Z-1));
1574
    roundCorners(mesh, center, vertices, strength, radius);
1575

    
1576
    vertices[0] = new Static3D(-0.5f*X,-0.5f*Y,+0.5f*Z);
1577
    center = new Static3D(-0.5f*(X-1),-0.5f*(Y-1),+0.5f*(Z-1));
1578
    roundCorners(mesh, center, vertices, strength, radius);
1579

    
1580
    vertices[0] = new Static3D(-0.5f*X,-0.5f*Y,-0.5f*Z);
1581
    center = new Static3D(-0.5f*(X-1),-0.5f*(Y-1),-0.5f*(Z-1));
1582
    roundCorners(mesh, center, vertices, strength, radius);
1583

    
1584
    mesh.mergeEffComponents();
1585

    
1586
    return mesh;
1587
    }
1588

    
1589

    
1590

    
1591

    
1592
///////////////////////////////////////////////////////////////////////////////////////////////////
1593

    
1594
  private boolean areColinear(double[][] vertices, int index1, int index2, int index3)
1595
    {
1596
    double x1 = vertices[index1][0];
1597
    double y1 = vertices[index1][1];
1598
    double z1 = vertices[index1][2];
1599
    double x2 = vertices[index2][0];
1600
    double y2 = vertices[index2][1];
1601
    double z2 = vertices[index2][2];
1602
    double x3 = vertices[index3][0];
1603
    double y3 = vertices[index3][1];
1604
    double z3 = vertices[index3][2];
1605

    
1606
    double v1x = x2-x1;
1607
    double v1y = y2-y1;
1608
    double v1z = z2-z1;
1609
    double v2x = x3-x1;
1610
    double v2y = y3-y1;
1611
    double v2z = z3-z1;
1612

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

    
1615
    return (v1x==A*v2x && v1y==A*v2y && v1z==A*v2z);
1616
    }
1617

    
1618
///////////////////////////////////////////////////////////////////////////////////////////////////
1619

    
1620
  private void computeNormalVector(double[][] vertices, int index1, int index2, int index3)
1621
    {
1622
    double x1 = vertices[index1][0];
1623
    double y1 = vertices[index1][1];
1624
    double z1 = vertices[index1][2];
1625
    double x2 = vertices[index2][0];
1626
    double y2 = vertices[index2][1];
1627
    double z2 = vertices[index2][2];
1628
    double x3 = vertices[index3][0];
1629
    double y3 = vertices[index3][1];
1630
    double z3 = vertices[index3][2];
1631

    
1632
    double v1x = x2-x1;
1633
    double v1y = y2-y1;
1634
    double v1z = z2-z1;
1635
    double v2x = x3-x1;
1636
    double v2y = y3-y1;
1637
    double v2z = z3-z1;
1638

    
1639
    mBuffer[0] = v1y*v2z - v2y*v1z;
1640
    mBuffer[1] = v1z*v2x - v2z*v1x;
1641
    mBuffer[2] = v1x*v2y - v2x*v1y;
1642

    
1643
    double len = mBuffer[0]*mBuffer[0] + mBuffer[1]*mBuffer[1] + mBuffer[2]*mBuffer[2];
1644
    len = Math.sqrt(len);
1645
    mBuffer[0] /= len;
1646
    mBuffer[1] /= len;
1647
    mBuffer[2] /= len;
1648
    }
1649

    
1650
///////////////////////////////////////////////////////////////////////////////////////////////////
1651
// return quat1*quat2
1652

    
1653
  private static void quatMultiply( double[] quat1, double[] quat2, double[] result )
1654
    {
1655
    double qx = quat1[0];
1656
    double qy = quat1[1];
1657
    double qz = quat1[2];
1658
    double qw = quat1[3];
1659

    
1660
    double rx = quat2[0];
1661
    double ry = quat2[1];
1662
    double rz = quat2[2];
1663
    double rw = quat2[3];
1664

    
1665
    result[0] = rw*qx - rz*qy + ry*qz + rx*qw;
1666
    result[1] = rw*qy + rz*qx + ry*qw - rx*qz;
1667
    result[2] = rw*qz + rz*qw - ry*qx + rx*qy;
1668
    result[3] = rw*qw - rz*qz - ry*qy - rx*qx;
1669
    }
1670

    
1671
///////////////////////////////////////////////////////////////////////////////////////////////////
1672

    
1673
  private void fitInSquare(FaceTransform info, double[][] vert3D)
1674
    {
1675
    double minX = Double.MAX_VALUE;
1676
    double maxX =-Double.MAX_VALUE;
1677
    double minY = Double.MAX_VALUE;
1678
    double maxY =-Double.MAX_VALUE;
1679

    
1680
    for (double[] vert : vert3D)
1681
      {
1682
      double x = vert[0];
1683
      double y = vert[1];
1684

    
1685
      if (x > maxX) maxX = x;
1686
      if (x < minX) minX = x;
1687
      if (y > maxY) maxY = y;
1688
      if (y < minY) minY = y;
1689
      }
1690

    
1691
    minX = minX<0 ? -minX:minX;
1692
    maxX = maxX<0 ? -maxX:maxX;
1693
    minY = minY<0 ? -minY:minY;
1694
    maxY = maxY<0 ? -maxY:maxY;
1695

    
1696
    double max1 = Math.max(minX,minY);
1697
    double max2 = Math.max(maxX,maxY);
1698
    double max3 = Math.max(max1,max2);
1699

    
1700
    info.scale = max3/0.5;
1701

    
1702
    int len = vert3D.length;
1703
    StickerCoords sInfo = new StickerCoords();
1704
    sInfo.vertices = new double[2*len];
1705

    
1706
    for( int vertex=0; vertex<len; vertex++ )
1707
      {
1708
      sInfo.vertices[2*vertex  ] = vert3D[vertex][0] / info.scale;
1709
      sInfo.vertices[2*vertex+1] = vert3D[vertex][1] / info.scale;
1710
      }
1711

    
1712
    mStickerCoords.add(sInfo);
1713

    
1714
    info.sticker = mStickerCoords.size() -1;
1715
    info.flip = false;
1716
    }
1717

    
1718
///////////////////////////////////////////////////////////////////////////////////////////////////
1719

    
1720
  private FaceTransform constructNewTransform(final double[][] vert3D)
1721
    {
1722
    FaceTransform ft = new FaceTransform();
1723

    
1724
    // compute center of gravity
1725
    ft.vx = 0.0f;
1726
    ft.vy = 0.0f;
1727
    ft.vz = 0.0f;
1728
    int len = vert3D.length;
1729

    
1730
    for (double[] vert : vert3D)
1731
      {
1732
      ft.vx += vert[0];
1733
      ft.vy += vert[1];
1734
      ft.vz += vert[2];
1735
      }
1736

    
1737
    ft.vx /= len;
1738
    ft.vy /= len;
1739
    ft.vz /= len;
1740

    
1741
    // move all vertices so that their center of gravity is at (0,0,0)
1742
    for (int i=0; i<len; i++)
1743
      {
1744
      vert3D[i][0] -= ft.vx;
1745
      vert3D[i][1] -= ft.vy;
1746
      vert3D[i][2] -= ft.vz;
1747
      }
1748

    
1749
    // find 3 non-colinear vertices
1750
    int foundIndex = -1;
1751

    
1752
    for(int vertex=2; vertex<len; vertex++)
1753
      {
1754
      if( !areColinear(vert3D,0,1,vertex) )
1755
        {
1756
        foundIndex = vertex;
1757
        break;
1758
        }
1759
      }
1760

    
1761
    // compute the normal vector
1762
    if( foundIndex==-1 )
1763
      {
1764
      throw new RuntimeException("all vertices colinear");
1765
      }
1766

    
1767
    computeNormalVector(vert3D,0,1,foundIndex);
1768

    
1769
    // rotate so that the normal vector becomes (0,0,1)
1770
    double axisX, axisY, axisZ;
1771

    
1772
    if( mBuffer[0]!=0.0f || mBuffer[1]!=0.0f )
1773
      {
1774
      axisX = -mBuffer[1];
1775
      axisY =  mBuffer[0];
1776
      axisZ = 0.0f;
1777

    
1778
      double axiLen = axisX*axisX + axisY*axisY;
1779
      axiLen = Math.sqrt(axiLen);
1780
      axisX /= axiLen;
1781
      axisY /= axiLen;
1782
      axisZ /= axiLen;
1783
      }
1784
    else
1785
      {
1786
      axisX = 0.0f;
1787
      axisY = 1.0f;
1788
      axisZ = 0.0f;
1789
      }
1790

    
1791
    double cosTheta = mBuffer[2];
1792
    double sinTheta = Math.sqrt(1-cosTheta*cosTheta);
1793
    double sinHalfTheta = computeSinHalf(cosTheta);
1794
    double cosHalfTheta = computeCosHalf(sinTheta,cosTheta);
1795

    
1796
    mQuat1[0] = axisX*sinHalfTheta;
1797
    mQuat1[1] = axisY*sinHalfTheta;
1798
    mQuat1[2] = axisZ*sinHalfTheta;
1799
    mQuat1[3] = cosHalfTheta;
1800
    mQuat2[0] =-axisX*sinHalfTheta;
1801
    mQuat2[1] =-axisY*sinHalfTheta;
1802
    mQuat2[2] =-axisZ*sinHalfTheta;
1803
    mQuat2[3] = cosHalfTheta;
1804

    
1805
    for (double[] vert : vert3D)
1806
      {
1807
      quatMultiply(mQuat1, vert  , mQuat3);
1808
      quatMultiply(mQuat3, mQuat2, vert  );
1809
      }
1810

    
1811
    // fit the whole thing in a square and remember the scale & 2D vertices
1812
    fitInSquare(ft, vert3D);
1813

    
1814
    // remember the rotation
1815
    ft.qx =-mQuat1[0];
1816
    ft.qy =-mQuat1[1];
1817
    ft.qz =-mQuat1[2];
1818
    ft.qw = mQuat1[3];
1819

    
1820
    return ft;
1821
    }
1822

    
1823
///////////////////////////////////////////////////////////////////////////////////////////////////
1824

    
1825
  private double computeCos(double oldX, double oldY, double newX, double newY, double len1, double len2)
1826
    {
1827
    double ret= (oldX*newX+oldY*newY) / (len1*len2);
1828
    if( ret<-1.0 ) return -1.0;
1829
    if( ret> 1.0 ) return  1.0;
1830

    
1831
    return ret;
1832
    }
1833

    
1834
///////////////////////////////////////////////////////////////////////////////////////////////////
1835
// sin of (signed!) angle between vectors 'old' and 'new', counterclockwise!
1836

    
1837
  private double computeSin(double oldX, double oldY, double newX, double newY, double len1, double len2)
1838
    {
1839
    double ret= (newX*oldY-oldX*newY) / (len1*len2);
1840
    if( ret<-1.0 ) return -1.0;
1841
    if( ret> 1.0 ) return  1.0;
1842

    
1843
    return ret;
1844
    }
1845

    
1846
///////////////////////////////////////////////////////////////////////////////////////////////////
1847

    
1848
  private void rotateAllVertices(double[] result, int len, double[] vertices, double sin, double cos)
1849
    {
1850
    for(int i=0; i<len; i++)
1851
      {
1852
      result[2*i  ] = vertices[2*i  ]*cos - vertices[2*i+1]*sin;
1853
      result[2*i+1] = vertices[2*i  ]*sin + vertices[2*i+1]*cos;
1854
      }
1855
    }
1856

    
1857
///////////////////////////////////////////////////////////////////////////////////////////////////
1858

    
1859
  private double computeScale(double[] v1, double[] v2, int v1i, int v2i)
1860
    {
1861
    double v1x = v1[2*v1i];
1862
    double v1y = v1[2*v1i+1];
1863
    double v2x = v2[2*v2i];
1864
    double v2y = v2[2*v2i+1];
1865

    
1866
    double lenSq1 = v1x*v1x + v1y*v1y;
1867
    double lenSq2 = v2x*v2x + v2y*v2y;
1868

    
1869
    return Math.sqrt(lenSq2/lenSq1);
1870
    }
1871

    
1872
///////////////////////////////////////////////////////////////////////////////////////////////////
1873
// valid for 0<angle<2*PI
1874

    
1875
  private double computeSinHalf(double cos)
1876
    {
1877
    return Math.sqrt((1-cos)/2);
1878
    }
1879

    
1880
///////////////////////////////////////////////////////////////////////////////////////////////////
1881
// valid for 0<angle<2*PI
1882

    
1883
  private double computeCosHalf(double sin, double cos)
1884
    {
1885
    double cosHalf = Math.sqrt((1+cos)/2);
1886
    return sin<0 ? -cosHalf : cosHalf;
1887
    }
1888

    
1889
///////////////////////////////////////////////////////////////////////////////////////////////////
1890

    
1891
  private int computeRotatedIndex(int oldVertex, int len, int rotatedVertex, boolean inverted)
1892
    {
1893
    int v = (rotatedVertex + (inverted? -oldVertex : oldVertex));
1894
    if( v>=len ) v-=len;
1895
    if( v< 0   ) v+=len;
1896

    
1897
    return v;
1898
    }
1899

    
1900
///////////////////////////////////////////////////////////////////////////////////////////////////
1901

    
1902
  private boolean isScaledVersionOf(double[] newVert, double[] oldVert, int len, int vertex, boolean inverted)
1903
    {
1904
    int newZeroIndex = computeRotatedIndex(0,len,vertex,inverted);
1905
    double EPSILON = 0.001;
1906
    double scale = computeScale(newVert,oldVert,newZeroIndex,0);
1907

    
1908
    for(int i=1; i<len; i++)
1909
      {
1910
      int index = computeRotatedIndex(i,len,vertex,inverted);
1911

    
1912
      double horz = oldVert[2*i  ] - scale*newVert[2*index  ];
1913
      double vert = oldVert[2*i+1] - scale*newVert[2*index+1];
1914

    
1915
      if( horz>EPSILON || horz<-EPSILON || vert>EPSILON || vert<-EPSILON ) return false;
1916
      }
1917

    
1918
    return true;
1919
    }
1920

    
1921
///////////////////////////////////////////////////////////////////////////////////////////////////
1922

    
1923
  private void mirrorAllVertices(double[] output, int len, double[] input)
1924
    {
1925
    for(int vertex=0; vertex<len; vertex++)
1926
      {
1927
      output[2*vertex  ] = input[2*vertex  ];
1928
      output[2*vertex+1] =-input[2*vertex+1];
1929
      }
1930
    }
1931

    
1932
///////////////////////////////////////////////////////////////////////////////////////////////////
1933

    
1934
  private void correctInfo(FaceTransform info, double scale, double sin, double cos, int oldSticker, boolean flip)
1935
    {
1936
    mStickerCoords.remove(info.sticker);
1937

    
1938
    info.flip    = flip;
1939
    info.sticker = oldSticker;
1940
    info.scale  *= scale;
1941

    
1942
    mQuat1[0] = info.qx;
1943
    mQuat1[1] = info.qy;
1944
    mQuat1[2] = info.qz;
1945
    mQuat1[3] = info.qw;
1946

    
1947
    double sinHalf = computeSinHalf(cos);
1948
    double cosHalf = computeCosHalf(sin,cos);
1949

    
1950
    if( flip )
1951
      {
1952
      mQuat3[0] = 0.0f;
1953
      mQuat3[1] = 0.0f;
1954
      mQuat3[2] = sinHalf;
1955
      mQuat3[3] = cosHalf;
1956

    
1957
      mQuat4[0] = 1.0;
1958
      mQuat4[1] = 0.0;
1959
      mQuat4[2] = 0.0;
1960
      mQuat4[3] = 0.0;
1961

    
1962
      quatMultiply( mQuat3, mQuat4, mQuat2 );
1963
      }
1964
    else
1965
      {
1966
      mQuat2[0] = 0.0f;
1967
      mQuat2[1] = 0.0f;
1968
      mQuat2[2] = sinHalf;
1969
      mQuat2[3] = cosHalf;
1970
      }
1971

    
1972
    quatMultiply( mQuat1, mQuat2, mQuat3 );
1973

    
1974
    info.qx = mQuat3[0];
1975
    info.qy = mQuat3[1];
1976
    info.qz = mQuat3[2];
1977
    info.qw = mQuat3[3];
1978
    }
1979

    
1980
///////////////////////////////////////////////////////////////////////////////////////////////////
1981

    
1982
  private void printVert(double[] buffer)
1983
    {
1984
    int len = buffer.length/2;
1985
    String str = "";
1986

    
1987
    for(int i=0; i<len; i++)
1988
      {
1989
      str += (" ("+buffer[2*i]+" , "+buffer[2*i+1]+" ) ");
1990
      }
1991

    
1992
    android.util.Log.d("D", str);
1993
    }
1994

    
1995
///////////////////////////////////////////////////////////////////////////////////////////////////
1996

    
1997
  private boolean foundVertex(FaceTransform info, double[] buffer, int len, double[] newVert,
1998
                              double[] oldVert, double lenFirstOld, int oldSticker, boolean inverted)
1999
    {
2000
    for(int vertex=0; vertex<len; vertex++)
2001
      {
2002
      double newX = newVert[2*vertex  ];
2003
      double newY = newVert[2*vertex+1];
2004
      double lenIthNew = Math.sqrt(newX*newX + newY*newY);
2005
      double cos = computeCos( oldVert[0], oldVert[1], newX, newY, lenIthNew, lenFirstOld);
2006
      double sin = computeSin( oldVert[0], oldVert[1], newX, newY, lenIthNew, lenFirstOld);
2007

    
2008
      rotateAllVertices(buffer,len,newVert,sin,cos);
2009

    
2010
      if( isScaledVersionOf(buffer,oldVert,len,vertex,inverted) )
2011
        {
2012
        int newZeroIndex = computeRotatedIndex(0,len,vertex,inverted);
2013
        double scale = computeScale(oldVert,newVert,0,newZeroIndex);
2014
        correctInfo(info,scale,sin,cos,oldSticker,inverted);
2015
        return true;
2016
        }
2017
      }
2018

    
2019
    return false;
2020
    }
2021

    
2022
///////////////////////////////////////////////////////////////////////////////////////////////////
2023

    
2024
  private boolean successfullyCollapsedStickers(final FaceTransform newInfo, final FaceTransform oldInfo)
2025
    {
2026
    StickerCoords sNewInfo = mStickerCoords.get(newInfo.sticker);
2027
    StickerCoords sOldInfo = mStickerCoords.get(oldInfo.sticker);
2028
    double[] newVert = sNewInfo.vertices;
2029
    double[] oldVert = sOldInfo.vertices;
2030
    int oldLen = oldVert.length;
2031
    int newLen = newVert.length;
2032

    
2033
    if( oldLen == newLen )
2034
      {
2035
      int oldSticker = oldInfo.sticker;
2036
      double[] buffer1 = new double[oldLen];
2037
      double lenFirstOld = Math.sqrt(oldVert[0]*oldVert[0] + oldVert[1]*oldVert[1]);
2038
      if( foundVertex(newInfo, buffer1, oldLen/2, newVert, oldVert, lenFirstOld, oldSticker, false) ) return true;
2039
      double[] buffer2 = new double[oldLen];
2040
      mirrorAllVertices(buffer2, newLen/2, newVert);
2041
      if( foundVertex(newInfo, buffer1, oldLen/2, buffer2, oldVert, lenFirstOld, oldSticker, true ) ) return true;
2042
      }
2043

    
2044
    return false;
2045
    }
2046

    
2047
///////////////////////////////////////////////////////////////////////////////////////////////////
2048

    
2049
  private double[][] constructVert(double[][] vertices, int[] index)
2050
    {
2051
    int len = index.length;
2052
    double[][] ret = new double[len][4];
2053

    
2054
    for(int i=0; i<len; i++)
2055
      {
2056
      ret[i][0] = vertices[index[i]][0];
2057
      ret[i][1] = vertices[index[i]][1];
2058
      ret[i][2] = vertices[index[i]][2];
2059
      ret[i][3] = 1.0f;
2060
      }
2061

    
2062
    return ret;
2063
    }
2064

    
2065
///////////////////////////////////////////////////////////////////////////////////////////////////
2066

    
2067
  private void prepareAndRoundCorners(MeshBase mesh, double[][] vertices,
2068
                                      float[][] corners, int[] cornerIndexes,
2069
                                      float[][] centers, int[] centerIndexes )
2070
    {
2071
    int lenV = vertices.length;
2072
    Static3D[] staticVert = new Static3D[1];
2073
    Static3D center = new Static3D(0,0,0);
2074

    
2075
    for(int v=0; v<lenV; v++)
2076
      {
2077
      staticVert[0] = new Static3D( (float)vertices[v][0], (float)vertices[v][1], (float)vertices[v][2]);
2078

    
2079
      int cent = centerIndexes[v];
2080

    
2081
      if( cent>=0 )
2082
        {
2083
        center.set( centers[cent][0], centers[cent][1], centers[cent][2]);
2084

    
2085
        int corn = cornerIndexes[v];
2086
        float strength = corners[corn][0];
2087
        float radius   = corners[corn][1];
2088

    
2089
        roundCorners(mesh, center, staticVert, strength, radius);
2090
        }
2091
      }
2092
    }
2093

    
2094
///////////////////////////////////////////////////////////////////////////////////////////////////
2095

    
2096
  private void correctComponents(MeshBase mesh, int numComponents)
2097
    {
2098
    int numTexToBeAdded = numComponents-mesh.getNumTexComponents();
2099

    
2100
    mesh.mergeEffComponents();
2101

    
2102
    for(int i=0; i<numTexToBeAdded; i++ ) mesh.addEmptyTexComponent();
2103
    }
2104

    
2105
///////////////////////////////////////////////////////////////////////////////////////////////////
2106

    
2107
  private void printTransform(FaceTransform f)
2108
    {
2109
    android.util.Log.e("D", "q=("+f.qx+", "+f.qy+", "+f.qz+", "+f.qw+") v=("
2110
                       +f.vx+", "+f.vy+", "+f.vz+") scale="+f.scale+" sticker="+f.sticker);
2111
    }
2112

    
2113
///////////////////////////////////////////////////////////////////////////////////////////////////
2114
// PUBLIC
2115

    
2116
  public void printStickerCoords()
2117
    {
2118
    int stickers = mStickerCoords.size();
2119

    
2120
    android.util.Log.d("D", "---- STICKER COORDS ----");
2121

    
2122
    for(int s=0; s<stickers; s++)
2123
      {
2124
      String ver = "{ ";
2125
      StickerCoords info = mStickerCoords.get(s);
2126
      int len = info.vertices.length/2;
2127

    
2128
      for(int i =0; i<len; i++)
2129
        {
2130
        if( i!=0 ) ver += ", ";
2131
        ver += ( (float)info.vertices[2*i]+"f, "+(float)info.vertices[2*i+1]+"f");
2132
        }
2133

    
2134
      ver += " }";
2135
      android.util.Log.d("D", ver);
2136
      }
2137

    
2138
    android.util.Log.d("D", "---- END STICKER COORDS ----");
2139
    }
2140

    
2141
///////////////////////////////////////////////////////////////////////////////////////////////////
2142

    
2143
  public void printFaceTransform()
2144
    {
2145
    android.util.Log.d("D", "---- OLD FACE TRANSFORM ---");
2146

    
2147
    int oldfaces = mOldFaceTransf.size();
2148

    
2149
    for(int f=0; f<oldfaces; f++)
2150
      {
2151
      printTransform(mOldFaceTransf.get(f));
2152
      }
2153

    
2154
    android.util.Log.d("D", "---- NEW FACE TRANSFORM ---");
2155

    
2156
    int newfaces = mNewFaceTransf.size();
2157

    
2158
    for(int f=0; f<newfaces; f++)
2159
      {
2160
      printTransform(mNewFaceTransf.get(f));
2161
      }
2162
    }
2163

    
2164
///////////////////////////////////////////////////////////////////////////////////////////////////
2165

    
2166
  public void clear()
2167
    {
2168
    mStickerCoords.clear();
2169
    mNewFaceTransf.clear();
2170
    mOldFaceTransf.clear();
2171
    }
2172

    
2173
///////////////////////////////////////////////////////////////////////////////////////////////////
2174

    
2175
  public void createNewFaceTransform( final double[][] vertices, final int[][] indexes)
2176
    {
2177
    FaceTransform ft;
2178
    int numNew = mNewFaceTransf.size();
2179

    
2180
    for(int i=0; i<numNew; i++)
2181
      {
2182
      ft = mNewFaceTransf.remove(0);
2183
      mOldFaceTransf.add(ft);
2184
      }
2185

    
2186
    int numFaces = indexes.length;
2187
    int numOld = mOldFaceTransf.size();
2188

    
2189
    for (int face=0; face<numFaces; face++)
2190
      {
2191
      boolean collapsed = false;
2192

    
2193
      double[][] vert = constructVert(vertices, indexes[face]);
2194
      FaceTransform newT = constructNewTransform(vert);
2195

    
2196
      for (int old=0; !collapsed && old<numOld; old++)
2197
        {
2198
        ft = mOldFaceTransf.get(old);
2199
        if (successfullyCollapsedStickers(newT, ft)) collapsed = true;
2200
        }
2201

    
2202
      for (int pre=0; !collapsed && pre<face; pre++)
2203
        {
2204
        ft = mNewFaceTransf.get(pre);
2205
        if (successfullyCollapsedStickers(newT, ft)) collapsed = true;
2206
        }
2207

    
2208
      mNewFaceTransf.add(newT);
2209
      }
2210
    }
2211

    
2212
///////////////////////////////////////////////////////////////////////////////////////////////////
2213

    
2214
  public MeshBase createRoundedSolid(final double[][] vertices, final int[][] vertIndexes,
2215
                                     final float[][] bands    , final int[]   bandIndexes,
2216
                                     final float[][] corners  , final int[]   cornerIndexes,
2217
                                     final float[][] centers  , final int[]   centerIndexes,
2218
                                     final int numComponents )
2219
    {
2220
    int numFaces = vertIndexes.length;
2221
    float[] band, bandsComputed;
2222
    MeshBase[] meshes = new MeshBase[numFaces];
2223
    FaceTransform fInfo;
2224
    StickerCoords sInfo;
2225

    
2226
    for(int face=0; face<numFaces; face++)
2227
      {
2228
      fInfo = mNewFaceTransf.get(face);
2229
      sInfo = mStickerCoords.get(fInfo.sticker);
2230

    
2231
      double[] verts = sInfo.vertices;
2232
      int lenVerts = verts.length;
2233
      float[] vertsFloat = new float[lenVerts];
2234
      for(int i=0; i<lenVerts; i++) vertsFloat[i] = (float)verts[i];
2235

    
2236
      band = bands[bandIndexes[face]];
2237
      bandsComputed = computeBands( band[0], (int)band[1], band[2], band[3], (int)band[4]);
2238
      meshes[face] = new MeshPolygon(vertsFloat,bandsComputed,(int)band[5],(int)band[6]);
2239
      meshes[face].setEffectAssociation(0,(1<<face),0);
2240
      }
2241

    
2242
    MeshBase mesh = new MeshJoined(meshes);
2243
    Static3D center = new Static3D(0,0,0);
2244

    
2245
    for(int face=0; face<numFaces; face++)
2246
      {
2247
      int assoc = (1<<face);
2248
      fInfo = mNewFaceTransf.get(face);
2249

    
2250
      float vx = (float)fInfo.vx;
2251
      float vy = (float)fInfo.vy;
2252
      float vz = (float)fInfo.vz;
2253
      float sc = (float)fInfo.scale;
2254
      float qx = (float)fInfo.qx;
2255
      float qy = (float)fInfo.qy;
2256
      float qz = (float)fInfo.qz;
2257
      float qw = (float)fInfo.qw;
2258

    
2259
      Static3D scale = new Static3D(sc,sc, fInfo.flip ? -sc : sc);
2260
      Static3D move3D= new Static3D(vx,vy,vz);
2261
      Static4D quat  = new Static4D(qx,qy,qz,qw);
2262

    
2263
      mesh.apply(new MatrixEffectScale(scale)           ,assoc,-1);
2264
      mesh.apply(new MatrixEffectQuaternion(quat,center),assoc,-1);
2265
      mesh.apply(new MatrixEffectMove(move3D)           ,assoc,-1);
2266
      }
2267

    
2268
    prepareAndRoundCorners(mesh, vertices, corners, cornerIndexes, centers, centerIndexes);
2269

    
2270
    correctComponents(mesh,numComponents);
2271

    
2272
    return mesh;
2273
    }
2274
  }
(3-3/4)