Project

General

Profile

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

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

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 createFacesSkewbCorner()
244
    {
245
    MeshBase[] meshes = new MeshBase[6];
246

    
247
    float E = 0.5f;
248
    float F = SQ2/2;
249
    float G = SQ6/16;
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/3,0.7f,7);
252

    
253
    meshes[0] = new MeshPolygon(vertices0, bands0, 3, 3);
254
    meshes[0].setEffectAssociation(0,1,0);
255
    meshes[1] = meshes[0].copy(true);
256
    meshes[1].setEffectAssociation(0,2,0);
257
    meshes[2] = meshes[0].copy(true);
258
    meshes[2].setEffectAssociation(0,4,0);
259

    
260
    float[] vertices1 = { -F/2,-2*G, F/2,-2*G, 3*F/8,-G, 1*F/8,G, 0,2*G };
261
    float[] bands1 = computeBands(0,0,1,0,3);
262

    
263
    meshes[3] = new MeshPolygon(vertices1,bands1,1,5);
264
    meshes[3].setEffectAssociation(0,8,0);
265
    meshes[4] = meshes[3].copy(true);
266
    meshes[4].setEffectAssociation(0,16,0);
267
    meshes[5] = meshes[3].copy(true);
268
    meshes[5].setEffectAssociation(0,32,0);
269

    
270
    return new MeshJoined(meshes);
271
    }
272

    
273
///////////////////////////////////////////////////////////////////////////////////////////////////
274

    
275
  MeshBase createFacesSkewbFace()
276
    {
277
    MeshBase[] meshes = new MeshBase[5];
278

    
279
    float E = SQ2/4;
280
    float[] vertices0 = { -E,-E, +E,-E, +E,+E, -E,+E };
281
    float[] bands0 = computeBands(0.051f,35,E/2,0.9f,7);
282

    
283
    meshes[0] = new MeshPolygon(vertices0, bands0, 3, 3);
284
    meshes[0].setEffectAssociation(0,1,0);
285

    
286
    float[] vertices1 = { -E,-SQ3*E, -E*0.7f,-SQ3*E, +E*0.7f,-SQ3*E, +E,-SQ3*E, 0,0 };
287
    float[] bands1 = computeBands(0,0,1,0,3);
288

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

    
298
    return new MeshJoined(meshes);
299
    }
300

    
301
///////////////////////////////////////////////////////////////////////////////////////////////////
302

    
303
  MeshBase createFacesHelicopterCorner()
304
    {
305
    MeshBase[] meshes = new MeshBase[6];
306

    
307
    float E = 0.5f;
308
    float F = SQ2/4;
309
    float G = 1.0f/12;
310
    float[] vertices0 = { -E+E/4,E/4, E/4,-E+E/4, E/4,E/4};
311
    float[] bands0 = computeBands(0.028f,35,E/4,0.7f,7);
312

    
313
    meshes[0] = new MeshPolygon(vertices0, bands0, 3, 3);
314
    meshes[0].setEffectAssociation(0,1,0);
315
    meshes[1] = meshes[0].copy(true);
316
    meshes[1].setEffectAssociation(0,2,0);
317
    meshes[2] = meshes[0].copy(true);
318
    meshes[2].setEffectAssociation(0,4,0);
319

    
320
    float[] vertices1 = { -F,-G, 0,-G, +F,-G, 0,2*G };
321
    float[] bands1 = computeBands(0.00f,0,0,0.0f,3);
322
    meshes[3] = new MeshPolygon(vertices1,bands1,1,5);
323
    meshes[3].setEffectAssociation(0,8,0);
324
    meshes[4] = meshes[3].copy(true);
325
    meshes[4].setEffectAssociation(0,16,0);
326
    meshes[5] = meshes[3].copy(true);
327
    meshes[5].setEffectAssociation(0,32,0);
328

    
329
    return new MeshJoined(meshes);
330
    }
331

    
332
///////////////////////////////////////////////////////////////////////////////////////////////////
333

    
334
  MeshBase createFacesHelicopterFace()
335
    {
336
    MeshBase[] meshes = new MeshBase[4];
337

    
338
    float E = 0.5f;
339
    float F = SQ2/4;
340
    float G = 1.0f/12;
341
    float[] vertices0 = { -E+E/4,E/4, E/4,-E+E/4, E/4,E/4};
342
    float[] bands0 = computeBands(0.028f,35,E/4,0.7f,7);
343

    
344
    meshes[0] = new MeshPolygon(vertices0, bands0, 3, 3);
345
    meshes[0].setEffectAssociation(0,1,0);
346

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

    
350
    meshes[1] = new MeshPolygon(vertices1, bands1, 1, 3);
351
    meshes[1].setEffectAssociation(0,2,0);
352

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

    
355
    meshes[2] = new MeshPolygon(vertices2, bands1, 1, 3);
356
    meshes[2].setEffectAssociation(0,4,0);
357
    meshes[3] = meshes[2].copy(true);
358
    meshes[3].setEffectAssociation(0,8,0);
359

    
360
    return new MeshJoined(meshes);
361
    }
362

    
363
///////////////////////////////////////////////////////////////////////////////////////////////////
364

    
365
  MeshBase createFacesRediEdge()
366
    {
367
    MeshBase[] meshes = new MeshPolygon[6];
368

    
369
    float F = 0.25f;
370
    float[] vertices0 = { -F,+F, -F,-F, 0, -2*F, +F,-F, +F,+F };
371
    float[] bands0 = computeBands(0.038f,35,F,0.7f,7);
372

    
373
    meshes[0] = new MeshPolygon(vertices0, bands0, 2, 2);
374
    meshes[0].setEffectAssociation(0,1,0);
375
    meshes[1] = meshes[0].copy(true);
376
    meshes[1].setEffectAssociation(0,2,0);
377

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

    
381
    meshes[2] = new MeshPolygon(vertices1, bands1, 1, 2);
382
    meshes[2].setEffectAssociation(0,4,0);
383
    meshes[3] = meshes[2].copy(true);
384
    meshes[3].setEffectAssociation(0,8,0);
385

    
386
    float X = 0.25f*SQ2;
387
    float Y = SQ6/16;
388
    float[] vertices2 = { -X, Y, -1.5f*X, -Y, +1.5f*X, -Y, +X, Y };
389

    
390
    meshes[4] = new MeshPolygon(vertices2, bands1, 1, 1);
391
    meshes[4].setEffectAssociation(0,16,0);
392
    meshes[5] = meshes[4].copy(true);
393
    meshes[5].setEffectAssociation(0,32,0);
394

    
395
    return new MeshJoined(meshes);
396
    }
397

    
398
///////////////////////////////////////////////////////////////////////////////////////////////////
399

    
400
  MeshBase createFacesRediCorner()
401
    {
402
    MeshBase[] meshes = new MeshBase[6];
403

    
404
    float E = 0.5f;
405
    float[] vertices0 = { -E,-E, +E,-E, +E,+E, -E,+E };
406
    float[] bands0 = computeBands(0.06f,35,E,0.7f,6);
407

    
408
    meshes[0] = new MeshPolygon(vertices0,bands0,2,2);
409
    meshes[0].setEffectAssociation(0,1,0);
410
    meshes[1] = meshes[0].copy(true);
411
    meshes[1].setEffectAssociation(0,2,0);
412
    meshes[2] = meshes[0].copy(true);
413
    meshes[2].setEffectAssociation(0,4,0);
414

    
415
    float F = 0.5f;
416
    float X = 0.5f;
417
    float G = 0.72f;
418
    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 };
419
    float[] bands1 = computeBands(0.0f,0,1.0f,0.0f,2);
420

    
421
    meshes[3] = new MeshPolygon(vertices1,bands1,0,0);
422
    meshes[3].setEffectAssociation(0,8,0);
423
    meshes[4] = meshes[3].copy(true);
424
    meshes[4].setEffectAssociation(0,16,0);
425
    meshes[5] = meshes[3].copy(true);
426
    meshes[5].setEffectAssociation(0,32,0);
427

    
428
    return new MeshJoined(meshes);
429
    }
430

    
431
///////////////////////////////////////////////////////////////////////////////////////////////////
432

    
433
  MeshBase createFacesIvyCorner()
434
    {
435
    MeshBase[] meshes = new MeshBase[6];
436

    
437
    final float angle = (float)Math.PI/(2*IVY_N);
438
    final float CORR  = 1.0f - 2*IVY_D;
439
    final float DIST  = -0.5f*CORR + IVY_D;
440
    float[] vertices  = new float[2*(IVY_N+1)+6];
441

    
442
    vertices[0] = (0.5f-IVY_M) * IVY_C;
443
    vertices[1] = (DIST-IVY_M) * IVY_C;
444
    vertices[2] = (0.5f-IVY_M) * IVY_C;
445
    vertices[3] = (0.5f-IVY_M) * IVY_C;
446
    vertices[4] = (DIST-IVY_M) * IVY_C;
447
    vertices[5] = (0.5f-IVY_M) * IVY_C;
448

    
449
    for(int i=0; i<=IVY_N; i++)
450
      {
451
      float ang = (IVY_N-i)*angle;
452
      float sin = (float)Math.sin(ang);
453
      float cos = (float)Math.cos(ang);
454

    
455
      vertices[2*i+6] = (CORR*(cos-0.5f)-IVY_M)*IVY_C;
456
      vertices[2*i+7] = (CORR*(sin-0.5f)-IVY_M)*IVY_C;
457
      }
458

    
459
    float[] bands0 = computeBands(+0.012f,20,0.2f,0.5f,7);
460
    float[] bands1 = computeBands(-0.100f,20,0.2f,0.0f,2);
461

    
462
    meshes[0] = new MeshPolygon(vertices,bands0,1,2);
463
    meshes[0].setEffectAssociation(0,1,0);
464
    meshes[1] = meshes[0].copy(true);
465
    meshes[1].setEffectAssociation(0,2,0);
466
    meshes[2] = meshes[0].copy(true);
467
    meshes[2].setEffectAssociation(0,4,0);
468
    meshes[3] = new MeshPolygon(vertices,bands1,1,2);
469
    meshes[3].setEffectAssociation(0,8,0);
470
    meshes[4] = meshes[3].copy(true);
471
    meshes[4].setEffectAssociation(0,16,0);
472
    meshes[5] = meshes[3].copy(true);
473
    meshes[5].setEffectAssociation(0,32,0);
474

    
475
    return new MeshJoined(meshes);
476
    }
477

    
478
///////////////////////////////////////////////////////////////////////////////////////////////////
479

    
480
  MeshBase createFacesIvyFace()
481
    {
482
    MeshBase[] meshes = new MeshBase[2];
483

    
484
    final float angle = (float)Math.PI/(2*IVY_N);
485
    final float CORR  = 1.0f - 2*IVY_D;
486
    float[] vertices = new float[4*IVY_N];
487

    
488
    for(int i=0; i<IVY_N; i++)
489
      {
490
      float sin = (float)Math.sin(i*angle);
491
      float cos = (float)Math.cos(i*angle);
492

    
493
      vertices[2*i          ] = CORR*(0.5f-cos);
494
      vertices[2*i+1        ] = CORR*(0.5f-sin);
495
      vertices[2*i  +2*IVY_N] = CORR*(cos-0.5f);
496
      vertices[2*i+1+2*IVY_N] = CORR*(sin-0.5f);
497
      }
498

    
499
    float[] bands0 = computeBands(+0.03f,35,0.5f,0.5f,5);
500
    float[] bands1 = computeBands(-0.10f,45,0.5f,0.0f,2);
501

    
502
    meshes[0] = new MeshPolygon(vertices,bands0,0,0);
503
    meshes[0].setEffectAssociation(0,1,0);
504
    meshes[1] = new MeshPolygon(vertices,bands1,0,0);
505
    meshes[1].setEffectAssociation(0,2,0);
506

    
507
    return new MeshJoined(meshes);
508
    }
509

    
510
///////////////////////////////////////////////////////////////////////////////////////////////////
511

    
512
  MeshBase createFacesRexCorner()
513
    {
514
    MeshBase[] meshes = new MeshBase[2];
515

    
516
    float F = REX_D*SQ2;
517
    float G = (1-REX_D)*SQ2/2;
518
    float H = 0.1f;
519
    float J = +2*G/3 - H*G;
520

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

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

    
526
    meshes[0] = new MeshPolygon(vertices,bands0,1,1);
527
    meshes[0].setEffectAssociation(0,1,0);
528
    meshes[1] = new MeshPolygon(vertices,bands1,0,0);
529
    meshes[1].setEffectAssociation(0,2,0);
530

    
531
    return new MeshJoined(meshes);
532
    }
533

    
534
///////////////////////////////////////////////////////////////////////////////////////////////////
535

    
536
  MeshBase createFacesRexFace()
537
    {
538
    MeshBase[] meshes = new MeshBase[2];
539

    
540
    float[] vertices = { -REX_D,0.0f, 0.0f, -REX_D, +REX_D, 0.0f, 0.0f, +REX_D};
541

    
542
    float[] bands0 = computeBands(0.016f,10,REX_D/2,0.5f,5);
543
    float[] bands1 = computeBands(0.000f,45,REX_D/2,0.0f,2);
544

    
545
    meshes[0] = new MeshPolygon(vertices,bands0,0,0);
546
    meshes[0].setEffectAssociation(0,1,0);
547
    meshes[1] = new MeshPolygon(vertices,bands1,0,0);
548
    meshes[1].setEffectAssociation(0,2,0);
549

    
550
    return new MeshJoined(meshes);
551
    }
552

    
553
///////////////////////////////////////////////////////////////////////////////////////////////////
554

    
555
  MeshBase createFacesRexEdge()
