Project

General

Profile

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

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

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 Static1D RADIUS = new Static1D(1);
45
  private static FactoryCubit mThis;
46

    
47
  // IVY
48
  static final float IVY_D = 0.003f;
49
  static final float IVY_C = 0.59f;
50
  static final float IVY_M = 0.35f;
51
  private static final int IVY_N = 8;
52

    
53
  // REX
54
  public static final float REX_D = 0.2f;
55

    
56
  private static final double[] mBuffer = new double[3];
57
  private static final double[] mQuat1  = new double[4];
58
  private static final double[] mQuat2  = new double[4];
59
  private static final double[] mQuat3  = new double[4];
60
  private static final double[] mQuat4  = new double[4];
61

    
62
  private static class StickerCoords
63
    {
64
    double[] vertices;
65
    }
66

    
67
  private static class FaceTransform
68
    {
69
    int sticker;
70
    double vx,vy,vz;
71
    double scale;
72
    double qx,qy,qz,qw;
73
    boolean flip;
74
    }
75

    
76
  private static final ArrayList<FaceTransform> mNewFaceTransf = new ArrayList<>();
77
  private static final ArrayList<FaceTransform> mOldFaceTransf = new ArrayList<>();
78
  private static final ArrayList<StickerCoords> mStickerCoords = new ArrayList<>();
79

    
80
///////////////////////////////////////////////////////////////////////////////////////////////////
81

    
82
  private FactoryCubit()
83
    {
84

    
85
    }
86

    
87
///////////////////////////////////////////////////////////////////////////////////////////////////
88

    
89
  public static FactoryCubit getInstance()
90
    {
91
    if( mThis==null ) mThis = new FactoryCubit();
92

    
93
    return mThis;
94
    }
95

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

    
131
///////////////////////////////////////////////////////////////////////////////////////////////////
132

    
133
  private float f(float D, float B, float x)
134
    {
135
    return ((D-B)*x + B*(1-D))/(1-B);
136
    }
137

    
138
///////////////////////////////////////////////////////////////////////////////////////////////////
139

    
140
  private float g(float R, float D, float x, float cosAlpha)
141
    {
142
    float d = x-D;
143
    return (float)(Math.sqrt(R*R-d*d)-R*cosAlpha);
144
    }
145

    
146
///////////////////////////////////////////////////////////////////////////////////////////////////
147

    
148
  private float h(float R, float sinAlpha, float x)
149
    {
150
    return R*(sinAlpha-(float)Math.sin(x));
151
    }
152

    
153
///////////////////////////////////////////////////////////////////////////////////////////////////
154

    
155
  private float[] computeBands(float H, int alpha, float dist, float K, int N)
156
    {
157
    float[] bands = new float[2*N];
158

    
159
    bands[0] = 1.0f;
160
    bands[1] = 0.0f;
161

    
162
    float beta = (float)Math.atan(dist*Math.tan(Math.PI*alpha/180));
163
    float sinBeta = (float)Math.sin(beta);
164
    float cosBeta = (float)Math.cos(beta);
165
    float R = cosBeta<1.0f ? H/(1.0f-cosBeta) : 0.0f;
166
    float D = R*sinBeta;
167
    float B = h(R,sinBeta,K*beta);
168

    
169
    if( D>1.0f )
170
      {
171
      for(int i=1; i<N; i++)
172
        {
173
        bands[2*i  ] = (float)(N-1-i)/(N-1);
174
        bands[2*i+1] = H*(1-bands[2*i]);
175
        }
176
      }
177
    else
178
      {
179
      int K2 = (int)((N-3)*K);
180
      int K1 = (N-3)-K2;
181

    
182
      for(int i=0; i<=K1; i++)
183
        {
184
        float angle = K*beta + (1-K)*beta*(K1-i)/(K1+1);
185
        float x = h(R,sinBeta,angle);
186
        bands[2*i+2] = 1.0f - x;
187
        bands[2*i+3] = g(R,D,x,cosBeta);
188
        }
189

    
190
      for(int i=0; i<=K2; i++)
191
        {
192
        float x = (1-B)*(i+1)/(K2+1) + B;
193
        bands[2*K1+2 + 2*i+2] = 1.0f - x;
194
        bands[2*K1+2 + 2*i+3] = g(R,D,f(D,B,x),cosBeta);
195
        }
196
      }
197

    
198
    bands[2*N-2] = 0.0f;
199
    bands[2*N-1] =    H;
200

    
201
    return bands;
202
    }
203

    
204
///////////////////////////////////////////////////////////////////////////////////////////////////
205

    
206
  private void roundCorners(MeshBase mesh, Static3D center, Static3D[] vertices, float strength, float regionRadius)
207
    {
208
    Static4D reg= new Static4D(0,0,0,regionRadius);
209

    
210
    float centX = center.get0();
211
    float centY = center.get1();
212
    float centZ = center.get2();
213

    
214
    for (Static3D vertex : vertices)
215
      {
216
      float x = strength*(centX - vertex.get0());
217
      float y = strength*(centY - vertex.get1());
218
      float z = strength*(centZ - vertex.get2());
219

    
220
      VertexEffect effect = new VertexEffectDeform(new Static3D(x,y,z), RADIUS, vertex, reg);
221
      mesh.apply(effect);
222
      }
223
    }
224

    
225
///////////////////////////////////////////////////////////////////////////////////////////////////
226

    
227
  MeshBase createFacesIvyCorner()
228
    {
229
    MeshBase[] meshes = new MeshBase[6];
230

    
231
    final float angle = (float)Math.PI/(2*IVY_N);
232
    final float CORR  = 1.0f - 2*IVY_D;
233
    final float DIST  = -0.5f*CORR + IVY_D;
234
    float[] vertices  = new float[2*(IVY_N+1)+6];
235

    
236
    vertices[0] = (0.5f-IVY_M) * IVY_C;
237
    vertices[1] = (DIST-IVY_M) * IVY_C;
238
    vertices[2] = (0.5f-IVY_M) * IVY_C;
239
    vertices[3] = (0.5f-IVY_M) * IVY_C;
240
    vertices[4] = (DIST-IVY_M) * IVY_C;
241
    vertices[5] = (0.5f-IVY_M) * IVY_C;
242

    
243
    for(int i=0; i<=IVY_N; i++)
244
      {
245
      float ang = (IVY_N-i)*angle;
246
      float sin = (float)Math.sin(ang);
247
      float cos = (float)Math.cos(ang);
248

    
249
      vertices[2*i+6] = (CORR*(cos-0.5f)-IVY_M)*IVY_C;
250
      vertices[2*i+7] = (CORR*(sin-0.5f)-IVY_M)*IVY_C;
251
      }
252

    
253
    float[] bands0 = computeBands(+0.012f,20,0.2f,0.5f,7);
254
    float[] bands1 = computeBands(-0.100f,20,0.2f,0.0f,2);
255

    
256
    meshes[0] = new MeshPolygon(vertices,bands0,1,2);
257
    meshes[0].setEffectAssociation(0,1,0);
258
    meshes[1] = meshes[0].copy(true);
259
    meshes[1].setEffectAssociation(0,2,0);
260
    meshes[2] = meshes[0].copy(true);
261
    meshes[2].setEffectAssociation(0,4,0);
262
    meshes[3] = new MeshPolygon(vertices,bands1,1,2);
263
    meshes[3].setEffectAssociation(0,8,0);
264
    meshes[4] = meshes[3].copy(true);
265
    meshes[4].setEffectAssociation(0,16,0);
266
    meshes[5] = meshes[3].copy(true);
267
    meshes[5].setEffectAssociation(0,32,0);
268

    
269
    return new MeshJoined(meshes);
270
    }