556
    {
557
    MeshBase[] meshes = new MeshPolygon[6];
558

    
559
    float E = 0.5f - REX_D;
560
    float F = 0.5f;
561
    float[] vertices0 = { -F,E/3, 0,-2*E/3, +F,E/3 };
562
    float[] bands0 = computeBands(0.03f,27,F/3,0.8f,5);
563

    
564
    meshes[0] = new MeshPolygon(vertices0, bands0, 2, 3);
565
    meshes[0].setEffectAssociation(0,1,0);
566
    meshes[1] = meshes[0].copy(true);
567
    meshes[1].setEffectAssociation(0,2,0);
568

    
569
    float G = (float)Math.sqrt(E*E+F*F);
570
    float[] vertices1 = { -2*G/3, -E/3, G/3, -E/3, G/3, 2*E/3 };
571
    float[] bands1 = computeBands(0.00f,45,G/3,0.2f,3);
572

    
573
    meshes[2] = new MeshPolygon(vertices1, bands1, 1, 2);
574
    meshes[2].setEffectAssociation(0,4,0);
575
    meshes[3] = meshes[2].copy(true);
576
    meshes[3].setEffectAssociation(0,8,0);
577
    meshes[4] = meshes[2].copy(true);
578
    meshes[4].setEffectAssociation(0,16,0);
579
    meshes[5] = meshes[2].copy(true);
580
    meshes[5].setEffectAssociation(0,32,0);
581

    
582
    return new MeshJoined(meshes);
583
    }
584

    
585
///////////////////////////////////////////////////////////////////////////////////////////////////
586

    
587
  MeshBase createFacesKilominxCenter()
588
    {
589
    MeshBase[] meshes = new MeshPolygon[6];
590

    
591
    float X1= 0.5f*SIN54;
592
    float Y1= 0.5f*SIN_HALFD;
593
    float Y2= Y1 - 0.5f*COS54;
594
    float H = 0.5f* SIN54 /COS54  ;
595
    float X2= MINX_SC*H* SIN_HALFD;
596
    float Y3= MINX_SC*H/(2*COS_HALFD);
597
    float Y4= MINX_SC*H*(1/(2*COS_HALFD) - COS_HALFD);
598

    
599
    float[] vertices0 = { -X1, Y2, 0, -Y1, X1, Y2, 0, Y1 };
600
    float[] bands0 = computeBands(0.04f,17,0.3f,0.2f,5);
601
    float[] vertices1 = { -X2, Y4, 0, -Y3, X2, Y4, 0, Y3 };
602
    float[] bands1 = computeBands(0.00f, 0,0.25f,0.5f,2);
603

    
604
    meshes[0] = new MeshPolygon(vertices0, bands0, 1, 1);
605
    meshes[0].setEffectAssociation(0, 1,0);
606
    meshes[1] = meshes[0].copy(true);
607
    meshes[1].setEffectAssociation(0, 2,0);
608
    meshes[2] = meshes[0].copy(true);
609
    meshes[2].setEffectAssociation(0, 4,0);
610
    meshes[3] = new MeshPolygon(vertices1, bands1, 0, 0);
611
    meshes[3].setEffectAssociation(0, 8,0);
612
    meshes[4] = meshes[3].copy(true);
613
    meshes[4].setEffectAssociation(0,16,0);
614
    meshes[5] = meshes[3].copy(true);
615
    meshes[5].setEffectAssociation(0,32,0);
616

    
617
    return new MeshJoined(meshes);
618
    }
619

    
620
///////////////////////////////////////////////////////////////////////////////////////////////////
621

    
622
  MeshBase createFacesMinxCorner(int numLayers)
623
    {
624
    MeshBase[] meshes = new MeshPolygon[6];
625

    
626
    float Y = COS54/(2*SIN54);
627

    
628
    float[] vertices0 = { -0.5f, 0.0f, 0.0f, -Y, 0.5f, 0.0f, 0.0f, Y };
629

    
630
    int numBands0 = numLayers==3 ? 5 : 3;
631
    int numBands1 = numLayers==3 ? 2 : 2;
632
    float h       = numLayers==3 ? 0.04f : 0.03f;
633
    int   e       = numLayers==3 ? 4 : 1;
634

    
635
    float[] bands0 = computeBands(h    ,34,0.3f,0.2f, numBands0);
636
    float[] bands1 = computeBands(0.00f,34,0.3f,0.2f, numBands1);
637

    
638
    meshes[0] = new MeshPolygon(vertices0, bands0, 1, 1);
639
    meshes[0].setEffectAssociation(0, 1,0);
640
    meshes[1] = meshes[0].copy(true);
641
    meshes[1].setEffectAssociation(0, 2,0);
642
    meshes[2] = meshes[0].copy(true);
643
    meshes[2].setEffectAssociation(0, 4,0);
644
    meshes[3] = new MeshPolygon(vertices0, bands1, 1, e);
645
    meshes[3].setEffectAssociation(0, 8,0);
646
    meshes[4] = meshes[3].copy(true);
647
    meshes[4].setEffectAssociation(0,16,0);
648
    meshes[5] = meshes[3].copy(true);
649
    meshes[5].setEffectAssociation(0,32,0);
650

    
651
    return new MeshJoined(meshes);
652
    }
653

    
654
///////////////////////////////////////////////////////////////////////////////////////////////////
655

    
656
  MeshBase createFacesKilominxEdge(int numLayers, float width, float height)
657
    {
658
     MeshBase[] meshes = new MeshPolygon[6];
659

    
660
    float D = height/COS18;
661
    float W = D*SIN18;
662
    float X1 = height/2;
663
    float Y1 = width/2;
664
    float Y2 = (width+W)/2;
665
    float X3 = D*SIN54;
666
    float Y3 = D*COS54;
667
    float X4 = height*SIN_HALFD;
668
    float Y4 = height*COS_HALFD;
669

    
670
    float[] vertices0 = { -X1,-Y1, X1, -Y1, X1, Y1+W,-X1, Y1 };
671
    float[] vertices1 = { -X1,-Y2, X1, -Y2, X1, Y2+W,-X1, Y2 };
672
    float[] vertices2 = { -X3, 0.0f, 0.0f, -Y3, X3, 0.0f, 0.0f, Y3 };
673
    float[] vertices3 = { -X4, 0.0f, 0.0f, -Y4, X4, 0.0f, 0.0f, Y4 };
674

    
675
    int numBands0 = numLayers<=5 ? 5 : 3;
676
    int numBands1 = numLayers<=5 ? 3 : 2;
677
    float h       = numLayers<=5 ? 0.03f : 0.03f;
678

    
679
    float[] bands0 = computeBands(h    ,34,0.2f,0.2f,numBands0);
680
    float[] bands1 = computeBands(0.01f,34,0.3f,0.2f,numBands1);
681

    
682
    meshes[0] = new MeshPolygon(vertices0, bands0, 1, 1);
683
    meshes[0].setEffectAssociation(0, 1,0);
684
    meshes[1] = meshes[0].copy(true);
685
    meshes[1].setEffectAssociation(0, 2,0);
686
    meshes[2] = new MeshPolygon(vertices1, bands1, 0, 0);
687
    meshes[2].setEffectAssociation(0, 4,0);
688
    meshes[3] = meshes[2].copy(true);
689
    meshes[3].setEffectAssociation(0, 8,0);
690
    meshes[4] = new MeshPolygon(vertices2, bands1, 0, 0);
691
    meshes[4].setEffectAssociation(0,16,0);
692
    meshes[5] = new MeshPolygon(vertices3, bands1, 0, 0);
693
    meshes[5].setEffectAssociation(0,32,0);
694

    
695
    return new MeshJoined(meshes);
696
    }
697

    
698
///////////////////////////////////////////////////////////////////////////////////////////////////
699

    
700
  MeshBase createFacesMegaminxEdge(int numLayers, float width, float height)
701
    {
702
    MeshBase[] meshes = new MeshPolygon[6];
703

    
704
    float D = height/COS18;
705
    float W = D*SIN18;
706

    
707
    float Y1 = 0.5f*width;
708
    float Y2 = 0.5f*width + W;
709
    float Y3 = 0.5f*width + 2*W;
710
    float X2 = D*SIN54;
711
    float X1 = 0.5f*height;
712
    float Y4 = D*COS54;
713

    
714
    float[] vertices0 = { -X1, Y1, -X1, -Y1, X1, -Y2, X1, Y2 };
715
    float[] vertices1 = { -X1, Y3, -X1, -Y3, X1, -Y2, X1, Y2 };
716
    float[] vertices2 = { -X2, 0.0f, 0.0f, -Y4, X2, 0.0f, 0.0f, Y4 };
717

    
718
    int numBands0 = numLayers==3 ? 5 : 3;
719
    int numBands1 = numLayers==3 ? 2 : 2;
720
    float h       = numLayers==3 ? 0.03f : 0.03f;
721

    
722
    float[] bands0 = computeBands(h    ,34,0.2f,0.2f,numBands0);
723
    float[] bands1 = computeBands(0.00f,34,0.3f,0.2f,numBands1);
724

    
725
    meshes[0] = new MeshPolygon(vertices0, bands0, 0, 0);
726
    meshes[0].setEffectAssociation(0, 1,0);
727
    meshes[1] = meshes[0].copy(true);
728
    meshes[1].setEffectAssociation(0, 2,0);
729
    meshes[2] = new MeshPolygon(vertices1, bands1, 0, 0);
730
    meshes[2].setEffectAssociation(0, 4,0);
731
    meshes[3] = meshes[2].copy(true);
732
    meshes[3].setEffectAssociation(0, 8,0);
733
    meshes[4] = new MeshPolygon(vertices2, bands1, 0, 0);
734
    meshes[4].setEffectAssociation(0,16,0);
735
    meshes[5] = meshes[4].copy(true);
736
    meshes[5].setEffectAssociation(0,32,0);
737

    
738
    return new MeshJoined(meshes);
739
    }
740

    
741
///////////////////////////////////////////////////////////////////////////////////////////////////
742

    
743
  MeshBase createFacesMegaminxCenter(int numLayers)
744
    {
745
    MeshBase[] meshes = new MeshPolygon[2];
746

    
747
    float R  = 0.5f;
748
    float X1 = R*COS54;
749
    float Y1 = R*SIN54;
750
    float X2 = R*COS18;
751
    float Y2 = R*SIN18;
752

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

    
755
    int numBands0 = numLayers==3 ? 4 : 3;
756
    int numBands1 = numLayers==3 ? 2 : 2;
757
    float h       = numLayers==3 ? 0.04f : 0.04f;
758

    
759
    float[] bands0 = computeBands( h    ,45, R/3,0.2f, numBands0);
760
    float[] bands1 = computeBands( 0.00f,34, R/3,0.2f, numBands1);
761

    
762
    meshes[0] = new MeshPolygon(vertices0, bands0, 0, 0);
763
    meshes[0].setEffectAssociation(0,1,0);
764
    meshes[1] = new MeshPolygon(vertices0, bands1, 0, 0);
765
    meshes[1].setEffectAssociation(0,2,0);
766

    
767
    return new MeshJoined(meshes);
768
    }
769

    
770
///////////////////////////////////////////////////////////////////////////////////////////////////
771

    
772
  private float[] createVertices(int A, int B)
773
    {
774
    float E = 0.5f / Math.max(A,B);
775
    return new float[] { -A*E,-B*E, +A*E,-B*E, +A*E,+B*E, -A*E,+B*E };
776
    }
777

    
778
///////////////////////////////////////////////////////////////////////////////////////////////////
779

    
780
  MeshBase createCuboid(int[] dimensions)
781
    {
782
    int X = dimensions[0];
783
    int Y = dimensions[1];
784
    int Z = dimensions[2];
785

    
786
    float[] verticesXY = createVertices(X,Y);
787
    float[] verticesXZ = createVertices(X,Z);
788
    float[] verticesYZ = createVertices(Z,Y);
789

    
790
    float defHeight = 0.048f;
791

    
792
    float[] bandsX = computeBands( defHeight/X,65,0.25f,0.5f,5);
793
    float[] bandsY = computeBands( defHeight/Y,65,0.25f,0.5f,5);
794
    float[] bandsZ = computeBands( defHeight/Z,65,0.25f,0.5f,5);
795

    
796
    MeshBase[] meshes = new MeshPolygon[6];
797

    
798
    meshes[0] = new MeshPolygon(verticesYZ,bandsX,1,2);
799
    meshes[0].setEffectAssociation(0,1,0);
800
    meshes[1] = meshes[0].copy(true);
801
    meshes[1].setEffectAssociation(0,2,0);
802
    meshes[2] = new MeshPolygon(verticesXZ,bandsY,1,2);
803
    meshes[2].setEffectAssociation(0,4,0);
804
    meshes[3] = meshes[2].copy(true);
805
    meshes[3].setEffectAssociation(0,8,0);
806
    meshes[4] = new MeshPolygon(verticesXY,bandsZ,1,2);
807
    meshes[4].setEffectAssociation(0,16,0);
808
    meshes[5] = meshes[4].copy(true);
809
    meshes[5].setEffectAssociation(0,32,0);
810

    
811
    return new MeshJoined(meshes);
812
    }
813

    
814
///////////////////////////////////////////////////////////////////////////////////////////////////
815
// EFFECTS
816
///////////////////////////////////////////////////////////////////////////////////////////////////
817

    
818
///////////////////////////////////////////////////////////////////////////////////////////////////
819

    
820
  VertexEffect[] createVertexEffectsSkewbCorner()
821
    {
822
    float E = 0.5f;
823

    
824
    Static3D axisX  = new Static3D(1,0,0);
825
    Static3D axisY  = new Static3D(0,1,0);
826
    Static3D axis0  = new Static3D(-SQ2/2,0,SQ2/2);
827
    Static3D axis1  = new Static3D(+SQ3/3,+SQ3/3,+SQ3/3);
828
    Static1D angle1 = new Static1D(+90);
829
    Static1D angle2 = new Static1D(-90);
830
    Static1D angle3 = new Static1D(-15);
831
    Static1D angle4 = new Static1D((float)((180.0f/Math.PI)*Math.acos(SQ3/3)));
832
    Static1D angle5 = new Static1D(120);
833
    Static1D angle6 = new Static1D(240);
834
    Static3D center1= new Static3D(0,0,0);
835
    Static3D center2= new Static3D(-0.5f,-0.5f,-0.5f);
836
    Static3D move1  = new Static3D(-E/4,-E/4,0);
837
    Static3D move2  = new Static3D(-0.5f+SQ2/4,-0.5f+SQ6/8,-0.5f);
838

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

    
841
    effect[0] = new VertexEffectMove(move1);
842
    effect[1] = new VertexEffectScale(new Static3D(1,1,-1));
843
    effect[2] = new VertexEffectRotate(angle1,axisX,center1);
844
    effect[3] = new VertexEffectRotate(angle2,axisY,center1);
845
    effect[4] = new VertexEffectMove(move2);
846
    effect[5] = new VertexEffectRotate(angle1,axisX,center2);
847
    effect[6] = new VertexEffectRotate(angle3,axisY,center2);
848
    effect[7] = new VertexEffectRotate(angle4,axis0,center2);
849
    effect[8] = new VertexEffectRotate(angle5,axis1,center2);
850
    effect[9] = new VertexEffectRotate(angle6,axis1,center2);
851

    
852
    effect[0].setMeshAssociation( 7,-1);  // meshes 0,1,2
853
    effect[1].setMeshAssociation( 6,-1);  // meshes 1,2
854
    effect[2].setMeshAssociation( 2,-1);  // mesh 1
855
    effect[3].setMeshAssociation( 4,-1);  // mesh 2
856
    effect[4].setMeshAssociation(56,-1);  // meshes 3,4,5
857
    effect[5].setMeshAssociation(56,-1);  // meshes 3,4,5
858
    effect[6].setMeshAssociation(56,-1);  // meshes 3,4,5
859
    effect[7].setMeshAssociation(56,-1);  // meshes 3,4,5
860
    effect[8].setMeshAssociation(16,-1);  // mesh 4
861
    effect[9].setMeshAssociation(32,-1);  // mesh 5
862

    
863
    return effect;
864
    }
865

    
866
///////////////////////////////////////////////////////////////////////////////////////////////////
867

    
868
  VertexEffect[] createVertexEffectsSkewbFace()
869
    {
870
    Static3D center = new Static3D(0,0,0);
871
    Static3D axisX  = new Static3D(1,0,0);
872
    Static3D axisZ  = new Static3D(0,0,1);
873
    float angle = -(float)((180.0f/Math.PI)*Math.acos(SQ3/3));
874

    
875
    VertexEffect[] effect = new VertexEffect[6];
876

    
877
    effect[0] = new VertexEffectRotate( new Static1D(angle), axisX, center);
878
    effect[1] = new VertexEffectRotate( new Static1D(  135), axisZ, center);
879
    effect[2] = new VertexEffectRotate( new Static1D(   45), axisZ, center);
880
    effect[3] = new VertexEffectRotate( new Static1D(  -45), axisZ, center);
881
    effect[4] = new VertexEffectRotate( new Static1D( -135), axisZ, center);
882
    effect[5] = new VertexEffectMove( new Static3D(0,0,-0.5f) );
883

    
884
    effect[0].setMeshAssociation(30,-1);  // meshes 1,2,3,4
885
    effect[1].setMeshAssociation( 2,-1);  // mesh 1
886
    effect[2].setMeshAssociation( 5,-1);  // meshes 0,2
887
    effect[3].setMeshAssociation( 8,-1);  // mesh 3
888
    effect[4].setMeshAssociation(16,-1);  // mesh 4
889
    effect[5].setMeshAssociation(30,-1);  // meshes 1,2,3,4
890

    
891
    return effect;
892
    }
893

    
894
///////////////////////////////////////////////////////////////////////////////////////////////////
895

    
896
  VertexEffect[] createVertexEffectsHelicopterCorner()
897
    {
898
    float E = 0.5f;
899

    
900
    Static3D axisX  = new Static3D(1,0,0);
901
    Static3D axisY  = new Static3D(0,1,0);
902
    Static3D axis0  = new Static3D(-SQ2/2,0,SQ2/2);
903
    Static3D axis1  = new Static3D(+SQ3/3,+SQ3/3,+SQ3/3);
904
    Static1D angle1 = new Static1D(+90);
905
    Static1D angle2 = new Static1D(-90);
906
    Static1D angle3 = new Static1D(-135);
907
    Static1D angle4 = new Static1D(90);
908
    Static1D angle5 = new Static1D(120);
909
    Static1D angle6 = new Static1D(240);
910
    Static3D center1= new Static3D(0,0,0);
911
    Static3D center2= new Static3D(-0.25f,-0.25f,-0.25f);
912
    Static3D move1  = new Static3D(-E/4,-E/4,0);
913
    Static3D move2  = new Static3D(-0.25f,(-1.0f/6)-0.25f,-0.25f);
914

    
915
    VertexEffect[] effect = new VertexEffect[10];
916

    
917
    effect[0] = new VertexEffectMove(move1);
918
    effect[1] = new VertexEffectScale(new Static3D(1,1,-1));
919
    effect[2] = new VertexEffectRotate(angle1,axisX,center1);
920
    effect[3] = new VertexEffectRotate(angle2,axisY,center1);
921
    effect[4] = new VertexEffectMove(move2);
922
    effect[5] = new VertexEffectRotate(angle1,axisX,center2);
923
    effect[6] = new VertexEffectRotate(angle3,axisY,center2);
924
    effect[7] = new VertexEffectRotate(angle4,axis0,center2);
925
    effect[8] = new VertexEffectRotate(angle5,axis1,center2);
926
    effect[9] = new VertexEffectRotate(angle6,axis1,center2);
927

    
928
    effect[0].setMeshAssociation( 7,-1);  // meshes 0,1,2
929
    effect[1].setMeshAssociation( 6,-1);  // meshes 1,2
930
    effect[2].setMeshAssociation( 2,-1);  // mesh 1
931
    effect[3].setMeshAssociation( 4,-1);  // mesh 2
932
    effect[4].setMeshAssociation(56,-1);  // meshes 3,4,5
933
    effect[5].setMeshAssociation(56,-1);  // meshes 3,4,5
934
    effect[6].setMeshAssociation(56,-1);  // meshes 3,4,5
935
    effect[7].setMeshAssociation(56,-1);  // meshes 3,4,5
936
    effect[8].setMeshAssociation(16,-1);  // mesh 4
937
    effect[9].setMeshAssociation(32,-1);  // mesh 5
938

    
939
    return effect;
940
    }
941

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

    
944
  VertexEffect[] createVertexEffectsHelicopterFace()
945
    {
946
    float E = 0.5f;
947
    float F = SQ2/4;
948

    
949
    Static3D move0  = new Static3D(-E/4, -E/4, 0);
950
    Static3D move1  = new Static3D(-(SQ2/24)-E/2, -(SQ2/24)-E/2, 0);
951
    Static3D move2  = new Static3D(-E/2, F/3, 0);
952
    Static3D move3  = new Static3D(+E/2, F/3, 0);
953
    Static3D move4  = new Static3D(+E/3,+E/3, 0);
954
    Static1D angle1 = new Static1D(135);
955
    Static1D angle2 = new Static1D(90);
956
    Static1D angle3 = new Static1D(-90);
957
    Static1D angle4 = new Static1D(-135);
958
    Static3D axisX  = new Static3D(1,0,0);
959
    Static3D axisY  = new Static3D(0,1,0);
960
    Static3D axisZ  = new Static3D(0,0,1);
961
    Static3D axis1  = new Static3D(1,-1,0);
962
    Static3D center = new Static3D(0,0,0);
963
    Static3D center1= new Static3D(-E/2,-E/2,0);
964

    
965
    VertexEffect[] effect = new VertexEffect[10];
966

    
967
    effect[0] = new VertexEffectMove(move0);
968
    effect[1] = new VertexEffectRotate(angle1, axisZ, center);
969
    effect[2] = new VertexEffectMove(move1);
970
    effect[3] = new VertexEffectRotate(angle2, axis1, center1);
971
    effect[4] = new VertexEffectMove(move2);
972
    effect[5] = new VertexEffectMove(move3);
973
    effect[6] = new VertexEffectRotate(angle3, axisZ, center);
974
    effect[7] = new VertexEffectRotate(angle4, axisX, center);
975
    effect[8] = new VertexEffectRotate(angle1, axisY, center);
976
    effect[9] = new VertexEffectMove(move4);
977

    
978
    effect[0].setMeshAssociation( 1,-1);  // mesh 0
979
    effect[1].setMeshAssociation( 2,-1);  // mesh 1
980
    effect[2].setMeshAssociation( 2,-1);  // mesh 1
981
    effect[3].setMeshAssociation( 2,-1);  // mesh 1
982
    effect[4].setMeshAssociation( 4,-1);  // mesh 2
983
    effect[5].setMeshAssociation( 8,-1);  // mesh 3
984
    effect[6].setMeshAssociation( 8,-1);  // mesh 3
985
    effect[7].setMeshAssociation( 4,-1);  // mesh 2
986
    effect[8].setMeshAssociation( 8,-1);  // mesh 3
987
    effect[9].setMeshAssociation(15,-1);  // meshes 0,1,2,3
988

    
989
    return effect;
990
    }
991

    
992
///////////////////////////////////////////////////////////////////////////////////////////////////
993

    
994
  VertexEffect[] createVertexEffectsRediEdge()
995
    {
996
    Static3D move0 = new Static3D(0.0f, -0.5f, 0.0f);
997
    Static3D move1 = new Static3D(0.25f, -0.25f, 0.0f);
998
    Static3D move2 = new Static3D(0.5f, 0.0f, 0.0f);
999
    Static3D move3 = new Static3D(0.0f, (SQ3-6)/8, (SQ3-6)/8);
1000
    Static3D flipZ = new Static3D(1,1,-1);
1001
    Static3D flipX = new Static3D(-1,1,1);
1002
    Static3D scale = new Static3D(2,2,2);
1003
    Static3D cent0 = new Static3D(0,0, 0);
1004
    Static3D cent1 = new Static3D(0,0, -1.5f);
1005
    Static3D axisX = new Static3D(1,0, 0);
1006
    Static3D axisY = new Static3D(0,1, 0);
1007
    Static3D axis  = new Static3D(0,SQ2/2,-SQ2/2);
1008
    Static1D angle1= new Static1D(90);
1009
    Static1D angle2= new Static1D(45);
1010
    Static1D angle3= new Static1D( (float)(180/Math.PI*Math.acos(SQ3/3)) );
1011

    
1012
    VertexEffect[] effect = new VertexEffect[12];
1013

    
1014
    effect[0] = new VertexEffectScale(scale);
1015
    effect[1] = new VertexEffectMove(move0);
1016
    effect[2] = new VertexEffectScale(flipZ);
1017
    effect[3] = new VertexEffectRotate(angle1,axisX,cent0);
1018
    effect[4] = new VertexEffectMove(move1);
1019
    effect[5] = new VertexEffectRotate(angle1,axisY,cent0);
1020
    effect[6] = new VertexEffectMove(move2);
1021
    effect[7] = new VertexEffectScale(flipX);
1022
    effect[8] = new VertexEffectRotate(angle2,axisX,cent0);
1023
    effect[9] = new VertexEffectMove(move3);
1024
    effect[10]= new VertexEffectRotate(angle3,axis ,cent1);
1025
    effect[11]= new VertexEffectScale(flipX);
1026

    
1027
    effect[0].setMeshAssociation(63,-1);  // meshes 0,1,2,3,4,5
1028
    effect[1].setMeshAssociation( 3,-1);  // meshes 0,1
1029
    effect[2].setMeshAssociation( 2,-1);  // mesh 1
1030
    effect[3].setMeshAssociation( 2,-1);  // mesh 1
1031
    effect[4].setMeshAssociation(12,-1);  // meshes 2,3
1032
    effect[5].setMeshAssociation(60,-1);  // meshes 2,3,4,5
1033
    effect[6].setMeshAssociation(12,-1);  // meshes 2,3
1034
    effect[7].setMeshAssociation( 8,-1);  // mesh 3
1035
    effect[8].setMeshAssociation(48,-1);  // meshes 4,5
1036
    effect[9].setMeshAssociation(48,-1);  // meshes 4,5
1037
    effect[10].setMeshAssociation(48,-1); // meshes 4,5
1038
    effect[11].setMeshAssociation(32,-1); // mesh 5
1039

    
1040
    return effect;
1041
    }
1042

    
1043
///////////////////////////////////////////////////////////////////////////////////////////////////
1044

    
1045
  VertexEffect[] createVertexEffectsRediCorner()
1046
    {
1047
    Static3D axisY   = new Static3D(0,1,0);
1048
    Static3D axisX   = new Static3D(1,0,0);
1049
    Static3D axisZ   = new Static3D(0,0,1);
1050
    Static3D center  = new Static3D(0,0,0);
1051
    Static1D angle90 = new Static1D(90);
1052
    Static1D angle270= new Static1D(270);
1053
    Static1D angle45 = new Static1D(-45);
1054
    Static3D scale   = new Static3D(1.0f, SQ2, 1.0f);
1055

    
1056
    VertexEffect[] effect = new VertexEffect[7];
1057

    
1058
    effect[0] = new VertexEffectMove(new Static3D(0,0,+0.5f));
1059
    effect[1] = new VertexEffectRotate( angle270, axisX, center );
1060
    effect[2] = new VertexEffectRotate( angle90 , axisY, center );
1061
    effect[3] = new VertexEffectScale(scale);
1062
    effect[4] = new VertexEffectRotate( angle45 , axisX, center );
1063
    effect[5] = new VertexEffectRotate( angle90 , axisY, center );
1064
    effect[6] = new VertexEffectRotate( angle270, axisZ, center );
1065

    
1066
    effect[0].setMeshAssociation( 7,-1);  // 0,1,2
1067
    effect[1].setMeshAssociation( 2,-1);  // 1
1068
    effect[2].setMeshAssociation( 4,-1);  // 2
1069
    effect[3].setMeshAssociation(56,-1);  // 3,4,5
1070
    effect[4].setMeshAssociation(56,-1);  // 3,4,5
1071
    effect[5].setMeshAssociation(16,-1);  // 4
1072
    effect[6].setMeshAssociation(32,-1);  // 5
1073

    
1074
    return effect;
1075
    }