271

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

    
274
  MeshBase createFacesIvyFace()
275
    {
276
    MeshBase[] meshes = new MeshBase[2];
277

    
278
    final float angle = (float)Math.PI/(2*IVY_N);
279
    final float CORR  = 1.0f - 2*IVY_D;
280
    float[] vertices = new float[4*IVY_N];
281

    
282
    for(int i=0; i<IVY_N; i++)
283
      {
284
      float sin = (float)Math.sin(i*angle);
285
      float cos = (float)Math.cos(i*angle);
286

    
287
      vertices[2*i          ] = CORR*(0.5f-cos);
288
      vertices[2*i+1        ] = CORR*(0.5f-sin);
289
      vertices[2*i  +2*IVY_N] = CORR*(cos-0.5f);
290
      vertices[2*i+1+2*IVY_N] = CORR*(sin-0.5f);
291
      }
292

    
293
    float[] bands0 = computeBands(+0.03f,35,0.5f,0.5f,5);
294
    float[] bands1 = computeBands(-0.10f,45,0.5f,0.0f,2);
295

    
296
    meshes[0] = new MeshPolygon(vertices,bands0,0,0);
297
    meshes[0].setEffectAssociation(0,1,0);
298
    meshes[1] = new MeshPolygon(vertices,bands1,0,0);
299
    meshes[1].setEffectAssociation(0,2,0);
300

    
301
    return new MeshJoined(meshes);
302
    }
303

    
304
///////////////////////////////////////////////////////////////////////////////////////////////////
305

    
306
  MeshBase createFacesRexCorner()
307
    {
308
    MeshBase[] meshes = new MeshBase[2];
309

    
310
    float F = REX_D*SQ2;
311
    float G = (1-REX_D)*SQ2/2;
312
    float H = 0.1f;
313
    float J = +2*G/3 - H*G;
314

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

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

    
320
    meshes[0] = new MeshPolygon(vertices,bands0,1,1);
321
    meshes[0].setEffectAssociation(0,1,0);
322
    meshes[1] = new MeshPolygon(vertices,bands1,0,0);
323
    meshes[1].setEffectAssociation(0,2,0);
324

    
325
    return new MeshJoined(meshes);
326
    }
327

    
328
///////////////////////////////////////////////////////////////////////////////////////////////////
329

    
330
  MeshBase createFacesRexFace()
331
    {
332
    MeshBase[] meshes = new MeshBase[2];
333

    
334
    float[] vertices = { -REX_D,0.0f, 0.0f, -REX_D, +REX_D, 0.0f, 0.0f, +REX_D};
335

    
336
    float[] bands0 = computeBands(0.016f,10,REX_D/2,0.5f,5);
337
    float[] bands1 = computeBands(0.000f,45,REX_D/2,0.0f,2);
338

    
339
    meshes[0] = new MeshPolygon(vertices,bands0,0,0);
340
    meshes[0].setEffectAssociation(0,1,0);
341
    meshes[1] = new MeshPolygon(vertices,bands1,0,0);
342
    meshes[1].setEffectAssociation(0,2,0);
343

    
344
    return new MeshJoined(meshes);
345
    }
346

    
347
///////////////////////////////////////////////////////////////////////////////////////////////////
348

    
349
  MeshBase createFacesRexEdge()
350
    {
351
    MeshBase[] meshes = new MeshPolygon[6];
352

    
353
    float E = 0.5f - REX_D;
354
    float F = 0.5f;
355
    float[] vertices0 = { -F,E/3, 0,-2*E/3, +F,E/3 };
356
    float[] bands0 = computeBands(0.03f,27,F/3,0.8f,5);
357

    
358
    meshes[0] = new MeshPolygon(vertices0, bands0, 2, 3);
359
    meshes[0].setEffectAssociation(0,1,0);
360
    meshes[1] = meshes[0].copy(true);
361
    meshes[1].setEffectAssociation(0,2,0);
362

    
363
    float G = (float)Math.sqrt(E*E+F*F);
364
    float[] vertices1 = { -2*G/3, -E/3, G/3, -E/3, G/3, 2*E/3 };
365
    float[] bands1 = computeBands(0.00f,45,G/3,0.2f,3);
366

    
367
    meshes[2] = new MeshPolygon(vertices1, bands1, 1, 2);
368
    meshes[2].setEffectAssociation(0,4,0);
369
    meshes[3] = meshes[2].copy(true);
370
    meshes[3].setEffectAssociation(0,8,0);
371
    meshes[4] = meshes[2].copy(true);
372
    meshes[4].setEffectAssociation(0,16,0);
373
    meshes[5] = meshes[2].copy(true);
374
    meshes[5].setEffectAssociation(0,32,0);
375

    
376
    return new MeshJoined(meshes);
377
    }
378

    
379
///////////////////////////////////////////////////////////////////////////////////////////////////
380

    
381
  private float[] createVertices(int A, int B)
382
    {
383
    float E = 0.5f / Math.max(A,B);
384
    return new float[] { -A*E,-B*E, +A*E,-B*E, +A*E,+B*E, -A*E,+B*E };
385
    }
386

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

    
389
  MeshBase createCuboid(int[] dimensions)
390
    {
391
    int X = dimensions[0];
392
    int Y = dimensions[1];
393
    int Z = dimensions[2];
394

    
395
    float[] verticesXY = createVertices(X,Y);
396
    float[] verticesXZ = createVertices(X,Z);
397
    float[] verticesYZ = createVertices(Z,Y);
398

    
399
    float defHeight = 0.048f;
400

    
401
    float[] bandsX = computeBands( defHeight/X,65,0.25f,0.5f,5);
402
    float[] bandsY = computeBands( defHeight/Y,65,0.25f,0.5f,5);
403
    float[] bandsZ = computeBands( defHeight/Z,65,0.25f,0.5f,5);
404

    
405
    MeshBase[] meshes = new MeshPolygon[6];
406

    
407
    meshes[0] = new MeshPolygon(verticesYZ,bandsX,1,2);
408
    meshes[0].setEffectAssociation(0,1,0);
409
    meshes[1] = meshes[0].copy(true);
410
    meshes[1].setEffectAssociation(0,2,0);
411
    meshes[2] = new MeshPolygon(verticesXZ,bandsY,1,2);
412
    meshes[2].setEffectAssociation(0,4,0);
413
    meshes[3] = meshes[2].copy(true);
414
    meshes[3].setEffectAssociation(0,8,0);
415
    meshes[4] = new MeshPolygon(verticesXY,bandsZ,1,2);
416
    meshes[4].setEffectAssociation(0,16,0);
417
    meshes[5] = meshes[4].copy(true);
418
    meshes[5].setEffectAssociation(0,32,0);
419

    
420
    return new MeshJoined(meshes);
421
    }
422

    
423
///////////////////////////////////////////////////////////////////////////////////////////////////
424
// EFFECTS
425
///////////////////////////////////////////////////////////////////////////////////////////////////
426

    
427
  VertexEffect[] createVertexEffectsIvyCorner()
428
    {
429
    Static3D axisX  = new Static3D(1,0,0);
430
    Static3D axisY  = new Static3D(0,1,0);
431
    Static1D angle1 = new Static1D(+90);
432
    Static1D angle2 = new Static1D(-90);
433
    Static3D center = new Static3D(0,0,0);
434
    Static3D move1  = new Static3D(IVY_M-0.5f,IVY_M-0.5f,0);
435

    
436
    VertexEffect[] effect = new VertexEffect[5];
437

    
438
    effect[0] = new VertexEffectScale(1/IVY_C);
439
    effect[1] = new VertexEffectMove(move1);
440
    effect[2] = new VertexEffectScale(new Static3D(1,1,-1));
441
    effect[3] = new VertexEffectRotate(angle1,axisX,center);
442
    effect[4] = new VertexEffectRotate(angle2,axisY,center);
443

    
444
    effect[2].setMeshAssociation(54,-1);  // meshes 1,2,4,5
445
    effect[3].setMeshAssociation(18,-1);  // meshes 1,4
446
    effect[4].setMeshAssociation(36,-1);  // meshes 2,5
447

    
448
    return effect;
449
    }
450

    
451
///////////////////////////////////////////////////////////////////////////////////////////////////
452

    
453
  VertexEffect[] createVertexEffectsRexEdge()
454
    {
455
    float E = 0.5f - REX_D;
456
    float F = 0.5f;
457
    float G = (float)Math.sqrt(E*E+F*F);
458
    float A = (float)((180/Math.PI)*Math.asin(E/G));
459

    
460
    Static3D move1 = new Static3D(    0.0f, -E/3, 0.0f);
461
    Static3D move2 = new Static3D(2*G/3 -F, +E/3, 0.0f);
462

    
463
    Static3D center0= new Static3D(0.0f, 0.0f, 0.0f);
464
    Static3D center1= new Static3D(  -F, 0.0f, 0.0f);
465
    Static3D center2= new Static3D(  +F, 0.0f, 0.0f);
466
    Static3D axisX  = new Static3D(1.0f, 0.0f, 0.0f);
467
    Static3D axisY  = new Static3D(0.0f, 1.0f, 0.0f);
468
    Static3D axisZ  = new Static3D(0.0f, 0.0f, 1.0f);
469

    
470
    Static1D angle180 = new Static1D(180);
471
    Static1D angle90  = new Static1D( 90);
472
    Static1D angle270 = new Static1D(270);
473
    Static1D angle1   = new Static1D(+A);
474
    Static1D angle2   = new Static1D(-A);
475

    
476
    VertexEffect[] effect = new VertexEffect[12];
477

    
478
    effect[0] = new VertexEffectMove(move1);
479
    effect[1] = new VertexEffectMove(move2);
480
    effect[2] = new VertexEffectRotate(  angle90, axisX, center0 );
481
    effect[3] = new VertexEffectRotate( angle270, axisX, center0 );
482
    effect[4] = new VertexEffectRotate( angle180, axisX, center0 );
483
    effect[5] = new VertexEffectRotate( angle180, axisY, center0 );
484
    effect[6] = new VertexEffectScale ( new Static3D(-1, 1, 1) );
485
    effect[7] = new VertexEffectScale ( new Static3D( 1,-1, 1) );
486
    effect[8] = new VertexEffectRotate(   angle1, axisY, center1);
487
    effect[9] = new VertexEffectRotate(   angle2, axisY, center2);
488
    effect[10]= new VertexEffectRotate(   angle2, axisZ, center1);
489
    effect[11]= new VertexEffectRotate(   angle1, axisZ, center2);
490

    
491
    effect[0].setMeshAssociation( 3,-1);  // meshes 0 & 1
492
    effect[1].setMeshAssociation(60,-1);  // meshes 2,3,4,5
493
    effect[2].setMeshAssociation( 2,-1);  // meshes 1
494
    effect[3].setMeshAssociation(12,-1);  // meshes 2,3
495
    effect[4].setMeshAssociation(48,-1);  // meshes 4,5
496
    effect[5].setMeshAssociation(32,-1);  // mesh 5
497
    effect[6].setMeshAssociation( 8,-1);  // apply to mesh 3
498
    effect[7].setMeshAssociation( 2,-1);  // apply to mesh 1
499
    effect[8].setMeshAssociation(16,-1);  // apply to mesh 4
500
    effect[9].setMeshAssociation(32,-1);  // apply to mesh 5
501
    effect[10].setMeshAssociation(4,-1);  // apply to mesh 2
502
    effect[11].setMeshAssociation(8,-1);  // apply to mesh 3
503

    
504
    return effect;
505
    }
506

    
507
///////////////////////////////////////////////////////////////////////////////////////////////////
508

    
509
  VertexEffect[] createVertexEffectsRexCorner()
510
    {
511
    Static3D center= new Static3D(0.0f, 0.0f, 0.0f);
512
    Static3D axisZ = new Static3D(0.0f, 0.0f, 1.0f);
513
    Static1D angle = new Static1D(225);
514

    
515
    VertexEffect[] effect = new VertexEffect[1];
516
    effect[0] = new VertexEffectRotate(angle, axisZ, center);
517

    
518
    return effect;
519
    }
520

    
521
///////////////////////////////////////////////////////////////////////////////////////////////////
522

    
523
  VertexEffect[] createCuboidEffects(int[] dimensions)
524
    {
525
    float X = dimensions[0];
526
    float Y = dimensions[1];
527
    float Z = dimensions[2];
528

    
529
    float MAX_XY = Math.max(X,Y);
530
    float MAX_XZ = Math.max(X,Z);
531
    float MAX_YZ = Math.max(Z,Y);
532

    
533
    Static1D angle = new Static1D(90);
534
    Static3D move  = new Static3D( 0.0f, 0.0f, 0.5f);
535
    Static3D axisX = new Static3D( 1.0f, 0.0f, 0.0f);
536
    Static3D axisY = new Static3D( 0.0f, 1.0f, 0.0f);
537
    Static3D center= new Static3D( 0.0f, 0.0f, 0.0f);
538

    
539
    Static3D scale3 = new Static3D(MAX_XY,MAX_XY,+Z);
540
    Static3D scale4 = new Static3D(MAX_XY,MAX_XY,-Z);
541
    Static3D scale5 = new Static3D(MAX_XZ,+Y,MAX_XZ);
542
    Static3D scale6 = new Static3D(MAX_XZ,-Y,MAX_XZ);
543
    Static3D scale7 = new Static3D(+X,MAX_YZ,MAX_YZ);
544
    Static3D scale8 = new Static3D(-X,MAX_YZ,MAX_YZ);
545

    
546
    VertexEffect[] effect = new VertexEffect[9];
547

    
548
    effect[0] = new VertexEffectMove(move);
549
    effect[1] = new VertexEffectRotate(angle, axisX, center);
550
    effect[2] = new VertexEffectRotate(angle, axisY, center);
551
    effect[3] = new VertexEffectScale(scale3);
552
    effect[4] = new VertexEffectScale(scale4);
553
    effect[5] = new VertexEffectScale(scale5);
554
    effect[6] = new VertexEffectScale(scale6);
555
    effect[7] = new VertexEffectScale(scale7);
556
    effect[8] = new VertexEffectScale(scale8);
557

    
558
    effect[1].setMeshAssociation(12,-1);  // meshes 2,3
559
    effect[2].setMeshAssociation( 3,-1);  // meshes 0,1
560
    effect[3].setMeshAssociation(16,-1);  // mesh 4
561
    effect[4].setMeshAssociation(32,-1);  // mesh 5
562
    effect[5].setMeshAssociation( 8,-1);  // mesh 3
563
    effect[6].setMeshAssociation( 4,-1);  // mesh 2
564
    effect[7].setMeshAssociation( 1,-1);  // mesh 0
565
    effect[8].setMeshAssociation( 2,-1);  // mesh 1
566

    
567
    return effect;
568
    }