1076

    
1077
///////////////////////////////////////////////////////////////////////////////////////////////////
1078

    
1079
  VertexEffect[] createVertexEffectsIvyCorner()
1080
    {
1081
    Static3D axisX  = new Static3D(1,0,0);
1082
    Static3D axisY  = new Static3D(0,1,0);
1083
    Static1D angle1 = new Static1D(+90);
1084
    Static1D angle2 = new Static1D(-90);
1085
    Static3D center = new Static3D(0,0,0);
1086
    Static3D move1  = new Static3D(IVY_M-0.5f,IVY_M-0.5f,0);
1087

    
1088
    VertexEffect[] effect = new VertexEffect[5];
1089

    
1090
    effect[0] = new VertexEffectScale(1/IVY_C);
1091
    effect[1] = new VertexEffectMove(move1);
1092
    effect[2] = new VertexEffectScale(new Static3D(1,1,-1));
1093
    effect[3] = new VertexEffectRotate(angle1,axisX,center);
1094
    effect[4] = new VertexEffectRotate(angle2,axisY,center);
1095

    
1096
    effect[2].setMeshAssociation(54,-1);  // meshes 1,2,4,5
1097
    effect[3].setMeshAssociation(18,-1);  // meshes 1,4
1098
    effect[4].setMeshAssociation(36,-1);  // meshes 2,5
1099

    
1100
    return effect;
1101
    }
1102

    
1103
///////////////////////////////////////////////////////////////////////////////////////////////////
1104

    
1105
  VertexEffect[] createVertexEffectsRexEdge()
1106
    {
1107
    float E = 0.5f - REX_D;
1108
    float F = 0.5f;
1109
    float G = (float)Math.sqrt(E*E+F*F);
1110
    float A = (float)((180/Math.PI)*Math.asin(E/G));
1111

    
1112
    Static3D move1 = new Static3D(    0.0f, -E/3, 0.0f);
1113
    Static3D move2 = new Static3D(2*G/3 -F, +E/3, 0.0f);
1114

    
1115
    Static3D center0= new Static3D(0.0f, 0.0f, 0.0f);
1116
    Static3D center1= new Static3D(  -F, 0.0f, 0.0f);
1117
    Static3D center2= new Static3D(  +F, 0.0f, 0.0f);
1118
    Static3D axisX  = new Static3D(1.0f, 0.0f, 0.0f);
1119
    Static3D axisY  = new Static3D(0.0f, 1.0f, 0.0f);
1120
    Static3D axisZ  = new Static3D(0.0f, 0.0f, 1.0f);
1121

    
1122
    Static1D angle180 = new Static1D(180);
1123
    Static1D angle90  = new Static1D( 90);
1124
    Static1D angle270 = new Static1D(270);
1125
    Static1D angle1   = new Static1D(+A);
1126
    Static1D angle2   = new Static1D(-A);
1127

    
1128
    VertexEffect[] effect = new VertexEffect[12];
1129

    
1130
    effect[0] = new VertexEffectMove(move1);
1131
    effect[1] = new VertexEffectMove(move2);
1132
    effect[2] = new VertexEffectRotate(  angle90, axisX, center0 );
1133
    effect[3] = new VertexEffectRotate( angle270, axisX, center0 );
1134
    effect[4] = new VertexEffectRotate( angle180, axisX, center0 );
1135
    effect[5] = new VertexEffectRotate( angle180, axisY, center0 );
1136
    effect[6] = new VertexEffectScale ( new Static3D(-1, 1, 1) );
1137
    effect[7] = new VertexEffectScale ( new Static3D( 1,-1, 1) );
1138
    effect[8] = new VertexEffectRotate(   angle1, axisY, center1);
1139
    effect[9] = new VertexEffectRotate(   angle2, axisY, center2);
1140
    effect[10]= new VertexEffectRotate(   angle2, axisZ, center1);
1141
    effect[11]= new VertexEffectRotate(   angle1, axisZ, center2);
1142

    
1143
    effect[0].setMeshAssociation( 3,-1);  // meshes 0 & 1
1144
    effect[1].setMeshAssociation(60,-1);  // meshes 2,3,4,5
1145
    effect[2].setMeshAssociation( 2,-1);  // meshes 1
1146
    effect[3].setMeshAssociation(12,-1);  // meshes 2,3
1147
    effect[4].setMeshAssociation(48,-1);  // meshes 4,5
1148
    effect[5].setMeshAssociation(32,-1);  // mesh 5
1149
    effect[6].setMeshAssociation( 8,-1);  // apply to mesh 3
1150
    effect[7].setMeshAssociation( 2,-1);  // apply to mesh 1
1151
    effect[8].setMeshAssociation(16,-1);  // apply to mesh 4
1152
    effect[9].setMeshAssociation(32,-1);  // apply to mesh 5
1153
    effect[10].setMeshAssociation(4,-1);  // apply to mesh 2
1154
    effect[11].setMeshAssociation(8,-1);  // apply to mesh 3
1155

    
1156
    return effect;
1157
    }
1158

    
1159
///////////////////////////////////////////////////////////////////////////////////////////////////
1160

    
1161
  VertexEffect[] createVertexEffectsRexCorner()
1162
    {
1163
    Static3D center= new Static3D(0.0f, 0.0f, 0.0f);
1164
    Static3D axisZ = new Static3D(0.0f, 0.0f, 1.0f);
1165
    Static1D angle = new Static1D(225);
1166

    
1167
    VertexEffect[] effect = new VertexEffect[1];
1168
    effect[0] = new VertexEffectRotate(angle, axisZ, center);
1169

    
1170
    return effect;
1171
    }
1172

    
1173
///////////////////////////////////////////////////////////////////////////////////////////////////
1174

    
1175
  VertexEffect[] createVertexEffectsKilominxCenter(float width)
1176
    {
1177
    VertexEffect[] effect = new VertexEffect[11];
1178

    
1179
    float H = 0.5f*(SIN54/COS54);
1180
    float Y1= 0.5f*SIN_HALFD;
1181
    float Y2= H/(2*COS_HALFD);
1182
    float cos18 = (float)(Math.sqrt(1- SIN18 * SIN18));
1183
    float LEN   = (float)Math.sqrt(H*H/(COS_HALFD*COS_HALFD) + 0.25f);
1184

    
1185
    Static3D axisZ = new Static3D(0.0f  , 0.0f , 1.0f);
1186
    Static3D axisY = new Static3D(0.0f  , 1.0f , 0.0f);
1187
    Static3D axisA = new Static3D(-SIN18, cos18, 0.0f);
1188
    Static3D axisC = new Static3D( H/LEN, -0.5f/LEN,-H* SIN_HALFD /(COS_HALFD*LEN));
1189

    
1190
    Static3D move1 = new Static3D(0,-Y1,0);
1191
    Static3D move2 = new Static3D(0,-Y2,0);
1192
    Static3D move3 = new Static3D(0.5f*cos18,0.5f*SIN18,0);
1193
    Static3D center= new Static3D(0.0f, 0.0f, 0.0f);
1194

    
1195
    Static1D angle1 = new Static1D(54);
1196
    Static1D angle2 = new Static1D(DIHEDRAL1/2+18);
1197
    Static1D angle3 = new Static1D(90);
1198
    Static1D angle4 = new Static1D(120);
1199
    Static1D angle5 = new Static1D(240);
1200
    Static1D angle6 = new Static1D(90-DIHEDRAL1/2);
1201

    
1202
    effect[0] = new VertexEffectMove(move1);
1203
    effect[1] = new VertexEffectScale(1/MINX_SC);
1204
    effect[2] = new VertexEffectMove(move2);
1205
    effect[3] = new VertexEffectRotate(angle1, axisZ, center);
1206
    effect[4] = new VertexEffectRotate(angle2, axisZ, center);
1207
    effect[5] = new VertexEffectRotate(angle3, axisA, center);
1208
    effect[6] = new VertexEffectMove(move3);
1209
    effect[7] = new VertexEffectRotate(angle4, axisC, center);
1210
    effect[8] = new VertexEffectRotate(angle5, axisC, center);
1211
    effect[9] = new VertexEffectRotate(angle6, axisY, center);
1212
    effect[10]= new VertexEffectScale(width/0.5f);
1213

    
1214
    effect[0].setMeshAssociation( 7,-1);  // meshes 0,1,2
1215
    effect[1].setMeshAssociation(56,-1);  // meshes 3,4,5
1216
    effect[2].setMeshAssociation(56,-1);  // meshes 3,4,5
1217
    effect[3].setMeshAssociation( 7,-1);  // meshes 0,1,2
1218
    effect[4].setMeshAssociation(56,-1);  // meshes 3,4,5
1219
    effect[5].setMeshAssociation(56,-1);  // meshes 3,4,5
1220
    effect[6].setMeshAssociation(56,-1);  // meshes 3,4,5
1221
    effect[7].setMeshAssociation(18,-1);  // meshes 1,4
1222
    effect[8].setMeshAssociation(36,-1);  // meshes 2,5
1223

    
1224
    return effect;
1225
    }
1226

    
1227
///////////////////////////////////////////////////////////////////////////////////////////////////
1228

    
1229
  VertexEffect[] createVertexEffectsMinxCorner(float width)
1230
    {
1231
    VertexEffect[] effect = new VertexEffect[9];
1232

    
1233
    float Y = COS54/(2*SIN54);
1234

    
1235
    float sinA = (2*SIN54*SIN54-1)/COS54;
1236
    float cosA = (float)Math.sqrt(1-sinA*sinA);
1237
    float LEN  = 0.5f/SIN54;
1238
    float scale= width/LEN;
1239

    
1240
    Static3D axisA = new Static3D( SIN54, COS54, 0.0f);
1241
    Static3D axisB = new Static3D(-SIN54, COS54, 0.0f);
1242
    Static3D axisX = new Static3D(  1.0f,  0.0f, 0.0f);
1243

    
1244
    Static3D centerU = new Static3D( 0.0f, Y, 0.0f);
1245
    Static3D centerD = new Static3D( 0.0f,-Y, 0.0f);
1246

    
1247
    Static3D move1= new Static3D(0.0f, -sinA*LEN, -cosA*LEN );
1248
    Static3D move2= new Static3D(0.0f, Y , 0.0f );
1249

    
1250
    Static1D angleD = new Static1D(DIHEDRAL1);
1251
    Static1D angleE = new Static1D(360-DIHEDRAL1);
1252
    Static1D angleF = new Static1D(DIHEDRAL2);
1253

    
1254
    effect[0] = new VertexEffectScale ( new Static3D( 1, 1,-1) );
1255
    effect[1] = new VertexEffectRotate(angleE, axisA, centerU);
1256
    effect[2] = new VertexEffectRotate(angleD, axisB, centerU);
1257
    effect[3] = new VertexEffectMove(move1);
1258
    effect[4] = new VertexEffectRotate(angleE, axisA, centerD);
1259
    effect[5] = new VertexEffectRotate(angleD, axisB, centerD);
1260
    effect[6] = new VertexEffectRotate(angleF, axisX, centerD);
1261
    effect[7] = new VertexEffectMove(move2);
1262
    effect[8] = new VertexEffectScale(scale);
1263

    
1264
    effect[0].setMeshAssociation(  3,-1);  // meshes 0,1
1265
    effect[1].setMeshAssociation( 16,-1);  // mesh 4
1266
    effect[2].setMeshAssociation( 32,-1);  // mesh 5
1267
    effect[3].setMeshAssociation( 56,-1);  // meshes 3,4,5
1268
    effect[4].setMeshAssociation(  1,-1);  // mesh 0
1269
    effect[5].setMeshAssociation(  2,-1);  // mesh 1
1270

    
1271
    return effect;
1272
    }
1273

    
1274
///////////////////////////////////////////////////////////////////////////////////////////////////
1275

    
1276
  VertexEffect[] createVertexEffectsKilominxEdge(float width, float height, boolean left)
1277
    {
1278
    VertexEffect[] effect = new VertexEffect[11 + (left ? 0:1)];
1279

    
1280
    float D = height/COS18;
1281
    float W = D*SIN18;
1282
    float X1 = height/2;
1283
    float Y1 = width/2;
1284
    float Y2 = (width+W)/2;
1285
    float Y3 = D*COS54;
1286
    float Y4 = height*COS_HALFD;
1287
    float Z = 2*height*COS_HALFD;
1288
    float alpha = 90-DIHEDRAL1/2;
1289

    
1290
    Static1D angle1 = new Static1D(alpha);
1291
    Static1D angle2 = new Static1D(180-alpha);
1292
    Static1D angle3 = new Static1D(DIHEDRAL2);
1293
    Static1D angle4 = new Static1D(90);
1294

    
1295
    Static3D move1 = new Static3D(+X1,-Y1,0);
1296
    Static3D move2 = new Static3D(-X1,-Y2+W,-Z);
1297
    Static3D move3 = new Static3D(0,+Y3,0);
1298
    Static3D move4 = new Static3D(0,-Y4-width,0);
1299
    Static3D scale = new Static3D(+1,+1,-1);
1300

    
1301
    Static3D axisXplus = new Static3D(+1, 0, 0);
1302
    Static3D axisYplus = new Static3D( 0,+1, 0);
1303

    
1304
    Static3D center1= new Static3D( 0, 0, 0);
1305
    Static3D center2= new Static3D( 0, 0,-Z);
1306
    Static3D center3= new Static3D( 0,-width, 0);
1307

    
1308
    effect[ 0] = new VertexEffectMove(move1);
1309
    effect[ 1] = new VertexEffectMove(move2);
1310
    effect[ 2] = new VertexEffectMove(move3);
1311
    effect[ 3] = new VertexEffectMove(move4);
1312
    effect[ 4] = new VertexEffectScale(scale);
1313
    effect[ 5] = new VertexEffectRotate(angle1, axisYplus , center1);
1314
    effect[ 6] = new VertexEffectRotate(angle2, axisYplus , center1);
1315
    effect[ 7] = new VertexEffectRotate(angle1, axisYplus , center2);
1316
    effect[ 8] = new VertexEffectRotate(angle2, axisYplus , center2);
1317
    effect[ 9] = new VertexEffectRotate(angle3, axisXplus , center1);
1318
    effect[10] = new VertexEffectRotate(angle4, axisXplus , center3);
1319

    
1320
    if( !left )
1321
      {
1322
      Static3D scale1 = new Static3D(+1,-1,+1);
1323
      effect[11] = new VertexEffectScale(scale1);
1324
      }
1325

    
1326
    effect[ 0].setMeshAssociation( 3,-1);  // meshes 0,1
1327
    effect[ 1].setMeshAssociation(12,-1);  // meshes 2,3
1328
    effect[ 2].setMeshAssociation(16,-1);  // mesh 4
1329
    effect[ 3].setMeshAssociation(32,-1);  // mesh 5
1330
    effect[ 4].setMeshAssociation( 2,-1);  // mesh 1
1331
    effect[ 5].setMeshAssociation( 1,-1);  // mesh 0
1332
    effect[ 6].setMeshAssociation( 2,-1);  // mesh 1
1333
    effect[ 7].setMeshAssociation( 4,-1);  // mesh 2
1334
    effect[ 8].setMeshAssociation( 8,-1);  // mesh 3
1335
    effect[ 9].setMeshAssociation(16,-1);  // mesh 4
1336
    effect[10].setMeshAssociation(32,-1);  // mesh 5
1337

    
1338
    return effect;
1339
    }