569

    
570
///////////////////////////////////////////////////////////////////////////////////////////////////
571
// OBJECTS
572
///////////////////////////////////////////////////////////////////////////////////////////////////
573

    
574
  public MeshBase createIvyCornerMesh()
575
    {
576
    MeshBase mesh = createFacesIvyCorner();
577
    VertexEffect[] effects = createVertexEffectsIvyCorner();
578
    for( VertexEffect effect : effects ) mesh.apply(effect);
579

    
580
    Static3D center = new Static3D(-0.5f,-0.5f,-0.5f);
581
    Static3D[] vertices = new Static3D[4];
582
    vertices[0] = new Static3D(+0.0f,+0.0f,+0.0f);
583
    vertices[1] = new Static3D(-1.0f,+0.0f,+0.0f);
584
    vertices[2] = new Static3D(+0.0f,-1.0f,+0.0f);
585
    vertices[3] = new Static3D(+0.0f,+0.0f,-1.0f);
586

    
587
    roundCorners(mesh,center,vertices,0.03f,0.10f);
588

    
589
    mesh.mergeEffComponents();
590

    
591
    return mesh;
592
    }
593

    
594
///////////////////////////////////////////////////////////////////////////////////////////////////
595

    
596
  public MeshBase createIvyFaceMesh()
597
    {
598
    MeshBase mesh = createFacesIvyFace();
599

    
600
    Static3D center = new Static3D(-0.0f,-0.0f,-0.5f);
601
    Static3D[] vertices = new Static3D[2];
602
    vertices[0] = new Static3D(-0.5f,+0.5f,+0.0f);
603
    vertices[1] = new Static3D(+0.5f,-0.5f,+0.0f);
604

    
605
    roundCorners(mesh,center,vertices,0.03f,0.10f);
606

    
607
    mesh.mergeEffComponents();
608
    mesh.addEmptyTexComponent();
609
    mesh.addEmptyTexComponent();
610
    mesh.addEmptyTexComponent();
611
    mesh.addEmptyTexComponent();
612

    
613
    return mesh;
614
    }
615

    
616
///////////////////////////////////////////////////////////////////////////////////////////////////
617

    
618
  public MeshBase createRexCornerMesh()
619
    {
620
    MeshBase mesh = createFacesRexCorner();
621
    VertexEffect[] effects = createVertexEffectsRexCorner();
622
    for( VertexEffect effect : effects ) mesh.apply(effect);
623

    
624
    final float G = (1-REX_D)/3;
625
    Static3D center = new Static3D(0.0f,0.0f,-G*SQ2/2);
626
    Static3D[] vertices = new Static3D[1];
627
    vertices[0] = new Static3D(+G,-G,+0.0f);
628
    roundCorners(mesh,center,vertices,0.10f,0.10f);
629

    
630
    mesh.mergeEffComponents();
631
    mesh.addEmptyTexComponent();
632
    mesh.addEmptyTexComponent();
633
    mesh.addEmptyTexComponent();
634
    mesh.addEmptyTexComponent();
635

    
636
    return mesh;
637
    }
638

    
639
///////////////////////////////////////////////////////////////////////////////////////////////////
640

    
641
  public MeshBase createRexFaceMesh()
642
    {
643
    MeshBase mesh = createFacesRexFace();
644

    
645
    mesh.mergeEffComponents();
646
    mesh.addEmptyTexComponent();
647
    mesh.addEmptyTexComponent();
648
    mesh.addEmptyTexComponent();
649
    mesh.addEmptyTexComponent();
650

    
651
    return mesh;
652
    }
653

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

    
656
  public MeshBase createRexEdgeMesh()
657
    {
658
    MeshBase mesh = createFacesRexEdge();
659
    VertexEffect[] effects = createVertexEffectsRexEdge();
660
    for( VertexEffect effect : effects ) mesh.apply(effect);
661

    
662
    Static3D center = new Static3D(0.0f,-0.5f,-0.5f);
663
    Static3D[] vertices = new Static3D[2];
664
    vertices[0] = new Static3D(+0.5f,+0.0f,+0.0f);
665
    vertices[1] = new Static3D(-0.5f,+0.0f,+0.0f);
666
    roundCorners(mesh,center,vertices,0.06f,0.10f);
667

    
668
    mesh.mergeEffComponents();
669

    
670
    return mesh;
671
    }
672

    
673
///////////////////////////////////////////////////////////////////////////////////////////////////
674

    
675
  public MeshBase createCuboidMesh(int[] dimensions)
676
    {
677
    MeshBase mesh = createCuboid(dimensions);
678
    VertexEffect[] effects = createCuboidEffects(dimensions);
679
    for( VertexEffect effect : effects ) mesh.apply(effect);
680

    
681
    int X = dimensions[0];
682
    int Y = dimensions[1];
683
    int Z = dimensions[2];
684

    
685
    float strength = 0.04f;
686
    float radius   = 0.15f;
687

    
688
    Static3D[] vertices = new Static3D[1];
689
    Static3D center;
690

    
691
    vertices[0] = new Static3D(+0.5f*X,+0.5f*Y,+0.5f*Z);
692
    center = new Static3D(+0.5f*(X-1),+0.5f*(Y-1),+0.5f*(Z-1));
693
    roundCorners(mesh, center, vertices, strength, radius);
694

    
695
    vertices[0] = new Static3D(+0.5f*X,+0.5f*Y,-0.5f*Z);
696
    center = new Static3D(+0.5f*(X-1),+0.5f*(Y-1),-0.5f*(Z-1));
697
    roundCorners(mesh, center, vertices, strength, radius);
698

    
699
    vertices[0] = new Static3D(+0.5f*X,-0.5f*Y,+0.5f*Z);
700
    center = new Static3D(+0.5f*(X-1),-0.5f*(Y-1),+0.5f*(Z-1));
701
    roundCorners(mesh, center, vertices, strength, radius);
702

    
703
    vertices[0] = new Static3D(+0.5f*X,-0.5f*Y,-0.5f*Z);
704
    center = new Static3D(+0.5f*(X-1),-0.5f*(Y-1),-0.5f*(Z-1));
705
    roundCorners(mesh, center, vertices, strength, radius);
706

    
707
    vertices[0] = new Static3D(-0.5f*X,+0.5f*Y,+0.5f*Z);
708
    center = new Static3D(-0.5f*(X-1),+0.5f*(Y-1),+0.5f*(Z-1));
709
    roundCorners(mesh, center, vertices, strength, radius);
710

    
711
    vertices[0] = new Static3D(-0.5f*X,+0.5f*Y,-0.5f*Z);
712
    center = new Static3D(-0.5f*(X-1),+0.5f*(Y-1),-0.5f*(Z-1));
713
    roundCorners(mesh, center, vertices, strength, radius);
714

    
715
    vertices[0] = new Static3D(-0.5f*X,-0.5f*Y,+0.5f*Z);
716
    center = new Static3D(-0.5f*(X-1),-0.5f*(Y-1),+0.5f*(Z-1));
717
    roundCorners(mesh, center, vertices, strength, radius);
718

    
719
    vertices[0] = new Static3D(-0.5f*X,-0.5f*Y,-0.5f*Z);
720
    center = new Static3D(-0.5f*(X-1),-0.5f*(Y-1),-0.5f*(Z-1));
721
    roundCorners(mesh, center, vertices, strength, radius);
722

    
723
    mesh.mergeEffComponents();
724

    
725
    return mesh;
726
    }
727

    
728
///////////////////////////////////////////////////////////////////////////////////////////////////
729

    
730
  private boolean areColinear(double[][] vertices, int index1, int index2, int index3)
731
    {
732
    double x1 = vertices[index1][0];
733
    double y1 = vertices[index1][1];
734
    double z1 = vertices[index1][2];
735
    double x2 = vertices[index2][0];
736
    double y2 = vertices[index2][1];
737
    double z2 = vertices[index2][2];
738
    double x3 = vertices[index3][0];
739
    double y3 = vertices[index3][1];
740
    double z3 = vertices[index3][2];
741

    
742
    double v1x = x2-x1;
743
    double v1y = y2-y1;
744
    double v1z = z2-z1;
745
    double v2x = x3-x1;
746
    double v2y = y3-y1;
747
    double v2z = z3-z1;
748

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

    
751
    return (v1x==A*v2x && v1y==A*v2y && v1z==A*v2z);
752
    }
753

    
754
///////////////////////////////////////////////////////////////////////////////////////////////////
755

    
756
  private void computeNormalVector(double[][] vertices, int index1, int index2, int index3)
757
    {
758
    double x1 = vertices[index1][0];
759
    double y1 = vertices[index1][1];
760
    double z1 = vertices[index1][2];
761
    double x2 = vertices[index2][0];
762
    double y2 = vertices[index2][1];
763
    double z2 = vertices[index2][2];
764
    double x3 = vertices[index3][0];
765
    double y3 = vertices[index3][1];
766
    double z3 = vertices[index3][2];
767

    
768
    double v1x = x2-x1;
769
    double v1y = y2-y1;
770
    double v1z = z2-z1;
771
    double v2x = x3-x1;
772
    double v2y = y3-y1;
773
    double v2z = z3-z1;
774

    
775
    mBuffer[0] = v1y*v2z - v2y*v1z;
776
    mBuffer[1] = v1z*v2x - v2z*v1x;
777
    mBuffer[2] = v1x*v2y - v2x*v1y;
778

    
779
    double len = mBuffer[0]*mBuffer[0] + mBuffer[1]*mBuffer[1] + mBuffer[2]*mBuffer[2];
780
    len = Math.sqrt(len);
781
    mBuffer[0] /= len;
782
    mBuffer[1] /= len;
783
    mBuffer[2] /= len;
784
    }
785

    
786
///////////////////////////////////////////////////////////////////////////////////////////////////
787
// return quat1*quat2
788

    
789
  private static void quatMultiply( double[] quat1, double[] quat2, double[] result )
790
    {
791
    double qx = quat1[0];
792
    double qy = quat1[1];
793
    double qz = quat1[2];
794
    double qw = quat1[3];
795

    
796
    double rx = quat2[0];
797
    double ry = quat2[1];
798
    double rz = quat2[2];
799
    double rw = quat2[3];
800

    
801
    result[0] = rw*qx - rz*qy + ry*qz + rx*qw;
802
    result[1] = rw*qy + rz*qx + ry*qw - rx*qz;
803
    result[2] = rw*qz + rz*qw - ry*qx + rx*qy;
804
    result[3] = rw*qw - rz*qz - ry*qy - rx*qx;
805
    }
806

    
807
///////////////////////////////////////////////////////////////////////////////////////////////////
808

    
809
  private void fitInSquare(FaceTransform info, double[][] vert3D)
810
    {
811
    double minX = Double.MAX_VALUE;
812
    double maxX =-Double.MAX_VALUE;
813
    double minY = Double.MAX_VALUE;
814
    double maxY =-Double.MAX_VALUE;
815

    
816
    for (double[] vert : vert3D)
817
      {
818
      double x = vert[0];
819
      double y = vert[1];
820

    
821
      if (x > maxX) maxX = x;
822
      if (x < minX) minX = x;
823
      if (y > maxY) maxY = y;
824
      if (y < minY) minY = y;
825
      }
826

    
827
    minX = minX<0 ? -minX:minX;
828
    maxX = maxX<0 ? -maxX:maxX;
829
    minY = minY<0 ? -minY:minY;
830
    maxY = maxY<0 ? -maxY:maxY;
831

    
832
    double max1 = Math.max(minX,minY);
833
    double max2 = Math.max(maxX,maxY);
834
    double max3 = Math.max(max1,max2);
835

    
836
    info.scale = max3/0.5;
837

    
838
    int len = vert3D.length;
839
    StickerCoords sInfo = new StickerCoords();
840
    sInfo.vertices = new double[2*len];
841

    
842
    for( int vertex=0; vertex<len; vertex++ )
843
      {
844
      sInfo.vertices[2*vertex  ] = vert3D[vertex][0] / info.scale;
845
      sInfo.vertices[2*vertex+1] = vert3D[vertex][1] / info.scale;
846
      }
847

    
848
    mStickerCoords.add(sInfo);
849

    
850
    info.sticker = mStickerCoords.size() -1;
851
    info.flip = false;
852
    }
853

    
854
///////////////////////////////////////////////////////////////////////////////////////////////////
855

    
856
  private FaceTransform constructNewTransform(final double[][] vert3D)