1340

    
1341
///////////////////////////////////////////////////////////////////////////////////////////////////
1342

    
1343
  VertexEffect[] createVertexEffectsMegaminxEdge(float width, float height)
1344
    {
1345
    VertexEffect[] effect = new VertexEffect[11];
1346

    
1347
    float X = 0.5f*height;
1348
    float Y = height*(COS54/COS18) + width*0.5f;
1349
    float Z = 2*height*COS_HALFD;
1350

    
1351
    float alpha = 90-DIHEDRAL1/2;
1352
    float beta  = DIHEDRAL2;
1353

    
1354
    Static1D angle1 = new Static1D(alpha);
1355
    Static1D angle2 = new Static1D(180-alpha);
1356
    Static1D angle3 = new Static1D(beta);
1357

    
1358
    Static3D move1 = new Static3D(X,0,0);
1359
    Static3D move2 = new Static3D(X,0,-Z);
1360
    Static3D move3 = new Static3D(0,+Y,0);
1361
    Static3D move4 = new Static3D(0,-Y,0);
1362
    Static3D scale = new Static3D(+1,+1,-1);
1363

    
1364
    Static3D axisXplus = new Static3D(+1, 0, 0);
1365
    Static3D axisXminus= new Static3D(-1, 0, 0);
1366
    Static3D axisYplus = new Static3D( 0,+1, 0);
1367
    Static3D axisYminus= new Static3D( 0,-1, 0);
1368

    
1369
    Static3D center1= new Static3D( 0, 0, 0);
1370
    Static3D center2= new Static3D( 0, 0,-Z);
1371
    Static3D center3= new Static3D( 0,+width*0.5f, 0);
1372
    Static3D center4= new Static3D( 0,-width*0.5f, 0);
1373

    
1374
    effect[ 0] = new VertexEffectMove(move1);
1375
    effect[ 1] = new VertexEffectMove(move2);
1376
    effect[ 2] = new VertexEffectMove(move3);
1377
    effect[ 3] = new VertexEffectMove(move4);
1378
    effect[ 4] = new VertexEffectScale(scale);
1379
    effect[ 5] = new VertexEffectRotate(angle1, axisYplus , center1);
1380
    effect[ 6] = new VertexEffectRotate(angle2, axisYplus , center1);
1381
    effect[ 7] = new VertexEffectRotate(angle1, axisYminus, center2);
1382
    effect[ 8] = new VertexEffectRotate(angle2, axisYminus, center2);
1383
    effect[ 9] = new VertexEffectRotate(angle3, axisXplus , center3);
1384
    effect[10] = new VertexEffectRotate(angle3, axisXminus, center4);
1385

    
1386
    effect[ 0].setMeshAssociation( 3,-1);  // meshes 0,1
1387
    effect[ 1].setMeshAssociation(12,-1);  // meshes 2,3
1388
    effect[ 2].setMeshAssociation(16,-1);  // mesh 4
1389
    effect[ 3].setMeshAssociation(32,-1);  // mesh 5
1390
    effect[ 4].setMeshAssociation( 2,-1);  // mesh 1
1391
    effect[ 5].setMeshAssociation( 1,-1);  // mesh 0
1392
    effect[ 6].setMeshAssociation( 2,-1);  // mesh 1
1393
    effect[ 7].setMeshAssociation( 4,-1);  // mesh 2
1394
    effect[ 8].setMeshAssociation( 8,-1);  // mesh 3
1395
    effect[ 9].setMeshAssociation(16,-1);  // mesh 4
1396
    effect[10].setMeshAssociation(32,-1);  // mesh 5
1397

    
1398
    return effect;
1399
    }
1400

    
1401
///////////////////////////////////////////////////////////////////////////////////////////////////
1402

    
1403
  VertexEffect[] createVertexEffectsMegaminxCenter(float width)
1404
    {
1405
    VertexEffect[] effect = new VertexEffect[2];
1406

    
1407
    Static1D angle = new Static1D(DIHEDRAL2);
1408
    Static3D axisX = new Static3D( 1.0f, 0.0f, 0.0f);
1409
    Static3D center= new Static3D( 0, 0, 0);
1410

    
1411
    effect[0] = new VertexEffectScale(width/COS54);
1412
    effect[1] = new VertexEffectRotate(angle, axisX, center);
1413

    
1414
    return effect;
1415
    }
1416

    
1417
///////////////////////////////////////////////////////////////////////////////////////////////////
1418

    
1419
  VertexEffect[] createCuboidEffects(int[] dimensions)
1420
    {
1421
    float X = dimensions[0];
1422
    float Y = dimensions[1];
1423
    float Z = dimensions[2];
1424

    
1425
    float MAX_XY = Math.max(X,Y);
1426
    float MAX_XZ = Math.max(X,Z);
1427
    float MAX_YZ = Math.max(Z,Y);
1428

    
1429
    Static1D angle = new Static1D(90);
1430
    Static3D move  = new Static3D( 0.0f, 0.0f, 0.5f);
1431
    Static3D axisX = new Static3D( 1.0f, 0.0f, 0.0f);
1432
    Static3D axisY = new Static3D( 0.0f, 1.0f, 0.0f);
1433
    Static3D center= new Static3D( 0.0f, 0.0f, 0.0f);
1434

    
1435
    Static3D scale3 = new Static3D(MAX_XY,MAX_XY,+Z);
1436
    Static3D scale4 = new Static3D(MAX_XY,MAX_XY,-Z);
1437
    Static3D scale5 = new Static3D(MAX_XZ,+Y,MAX_XZ);
1438
    Static3D scale6 = new Static3D(MAX_XZ,-Y,MAX_XZ);
1439
    Static3D scale7 = new Static3D(+X,MAX_YZ,MAX_YZ);
1440
    Static3D scale8 = new Static3D(-X,MAX_YZ,MAX_YZ);
1441

    
1442
    VertexEffect[] effect = new VertexEffect[9];
1443

    
1444
    effect[0] = new VertexEffectMove(move);
1445
    effect[1] = new VertexEffectRotate(angle, axisX, center);
1446
    effect[2] = new VertexEffectRotate(angle, axisY, center);
1447
    effect[3] = new VertexEffectScale(scale3);
1448
    effect[4] = new VertexEffectScale(scale4);
1449
    effect[5] = new VertexEffectScale(scale5);
1450
    effect[6] = new VertexEffectScale(scale6);
1451
    effect[7] = new VertexEffectScale(scale7);
1452
    effect[8] = new VertexEffectScale(scale8);
1453

    
1454
    effect[1].setMeshAssociation(12,-1);  // meshes 2,3
1455
    effect[2].setMeshAssociation( 3,-1);  // meshes 0,1
1456
    effect[3].setMeshAssociation(16,-1);  // mesh 4
1457
    effect[4].setMeshAssociation(32,-1);  // mesh 5
1458
    effect[5].setMeshAssociation( 8,-1);  // mesh 3
1459
    effect[6].setMeshAssociation( 4,-1);  // mesh 2
1460
    effect[7].setMeshAssociation( 1,-1);  // mesh 0
1461
    effect[8].setMeshAssociation( 2,-1);  // mesh 1
1462

    
1463
    return effect;
1464
    }
1465

    
1466
///////////////////////////////////////////////////////////////////////////////////////////////////
1467
// OBJECTS
1468
///////////////////////////////////////////////////////////////////////////////////////////////////
1469

    
1470

    
1471
///////////////////////////////////////////////////////////////////////////////////////////////////
1472
// SKEWB
1473

    
1474
  public MeshBase createSkewbCornerMesh()
1475
    {
1476
    MeshBase mesh = createFacesSkewbCorner();
1477
    VertexEffect[] effects = createVertexEffectsSkewbCorner();
1478
    for( VertexEffect effect : effects ) mesh.apply(effect);
1479

    
1480
    float E = 0.5f;
1481
    Static3D roundingCenter = new Static3D(-E/2,-E/2,-E/2);
1482

    
1483
    Static3D[] verticesType1 = new Static3D[1];
1484
    verticesType1[0] = new Static3D(0.0f,0.0f,0.0f);
1485
    roundCorners(mesh,roundingCenter,verticesType1,0.08f,0.15f);
1486

    
1487
    Static3D[] verticesType2 = new Static3D[3];
1488
    verticesType2[0] = new Static3D(-E, 0, 0);
1489
    verticesType2[1] = new Static3D( 0,-E, 0);
1490
    verticesType2[2] = new Static3D( 0, 0,-E);
1491
    roundCorners(mesh,roundingCenter,verticesType2,0.08f,0.20f);
1492

    
1493
    mesh.mergeEffComponents();
1494

    
1495
    return mesh;
1496
    }
1497

    
1498
///////////////////////////////////////////////////////////////////////////////////////////////////
1499

    
1500
  public MeshBase createSkewbFaceMesh()
1501
    {
1502
    MeshBase mesh = createFacesSkewbFace();
1503
    VertexEffect[] effects = createVertexEffectsSkewbFace();
1504
    for( VertexEffect effect : effects ) mesh.apply(effect);
1505

    
1506
    Static3D roundingCenter = new Static3D(0,0,-0.2f);
1507
    float E = SQ2/4;
1508
    Static3D[] vertices = new Static3D[4];
1509
    vertices[0] = new Static3D(-E*SQ2,      0, 0);
1510
    vertices[1] = new Static3D(+E*SQ2,      0, 0);
1511
    vertices[2] = new Static3D(     0, -E*SQ2, 0);
1512
    vertices[3] = new Static3D(     0, +E*SQ2, 0);
1513
    roundCorners(mesh,roundingCenter,vertices,0.06f,0.10f);
1514

    
1515
    mesh.mergeEffComponents();
1516
    mesh.addEmptyTexComponent();
1517

    
1518
    return mesh;
1519
    }
1520

    
1521
///////////////////////////////////////////////////////////////////////////////////////////////////
1522
// Helicopter
1523

    
1524
  public MeshBase createHelicopterCornerMesh()
1525
    {
1526
    MeshBase mesh = createFacesHelicopterCorner();
1527
    VertexEffect[] effects = createVertexEffectsHelicopterCorner();
1528
    for( VertexEffect effect : effects ) mesh.apply(effect);
1529

    
1530
    float E = 0.5f;
1531
    Static3D roundingCenter = new Static3D(-E/2,-E/2,-E/2);
1532

    
1533
    Static3D[] verticesType1 = new Static3D[1];
1534
    verticesType1[0] = new Static3D(0.0f,0.0f,0.0f);
1535
    roundCorners(mesh,roundingCenter,verticesType1,0.08f,0.15f);
1536

    
1537
    Static3D[] verticesType2 = new Static3D[3];
1538
    verticesType2[0] = new Static3D(-E, 0, 0);
1539
    verticesType2[1] = new Static3D( 0,-E, 0);
1540
    verticesType2[2] = new Static3D( 0, 0,-E);
1541
    roundCorners(mesh,roundingCenter,verticesType2,0.08f,0.20f);
1542

    
1543
    mesh.mergeEffComponents();
1544

    
1545
    return mesh;
1546
    }
1547

    
1548
///////////////////////////////////////////////////////////////////////////////////////////////////
1549

    
1550
  public MeshBase createHelicopterFaceMesh()
1551
    {
1552
    MeshBase mesh = createFacesHelicopterFace();
1553
    VertexEffect[] effects = createVertexEffectsHelicopterFace();
1554
    for( VertexEffect effect : effects ) mesh.apply(effect);
1555

    
1556
    float E = 0.5f;
1557
    Static3D roundingCenter = new Static3D(-E/2 + E/3,-E/2 + E/3,-E/2);
1558

    
1559
    Static3D[] verticesType1 = new Static3D[1];
1560
    verticesType1[0] = new Static3D(E/3,E/3,0.0f);
1561
    roundCorners(mesh,roundingCenter,verticesType1,0.06f,0.15f);
1562

    
1563
    Static3D[] verticesType2 = new Static3D[2];
1564
    verticesType2[0] = new Static3D(-E+E/3, E/3  , 0);
1565
    verticesType2[1] = new Static3D( E/3  ,-E+E/3, 0);
1566
    roundCorners(mesh,roundingCenter,verticesType2,0.08f,0.20f);
1567

    
1568
    mesh.mergeEffComponents();
1569
    mesh.addEmptyTexComponent();
1570
    mesh.addEmptyTexComponent();
1571

    
1572
    return mesh;
1573
    }
1574

    
1575
///////////////////////////////////////////////////////////////////////////////////////////////////
1576
// Redi cube
1577

    
1578
  public MeshBase createRediEdgeMesh()