857
    {
858
    FaceTransform ft = new FaceTransform();
859

    
860
    // compute center of gravity
861
    ft.vx = 0.0f;
862
    ft.vy = 0.0f;
863
    ft.vz = 0.0f;
864
    int len = vert3D.length;
865

    
866
    for (double[] vert : vert3D)
867
      {
868
      ft.vx += vert[0];
869
      ft.vy += vert[1];
870
      ft.vz += vert[2];
871
      }
872

    
873
    ft.vx /= len;
874
    ft.vy /= len;
875
    ft.vz /= len;
876

    
877
    // move all vertices so that their center of gravity is at (0,0,0)
878
    for (int i=0; i<len; i++)
879
      {
880
      vert3D[i][0] -= ft.vx;
881
      vert3D[i][1] -= ft.vy;
882
      vert3D[i][2] -= ft.vz;
883
      }
884

    
885
    // find 3 non-colinear vertices
886
    int foundIndex = -1;
887

    
888
    for(int vertex=2; vertex<len; vertex++)
889
      {
890
      if( !areColinear(vert3D,0,1,vertex) )
891
        {
892
        foundIndex = vertex;
893
        break;
894
        }
895
      }
896

    
897
    // compute the normal vector
898
    if( foundIndex==-1 )
899
      {
900
      throw new RuntimeException("all vertices colinear");
901
      }
902

    
903
    computeNormalVector(vert3D,0,1,foundIndex);
904

    
905
    // rotate so that the normal vector becomes (0,0,1)
906
    double axisX, axisY, axisZ;
907

    
908
    if( mBuffer[0]!=0.0f || mBuffer[1]!=0.0f )
909
      {
910
      axisX = -mBuffer[1];
911
      axisY =  mBuffer[0];
912
      axisZ = 0.0f;
913

    
914
      double axiLen = axisX*axisX + axisY*axisY;
915
      axiLen = Math.sqrt(axiLen);
916
      axisX /= axiLen;
917
      axisY /= axiLen;
918
      axisZ /= axiLen;
919
      }
920
    else
921
      {
922
      axisX = 0.0f;
923
      axisY = 1.0f;
924
      axisZ = 0.0f;
925
      }
926

    
927
    double cosTheta = mBuffer[2];
928
    double sinTheta = Math.sqrt(1-cosTheta*cosTheta);
929
    double sinHalfTheta = computeSinHalf(cosTheta);
930
    double cosHalfTheta = computeCosHalf(sinTheta,cosTheta);
931

    
932
    mQuat1[0] = axisX*sinHalfTheta;
933
    mQuat1[1] = axisY*sinHalfTheta;
934
    mQuat1[2] = axisZ*sinHalfTheta;
935
    mQuat1[3] = cosHalfTheta;
936
    mQuat2[0] =-axisX*sinHalfTheta;
937
    mQuat2[1] =-axisY*sinHalfTheta;
938
    mQuat2[2] =-axisZ*sinHalfTheta;
939
    mQuat2[3] = cosHalfTheta;
940

    
941
    for (double[] vert : vert3D)
942
      {
943
      quatMultiply(mQuat1, vert  , mQuat3);
944
      quatMultiply(mQuat3, mQuat2, vert  );
945
      }
946

    
947
    // fit the whole thing in a square and remember the scale & 2D vertices
948
    fitInSquare(ft, vert3D);
949

    
950
    // remember the rotation
951
    ft.qx =-mQuat1[0];
952
    ft.qy =-mQuat1[1];
953
    ft.qz =-mQuat1[2];
954
    ft.qw = mQuat1[3];
955

    
956
    return ft;
957
    }
958

    
959
///////////////////////////////////////////////////////////////////////////////////////////////////
960

    
961
  private double computeCos(double oldX, double oldY, double newX, double newY, double len1, double len2)
962
    {
963
    double ret= (oldX*newX+oldY*newY) / (len1*len2);
964
    if( ret<-1.0 ) return -1.0;
965
    if( ret> 1.0 ) return  1.0;
966

    
967
    return ret;
968
    }
969

    
970
///////////////////////////////////////////////////////////////////////////////////////////////////
971
// sin of (signed!) angle between vectors 'old' and 'new', counterclockwise!
972

    
973
  private double computeSin(double oldX, double oldY, double newX, double newY, double len1, double len2)
974
    {
975
    double ret= (newX*oldY-oldX*newY) / (len1*len2);
976
    if( ret<-1.0 ) return -1.0;
977
    if( ret> 1.0 ) return  1.0;
978

    
979
    return ret;
980
    }
981

    
982
///////////////////////////////////////////////////////////////////////////////////////////////////
983

    
984
  private void rotateAllVertices(double[] result, int len, double[] vertices, double sin, double cos)
985
    {
986
    for(int i=0; i<len; i++)
987
      {
988
      result[2*i  ] = vertices[2*i  ]*cos - vertices[2*i+1]*sin;
989
      result[2*i+1] = vertices[2*i  ]*sin + vertices[2*i+1]*cos;
990
      }
991
    }
992

    
993
///////////////////////////////////////////////////////////////////////////////////////////////////
994

    
995
  private double computeScale(double[] v1, double[] v2, int v1i, int v2i)
996
    {
997
    double v1x = v1[2*v1i];
998
    double v1y = v1[2*v1i+1];
999
    double v2x = v2[2*v2i];
1000
    double v2y = v2[2*v2i+1];
1001

    
1002
    double lenSq1 = v1x*v1x + v1y*v1y;
1003
    double lenSq2 = v2x*v2x + v2y*v2y;
1004

    
1005
    return Math.sqrt(lenSq2/lenSq1);
1006
    }
1007

    
1008
///////////////////////////////////////////////////////////////////////////////////////////////////
1009
// valid for 0<angle<2*PI
1010

    
1011
  private double computeSinHalf(double cos)
1012
    {
1013
    return Math.sqrt((1-cos)/2);
1014
    }
1015

    
1016
///////////////////////////////////////////////////////////////////////////////////////////////////
1017
// valid for 0<angle<2*PI
1018

    
1019
  private double computeCosHalf(double sin, double cos)
1020
    {
1021
    double cosHalf = Math.sqrt((1+cos)/2);
1022
    return sin<0 ? -cosHalf : cosHalf;
1023
    }
1024

    
1025
///////////////////////////////////////////////////////////////////////////////////////////////////
1026

    
1027
  private int computeRotatedIndex(int oldVertex, int len, int rotatedVertex, boolean inverted)
1028
    {
1029
    int v = (rotatedVertex + (inverted? -oldVertex : oldVertex));
1030
    if( v>=len ) v-=len;
1031
    if( v< 0   ) v+=len;
1032

    
1033
    return v;
1034
    }
1035

    
1036
///////////////////////////////////////////////////////////////////////////////////////////////////
1037

    
1038
  private boolean isScaledVersionOf(double[] newVert, double[] oldVert, int len, int vertex, boolean inverted)
1039
    {
1040
    int newZeroIndex = computeRotatedIndex(0,len,vertex,inverted);
1041
    double EPSILON = 0.001;
1042
    double scale = computeScale(newVert,oldVert,newZeroIndex,0);
1043

    
1044
    for(int i=1; i<len; i++)
1045
      {
1046
      int index = computeRotatedIndex(i,len,vertex,inverted);
1047

    
1048
      double horz = oldVert[2*i  ] - scale*newVert[2*index  ];
1049
      double vert = oldVert[2*i+1] - scale*newVert[2*index+1];
1050

    
1051
      if( horz>EPSILON || horz<-EPSILON || vert>EPSILON || vert<-EPSILON ) return false;
1052
      }
1053

    
1054
    return true;
1055
    }
1056

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

    
1059
  private void mirrorAllVertices(double[] output, int len, double[] input)
1060
    {
1061
    for(int vertex=0; vertex<len; vertex++)
1062
      {
1063
      output[2*vertex  ] = input[2*vertex  ];
1064
      output[2*vertex+1] =-input[2*vertex+1];
1065
      }
1066
    }