1579
    {
1580
    MeshBase mesh = createFacesRediEdge();
1581
    VertexEffect[] effects = createVertexEffectsRediEdge();
1582
    for( VertexEffect effect : effects ) mesh.apply(effect);
1583

    
1584
    Static3D center = new Static3D(0.0f,-0.75f,-0.75f);
1585
    Static3D[] vertices = new Static3D[2];
1586
    vertices[0] = new Static3D( 0.5f, 0.0f, 0.0f);
1587
    vertices[1] = new Static3D(-0.5f, 0.0f, 0.0f);
1588
    roundCorners(mesh,center,vertices,0.06f,0.20f);
1589

    
1590
    mesh.mergeEffComponents();
1591

    
1592
    return mesh;
1593
    }
1594

    
1595
///////////////////////////////////////////////////////////////////////////////////////////////////
1596

    
1597
  public MeshBase createRediCornerMesh()
1598
    {
1599
    MeshBase mesh = createFacesRediCorner();
1600
    VertexEffect[] effects = createVertexEffectsRediCorner();
1601
    for( VertexEffect effect : effects ) mesh.apply(effect);
1602

    
1603
    Static3D center = new Static3D(0,0,0);
1604
    Static3D[] vertices = new Static3D[8];
1605
    vertices[0] = new Static3D(+0.5f,+0.5f,+0.5f);
1606
    vertices[1] = new Static3D(+0.5f,+0.5f,-0.5f);
1607
    vertices[2] = new Static3D(+0.5f,-0.5f,+0.5f);
1608
    vertices[3] = new Static3D(+0.5f,-0.5f,-0.5f);
1609
    vertices[4] = new Static3D(-0.5f,+0.5f,+0.5f);
1610
    vertices[5] = new Static3D(-0.5f,+0.5f,-0.5f);
1611
    vertices[6] = new Static3D(-0.5f,-0.5f,+0.5f);
1612
    vertices[7] = new Static3D(-0.5f,-0.5f,-0.5f);
1613

    
1614
    roundCorners(mesh,center,vertices,0.06f,0.12f);
1615

    
1616
    mesh.mergeEffComponents();
1617

    
1618
    return mesh;
1619
    }
1620

    
1621
///////////////////////////////////////////////////////////////////////////////////////////////////
1622

    
1623
  public MeshBase createIvyCornerMesh()
1624
    {
1625
    MeshBase mesh = createFacesIvyCorner();
1626
    VertexEffect[] effects = createVertexEffectsIvyCorner();
1627
    for( VertexEffect effect : effects ) mesh.apply(effect);
1628

    
1629
    Static3D center = new Static3D(-0.5f,-0.5f,-0.5f);
1630
    Static3D[] vertices = new Static3D[4];
1631
    vertices[0] = new Static3D(+0.0f,+0.0f,+0.0f);
1632
    vertices[1] = new Static3D(-1.0f,+0.0f,+0.0f);
1633
    vertices[2] = new Static3D(+0.0f,-1.0f,+0.0f);
1634
    vertices[3] = new Static3D(+0.0f,+0.0f,-1.0f);
1635

    
1636
    roundCorners(mesh,center,vertices,0.03f,0.10f);
1637

    
1638
    mesh.mergeEffComponents();
1639

    
1640
    return mesh;
1641
    }
1642

    
1643
///////////////////////////////////////////////////////////////////////////////////////////////////
1644

    
1645
  public MeshBase createIvyFaceMesh()
1646
    {
1647
    MeshBase mesh = createFacesIvyFace();
1648

    
1649
    Static3D center = new Static3D(-0.0f,-0.0f,-0.5f);
1650
    Static3D[] vertices = new Static3D[2];
1651
    vertices[0] = new Static3D(-0.5f,+0.5f,+0.0f);
1652
    vertices[1] = new Static3D(+0.5f,-0.5f,+0.0f);
1653

    
1654
    roundCorners(mesh,center,vertices,0.03f,0.10f);
1655

    
1656
    mesh.mergeEffComponents();
1657
    mesh.addEmptyTexComponent();
1658
    mesh.addEmptyTexComponent();
1659
    mesh.addEmptyTexComponent();
1660
    mesh.addEmptyTexComponent();
1661

    
1662
    return mesh;
1663
    }
1664

    
1665
///////////////////////////////////////////////////////////////////////////////////////////////////
1666

    
1667
  public MeshBase createRexCornerMesh()
1668
    {
1669
    MeshBase mesh = createFacesRexCorner();
1670
    VertexEffect[] effects = createVertexEffectsRexCorner();
1671
    for( VertexEffect effect : effects ) mesh.apply(effect);
1672

    
1673
    final float G = (1-REX_D)/3;
1674
    Static3D center = new Static3D(0.0f,0.0f,-G*SQ2/2);
1675
    Static3D[] vertices = new Static3D[1];
1676
    vertices[0] = new Static3D(+G,-G,+0.0f);
1677
    roundCorners(mesh,center,vertices,0.10f,0.10f);
1678

    
1679
    mesh.mergeEffComponents();
1680
    mesh.addEmptyTexComponent();
1681
    mesh.addEmptyTexComponent();
1682
    mesh.addEmptyTexComponent();
1683
    mesh.addEmptyTexComponent();
1684

    
1685
    return mesh;
1686
    }
1687

    
1688
///////////////////////////////////////////////////////////////////////////////////////////////////
1689

    
1690
  public MeshBase createRexFaceMesh()
1691
    {
1692
    MeshBase mesh = createFacesRexFace();
1693

    
1694
    mesh.mergeEffComponents();
1695
    mesh.addEmptyTexComponent();
1696
    mesh.addEmptyTexComponent();
1697
    mesh.addEmptyTexComponent();
1698
    mesh.addEmptyTexComponent();
1699

    
1700
    return mesh;
1701
    }
1702

    
1703
///////////////////////////////////////////////////////////////////////////////////////////////////
1704

    
1705
  public MeshBase createRexEdgeMesh()
1706
    {
1707
    MeshBase mesh = createFacesRexEdge();
1708
    VertexEffect[] effects = createVertexEffectsRexEdge();
1709
    for( VertexEffect effect : effects ) mesh.apply(effect);
1710

    
1711
    Static3D center = new Static3D(0.0f,-0.5f,-0.5f);
1712
    Static3D[] vertices = new Static3D[2];
1713
    vertices[0] = new Static3D(+0.5f,+0.0f,+0.0f);
1714
    vertices[1] = new Static3D(-0.5f,+0.0f,+0.0f);
1715
    roundCorners(mesh,center,vertices,0.06f,0.10f);
1716

    
1717
    mesh.mergeEffComponents();
1718

    
1719
    return mesh;
1720
    }
1721

    
1722
///////////////////////////////////////////////////////////////////////////////////////////////////
1723

    
1724
  public MeshBase createKilominxCenterMesh(float width)
1725
    {
1726
    MeshBase mesh = createFacesKilominxCenter();
1727
    VertexEffect[] effects = createVertexEffectsKilominxCenter(width);
1728
    for( VertexEffect effect : effects ) mesh.apply(effect);
1729

    
1730
    float A = (2*SQ3/3)* SIN54;
1731
    float B = 0.4f;
1732
    float X = SIN_HALFD * SIN54 *COS54  ;
1733
    float Y = SIN54 * SIN54 - 0.5f;
1734
    float Z = COS_HALFD* SIN54 *COS54  ;
1735

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

    
1738
    Static3D[] vertices = new Static3D[4];
1739
    vertices[0] = new Static3D( 0.0f, 0.0f, 0.0f);
1740
    vertices[1] = new Static3D( 0.0f,-0.5f, 0.0f);
1741
    vertices[2] = new Static3D(-X   , Y   ,-Z   );
1742
    vertices[3] = new Static3D(+X   , Y   ,-Z   );
1743

    
1744
    roundCorners(mesh,center,vertices,0.03f,0.10f);
1745

    
1746
    mesh.mergeEffComponents();
1747

    
1748
    return mesh;
1749
    }
1750

    
1751
///////////////////////////////////////////////////////////////////////////////////////////////////
1752
// numLayers==3 --> index=0; numLayers=5 --> index=1 ...
1753
// type: 0,1,... 0 --> edge, 1 --> 1 layer deeper, etc
1754

    
1755
  public MeshBase createKilominxEdgeMesh(int numLayers, float width, float height, boolean left)
1756
    {
1757
    MeshBase mesh = createFacesKilominxEdge(numLayers,width,height);
1758
    VertexEffect[] effects = createVertexEffectsKilominxEdge(width,height,left);
1759
    for( VertexEffect effect : effects ) mesh.apply(effect);
1760

    
1761
// round...
1762

    
1763
    mesh.mergeEffComponents();
1764

    
1765
    return mesh;
1766
    }
1767

    
1768
///////////////////////////////////////////////////////////////////////////////////////////////////
1769

    
1770
  public MeshBase createMinxCornerMesh(int numLayers, float width)
1771
    {
1772
    MeshBase mesh = createFacesMinxCorner(numLayers);
1773
    VertexEffect[] effects = createVertexEffectsMinxCorner(width);
1774
    for( VertexEffect effect : effects ) mesh.apply(effect);
1775

    
1776
    float A = (2*SQ3/3)* SIN54;
1777
    float B = 0.4f;
1778
/*
1779
    float X = SIN_HALFD* SIN54 * COS54;
1780
    float Y = SIN54 * SIN54 - 0.5f;
1781
    float Z = COS_HALFD* SIN54 * COS54;
1782
    float S = 2*width;
1783
*/
1784
    Static3D center = new Static3D(0.0f, -(float)Math.sqrt(1-A*A)*B,-A*B);
1785
    Static3D[] vertices = new Static3D[1];
1786
    vertices[0] = new Static3D( 0.0f, 0.0f  , 0.0f);
1787
/*
1788
    vertices[1] = new Static3D( 0.0f,-0.5f*S, 0.0f);
1789
    vertices[2] = new Static3D(-X*S , Y*S   ,-Z*S );
1790
    vertices[3] = new Static3D(+X*S , Y*S   ,-Z*S );
1791
*/
1792
    roundCorners(mesh,center,vertices,0.04f,0.10f);
1793

    
1794
    mesh.mergeEffComponents();
1795

    
1796
    return mesh;
1797
    }
1798

    
1799
///////////////////////////////////////////////////////////////////////////////////////////////////
1800
// numLayers==3 --> index=0; numLayers=5 --> index=1 ...
1801
// type: 0,1,... 0 --> edge, 1 --> 1 layer deeper, etc
1802

    
1803
  public MeshBase createMegaminxEdgeMesh(int numLayers, float width, float height)
1804
    {
1805
    MeshBase mesh = createFacesMegaminxEdge(numLayers,width,height);
1806
    VertexEffect[] effects = createVertexEffectsMegaminxEdge(width,height);
1807
    for( VertexEffect effect : effects ) mesh.apply(effect);
1808

    
1809
    mesh.mergeEffComponents();
1810

    
1811
    return mesh;
1812
    }
1813

    
1814
///////////////////////////////////////////////////////////////////////////////////////////////////
1815

    
1816
  public MeshBase createMegaminxCenterMesh(int numLayers, float width)
1817
    {
1818
    MeshBase mesh = createFacesMegaminxCenter(numLayers);
1819
    VertexEffect[] effects = createVertexEffectsMegaminxCenter(width);
1820
    for( VertexEffect effect : effects ) mesh.apply(effect);
1821

    
1822
    mesh.mergeEffComponents();
1823
    mesh.addEmptyTexComponent();
1824
    mesh.addEmptyTexComponent();
1825
    mesh.addEmptyTexComponent();
1826
    mesh.addEmptyTexComponent();
1827

    
1828
    return mesh;
1829
    }
1830

    
1831
///////////////////////////////////////////////////////////////////////////////////////////////////
1832

    
1833
  public MeshBase createCuboidMesh(int[] dimensions)
1834
    {
1835
    MeshBase mesh = createCuboid(dimensions);
1836
    VertexEffect[] effects = createCuboidEffects(dimensions);
1837
    for( VertexEffect effect : effects ) mesh.apply(effect);
1838

    
1839
    int X = dimensions[0];
1840
    int Y = dimensions[1];
1841
    int Z = dimensions[2];
1842

    
1843
    float strength = 0.04f;
1844
    float radius   = 0.15f;
1845

    
1846
    Static3D[] vertices = new Static3D[1];
1847
    Static3D center;
1848

    
1849
    vertices[0] = new Static3D(+0.5f*X,+0.5f*Y,+0.5f*Z);
1850
    center = new Static3D(+0.5f*(X-1),+0.5f*(Y-1),+0.5f*(Z-1));
1851
    roundCorners(mesh, center, vertices, strength, radius);
1852

    
1853
    vertices[0] = new Static3D(+0.5f*X,+0.5f*Y,-0.5f*Z);
1854
    center = new Static3D(+0.5f*(X-1),+0.5f*(Y-1),-0.5f*(Z-1));
1855
    roundCorners(mesh, center, vertices, strength, radius);
1856

    
1857
    vertices[0] = new Static3D(+0.5f*X,-0.5f*Y,+0.5f*Z);
1858
    center = new Static3D(+0.5f*(X-1),-0.5f*(Y-1),+0.5f*(Z-1));
1859
    roundCorners(mesh, center, vertices, strength, radius);
1860

    
1861
    vertices[0] = new Static3D(+0.5f*X,-0.5f*Y,-0.5f*Z);
1862
    center = new Static3D(+0.5f*(X-1),-0.5f*(Y-1),-0.5f*(Z-1));
1863
    roundCorners(mesh, center, vertices, strength, radius);
1864

    
1865
    vertices[0] = new Static3D(-0.5f*X,+0.5f*Y,+0.5f*Z);
1866
    center = new Static3D(-0.5f*(X-1),+0.5f*(Y-1),+0.5f*(Z-1));
1867
    roundCorners(mesh, center, vertices, strength, radius);
1868

    
1869
    vertices[0] = new Static3D(-0.5f*X,+0.5f*Y,-0.5f*Z);
1870
    center = new Static3D(-0.5f*(X-1),+0.5f*(Y-1),-0.5f*(Z-1));
1871
    roundCorners(mesh, center, vertices, strength, radius);
1872

    
1873
    vertices[0] = new Static3D(-0.5f*X,-0.5f*Y,+0.5f*Z);
1874
    center = new Static3D(-0.5f*(X-1),-0.5f*(Y-1),+0.5f*(Z-1));
1875
    roundCorners(mesh, center, vertices, strength, radius);
1876

    
1877
    vertices[0] = new Static3D(-0.5f*X,-0.5f*Y,-0.5f*Z);
1878
    center = new Static3D(-0.5f*(X-1),-0.5f*(Y-1),-0.5f*(Z-1));
1879
    roundCorners(mesh, center, vertices, strength, radius);
1880

    
1881
    mesh.mergeEffComponents();
1882

    
1883
    return mesh;
1884
    }
1885

    
1886

    
1887

    
1888

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

    
1891
  private boolean areColinear(double[][] vertices, int index1, int index2, int index3)
1892
    {
1893
    double x1 = vertices[index1][0];
1894
    double y1 = vertices[index1][1];
1895
    double z1 = vertices[index1][2];
1896
    double x2 = vertices[index2][0];
1897
    double y2 = vertices[index2][1];
1898
    double z2 = vertices[index2][2];
1899
    double x3 = vertices[index3][0];
1900
    double y3 = vertices[index3][1];
1901
    double z3 = vertices[index3][2];
1902

    
1903
    double v1x = x2-x1;
1904
    double v1y = y2-y1;
1905
    double v1z = z2-z1;
1906
    double v2x = x3-x1;
1907
    double v2y = y3-y1;
1908
    double v2z = z3-z1;
1909

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

    
1912
    return (v1x==A*v2x && v1y==A*v2y && v1z==A*v2z);
1913
    }
1914

    
1915
///////////////////////////////////////////////////////////////////////////////////////////////////
1916

    
1917
  private void computeNormalVector(double[][] vertices, int index1, int index2, int index3)
1918
    {
1919
    double x1 = vertices[index1][0];
1920
    double y1 = vertices[index1][1];
1921
    double z1 = vertices[index1][2];
1922
    double x2 = vertices[index2][0];
1923
    double y2 = vertices[index2][1];
1924
    double z2 = vertices[index2][2];
1925
    double x3 = vertices[index3][0];
1926
    double y3 = vertices[index3][1];
1927
    double z3 = vertices[index3][2];
1928

    
1929
    double v1x = x2-x1;
1930
    double v1y = y2-y1;
1931
    double v1z = z2-z1;
1932
    double v2x = x3-x1;
1933
    double v2y = y3-y1;
1934
    double v2z = z3-z1;
1935

    
1936
    mBuffer[0] = v1y*v2z - v2y*v1z;
1937
    mBuffer[1] = v1z*v2x - v2z*v1x;
1938
    mBuffer[2] = v1x*v2y - v2x*v1y;
1939

    
1940
    double len = mBuffer[0]*mBuffer[0] + mBuffer[1]*mBuffer[1] + mBuffer[2]*mBuffer[2];
1941
    len = Math.sqrt(len);
1942
    mBuffer[0] /= len;
1943
    mBuffer[1] /= len;
1944
    mBuffer[2] /= len;
1945
    }
1946

    
1947
///////////////////////////////////////////////////////////////////////////////////////////////////
1948
// return quat1*quat2
1949

    
1950
  private static void quatMultiply( double[] quat1, double[] quat2, double[] result )
1951
    {
1952
    double qx = quat1[0];
1953
    double qy = quat1[1];
1954
    double qz = quat1[2];
1955
    double qw = quat1[3];
1956

    
1957
    double rx = quat2[0];
1958
    double ry = quat2[1];
1959
    double rz = quat2[2];
1960
    double rw = quat2[3];
1961

    
1962
    result[0] = rw*qx - rz*qy + ry*qz + rx*qw;
1963
    result[1] = rw*qy + rz*qx + ry*qw - rx*qz;
1964
    result[2] = rw*qz + rz*qw - ry*qx + rx*qy;
1965
    result[3] = rw*qw - rz*qz - ry*qy - rx*qx;
1966
    }
1967

    
1968
///////////////////////////////////////////////////////////////////////////////////////////////////
1969

    
1970
  private void fitInSquare(FaceTransform info, double[][] vert3D)
1971
    {
1972
    double minX = Double.MAX_VALUE;
1973
    double maxX =-Double.MAX_VALUE;
1974
    double minY = Double.MAX_VALUE;
1975
    double maxY =-Double.MAX_VALUE;
1976

    
1977
    for (double[] vert : vert3D)
1978
      {
1979
      double x = vert[0];
1980
      double y = vert[1];
1981

    
1982
      if (x > maxX) maxX = x;
1983
      if (x < minX) minX = x;
1984
      if (y > maxY) maxY = y;
1985
      if (y < minY) minY = y;
1986
      }
1987

    
1988
    minX = minX<0 ? -minX:minX;
1989
    maxX = maxX<0 ? -maxX:maxX;
1990
    minY = minY<0 ? -minY:minY;
1991
    maxY = maxY<0 ? -maxY:maxY;
1992

    
1993
    double max1 = Math.max(minX,minY);
1994
    double max2 = Math.max(maxX,maxY);
1995
    double max3 = Math.max(max1,max2);
1996

    
1997
    info.scale = max3/0.5;
1998

    
1999
    int len = vert3D.length;
2000
    StickerCoords sInfo = new StickerCoords();
2001
    sInfo.vertices = new double[2*len];
2002

    
2003
    for( int vertex=0; vertex<len; vertex++ )
2004
      {
2005
      sInfo.vertices[2*vertex  ] = vert3D[vertex][0] / info.scale;
2006
      sInfo.vertices[2*vertex+1] = vert3D[vertex][1] / info.scale;
2007
      }
2008

    
2009
    mStickerCoords.add(sInfo);
2010

    
2011
    info.sticker = mStickerCoords.size() -1;
2012
    info.flip = false;
2013
    }
2014

    
2015
///////////////////////////////////////////////////////////////////////////////////////////////////
2016

    
2017
  private FaceTransform constructNewTransform(final double[][] vert3D)
2018
    {
2019
    FaceTransform ft = new FaceTransform();
2020

    
2021
    // compute center of gravity
2022
    ft.vx = 0.0f;
2023
    ft.vy = 0.0f;
2024
    ft.vz = 0.0f;
2025
    int len = vert3D.length;
2026

    
2027
    for (double[] vert : vert3D)
2028
      {
2029
      ft.vx += vert[0];
2030
      ft.vy += vert[1];
2031
      ft.vz += vert[2];
2032
      }
2033

    
2034
    ft.vx /= len;
2035
    ft.vy /= len;
2036
    ft.vz /= len;
2037

    
2038
    // move all vertices so that their center of gravity is at (0,0,0)
2039
    for (int i=0; i<len; i++)
2040
      {
2041
      vert3D[i][0] -= ft.vx;
2042
      vert3D[i][1] -= ft.vy;
2043
      vert3D[i][2] -= ft.vz;
2044
      }
2045

    
2046
    // find 3 non-colinear vertices
2047
    int foundIndex = -1;
2048

    
2049
    for(int vertex=2; vertex<len; vertex++)
2050
      {
2051
      if( !areColinear(vert3D,0,1,vertex) )
2052
        {
2053
        foundIndex = vertex;
2054
        break;
2055
        }
2056
      }
2057

    
2058
    // compute the normal vector
2059
    if( foundIndex==-1 )
2060
      {
2061
      throw new RuntimeException("all vertices colinear");
2062
      }
2063

    
2064
    computeNormalVector(vert3D,0,1,foundIndex);
2065

    
2066
    // rotate so that the normal vector becomes (0,0,1)
2067
    double axisX, axisY, axisZ;
2068

    
2069
    if( mBuffer[0]!=0.0f || mBuffer[1]!=0.0f )
2070
      {
2071
      axisX = -mBuffer[1];
2072
      axisY =  mBuffer[0];
2073
      axisZ = 0.0f;
2074

    
2075
      double axiLen = axisX*axisX + axisY*axisY;
2076
      axiLen = Math.sqrt(axiLen);
2077
      axisX /= axiLen;
2078
      axisY /= axiLen;
2079
      axisZ /= axiLen;
2080
      }
2081
    else
2082
      {
2083
      axisX = 0.0f;
2084
      axisY = 1.0f;
2085
      axisZ = 0.0f;
2086
      }
2087

    
2088
    double cosTheta = mBuffer[2];
2089
    double sinTheta = Math.sqrt(1-cosTheta*cosTheta);
2090
    double sinHalfTheta = computeSinHalf(cosTheta);
2091
    double cosHalfTheta = computeCosHalf(sinTheta,cosTheta);
2092

    
2093
    mQuat1[0] = axisX*sinHalfTheta;
2094
    mQuat1[1] = axisY*sinHalfTheta;
2095
    mQuat1[2] = axisZ*sinHalfTheta;
2096
    mQuat1[3] = cosHalfTheta;
2097
    mQuat2[0] =-axisX*sinHalfTheta;
2098
    mQuat2[1] =-axisY*sinHalfTheta;
2099
    mQuat2[2] =-axisZ*sinHalfTheta;
2100
    mQuat2[3] = cosHalfTheta;
2101

    
2102
    for (double[] vert : vert3D)
2103
      {
2104
      quatMultiply(mQuat1, vert  , mQuat3);
2105
      quatMultiply(mQuat3, mQuat2, vert  );
2106
      }
2107

    
2108
    // fit the whole thing in a square and remember the scale & 2D vertices
2109
    fitInSquare(ft, vert3D);
2110

    
2111
    // remember the rotation
2112
    ft.qx =-mQuat1[0];
2113
    ft.qy =-mQuat1[1];
2114
    ft.qz =-mQuat1[2];
2115
    ft.qw = mQuat1[3];
2116

    
2117
    return ft;
2118
    }
2119

    
2120
///////////////////////////////////////////////////////////////////////////////////////////////////
2121

    
2122
  private double computeCos(double oldX, double oldY, double newX, double newY, double len1, double len2)
2123
    {
2124
    double ret= (oldX*newX+oldY*newY) / (len1*len2);
2125
    if( ret<-1.0 ) return -1.0;
2126
    if( ret> 1.0 ) return  1.0;
2127

    
2128
    return ret;
2129
    }
2130

    
2131
///////////////////////////////////////////////////////////////////////////////////////////////////
2132
// sin of (signed!) angle between vectors 'old' and 'new', counterclockwise!
2133

    
2134
  private double computeSin(double oldX, double oldY, double newX, double newY, double len1, double len2)
2135
    {
2136
    double ret= (newX*oldY-oldX*newY) / (len1*len2);
2137
    if( ret<-1.0 ) return -1.0;
2138
    if( ret> 1.0 ) return  1.0;
2139

    
2140
    return ret;
2141
    }
2142

    
2143
///////////////////////////////////////////////////////////////////////////////////////////////////
2144

    
2145
  private void rotateAllVertices(double[] result, int len, double[] vertices, double sin, double cos)
2146
    {
2147
    for(int i=0; i<len; i++)
2148
      {
2149
      result[2*i  ] = vertices[2*i  ]*cos - vertices[2*i+1]*sin;
2150
      result[2*i+1] = vertices[2*i  ]*sin + vertices[2*i+1]*cos;
2151
      }
2152
    }
2153

    
2154
///////////////////////////////////////////////////////////////////////////////////////////////////
2155

    
2156
  private double computeScale(double[] v1, double[] v2)
2157
    {
2158
    double lenSq1 = v1[0]*v1[0] + v1[1]*v1[1];
2159
    double lenSq2 = v2[0]*v2[0] + v2[1]*v2[1];
2160

    
2161
    return Math.sqrt(lenSq2/lenSq1);
2162
    }
2163

    
2164
///////////////////////////////////////////////////////////////////////////////////////////////////
2165
// valid for 0<angle<2*PI
2166

    
2167
  private double computeSinHalf(double cos)
2168
    {
2169
    return Math.sqrt((1-cos)/2);
2170
    }
2171

    
2172
///////////////////////////////////////////////////////////////////////////////////////////////////
2173
// valid for 0<angle<2*PI
2174

    
2175
  private double computeCosHalf(double sin, double cos)
2176
    {
2177
    double cosHalf = Math.sqrt((1+cos)/2);
2178
    return sin<0 ? -cosHalf : cosHalf;
2179
    }
2180

    
2181
///////////////////////////////////////////////////////////////////////////////////////////////////
2182

    
2183
  private int computeRotatedIndex(int oldVertex, int len, int rotatedVertex, boolean inverted)
2184
    {
2185
    int v = (rotatedVertex + (inverted? -oldVertex : oldVertex));
2186
    if( v>=len ) v-=len;
2187
    if( v< 0   ) v+=len;
2188

    
2189
    return v;
2190
    }
2191

    
2192
///////////////////////////////////////////////////////////////////////////////////////////////////
2193

    
2194
  private boolean isScaledVersionOf(double[] newVert, double[] oldVert, int len, int vertex, boolean inverted)
2195
    {
2196
    double EPSILON = 0.001;
2197
    double scale = computeScale(newVert,oldVert);
2198

    
2199
    for(int i=1; i<len; i++)
2200
      {
2201
      int index = computeRotatedIndex(i,len,vertex,inverted);
2202

    
2203
      double horz = oldVert[2*i  ] - scale*newVert[2*index  ];
2204
      double vert = oldVert[2*i+1] - scale*newVert[2*index+1];
2205

    
2206
      if( horz>EPSILON || horz<-EPSILON || vert>EPSILON || vert<-EPSILON ) return false;
2207
      }
2208

    
2209
    return true;
2210
    }
2211

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

    
2214
  private void mirrorAllVertices(double[] output, int len, double[] input)
2215
    {
2216
    for(int vertex=0; vertex<len; vertex++)
2217
      {
2218
      output[2*vertex  ] = input[2*vertex  ];
2219
      output[2*vertex+1] =-input[2*vertex+1];
2220
      }
2221
    }