1067

    
1068
///////////////////////////////////////////////////////////////////////////////////////////////////
1069

    
1070
  private void correctInfo(FaceTransform info, double scale, double sin, double cos, int oldSticker, boolean flip)
1071
    {
1072
    mStickerCoords.remove(info.sticker);
1073

    
1074
    info.flip    = flip;
1075
    info.sticker = oldSticker;
1076
    info.scale  *= scale;
1077

    
1078
    mQuat1[0] = info.qx;
1079
    mQuat1[1] = info.qy;
1080
    mQuat1[2] = info.qz;
1081
    mQuat1[3] = info.qw;
1082

    
1083
    double sinHalf = computeSinHalf(cos);
1084
    double cosHalf = computeCosHalf(sin,cos);
1085

    
1086
    if( flip )
1087
      {
1088
      mQuat3[0] = 0.0f;
1089
      mQuat3[1] = 0.0f;
1090
      mQuat3[2] = sinHalf;
1091
      mQuat3[3] = cosHalf;
1092

    
1093
      mQuat4[0] = 1.0;
1094
      mQuat4[1] = 0.0;
1095
      mQuat4[2] = 0.0;
1096
      mQuat4[3] = 0.0;
1097

    
1098
      quatMultiply( mQuat3, mQuat4, mQuat2 );
1099
      }
1100
    else
1101
      {
1102
      mQuat2[0] = 0.0f;
1103
      mQuat2[1] = 0.0f;
1104
      mQuat2[2] = sinHalf;
1105
      mQuat2[3] = cosHalf;
1106
      }
1107

    
1108
    quatMultiply( mQuat1, mQuat2, mQuat3 );
1109

    
1110
    info.qx = mQuat3[0];
1111
    info.qy = mQuat3[1];
1112
    info.qz = mQuat3[2];
1113
    info.qw = mQuat3[3];
1114
    }
1115

    
1116
///////////////////////////////////////////////////////////////////////////////////////////////////
1117

    
1118
  private void printVert(double[] buffer)
1119
    {
1120
    int len = buffer.length/2;
1121
    String str = "";
1122

    
1123
    for(int i=0; i<len; i++)
1124
      {
1125
      str += (" ("+buffer[2*i]+" , "+buffer[2*i+1]+" ) ");
1126
      }
1127

    
1128
    android.util.Log.d("D", str);
1129
    }
1130

    
1131
///////////////////////////////////////////////////////////////////////////////////////////////////
1132

    
1133
  private boolean foundVertex(FaceTransform info, double[] buffer, int len, double[] newVert,
1134
                              double[] oldVert, double lenFirstOld, int oldSticker, boolean inverted)
1135
    {
1136
    for(int vertex=0; vertex<len; vertex++)
1137
      {
1138
      double newX = newVert[2*vertex  ];
1139
      double newY = newVert[2*vertex+1];
1140
      double lenIthNew = Math.sqrt(newX*newX + newY*newY);
1141
      double cos = computeCos( oldVert[0], oldVert[1], newX, newY, lenIthNew, lenFirstOld);
1142
      double sin = computeSin( oldVert[0], oldVert[1], newX, newY, lenIthNew, lenFirstOld);
1143

    
1144
      rotateAllVertices(buffer,len,newVert,sin,cos);
1145

    
1146
      if( isScaledVersionOf(buffer,oldVert,len,vertex,inverted) )
1147
        {
1148
        int newZeroIndex = computeRotatedIndex(0,len,vertex,inverted);
1149
        double scale = computeScale(oldVert,newVert,0,newZeroIndex);
1150
        correctInfo(info,scale,sin,cos,oldSticker,inverted);
1151
        return true;
1152
        }
1153
      }
1154

    
1155
    return false;
1156
    }
1157

    
1158
///////////////////////////////////////////////////////////////////////////////////////////////////
1159

    
1160
  private boolean successfullyCollapsedStickers(final FaceTransform newInfo, final FaceTransform oldInfo)
1161
    {
1162
    StickerCoords sNewInfo = mStickerCoords.get(newInfo.sticker);
1163
    StickerCoords sOldInfo = mStickerCoords.get(oldInfo.sticker);
1164
    double[] newVert = sNewInfo.vertices;
1165
    double[] oldVert = sOldInfo.vertices;
1166
    int oldLen = oldVert.length;
1167
    int newLen = newVert.length;
1168

    
1169
    if( oldLen == newLen )
1170
      {
1171
      int oldSticker = oldInfo.sticker;
1172
      double[] buffer1 = new double[oldLen];
1173
      double lenFirstOld = Math.sqrt(oldVert[0]*oldVert[0] + oldVert[1]*oldVert[1]);
1174
      if( foundVertex(newInfo, buffer1, oldLen/2, newVert, oldVert, lenFirstOld, oldSticker, false) ) return true;
1175
      double[] buffer2 = new double[oldLen];
1176
      mirrorAllVertices(buffer2, newLen/2, newVert);
1177
      if( foundVertex(newInfo, buffer1, oldLen/2, buffer2, oldVert, lenFirstOld, oldSticker, true ) ) return true;
1178
      }
1179

    
1180
    return false;
1181
    }
1182

    
1183
///////////////////////////////////////////////////////////////////////////////////////////////////
1184

    
1185
  private double[][] constructVert(double[][] vertices, int[] index)
1186
    {
1187
    int len = index.length;
1188
    double[][] ret = new double[len][4];
1189

    
1190
    for(int i=0; i<len; i++)
1191
      {
1192
      ret[i][0] = vertices[index[i]][0];
1193
      ret[i][1] = vertices[index[i]][1];
1194
      ret[i][2] = vertices[index[i]][2];
1195
      ret[i][3] = 1.0f;
1196
      }
1197

    
1198
    return ret;
1199
    }
1200

    
1201
///////////////////////////////////////////////////////////////////////////////////////////////////
1202

    
1203
  private void prepareAndRoundCorners(MeshBase mesh, double[][] vertices,
1204
                                      float[][] corners, int[] cornerIndexes,
1205
                                      float[][] centers, int[] centerIndexes )
1206
    {
1207
    int lenV = vertices.length;
1208
    Static3D[] staticVert = new Static3D[1];
1209
    Static3D center = new Static3D(0,0,0);
1210

    
1211
    for(int v=0; v<lenV; v++)
1212
      {
1213
      staticVert[0] = new Static3D( (float)vertices[v][0], (float)vertices[v][1], (float)vertices[v][2]);
1214

    
1215
      int cent = centerIndexes[v];
1216

    
1217
      if( cent>=0 )
1218
        {
1219
        center.set( centers[cent][0], centers[cent][1], centers[cent][2]);
1220

    
1221
        int corn = cornerIndexes[v];
1222
        float strength = corners[corn][0];
1223
        float radius   = corners[corn][1];
1224

    
1225
        roundCorners(mesh, center, staticVert, strength, radius);
1226
        }
1227
      }
1228
    }
1229

    
1230
///////////////////////////////////////////////////////////////////////////////////////////////////
1231

    
1232
  private void correctComponents(MeshBase mesh, int numComponents)
1233
    {
1234
    int numTexToBeAdded = numComponents-mesh.getNumTexComponents();
1235

    
1236
    mesh.mergeEffComponents();
1237

    
1238
    for(int i=0; i<numTexToBeAdded; i++ ) mesh.addEmptyTexComponent();
1239
    }