2222

    
2223
///////////////////////////////////////////////////////////////////////////////////////////////////
2224

    
2225
  private void correctInfo(FaceTransform info, double scale, double sin, double cos, int oldSticker, boolean flip)
2226
    {
2227
    mStickerCoords.remove(info.sticker);
2228

    
2229
    info.flip    = flip;
2230
    info.sticker = oldSticker;
2231
    info.scale  *= scale;
2232

    
2233
    mQuat1[0] = info.qx;
2234
    mQuat1[1] = info.qy;
2235
    mQuat1[2] = info.qz;
2236
    mQuat1[3] = info.qw;
2237

    
2238
    double sinHalf = computeSinHalf(cos);
2239
    double cosHalf = computeCosHalf(sin,cos);
2240

    
2241
    if( flip )
2242
      {
2243
      mQuat3[0] = 0.0f;
2244
      mQuat3[1] = 0.0f;
2245
      mQuat3[2] = sinHalf;
2246
      mQuat3[3] = cosHalf;
2247

    
2248
      mQuat4[0] = 1.0;
2249
      mQuat4[1] = 0.0;
2250
      mQuat4[2] = 0.0;
2251
      mQuat4[3] = 0.0;
2252

    
2253
      quatMultiply( mQuat3, mQuat4, mQuat2 );
2254
      }
2255
    else
2256
      {
2257
      mQuat2[0] = 0.0f;
2258
      mQuat2[1] = 0.0f;
2259
      mQuat2[2] = sinHalf;
2260
      mQuat2[3] = cosHalf;
2261
      }
2262

    
2263
    quatMultiply( mQuat1, mQuat2, mQuat3 );
2264

    
2265
    info.qx = mQuat3[0];
2266
    info.qy = mQuat3[1];
2267
    info.qz = mQuat3[2];
2268
    info.qw = mQuat3[3];
2269
    }
2270

    
2271
///////////////////////////////////////////////////////////////////////////////////////////////////
2272

    
2273
  private void printVert(double[] buffer)
2274
    {
2275
    int len = buffer.length/2;
2276
    String str = "";
2277

    
2278
    for(int i=0; i<len; i++)
2279
      {
2280
      str += (" ("+buffer[2*i]+" , "+buffer[2*i+1]+" ) ");
2281
      }
2282

    
2283
    android.util.Log.d("D", str);
2284
    }
2285

    
2286
///////////////////////////////////////////////////////////////////////////////////////////////////
2287

    
2288
  private boolean foundVertex(FaceTransform info, double[] buffer, int len, double[] newVert,
2289
                              double[] oldVert, double lenFirstOld, int oldSticker, boolean inverted)
2290
    {
2291
    for(int vertex=0; vertex<len; vertex++)
2292
      {
2293
      double newX = newVert[2*vertex  ];
2294
      double newY = newVert[2*vertex+1];
2295
      double lenIthNew = Math.sqrt(newX*newX + newY*newY);
2296
      double cos = computeCos( oldVert[0], oldVert[1], newX, newY, lenIthNew, lenFirstOld);
2297
      double sin = computeSin( oldVert[0], oldVert[1], newX, newY, lenIthNew, lenFirstOld);
2298

    
2299
      rotateAllVertices(buffer,len,newVert,sin,cos);
2300

    
2301
      if( isScaledVersionOf(buffer,oldVert,len,vertex,inverted) )
2302
        {
2303
        double scale = computeScale(oldVert,newVert);
2304
        correctInfo(info,scale,sin,cos,oldSticker,inverted);
2305
        return true;
2306
        }
2307
      }
2308

    
2309
    return false;
2310
    }
2311

    
2312
///////////////////////////////////////////////////////////////////////////////////////////////////
2313

    
2314
  private boolean successfullyCollapsedStickers(final FaceTransform newInfo, final FaceTransform oldInfo)
2315
    {
2316
    StickerCoords sNewInfo = mStickerCoords.get(newInfo.sticker);
2317
    StickerCoords sOldInfo = mStickerCoords.get(oldInfo.sticker);
2318
    double[] newVert = sNewInfo.vertices;
2319
    double[] oldVert = sOldInfo.vertices;
2320
    int oldLen = oldVert.length;
2321
    int newLen = newVert.length;
2322

    
2323
    if( oldLen == newLen )
2324
      {
2325
      int oldSticker = oldInfo.sticker;
2326
      double[] buffer1 = new double[oldLen];
2327
      double lenFirstOld = Math.sqrt(oldVert[0]*oldVert[0] + oldVert[1]*oldVert[1]);
2328
      if( foundVertex(newInfo, buffer1, oldLen/2, newVert, oldVert, lenFirstOld, oldSticker, false) ) return true;
2329
      double[] buffer2 = new double[oldLen];
2330
      mirrorAllVertices(buffer2, newLen/2, newVert);
2331
      if( foundVertex(newInfo, buffer1, oldLen/2, buffer2, oldVert, lenFirstOld, oldSticker, true ) ) return true;
2332
      }
2333

    
2334
    return false;
2335
    }
2336

    
2337
///////////////////////////////////////////////////////////////////////////////////////////////////
2338

    
2339
  private double[][] constructVert(double[][] vertices, int[] index)
2340
    {
2341
    int len = index.length;
2342
    double[][] ret = new double[len][4];
2343

    
2344
    for(int i=0; i<len; i++)
2345
      {
2346
      ret[i][0] = vertices[index[i]][0];
2347
      ret[i][1] = vertices[index[i]][1];
2348
      ret[i][2] = vertices[index[i]][2];
2349
      ret[i][3] = 1.0f;
2350
      }
2351

    
2352
    return ret;
2353
    }
2354

    
2355
///////////////////////////////////////////////////////////////////////////////////////////////////
2356

    
2357
  private void prepareAndRoundCorners(MeshBase mesh, double[][] vertices,
2358
                                      float[][] corners, int[] cornerIndexes,
2359
                                      float[][] centers, int[] centerIndexes )
2360
    {
2361
    int lenV = vertices.length;
2362
    Static3D[] staticVert = new Static3D[1];
2363
    Static3D center = new Static3D(0,0,0);
2364

    
2365
    for(int v=0; v<lenV; v++)
2366
      {
2367
      staticVert[0] = new Static3D( (float)vertices[v][0], (float)vertices[v][1], (float)vertices[v][2]);
2368

    
2369
      int cent = centerIndexes[v];
2370
      center.set( centers[cent][0], centers[cent][1], centers[cent][2]);
2371

    
2372
      int corn = cornerIndexes[v];
2373
      float strength = corners[corn][0];
2374
      float radius   = corners[corn][1];
2375

    
2376
      roundCorners(mesh, center, staticVert, strength, radius);
2377
      }
2378
    }
2379

    
2380
///////////////////////////////////////////////////////////////////////////////////////////////////
2381

    
2382
  private void correctComponents(MeshBase mesh, int numComponents)
2383
    {
2384
    int numTexToBeAdded = numComponents-mesh.getNumTexComponents();
2385

    
2386
    mesh.mergeEffComponents();
2387

    
2388
    for(int i=0; i<numTexToBeAdded; i++ ) mesh.addEmptyTexComponent();
2389
    }
2390

    
2391
///////////////////////////////////////////////////////////////////////////////////////////////////
2392

    
2393
  private void printTransform(FaceTransform f)
2394
    {
2395
    android.util.Log.e("D", "q=("+f.qx+", "+f.qy+", "+f.qz+", "+f.qw+") v=("
2396
                       +f.vx+", "+f.vy+", "+f.vz+") scale="+f.scale+" sticker="+f.sticker);
2397
    }
2398

    
2399
///////////////////////////////////////////////////////////////////////////////////////////////////
2400
// PUBLIC
2401

    
2402
  public void printStickerCoords()
2403
    {
2404
    int stickers = mStickerCoords.size();
2405

    
2406
    android.util.Log.d("D", "---- STICKER COORDS ----");
2407

    
2408
    for(int s=0; s<stickers; s++)
2409
      {
2410
      String ver = "{ ";
2411
      StickerCoords info = mStickerCoords.get(s);
2412
      int len = info.vertices.length/2;
2413

    
2414
      for(int i =0; i<len; i++)
2415
        {
2416
        if( i!=0 ) ver += ", ";
2417
        ver += ( (float)info.vertices[2*i]+"f, "+(float)info.vertices[2*i+1]+"f");
2418
        }
2419

    
2420
      ver += " }";
2421
      android.util.Log.d("D", ver);
2422
      }
2423

    
2424
    android.util.Log.d("D", "---- END STICKER COORDS ----");
2425
    }
2426

    
2427
///////////////////////////////////////////////////////////////////////////////////////////////////
2428

    
2429
  public void printFaceTransform()
2430
    {
2431
    android.util.Log.d("D", "---- OLD FACE TRANSFORM ---");
2432

    
2433
    int oldfaces = mOldFaceTransf.size();
2434

    
2435
    for(int f=0; f<oldfaces; f++)
2436
      {
2437
      printTransform(mOldFaceTransf.get(f));
2438
      }
2439

    
2440
    android.util.Log.d("D", "---- NEW FACE TRANSFORM ---");
2441

    
2442
    int newfaces = mNewFaceTransf.size();
2443

    
2444
    for(int f=0; f<newfaces; f++)
2445
      {
2446
      printTransform(mNewFaceTransf.get(f));
2447
      }
2448
    }
2449

    
2450
///////////////////////////////////////////////////////////////////////////////////////////////////
2451

    
2452
  public void clear()
2453
    {
2454
    mStickerCoords.clear();
2455
    mNewFaceTransf.clear();
2456
    mOldFaceTransf.clear();
2457
    }
2458

    
2459
///////////////////////////////////////////////////////////////////////////////////////////////////
2460

    
2461
  public void createNewFaceTransform( final double[][] vertices, final int[][] indexes)
2462
    {
2463
    FaceTransform ft;
2464
    int numNew = mNewFaceTransf.size();
2465

    
2466
    for(int i=0; i<numNew; i++)
2467
      {
2468
      ft = mNewFaceTransf.remove(0);
2469
      mOldFaceTransf.add(ft);
2470
      }
2471

    
2472
    int numFaces = indexes.length;
2473
    int numOld = mOldFaceTransf.size();
2474

    
2475
    for (int face=0; face<numFaces; face++)
2476
      {
2477
      boolean collapsed = false;
2478

    
2479
      double[][] vert = constructVert(vertices, indexes[face]);
2480
      FaceTransform newT = constructNewTransform(vert);
2481

    
2482
      for (int old=0; !collapsed && old<numOld; old++)
2483
        {
2484
        ft = mOldFaceTransf.get(old);
2485
        if (successfullyCollapsedStickers(newT, ft)) collapsed = true;
2486
        }
2487

    
2488
      for (int pre=0; !collapsed && pre<face; pre++)
2489
        {
2490
        ft = mNewFaceTransf.get(pre);
2491
        if (successfullyCollapsedStickers(newT, ft)) collapsed = true;
2492
        }
2493

    
2494
      mNewFaceTransf.add(newT);
2495
      }
2496
    }
2497

    
2498
///////////////////////////////////////////////////////////////////////////////////////////////////
2499

    
2500
  public MeshBase createRoundedSolid(final double[][] vertices, final int[][] vertIndexes,
2501
                                     final float[][] bands    , final int[]   bandIndexes,
2502
                                     final float[][] corners  , final int[]   cornerIndexes,
2503
                                     final float[][] centers  , final int[]   centerIndexes,
2504
                                     final int numComponents )
2505
    {
2506
    int numFaces = vertIndexes.length;
2507
    float[] band, bandsComputed;
2508
    MeshBase[] meshes = new MeshBase[numFaces];
2509
    FaceTransform fInfo;
2510
    StickerCoords sInfo;
2511

    
2512
    for(int face=0; face<numFaces; face++)
2513
      {
2514
      fInfo = mNewFaceTransf.get(face);
2515
      sInfo = mStickerCoords.get(fInfo.sticker);
2516

    
2517
      double[] verts = sInfo.vertices;
2518
      int lenVerts = verts.length;
2519
      float[] vertsFloat = new float[lenVerts];
2520
      for(int i=0; i<lenVerts; i++) vertsFloat[i] = (float)verts[i];
2521

    
2522
      band = bands[bandIndexes[face]];
2523
      bandsComputed = computeBands( band[0], (int)band[1], band[2], band[3], (int)band[4]);
2524
      meshes[face] = new MeshPolygon(vertsFloat,bandsComputed,(int)band[5],(int)band[6]);
2525
      meshes[face].setEffectAssociation(0,(1<<face),0);
2526
      }
2527

    
2528
    MeshBase mesh = new MeshJoined(meshes);
2529
    Static3D center = new Static3D(0,0,0);
2530

    
2531
    for(int face=0; face<numFaces; face++)
2532
      {
2533
      int assoc = (1<<face);
2534
      fInfo = mNewFaceTransf.get(face);
2535

    
2536
      float vx = (float)fInfo.vx;
2537
      float vy = (float)fInfo.vy;
2538
      float vz = (float)fInfo.vz;
2539
      float sc = (float)fInfo.scale;
2540
      float qx = (float)fInfo.qx;
2541
      float qy = (float)fInfo.qy;
2542
      float qz = (float)fInfo.qz;
2543
      float qw = (float)fInfo.qw;
2544

    
2545
      Static3D scale = new Static3D(sc,sc, fInfo.flip ? -sc : sc);
2546
      Static3D move3D= new Static3D(vx,vy,vz);
2547
      Static4D quat  = new Static4D(qx,qy,qz,qw);
2548

    
2549
      mesh.apply(new MatrixEffectScale(scale)           ,assoc,-1);
2550
      mesh.apply(new MatrixEffectQuaternion(quat,center),assoc,-1);
2551
      mesh.apply(new MatrixEffectMove(move3D)           ,assoc,-1);
2552
      }
2553

    
2554
    prepareAndRoundCorners(mesh, vertices, corners, cornerIndexes, centers, centerIndexes);
2555

    
2556
    correctComponents(mesh,numComponents);
2557

    
2558
    return mesh;
2559
    }
2560
  }
(3-3/4)