1240

    
1241
///////////////////////////////////////////////////////////////////////////////////////////////////
1242

    
1243
  private void printTransform(FaceTransform f)
1244
    {
1245
    android.util.Log.e("D", "q=("+f.qx+", "+f.qy+", "+f.qz+", "+f.qw+") v=("
1246
                       +f.vx+", "+f.vy+", "+f.vz+") scale="+f.scale+" sticker="+f.sticker);
1247
    }
1248

    
1249
///////////////////////////////////////////////////////////////////////////////////////////////////
1250
// PUBLIC
1251

    
1252
  public void printStickerCoords()
1253
    {
1254
    int stickers = mStickerCoords.size();
1255

    
1256
    android.util.Log.d("D", "---- STICKER COORDS ----");
1257

    
1258
    for(int s=0; s<stickers; s++)
1259
      {
1260
      String ver = "{ ";
1261
      StickerCoords info = mStickerCoords.get(s);
1262
      int len = info.vertices.length/2;
1263

    
1264
      for(int i =0; i<len; i++)
1265
        {
1266
        if( i!=0 ) ver += ", ";
1267
        ver += ( (float)info.vertices[2*i]+"f, "+(float)info.vertices[2*i+1]+"f");
1268
        }
1269

    
1270
      ver += " }";
1271
      android.util.Log.d("D", ver);
1272
      }
1273

    
1274
    android.util.Log.d("D", "---- END STICKER COORDS ----");
1275
    }
1276

    
1277
///////////////////////////////////////////////////////////////////////////////////////////////////
1278

    
1279
  public void printFaceTransform()
1280
    {
1281
    android.util.Log.d("D", "---- OLD FACE TRANSFORM ---");
1282

    
1283
    int oldfaces = mOldFaceTransf.size();
1284

    
1285
    for(int f=0; f<oldfaces; f++)
1286
      {
1287
      printTransform(mOldFaceTransf.get(f));
1288
      }
1289

    
1290
    android.util.Log.d("D", "---- NEW FACE TRANSFORM ---");
1291

    
1292
    int newfaces = mNewFaceTransf.size();
1293

    
1294
    for(int f=0; f<newfaces; f++)
1295
      {
1296
      printTransform(mNewFaceTransf.get(f));
1297
      }
1298
    }
1299

    
1300
///////////////////////////////////////////////////////////////////////////////////////////////////
1301

    
1302
  public void clear()
1303
    {
1304
    mStickerCoords.clear();
1305
    mNewFaceTransf.clear();
1306
    mOldFaceTransf.clear();
1307
    }
1308

    
1309
///////////////////////////////////////////////////////////////////////////////////////////////////
1310

    
1311
  public void createNewFaceTransform( final double[][] vertices, final int[][] indexes)
1312
    {
1313
    FaceTransform ft;
1314
    int numNew = mNewFaceTransf.size();
1315

    
1316
    for(int i=0; i<numNew; i++)
1317
      {
1318
      ft = mNewFaceTransf.remove(0);
1319
      mOldFaceTransf.add(ft);
1320
      }
1321

    
1322
    int numFaces = indexes.length;
1323
    int numOld = mOldFaceTransf.size();
1324

    
1325
    for (int face=0; face<numFaces; face++)
1326
      {
1327
      boolean collapsed = false;
1328

    
1329
      double[][] vert = constructVert(vertices, indexes[face]);
1330
      FaceTransform newT = constructNewTransform(vert);
1331

    
1332
      for (int old=0; !collapsed && old<numOld; old++)
1333
        {
1334
        ft = mOldFaceTransf.get(old);
1335
        if (successfullyCollapsedStickers(newT, ft)) collapsed = true;
1336
        }
1337

    
1338
      for (int pre=0; !collapsed && pre<face; pre++)
1339
        {
1340
        ft = mNewFaceTransf.get(pre);
1341
        if (successfullyCollapsedStickers(newT, ft)) collapsed = true;
1342
        }
1343

    
1344
      mNewFaceTransf.add(newT);
1345
      }
1346
    }
1347

    
1348
///////////////////////////////////////////////////////////////////////////////////////////////////
1349

    
1350
  public MeshBase createRoundedSolid(final double[][] vertices, final int[][] vertIndexes,
1351
                                     final float[][] bands    , final int[]   bandIndexes,
1352
                                     final float[][] corners  , final int[]   cornerIndexes,
1353
                                     final float[][] centers  , final int[]   centerIndexes,
1354
                                     final int numComponents )
1355
    {
1356
    int numFaces = vertIndexes.length;
1357
    float[] band, bandsComputed;
1358
    MeshBase[] meshes = new MeshBase[numFaces];
1359
    FaceTransform fInfo;
1360
    StickerCoords sInfo;
1361

    
1362
    for(int face=0; face<numFaces; face++)
1363
      {
1364
      fInfo = mNewFaceTransf.get(face);
1365
      sInfo = mStickerCoords.get(fInfo.sticker);
1366

    
1367
      double[] verts = sInfo.vertices;
1368
      int lenVerts = verts.length;
1369
      float[] vertsFloat = new float[lenVerts];
1370
      for(int i=0; i<lenVerts; i++) vertsFloat[i] = (float)verts[i];
1371

    
1372
      band = bands[bandIndexes[face]];
1373
      bandsComputed = computeBands( band[0], (int)band[1], band[2], band[3], (int)band[4]);
1374
      meshes[face] = new MeshPolygon(vertsFloat,bandsComputed,(int)band[5],(int)band[6]);
1375
      meshes[face].setEffectAssociation(0,(1<<face),0);
1376
      }
1377

    
1378
    MeshBase mesh = new MeshJoined(meshes);
1379
    Static3D center = new Static3D(0,0,0);
1380

    
1381
    for(int face=0; face<numFaces; face++)
1382
      {
1383
      int assoc = (1<<face);
1384
      fInfo = mNewFaceTransf.get(face);
1385

    
1386
      float vx = (float)fInfo.vx;
1387
      float vy = (float)fInfo.vy;
1388
      float vz = (float)fInfo.vz;
1389
      float sc = (float)fInfo.scale;
1390
      float qx = (float)fInfo.qx;
1391
      float qy = (float)fInfo.qy;
1392
      float qz = (float)fInfo.qz;
1393
      float qw = (float)fInfo.qw;
1394

    
1395
      Static3D scale = new Static3D(sc,sc, fInfo.flip ? -sc : sc);
1396
      Static3D move3D= new Static3D(vx,vy,vz);
1397
      Static4D quat  = new Static4D(qx,qy,qz,qw);
1398

    
1399
      mesh.apply(new MatrixEffectScale(scale)           ,assoc,-1);
1400
      mesh.apply(new MatrixEffectQuaternion(quat,center),assoc,-1);
1401
      mesh.apply(new MatrixEffectMove(move3D)           ,assoc,-1);
1402
      }
1403

    
1404
    prepareAndRoundCorners(mesh, vertices, corners, cornerIndexes, centers, centerIndexes);
1405

    
1406
    correctComponents(mesh,numComponents);
1407

    
1408
    return mesh;
1409
    }
1410
  }
(3-3/4)