Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / helpers / FactoryCubit.java @ 43668bcc

1 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6 a7a40b3c Leszek Koltunski
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
9
10 198c5bf0 Leszek Koltunski
package org.distorted.objectlib.helpers;
11 29b82486 Leszek Koltunski
12 84a17011 Leszek Koltunski
import org.distorted.library.effect.EffectName;
13 29b82486 Leszek Koltunski
import org.distorted.library.effect.MatrixEffectMove;
14
import org.distorted.library.effect.MatrixEffectQuaternion;
15
import org.distorted.library.effect.MatrixEffectScale;
16
import org.distorted.library.effect.VertexEffect;
17 aacf5e27 Leszek Koltunski
import org.distorted.library.helpers.QuatHelper;
18 29b82486 Leszek Koltunski
import org.distorted.library.mesh.MeshBase;
19
import org.distorted.library.mesh.MeshJoined;
20 fe3dec09 Leszek Koltunski
import org.distorted.library.mesh.MeshMultigon;
21 29b82486 Leszek Koltunski
import org.distorted.library.mesh.MeshPolygon;
22
import org.distorted.library.type.Static3D;
23
import org.distorted.library.type.Static4D;
24
25
import java.util.ArrayList;
26
27
///////////////////////////////////////////////////////////////////////////////////////////////////
28
29
public class FactoryCubit
30
  {
31
  private static FactoryCubit mThis;
32
33 d99de43c Leszek Koltunski
  private static final float MAX_CORE_DIFF = 0.01f;
34
35 57ef6378 Leszek Koltunski
  private static final float[] mBuffer = new float[3];
36
  private static final float[] mQuat1  = new float[4];
37
  private static final float[] mQuat2  = new float[4];
38
  private static final float[] mQuat3  = new float[4];
39 29b82486 Leszek Koltunski
40 80fd07aa Leszek Koltunski
  public static final String NAME = EffectName.DEFORM.name();
41 84a17011 Leszek Koltunski
42 fe3dec09 Leszek Koltunski
  private static class StickerCoords
43 29b82486 Leszek Koltunski
    {
44 08bf6b98 leszek
    float[][][] outerVertices;
45 4b9d1df5 leszek
    float[][][] fullVertices;
46 1561a74f Leszek Koltunski
    float scale;
47 2617d26b Leszek Koltunski
    boolean outer;
48 29b82486 Leszek Koltunski
    }
49
50
  private static class FaceTransform
51
    {
52 7af68038 Leszek Koltunski
    int face;
53
    int numFaces;
54
55 29b82486 Leszek Koltunski
    int sticker;
56 57ef6378 Leszek Koltunski
    float vx,vy,vz;
57
    float scale;
58
    float qx,qy,qz,qw;
59 29b82486 Leszek Koltunski
    }
60
61
  private static final ArrayList<FaceTransform> mNewFaceTransf = new ArrayList<>();
62
  private static final ArrayList<FaceTransform> mOldFaceTransf = new ArrayList<>();
63
  private static final ArrayList<StickerCoords> mStickerCoords = new ArrayList<>();
64
65
///////////////////////////////////////////////////////////////////////////////////////////////////
66
67
  private FactoryCubit()
68
    {
69 3bf19410 Leszek Koltunski
70 29b82486 Leszek Koltunski
    }
71
72
///////////////////////////////////////////////////////////////////////////////////////////////////
73
// H - height of the band in the middle
74
// alpha - angle of the edge  [0,90]
75
// dist - often in a polygon the distance from edge to center is not 1, but something else.
76
// This is the distance.
77
// K - where to begin the second, much more flat part of the band. [0,1]
78
// N - number of bands. N>=3
79
//
80
// theory: two distinct parts to the band:
81
// 1) (0,B) - steep
82
// 2) (B,1) - flat
83
//
84
// In first part, we have y = g(x) ; in second - y = g(f(x)) where
85
//
86
// g(x) = sqrt( R^2 - (x-D)^2 ) - R*cos(alpha)
87
// f(x) = ((D-B)/(1-B)*x + B*(1-D)/(1-B)
88
// h(x) = R*(sin(alpha) - sin(x))
89
// R = H/(1-cos(alpha))
90
// D = H*sin(alpha)
91
// B = h(K*alpha)
92
//
93
// The N points are taken at:
94
//
95
// 1) in the second part, there are K2 = (N-3)/3 such points
96
// 2) in the first - K1 = (N-3) - K2
97
// 3) also, the 3 points 0,B,1
98
//
99
// so we have the sequence A[i] of N points
100
//
101
// 0
102
// h((i+1)*(1-K)*alpha/(K1+1)) (i=0,1,...,K1-1)
103
// B
104
// (1-B)*(i+1)/(K2+1) + B   (i=0,i,...,K2-1)
105
// 1
106
107
///////////////////////////////////////////////////////////////////////////////////////////////////
108
109
  private float f(float D, float B, float x)
110
    {
111
    return ((D-B)*x + B*(1-D))/(1-B);
112
    }
113
114
///////////////////////////////////////////////////////////////////////////////////////////////////
115
116
  private float g(float R, float D, float x, float cosAlpha)
117
    {
118
    float d = x-D;
119
    return (float)(Math.sqrt(R*R-d*d)-R*cosAlpha);
120
    }
121
122
///////////////////////////////////////////////////////////////////////////////////////////////////
123
124
  private float h(float R, float sinAlpha, float x)
125
    {
126
    return R*(sinAlpha-(float)Math.sin(x));
127
    }
128
129
///////////////////////////////////////////////////////////////////////////////////////////////////
130
131 4b9d1df5 leszek
  private boolean areNotColinear(float[][] vertices, int index)
132 29b82486 Leszek Koltunski
    {
133 4b9d1df5 leszek
    float x1 = vertices[0][0];
134
    float y1 = vertices[0][1];
135
    float z1 = vertices[0][2];
136
    float x2 = vertices[1][0];
137
    float y2 = vertices[1][1];
138
    float z2 = vertices[1][2];
139
    float x3 = vertices[index][0];
140
    float y3 = vertices[index][1];
141
    float z3 = vertices[index][2];
142 29b82486 Leszek Koltunski
143 57ef6378 Leszek Koltunski
    float v1x = x2-x1;
144
    float v1y = y2-y1;
145
    float v1z = z2-z1;
146
    float v2x = x3-x1;
147
    float v2y = y3-y1;
148
    float v2z = z3-z1;
149 29b82486 Leszek Koltunski
150
    double A = Math.sqrt( (v1x*v1x+v1y*v1y+v1z*v1z) / (v2x*v2x+v2y*v2y+v2z*v2z) );
151
152 7e9a35eb leszek
    return !(v1x==A*v2x && v1y==A*v2y && v1z==A*v2z);
153 29b82486 Leszek Koltunski
    }
154
155
///////////////////////////////////////////////////////////////////////////////////////////////////
156
157 4b9d1df5 leszek
  private void computeNormalVector(float[][] vertices, int index)
158 29b82486 Leszek Koltunski
    {
159 4b9d1df5 leszek
    float x1 = vertices[0][0];
160
    float y1 = vertices[0][1];
161
    float z1 = vertices[0][2];
162
    float x2 = vertices[1][0];
163
    float y2 = vertices[1][1];
164
    float z2 = vertices[1][2];
165
    float x3 = vertices[index][0];
166
    float y3 = vertices[index][1];
167
    float z3 = vertices[index][2];
168 29b82486 Leszek Koltunski
169 57ef6378 Leszek Koltunski
    float v1x = x2-x1;
170
    float v1y = y2-y1;
171
    float v1z = z2-z1;
172
    float v2x = x3-x1;
173
    float v2y = y3-y1;
174
    float v2z = z3-z1;
175 29b82486 Leszek Koltunski
176
    mBuffer[0] = v1y*v2z - v2y*v1z;
177
    mBuffer[1] = v1z*v2x - v2z*v1x;
178
    mBuffer[2] = v1x*v2y - v2x*v1y;
179
180
    double len = mBuffer[0]*mBuffer[0] + mBuffer[1]*mBuffer[1] + mBuffer[2]*mBuffer[2];
181
    len = Math.sqrt(len);
182
    mBuffer[0] /= len;
183
    mBuffer[1] /= len;
184
    mBuffer[2] /= len;
185
    }
186
187 fe3dec09 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
188
189 08bf6b98 leszek
  private float[][][] computeOuterEdge(float[][][] vertices)
190 fe3dec09 Leszek Koltunski
    {
191 7e9a35eb leszek
    int[][] edgesUp = MeshMultigon.computeEdgesUp(vertices);
192 08bf6b98 leszek
    return MeshMultigon.computeOuterAndHoleVertices(vertices,edgesUp);
193 fe3dec09 Leszek Koltunski
    }
194
195
///////////////////////////////////////////////////////////////////////////////////////////////////
196
// polygon
197
198 2617d26b Leszek Koltunski
  private void fitInSquare(FaceTransform info, float[][] vert3D, boolean isOuter)
199 29b82486 Leszek Koltunski
    {
200 57ef6378 Leszek Koltunski
    float minX = Float.MAX_VALUE;
201
    float maxX =-Float.MAX_VALUE;
202
    float minY = Float.MAX_VALUE;
203
    float maxY =-Float.MAX_VALUE;
204 29b82486 Leszek Koltunski
205 57ef6378 Leszek Koltunski
    for (float[] vert : vert3D)
206 29b82486 Leszek Koltunski
      {
207 57ef6378 Leszek Koltunski
      float x = vert[0];
208
      float y = vert[1];
209 29b82486 Leszek Koltunski
210
      if (x > maxX) maxX = x;
211
      if (x < minX) minX = x;
212
      if (y > maxY) maxY = y;
213
      if (y < minY) minY = y;
214
      }
215
216
    minX = minX<0 ? -minX:minX;
217
    maxX = maxX<0 ? -maxX:maxX;
218
    minY = minY<0 ? -minY:minY;
219
    maxY = maxY<0 ? -maxY:maxY;
220
221 57ef6378 Leszek Koltunski
    float max1 = Math.max(minX,minY);
222
    float max2 = Math.max(maxX,maxY);
223
    float max3 = Math.max(max1,max2);
224 29b82486 Leszek Koltunski
225 57ef6378 Leszek Koltunski
    info.scale = max3/0.5f;
226 29b82486 Leszek Koltunski
227
    int len = vert3D.length;
228
    StickerCoords sInfo = new StickerCoords();
229 2617d26b Leszek Koltunski
    sInfo.outer = isOuter;
230 1561a74f Leszek Koltunski
    sInfo.scale = info.scale;
231 08bf6b98 leszek
    sInfo.outerVertices = new float[1][len][2];
232 fe3dec09 Leszek Koltunski
    sInfo.fullVertices = null;
233 29b82486 Leszek Koltunski
234 9567a9ae leszek
    float[][] t = sInfo.outerVertices[0];
235
236 29b82486 Leszek Koltunski
    for( int vertex=0; vertex<len; vertex++ )
237
      {
238 9567a9ae leszek
      t[vertex][0] = vert3D[vertex][0] / info.scale;
239
      t[vertex][1] = vert3D[vertex][1] / info.scale;
240 29b82486 Leszek Koltunski
      }
241
242
    mStickerCoords.add(sInfo);
243
244
    info.sticker = mStickerCoords.size() -1;
245
    }
246
247 fe3dec09 Leszek Koltunski
248 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
249 fe3dec09 Leszek Koltunski
// multigon
250
251
  private void fitInSquare(FaceTransform info, float[][][] vert3D, boolean isOuter)
252
    {
253
    float minX = Float.MAX_VALUE;
254
    float maxX =-Float.MAX_VALUE;
255
    float minY = Float.MAX_VALUE;
256
    float maxY =-Float.MAX_VALUE;
257
258
    for( float[][] vert : vert3D)
259
      for( float[] v : vert)
260
        {
261
        float x = v[0];
262
        float y = v[1];
263
264
        if (x > maxX) maxX = x;
265
        if (x < minX) minX = x;
266
        if (y > maxY) maxY = y;
267
        if (y < minY) minY = y;
268
        }
269
270
    minX = minX<0 ? -minX:minX;
271
    maxX = maxX<0 ? -maxX:maxX;
272
    minY = minY<0 ? -minY:minY;
273
    maxY = maxY<0 ? -maxY:maxY;
274
275
    float max1 = Math.max(minX,minY);
276
    float max2 = Math.max(maxX,maxY);
277
    float max3 = Math.max(max1,max2);
278
279
    info.scale = max3/0.5f;
280
281
    int len = vert3D.length;
282
    StickerCoords sInfo = new StickerCoords();
283
    sInfo.outer = isOuter;
284
    sInfo.scale = info.scale;
285 4b9d1df5 leszek
    sInfo.fullVertices = new float[len][][];
286 fe3dec09 Leszek Koltunski
287
    for( int comp=0; comp<len; comp++ )
288
      {
289
      float[][] vert = vert3D[comp];
290
      int num = vert.length;
291 4b9d1df5 leszek
      sInfo.fullVertices[comp] = new float[num][2];
292
      float[][] t = sInfo.fullVertices[comp];
293 fe3dec09 Leszek Koltunski
294
      for( int vertex=0; vertex<num; vertex++)
295
        {
296 4b9d1df5 leszek
        t[vertex][0] = vert[vertex][0] / info.scale;
297
        t[vertex][1] = vert[vertex][1] / info.scale;
298 fe3dec09 Leszek Koltunski
        }
299
      }
300
301 08bf6b98 leszek
    sInfo.outerVertices = computeOuterEdge(sInfo.fullVertices);
302 fe3dec09 Leszek Koltunski
303
    mStickerCoords.add(sInfo);
304
305
    info.sticker = mStickerCoords.size() -1;
306
    }
307
308
///////////////////////////////////////////////////////////////////////////////////////////////////
309
// polygon
310 29b82486 Leszek Koltunski
311 7af68038 Leszek Koltunski
  private FaceTransform constructNewTransform(final float[][] vert3D, boolean isOuter, int face, int numFaces)
312 29b82486 Leszek Koltunski
    {
313
    FaceTransform ft = new FaceTransform();
314 7af68038 Leszek Koltunski
    ft.face = face;
315
    ft.numFaces = numFaces;
316 29b82486 Leszek Koltunski
317
    // compute center of gravity
318
    ft.vx = 0.0f;
319
    ft.vy = 0.0f;
320
    ft.vz = 0.0f;
321
    int len = vert3D.length;
322
323 57ef6378 Leszek Koltunski
    for (float[] vert : vert3D)
324 29b82486 Leszek Koltunski
      {
325
      ft.vx += vert[0];
326
      ft.vy += vert[1];
327
      ft.vz += vert[2];
328
      }
329
330
    ft.vx /= len;
331
    ft.vy /= len;
332
    ft.vz /= len;
333
334
    // move all vertices so that their center of gravity is at (0,0,0)
335
    for (int i=0; i<len; i++)
336
      {
337
      vert3D[i][0] -= ft.vx;
338
      vert3D[i][1] -= ft.vy;
339
      vert3D[i][2] -= ft.vz;
340
      }
341
342
    // find 3 non-colinear vertices
343
    int foundIndex = -1;
344
345
    for(int vertex=2; vertex<len; vertex++)
346
      {
347 4b9d1df5 leszek
      if( areNotColinear(vert3D,vertex) )
348 29b82486 Leszek Koltunski
        {
349
        foundIndex = vertex;
350
        break;
351
        }
352
      }
353
354
    // compute the normal vector
355
    if( foundIndex==-1 )
356
      {
357 03410dc1 Leszek Koltunski
      StringBuilder sb = new StringBuilder();
358
359 8e80135b Leszek Koltunski
      for (float[] floats : vert3D)
360 03410dc1 Leszek Koltunski
        {
361
        sb.append(' ');
362
        sb.append("(");
363 8e80135b Leszek Koltunski
        sb.append(floats[0]);
364 03410dc1 Leszek Koltunski
        sb.append(" ");
365 8e80135b Leszek Koltunski
        sb.append(floats[1]);
366 03410dc1 Leszek Koltunski
        sb.append(" ");
367 8e80135b Leszek Koltunski
        sb.append(floats[2]);
368 03410dc1 Leszek Koltunski
        sb.append(")");
369
        }
370
      android.util.Log.e("D", "verts: "+sb);
371
372 29b82486 Leszek Koltunski
      throw new RuntimeException("all vertices colinear");
373
      }
374
375 4b9d1df5 leszek
    computeNormalVector(vert3D,foundIndex);
376 29b82486 Leszek Koltunski
377
    // rotate so that the normal vector becomes (0,0,1)
378 57ef6378 Leszek Koltunski
    float axisX, axisY, axisZ;
379 29b82486 Leszek Koltunski
380
    if( mBuffer[0]!=0.0f || mBuffer[1]!=0.0f )
381
      {
382
      axisX = -mBuffer[1];
383
      axisY =  mBuffer[0];
384
      axisZ = 0.0f;
385
386 57ef6378 Leszek Koltunski
      float axiLen = axisX*axisX + axisY*axisY;
387
      axiLen = (float)Math.sqrt(axiLen);
388 29b82486 Leszek Koltunski
      axisX /= axiLen;
389
      axisY /= axiLen;
390
      axisZ /= axiLen;
391
      }
392
    else
393
      {
394
      axisX = 0.0f;
395
      axisY = 1.0f;
396
      axisZ = 0.0f;
397
      }
398
399 57ef6378 Leszek Koltunski
    float cosTheta = mBuffer[2];
400
    float sinTheta = (float)Math.sqrt(1-cosTheta*cosTheta);
401
    float sinHalfTheta = computeSinHalf(cosTheta);
402
    float cosHalfTheta = computeCosHalf(sinTheta,cosTheta);
403 29b82486 Leszek Koltunski
404
    mQuat1[0] = axisX*sinHalfTheta;
405
    mQuat1[1] = axisY*sinHalfTheta;
406
    mQuat1[2] = axisZ*sinHalfTheta;
407
    mQuat1[3] = cosHalfTheta;
408
    mQuat2[0] =-axisX*sinHalfTheta;
409
    mQuat2[1] =-axisY*sinHalfTheta;
410
    mQuat2[2] =-axisZ*sinHalfTheta;
411
    mQuat2[3] = cosHalfTheta;
412
413 57ef6378 Leszek Koltunski
    for (float[] vert : vert3D)
414 29b82486 Leszek Koltunski
      {
415 d809bf6f Leszek Koltunski
      QuatHelper.quatMultiply(mQuat3, mQuat1, vert  );
416
      QuatHelper.quatMultiply(  vert, mQuat3, mQuat2);
417 29b82486 Leszek Koltunski
      }
418
419
    // fit the whole thing in a square and remember the scale & 2D vertices
420 2617d26b Leszek Koltunski
    fitInSquare(ft, vert3D, isOuter);
421 29b82486 Leszek Koltunski
422
    // remember the rotation
423
    ft.qx =-mQuat1[0];
424
    ft.qy =-mQuat1[1];
425
    ft.qz =-mQuat1[2];
426
    ft.qw = mQuat1[3];
427
428
    return ft;
429
    }
430
431 fe3dec09 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
432
// multigon
433
434
  private FaceTransform constructNewTransform(final float[][][] vert3D, boolean isOuter, int face, int numFaces)
435
    {
436
    FaceTransform ft = new FaceTransform();
437
    ft.face = face;
438
    ft.numFaces = numFaces;
439
440
    // compute center of gravity
441
    ft.vx = 0.0f;
442
    ft.vy = 0.0f;
443
    ft.vz = 0.0f;
444
    int len = 0;
445
446
    for( float[][] vert : vert3D )
447
      for( float[] v : vert )
448
        {
449
        ft.vx += v[0];
450
        ft.vy += v[1];
451
        ft.vz += v[2];
452
        len++;
453
        }
454
455
    ft.vx /= len;
456
    ft.vy /= len;
457
    ft.vz /= len;
458
459
    // move all vertices so that their center of gravity is at (0,0,0)
460
    for( float[][] vert : vert3D )
461
      for( float[] v : vert )
462
        {
463
        v[0] -= ft.vx;
464
        v[1] -= ft.vy;
465
        v[2] -= ft.vz;
466
        }
467
468
    // find 3 non-colinear vertices
469
    int foundIndex = -1;
470
    len = vert3D[0].length;
471
472
    for(int vertex=2; vertex<len; vertex++)
473
      {
474 4b9d1df5 leszek
      if( areNotColinear(vert3D[0],vertex) )
475 fe3dec09 Leszek Koltunski
        {
476
        foundIndex = vertex;
477
        break;
478
        }
479
      }
480
481
    // compute the normal vector
482
    if( foundIndex==-1 )
483
      {
484
      StringBuilder sb = new StringBuilder();
485
486
      for (float[] v : vert3D[0])
487
        {
488
        sb.append(' ');
489
        sb.append("(");
490
        sb.append(v[0]);
491
        sb.append(" ");
492
        sb.append(v[1]);
493
        sb.append(" ");
494
        sb.append(v[2]);
495
        sb.append(")");
496
        }
497
      android.util.Log.e("D", "verts: "+sb);
498
499
      throw new RuntimeException("all vertices colinear");
500
      }
501
502 4b9d1df5 leszek
    computeNormalVector(vert3D[0],foundIndex);
503 fe3dec09 Leszek Koltunski
504
    // rotate so that the normal vector becomes (0,0,1)
505
    float axisX, axisY, axisZ;
506
507
    if( mBuffer[0]!=0.0f || mBuffer[1]!=0.0f )
508
      {
509
      axisX = -mBuffer[1];
510
      axisY =  mBuffer[0];
511
      axisZ = 0.0f;
512
513
      float axiLen = axisX*axisX + axisY*axisY;
514
      axiLen = (float)Math.sqrt(axiLen);
515
      axisX /= axiLen;
516
      axisY /= axiLen;
517
      axisZ /= axiLen;
518
      }
519
    else
520
      {
521
      axisX = 0.0f;
522
      axisY = 1.0f;
523
      axisZ = 0.0f;
524
      }
525
526
    float cosTheta = mBuffer[2];
527
    float sinTheta = (float)Math.sqrt(1-cosTheta*cosTheta);
528
    float sinHalfTheta = computeSinHalf(cosTheta);
529
    float cosHalfTheta = computeCosHalf(sinTheta,cosTheta);
530
531
    mQuat1[0] = axisX*sinHalfTheta;
532
    mQuat1[1] = axisY*sinHalfTheta;
533
    mQuat1[2] = axisZ*sinHalfTheta;
534
    mQuat1[3] = cosHalfTheta;
535
    mQuat2[0] =-axisX*sinHalfTheta;
536
    mQuat2[1] =-axisY*sinHalfTheta;
537
    mQuat2[2] =-axisZ*sinHalfTheta;
538
    mQuat2[3] = cosHalfTheta;
539
540
    for( float[][] vert : vert3D)
541
      for( float[] v : vert)
542
        {
543
        QuatHelper.quatMultiply(mQuat3, mQuat1, v  );
544
        QuatHelper.quatMultiply(  v, mQuat3, mQuat2);
545
        }
546
547
    // fit the whole thing in a square and remember the scale & 2D vertices
548
    fitInSquare(ft, vert3D, isOuter);
549
550
    // remember the rotation
551
    ft.qx =-mQuat1[0];
552
    ft.qy =-mQuat1[1];
553
    ft.qz =-mQuat1[2];
554
    ft.qw = mQuat1[3];
555
556
    return ft;
557
    }
558
559 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
560
561 7e9a35eb leszek
  private void rotateAllVertices(float[][] result, int len, float[][] vertices, float sin, float cos)
562 29b82486 Leszek Koltunski
    {
563
    for(int i=0; i<len; i++)
564
      {
565 7e9a35eb leszek
      float x = vertices[i][0];
566
      float y = vertices[i][1];
567
      result[i][0] = x*cos - y*sin;
568
      result[i][1] = x*sin + y*cos;
569 29b82486 Leszek Koltunski
      }
570
    }
571
572
///////////////////////////////////////////////////////////////////////////////////////////////////
573
574 7e9a35eb leszek
  private float computeScale(float[][] v1, float[][] v2, int v1i, int v2i)
575 29b82486 Leszek Koltunski
    {
576 7e9a35eb leszek
    float v1x = v1[v1i][0];
577
    float v1y = v1[v1i][1];
578
    float v2x = v2[v2i][0];
579
    float v2y = v2[v2i][1];
580 29b82486 Leszek Koltunski
581 57ef6378 Leszek Koltunski
    float lenSq1 = v1x*v1x + v1y*v1y;
582
    float lenSq2 = v2x*v2x + v2y*v2y;
583 29b82486 Leszek Koltunski
584 57ef6378 Leszek Koltunski
    return (float)Math.sqrt(lenSq2/lenSq1);
585 29b82486 Leszek Koltunski
    }
586
587
///////////////////////////////////////////////////////////////////////////////////////////////////
588
// valid for 0<angle<2*PI
589
590 57ef6378 Leszek Koltunski
  private float computeSinHalf(float cos)
591 29b82486 Leszek Koltunski
    {
592 57ef6378 Leszek Koltunski
    return (float)Math.sqrt((1-cos)/2);
593 29b82486 Leszek Koltunski
    }
594
595
///////////////////////////////////////////////////////////////////////////////////////////////////
596
// valid for 0<angle<2*PI
597
598 57ef6378 Leszek Koltunski
  private float computeCosHalf(float sin, float cos)
599 29b82486 Leszek Koltunski
    {
600 57ef6378 Leszek Koltunski
    float cosHalf = (float)Math.sqrt((1+cos)/2);
601 29b82486 Leszek Koltunski
    return sin<0 ? -cosHalf : cosHalf;
602
    }
603
604
///////////////////////////////////////////////////////////////////////////////////////////////////
605
606 846b69f3 Leszek Koltunski
  private int computeRotatedIndex(int oldVertex, int len, int rotatedVertex)
607 29b82486 Leszek Koltunski
    {
608 846b69f3 Leszek Koltunski
    int v = (rotatedVertex + oldVertex);
609 29b82486 Leszek Koltunski
    if( v>=len ) v-=len;
610
    if( v< 0   ) v+=len;
611
612
    return v;
613
    }
614
615
///////////////////////////////////////////////////////////////////////////////////////////////////
616
617 7e9a35eb leszek
  private boolean isScaledVersionOf(float[][] newVert, float[][] oldVert, int len, int vertex)
618 29b82486 Leszek Koltunski
    {
619 846b69f3 Leszek Koltunski
    int newZeroIndex = computeRotatedIndex(0,len,vertex);
620 57ef6378 Leszek Koltunski
    float EPSILON = 0.001f;
621
    float scale = computeScale(newVert,oldVert,newZeroIndex,0);
622 29b82486 Leszek Koltunski
623
    for(int i=1; i<len; i++)
624
      {
625 846b69f3 Leszek Koltunski
      int index = computeRotatedIndex(i,len,vertex);
626 29b82486 Leszek Koltunski
627 7e9a35eb leszek
      float horz = oldVert[i][0] - scale*newVert[index][0];
628
      float vert = oldVert[i][1] - scale*newVert[index][1];
629 29b82486 Leszek Koltunski
630
      if( horz>EPSILON || horz<-EPSILON || vert>EPSILON || vert<-EPSILON ) return false;
631
      }
632
633
    return true;
634
    }
635
636
///////////////////////////////////////////////////////////////////////////////////////////////////
637
638 846b69f3 Leszek Koltunski
  private void correctInfo(FaceTransform info, float scale, float sin, float cos, int oldSticker)
639 29b82486 Leszek Koltunski
    {
640
    mStickerCoords.remove(info.sticker);
641
642
    info.sticker = oldSticker;
643
    info.scale  *= scale;
644
645
    mQuat1[0] = info.qx;
646
    mQuat1[1] = info.qy;
647
    mQuat1[2] = info.qz;
648
    mQuat1[3] = info.qw;
649
650 57ef6378 Leszek Koltunski
    float sinHalf = computeSinHalf(cos);
651
    float cosHalf = computeCosHalf(sin,cos);
652 29b82486 Leszek Koltunski
653 846b69f3 Leszek Koltunski
    mQuat2[0] = 0.0f;
654
    mQuat2[1] = 0.0f;
655
    mQuat2[2] = sinHalf;
656
    mQuat2[3] = cosHalf;
657 29b82486 Leszek Koltunski
658 d809bf6f Leszek Koltunski
    QuatHelper.quatMultiply( mQuat3, mQuat1, mQuat2 );
659 29b82486 Leszek Koltunski
660
    info.qx = mQuat3[0];
661
    info.qy = mQuat3[1];
662
    info.qz = mQuat3[2];
663
    info.qw = mQuat3[3];
664
    }
665
666
///////////////////////////////////////////////////////////////////////////////////////////////////
667
668 7e9a35eb leszek
  private boolean foundVertex(FaceTransform info, float[][] buffer, float[][] newVert, float[][] oldVert, int oldSticker)
669 29b82486 Leszek Koltunski
    {
670 bf4e7e68 Leszek Koltunski
    float lenOld=0.0f, oldX=0.0f, oldY=0.0f;
671 7e9a35eb leszek
    int len = newVert.length;
672 bf4e7e68 Leszek Koltunski
673 7e9a35eb leszek
    for(float[] ov : oldVert)
674 bf4e7e68 Leszek Koltunski
      {
675 7e9a35eb leszek
      oldX = ov[0];
676
      oldY = ov[1];
677
      lenOld = (float) Math.sqrt(oldX*oldX+oldY*oldY);
678 bf4e7e68 Leszek Koltunski
679 7e9a35eb leszek
      if(lenOld!=0) break;
680 bf4e7e68 Leszek Koltunski
      }
681
682 29b82486 Leszek Koltunski
    for(int vertex=0; vertex<len; vertex++)
683
      {
684 7e9a35eb leszek
      float newX = newVert[vertex][0];
685
      float newY = newVert[vertex][1];
686 bf4e7e68 Leszek Koltunski
      float lenNew = (float)Math.sqrt(newX*newX + newY*newY);
687 29b82486 Leszek Koltunski
688 bf4e7e68 Leszek Koltunski
      if( lenNew!=0 )
689 29b82486 Leszek Koltunski
        {
690 bf4e7e68 Leszek Koltunski
        float cos = (float)QuatHelper.computeCos( oldX, oldY, newX, newY, lenNew, lenOld);
691
        float sin = (float)QuatHelper.computeSin( oldX, oldY, newX, newY, lenNew, lenOld);
692
693
        rotateAllVertices(buffer,len,newVert,sin,cos);
694
695
        if( isScaledVersionOf(buffer,oldVert,len,vertex) )
696
          {
697
          int newZeroIndex = computeRotatedIndex(0,len,vertex);
698
          float scale = computeScale(oldVert,newVert,0,newZeroIndex);
699
          correctInfo(info,scale,sin,cos,oldSticker);
700
          return true;
701
          }
702 29b82486 Leszek Koltunski
        }
703
      }
704
705
    return false;
706
    }
707
708 d99de43c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
709
710 7e9a35eb leszek
  private float computeCoreDistance(float[][] verts)
711 d99de43c Leszek Koltunski
    {
712
    float ret = 0.0f;
713
    float centerX=0.0f,centerY=0.0f;
714 7e9a35eb leszek
    int len = verts.length;
715 d99de43c Leszek Koltunski
716 7e9a35eb leszek
    for(float[] vert : verts)
717 d99de43c Leszek Koltunski
      {
718 7e9a35eb leszek
      centerX += vert[0];
719
      centerY += vert[1];
720 d99de43c Leszek Koltunski
      }
721
722 7e9a35eb leszek
    centerX /= len;
723
    centerY /= len;
724 d99de43c Leszek Koltunski
725 7e9a35eb leszek
    for(float[] vert : verts)
726 d99de43c Leszek Koltunski
      {
727 7e9a35eb leszek
      float distX = centerX-vert[0];
728
      float distY = centerY-vert[1];
729
      ret += (float) Math.sqrt(distX*distX+distY*distY);
730 d99de43c Leszek Koltunski
      }
731
732
    return ret;
733
    }
734
735 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
736 9567a9ae leszek
// even if this is a multigon, then StickerCoords.outerVertices is the outer edge!
737 8aceea06 leszek
// (see fitInSquare multigon variant)
738 29b82486 Leszek Koltunski
739
  private boolean successfullyCollapsedStickers(final FaceTransform newInfo, final FaceTransform oldInfo)
740
    {
741
    StickerCoords sNewInfo = mStickerCoords.get(newInfo.sticker);
742
    StickerCoords sOldInfo = mStickerCoords.get(oldInfo.sticker);
743 d99de43c Leszek Koltunski
744 08bf6b98 leszek
    if( sNewInfo.outerVertices.length>1 || sOldInfo.outerVertices.length>1 ) // the 'outer' path is composed of more than
745
      {                                                                      // one segment, i.e. the sticker has holes.
746
      return false;                                                          // do not collapse such stickers.
747
      }
748
749
    float[][] newVert = sNewInfo.outerVertices[0];
750
    float[][] oldVert = sOldInfo.outerVertices[0];
751 29b82486 Leszek Koltunski
    int oldLen = oldVert.length;
752
    int newLen = newVert.length;
753
754 f7d2e0e1 Leszek Koltunski
    if( oldLen==newLen )
755 29b82486 Leszek Koltunski
      {
756 bf4e7e68 Leszek Koltunski
      float coreDistOld = computeCoreDistance(oldVert);                     // the two stickers are at different scales,
757 d99de43c Leszek Koltunski
      float coreDistNew = computeCoreDistance(newVert);                     // so even if they are in fact the same, do not
758
      float diff = (coreDistOld*oldInfo.scale)/(coreDistNew*newInfo.scale); // collapse them into one. Example: Master Skewb
759
      if( diff<1.0-MAX_CORE_DIFF || diff>1.0+MAX_CORE_DIFF ) return false;  // and two triangular stickers of different size.
760
761 29b82486 Leszek Koltunski
      int oldSticker = oldInfo.sticker;
762 7e9a35eb leszek
      float[][] buffer = new float[oldLen][2];
763 bf4e7e68 Leszek Koltunski
764 7e9a35eb leszek
      if( foundVertex(newInfo, buffer, newVert, oldVert, oldSticker) )
765 f7d2e0e1 Leszek Koltunski
        {
766 d99de43c Leszek Koltunski
        if( sNewInfo.outer ) sOldInfo.outer = true;
767 f7d2e0e1 Leszek Koltunski
        return true;
768
        }
769 29b82486 Leszek Koltunski
      }
770
771
    return false;
772
    }
773
774
///////////////////////////////////////////////////////////////////////////////////////////////////
775 fe3dec09 Leszek Koltunski
// polygon
776 29b82486 Leszek Koltunski
777 57ef6378 Leszek Koltunski
  private float[][] constructVert(float[][] vertices, int[] index)
778 29b82486 Leszek Koltunski
    {
779
    int len = index.length;
780 57ef6378 Leszek Koltunski
    float[][] ret = new float[len][4];
781 29b82486 Leszek Koltunski
782
    for(int i=0; i<len; i++)
783
      {
784 84a17011 Leszek Koltunski
      float[] tmp = vertices[index[i]];
785
      ret[i][0] = tmp[0];
786
      ret[i][1] = tmp[1];
787
      ret[i][2] = tmp[2];
788 29b82486 Leszek Koltunski
      ret[i][3] = 1.0f;
789
      }
790
791
    return ret;
792
    }
793
794 fe3dec09 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
795
// multigon
796
797
  private float[][][] constructVert(float[][] vertices, int[][] index)
798
    {
799
    int len = index.length;
800
    float[][][] ret = new float[len][][];
801
802
    for(int i=0; i<len; i++)
803
      {
804
      int[] ind = index[i];
805
      int num = ind.length;
806
      ret[i] = new float[num][4];
807
808
      for(int j=0; j<num; j++)
809
        {
810
        float[] r = ret[i][j];
811
        float[] v = vertices[ind[j]];
812
        r[0] = v[0];
813
        r[1] = v[1];
814
        r[2] = v[2];
815
        r[3] = 1.0f;
816
        }
817
      }
818
819
    return ret;
820
    }
821
822 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
823
824 1fda81c4 leszek
  private void applyVertexEffects(MeshBase mesh, ObjectVertexEffects effects)
825 29b82486 Leszek Koltunski
    {
826 84a17011 Leszek Koltunski
    boolean[] uses      = effects.getUses();
827
    String[] names      = effects.getNames();
828
    float[][] variables = effects.getVariables();
829
    float[][] centers   = effects.getCenters();
830
    float[][] regions   = effects.getRegions();
831
    int numEffects = uses.length;
832
833
    for(int eff=0; eff<numEffects; eff++)
834 1fda81c4 leszek
      if( names[eff]!=null )
835 29b82486 Leszek Koltunski
        {
836 84a17011 Leszek Koltunski
        VertexEffect effect = VertexEffect.constructEffect(names[eff],variables[eff],centers[eff],regions[eff]);
837
        if( effect!=null ) mesh.apply(effect);
838 29b82486 Leszek Koltunski
        }
839
    }
840
841
///////////////////////////////////////////////////////////////////////////////////////////////////
842
843
  private void correctComponents(MeshBase mesh, int numComponents)
844
    {
845
    int numTexToBeAdded = numComponents-mesh.getNumTexComponents();
846
847
    mesh.mergeEffComponents();
848
849
    for(int i=0; i<numTexToBeAdded; i++ ) mesh.addEmptyTexComponent();
850
    }
851
852
///////////////////////////////////////////////////////////////////////////////////////////////////
853
854
  private void printTransform(FaceTransform f)
855
    {
856 9567a9ae leszek
    android.util.Log.e("D", "face="+f.face+" sticker="+f.sticker+" scale="+f.scale+
857
                            " q=("+f.qx+", "+f.qy+", "+f.qz+", "+f.qw+") v=("+f.vx+", "+f.vy+", "+f.vz+")");
858 29b82486 Leszek Koltunski
    }
859
860
///////////////////////////////////////////////////////////////////////////////////////////////////
861
862 b2c77ec3 Leszek Koltunski
  private float[] computeBands(float H, int alpha, float dist, float K, int N)
863 29b82486 Leszek Koltunski
    {
864
    float[] bands = new float[2*N];
865
866
    bands[0] = 1.0f;
867
    bands[1] = 0.0f;
868
869
    float beta = (float)Math.atan(dist*Math.tan(Math.PI*alpha/180));
870
    float sinBeta = (float)Math.sin(beta);
871
    float cosBeta = (float)Math.cos(beta);
872
    float R = cosBeta<1.0f ? H/(1.0f-cosBeta) : 0.0f;
873
    float D = R*sinBeta;
874
    float B = h(R,sinBeta,K*beta);
875
876
    if( D>1.0f )
877
      {
878
      for(int i=1; i<N; i++)
879
        {
880
        bands[2*i  ] = (float)(N-1-i)/(N-1);
881
        bands[2*i+1] = H*(1-bands[2*i]);
882
        }
883
      }
884
    else
885
      {
886
      int K2 = (int)((N-3)*K);
887
      int K1 = (N-3)-K2;
888
889
      for(int i=0; i<=K1; i++)
890
        {
891
        float angle = K*beta + (1-K)*beta*(K1-i)/(K1+1);
892
        float x = h(R,sinBeta,angle);
893
        bands[2*i+2] = 1.0f - x;
894
        bands[2*i+3] = g(R,D,x,cosBeta);
895
        }
896
897
      for(int i=0; i<=K2; i++)
898
        {
899
        float x = (1-B)*(i+1)/(K2+1) + B;
900
        bands[2*K1+2 + 2*i+2] = 1.0f - x;
901
        bands[2*K1+2 + 2*i+3] = g(R,D,f(D,B,x),cosBeta);
902
        }
903
      }
904
905
    bands[2*N-2] = 0.0f;
906
    bands[2*N-1] =    H;
907
908
    return bands;
909
    }
910
911
///////////////////////////////////////////////////////////////////////////////////////////////////
912
913 b2c77ec3 Leszek Koltunski
  private void computeConvexityCenter(float[] out, float[] in, FaceTransform ft)
914
    {
915
    if( in==null )
916
      {
917
      out[0] = out[1] = 0.0f;
918
      }
919
    else
920
      {
921
      out[0] = in[0] - ft.vx;
922
      out[1] = in[1] - ft.vy;
923
      out[2] = in[2] - ft.vz;
924
      out[3] = 1.0f;
925
926
      mQuat1[0] =-ft.qx;
927
      mQuat1[1] =-ft.qy;
928
      mQuat1[2] =-ft.qz;
929
      mQuat1[3] = ft.qw;
930
931
      mQuat2[0] = -mQuat1[0];
932
      mQuat2[1] = -mQuat1[1];
933
      mQuat2[2] = -mQuat1[2];
934 84a17011 Leszek Koltunski
      mQuat2[3] =  mQuat1[3];
935 b2c77ec3 Leszek Koltunski
936 d809bf6f Leszek Koltunski
      QuatHelper.quatMultiply( mQuat3, mQuat1,    out);
937
      QuatHelper.quatMultiply(    out, mQuat3, mQuat2);
938 b2c77ec3 Leszek Koltunski
939
      out[0] /= ft.scale;
940
      out[1] /= ft.scale;
941
      out[2] /= ft.scale;
942
      }
943
    }
944
945
///////////////////////////////////////////////////////////////////////////////////////////////////
946
947
  private void changeStickerPointers(int[][] table, int oldPointer, int newPointer)
948
    {
949 0d9a2083 leszek
    for(int[] tab : table)
950 b2c77ec3 Leszek Koltunski
      {
951 0d9a2083 leszek
      int len = tab.length;
952 b2c77ec3 Leszek Koltunski
953 0d9a2083 leszek
      for(int j=0; j<len; j++)
954
        if( tab[j]==oldPointer ) tab[j] = newPointer;
955 b2c77ec3 Leszek Koltunski
      }
956
    }
957
958 9567a9ae leszek
///////////////////////////////////////////////////////////////////////////////////////////////////
959
960
  private String printSticker(StickerCoords info)
961
    {
962
    String ret = (info.outer?"OUTER":"INNER")+" scale: "+info.scale+"\n";
963
964
    int len = info.outerVertices.length;
965
966
    for(int l=0; l<len; l++)
967
      {
968
      float[][] outer = info.outerVertices[l];
969
      int numV = outer.length;
970
971
      ret += "  Loop "+l+" verts: "+numV+" { ";
972
      for(int v=0; v<numV; v++)
973
        {
974
        if(v!=0) ret += ", ";
975
        ret += (outer[v][0]+"f, "+outer[v][1]+"f");
976
        }
977
978
      ret += "}\n";
979
      }
980
981
    return ret;
982
    }
983
984 b2c77ec3 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
985
// INTERNAL API
986
987 f7d2e0e1 Leszek Koltunski
  public int printStickerCoords()
988 29b82486 Leszek Koltunski
    {
989
    int stickers = mStickerCoords.size();
990 f7d2e0e1 Leszek Koltunski
    int ret = 0;
991 29b82486 Leszek Koltunski
992
    android.util.Log.d("D", "---- STICKER COORDS ----");
993
994
    for(int s=0; s<stickers; s++)
995
      {
996
      StickerCoords info = mStickerCoords.get(s);
997 f7d2e0e1 Leszek Koltunski
      if( info.outer )  ret++;
998 9567a9ae leszek
      String str = printSticker(info);
999
      android.util.Log.d("D", "Sticker "+s+" "+str);
1000 29b82486 Leszek Koltunski
      }
1001
1002
    android.util.Log.d("D", "---- END STICKER COORDS ----");
1003 f7d2e0e1 Leszek Koltunski
1004
    return ret;
1005 29b82486 Leszek Koltunski
    }
1006
1007
///////////////////////////////////////////////////////////////////////////////////////////////////
1008
1009
  public void printFaceTransform()
1010
    {
1011
    android.util.Log.d("D", "---- OLD FACE TRANSFORM ---");
1012
1013
    int oldfaces = mOldFaceTransf.size();
1014
1015
    for(int f=0; f<oldfaces; f++)
1016
      {
1017
      printTransform(mOldFaceTransf.get(f));
1018
      }
1019
1020
    android.util.Log.d("D", "---- NEW FACE TRANSFORM ---");
1021
1022
    int newfaces = mNewFaceTransf.size();
1023
1024
    for(int f=0; f<newfaces; f++)
1025
      {
1026
      printTransform(mNewFaceTransf.get(f));
1027
      }
1028
    }
1029
1030 7e9a35eb leszek
///////////////////////////////////////////////////////////////////////////////////////////////////
1031
1032
  private void printVert(double[][] buffer)
1033
    {
1034
    StringBuilder str = new StringBuilder();
1035
1036
    for(double[] buf : buffer)
1037
      {
1038
      str.append(" (");
1039
      str.append(buf[0]);
1040
      str.append(" , ");
1041
      str.append(buf[1]);
1042
      str.append(" ) ");
1043
      }
1044
1045
    android.util.Log.d("D", str.toString());
1046
    }
1047
1048 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
1049 b2c77ec3 Leszek Koltunski
// PUBLIC API
1050 29b82486 Leszek Koltunski
1051 b2c77ec3 Leszek Koltunski
  public static FactoryCubit getInstance()
1052 29b82486 Leszek Koltunski
    {
1053 b2c77ec3 Leszek Koltunski
    if( mThis==null ) mThis = new FactoryCubit();
1054
    return mThis;
1055 29b82486 Leszek Koltunski
    }
1056
1057 84a17011 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
1058
1059
  public static ObjectVertexEffects generateVertexEffect( float[][] vertices,
1060
                                                          float[][] corners, int[] cornerIndices,
1061
                                                          float[][] centers, int[] centerIndices )
1062
    {
1063
    int numVerts = vertices.length;
1064
    String[] names = new String[numVerts];
1065
    float[][] vars = new float[numVerts][];
1066
    float[][] cents= new float[numVerts][];
1067
    float[][] regs = new float[numVerts][];
1068
    boolean[] uses = new boolean[numVerts];
1069
1070
    for(int i=0; i<numVerts; i++)
1071
      {
1072
      int centerI = centerIndices[i];
1073
      int cornerI = cornerIndices[i];
1074
1075
      if( centerI>=0 && cornerI>=0 )
1076
        {
1077
        float[] ce = centers[centerI];
1078
        float[] ve = vertices[i];
1079
        float S = corners[cornerI][0];
1080
        float R = corners[cornerI][1];
1081
1082
        float CX = ve[0];
1083
        float CY = ve[1];
1084
        float CZ = ve[2];
1085
        float X = S*(ce[0]-CX);
1086
        float Y = S*(ce[1]-CY);
1087
        float Z = S*(ce[2]-CZ);
1088
1089
        names[i]= NAME;
1090
        vars[i] = new float[] { 0, X,Y,Z, 1 };
1091
        cents[i]= new float[] { CX, CY, CZ };
1092
        regs[i] = new float[] { 0,0,0, R };
1093
        uses[i] = false;
1094
        }
1095
      }
1096
1097
    return new ObjectVertexEffects(names,vars,cents,regs,uses);
1098
    }
1099
1100 1561a74f Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
1101
1102 3d2493ea Leszek Koltunski
  public float[] getStickerScales()
1103 1561a74f Leszek Koltunski
    {
1104
    int index=0,num=0,len = mStickerCoords.size();
1105
1106 3d2493ea Leszek Koltunski
    for(int i=0; i<len; i++) if( mStickerCoords.get(i).outer ) num++;
1107 1561a74f Leszek Koltunski
1108
    if( num>0 )
1109
      {
1110 b2c77ec3 Leszek Koltunski
      float[] scales = new float[num];
1111 1561a74f Leszek Koltunski
1112
      for(int i=0; i<len; i++)
1113
        {
1114
        StickerCoords sticker = mStickerCoords.get(i);
1115 3d2493ea Leszek Koltunski
        if( sticker.outer ) scales[index++] = sticker.scale;
1116 1561a74f Leszek Koltunski
        }
1117
1118 b2c77ec3 Leszek Koltunski
      return scales;
1119 1561a74f Leszek Koltunski
      }
1120
1121
    return null;
1122
    }
1123
1124
///////////////////////////////////////////////////////////////////////////////////////////////////
1125
1126 ebe8c08e leszek
  public float[][][][] getStickerCoords()
1127 1561a74f Leszek Koltunski
    {
1128
    int index=0,num=0,len = mStickerCoords.size();
1129
1130 3d2493ea Leszek Koltunski
    for(int i=0; i<len; i++) if( mStickerCoords.get(i).outer ) num++;
1131 1561a74f Leszek Koltunski
1132
    if( num>0 )
1133
      {
1134 ebe8c08e leszek
      float[][][][] coords = new float[num][][][];
1135 1561a74f Leszek Koltunski
1136
      for(int i=0; i<len; i++)
1137
        {
1138
        StickerCoords sticker = mStickerCoords.get(i);
1139 ebe8c08e leszek
        if( sticker.outer ) coords[index++] = sticker.outerVertices;
1140 1561a74f Leszek Koltunski
        }
1141
1142 b2c77ec3 Leszek Koltunski
      return coords;
1143 1561a74f Leszek Koltunski
      }
1144
1145
    return null;
1146
    }
1147
1148 7af68038 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
1149
1150
  public int[][] getStickerVariants()
1151
    {
1152
    int numvariants = 1; // there's one in the 'new' array
1153
1154
    int oldfaces = mOldFaceTransf.size();
1155
1156
    for(int f=0; f<oldfaces; f++)
1157
      {
1158
      FaceTransform ft = mOldFaceTransf.get(f);
1159
      if( ft.face==0 ) numvariants++;
1160
      }
1161
1162
    int[][] ret = new int[numvariants][];
1163 0d9a2083 leszek
    int face=0, variant=-1;
1164 7af68038 Leszek Koltunski
1165
    for(int f=0; f<oldfaces; f++)
1166
      {
1167
      FaceTransform ft = mOldFaceTransf.get(f);
1168
      if( ft.face==0 )
1169
        {
1170 0d9a2083 leszek
        variant++;
1171
        face=0;
1172
        ret[variant] = new int[ft.numFaces];
1173 7af68038 Leszek Koltunski
        }
1174
1175 0d9a2083 leszek
      ret[variant][face++] = ft.sticker;
1176 7af68038 Leszek Koltunski
      }
1177
1178
    int newfaces = mNewFaceTransf.size();
1179
1180
    for(int f=0; f<newfaces; f++)
1181
      {
1182
      FaceTransform ft = mNewFaceTransf.get(f);
1183
      if( ft.face==0 )
1184
        {
1185 0d9a2083 leszek
        variant++;
1186
        face=0;
1187
        ret[variant] = new int[ft.numFaces];
1188 7af68038 Leszek Koltunski
        }
1189
1190 0d9a2083 leszek
      ret[variant][face++] = ft.sticker;
1191 7af68038 Leszek Koltunski
      }
1192
1193
    int numStickers = mStickerCoords.size();
1194
    int numOuter=0;
1195
1196
    for(int i=0; i<numStickers; i++)
1197
      {
1198
      StickerCoords sc = mStickerCoords.get(i);
1199
      if( sc.outer )
1200
        {
1201 0d9a2083 leszek
        changeStickerPointers(ret,i, numOuter);
1202 7af68038 Leszek Koltunski
        numOuter++;
1203
        }
1204
      else
1205
        {
1206
        changeStickerPointers(ret,i,-1);
1207
        }
1208
      }
1209
1210
    return ret;
1211
    }
1212
1213 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
1214
1215 b2c77ec3 Leszek Koltunski
  public void clear()
1216 29b82486 Leszek Koltunski
    {
1217 b2c77ec3 Leszek Koltunski
    mStickerCoords.clear();
1218
    mNewFaceTransf.clear();
1219
    mOldFaceTransf.clear();
1220
    }
1221
1222 df781f1d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
1223
// This is for FactoryBandaged3x3Cubit. We need to know which direction each face faces.
1224
// This assumes the factory has just been cleared and 'createNewFaceTransform' has just
1225
// been called.
1226
1227
  public Static4D getQuaternion(int face)
1228
    {
1229
    FaceTransform ft = mNewFaceTransf.get(face);
1230
    return ft!=null ? new Static4D(ft.qx,ft.qy,ft.qz,ft.qw) : null;
1231
    }
1232
1233 b2c77ec3 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
1234
1235 59a971c1 Leszek Koltunski
  public void createNewFaceTransform(final ObjectShape shape, int[] outer)
1236 b2c77ec3 Leszek Koltunski
    {
1237
    float[][] vertices = shape.getVertices();
1238
    int[][] indices = shape.getVertIndices();
1239 fe3dec09 Leszek Koltunski
    int[][][] fullIndices = shape.getMultigonIndices();
1240
    boolean isMultigon = shape.isMultigon();
1241 b2c77ec3 Leszek Koltunski
    FaceTransform ft;
1242
    int numNew = mNewFaceTransf.size();
1243
1244
    for(int i=0; i<numNew; i++)
1245
      {
1246
      ft = mNewFaceTransf.remove(0);
1247
      mOldFaceTransf.add(ft);
1248
      }
1249
1250 fe3dec09 Leszek Koltunski
    int numFaces = shape.getNumFaces();
1251 b2c77ec3 Leszek Koltunski
    int numOld = mOldFaceTransf.size();
1252
1253
    for (int face=0; face<numFaces; face++)
1254
      {
1255
      boolean collapsed = false;
1256 59a971c1 Leszek Koltunski
      boolean isOuter = (outer!=null && outer[face]>0);
1257 fe3dec09 Leszek Koltunski
      FaceTransform newT;
1258
1259
      if( !isMultigon )
1260
        {
1261
        float[][] vert = constructVert(vertices, indices[face]);
1262
        newT = constructNewTransform(vert,isOuter,face,numFaces);
1263
        }
1264
      else
1265
        {
1266
        float[][][] vert = constructVert(vertices, fullIndices[face]);
1267
        newT = constructNewTransform(vert,isOuter,face,numFaces);
1268
        }
1269 b2c77ec3 Leszek Koltunski
1270
      for (int old=0; !collapsed && old<numOld; old++)
1271
        {
1272
        ft = mOldFaceTransf.get(old);
1273
        if (successfullyCollapsedStickers(newT, ft)) collapsed = true;
1274
        }
1275
1276
      for (int pre=0; !collapsed && pre<face; pre++)
1277
        {
1278
        ft = mNewFaceTransf.get(pre);
1279
        if (successfullyCollapsedStickers(newT, ft)) collapsed = true;
1280
        }
1281
1282
      mNewFaceTransf.add(newT);
1283
      }
1284 29b82486 Leszek Koltunski
    }
1285
1286
///////////////////////////////////////////////////////////////////////////////////////////////////
1287
1288 84a17011 Leszek Koltunski
  public MeshBase createRoundedSolid(final ObjectShape shape, final ObjectFaceShape faceShape,
1289 1fda81c4 leszek
                                     final ObjectVertexEffects effects, int numComponents)
1290 29b82486 Leszek Koltunski
    {
1291 b2c77ec3 Leszek Koltunski
    float[][] bands         = faceShape.getBands();
1292
    int[]   bandIndexes     = faceShape.getBandIndices();
1293
    float[] convexityCenter = faceShape.getConvexityCenter();
1294
1295 fe3dec09 Leszek Koltunski
    int numFaces = shape.getNumFaces();
1296 1fda81c4 leszek
    float[] bandsComputed;
1297 29b82486 Leszek Koltunski
    MeshBase[] meshes = new MeshBase[numFaces];
1298
    FaceTransform fInfo;
1299
    StickerCoords sInfo;
1300 57ef6378 Leszek Koltunski
    float[] convexXY = new float[4];
1301 29b82486 Leszek Koltunski
1302
    for(int face=0; face<numFaces; face++)
1303
      {
1304
      fInfo = mNewFaceTransf.get(face);
1305
      computeConvexityCenter(convexXY,convexityCenter,fInfo);
1306
1307 1fda81c4 leszek
      int index      = bandIndexes[face];
1308
      float[] band   = bands[index];
1309
      float height   = band[0];
1310
      int alpha      = (int)band[1];
1311
      float dist     = band[2];
1312
      float K        = band[3];
1313
      int N          = (int)band[4];
1314
      int exIndex    = (int)band[5];
1315
      int exVertices = (int)band[6];
1316 c3a033e9 Leszek Koltunski
1317 50fb62bf Leszek Koltunski
      bandsComputed = computeBands(height,alpha,dist,K,N);
1318 fe3dec09 Leszek Koltunski
1319 8aceea06 leszek
      sInfo = mStickerCoords.get(fInfo.sticker);
1320 4b9d1df5 leszek
      float[][][] vertsF = sInfo.fullVertices;
1321 8aceea06 leszek
1322
      // i.e. multigon which hasn't been 'successfully collapsed'
1323
      // with a previously computed polygon sticker!
1324
      if( vertsF!=null )
1325 fe3dec09 Leszek Koltunski
        {
1326 8aceea06 leszek
        int lenVerts = vertsF.length;
1327 4b9d1df5 leszek
        float[][][] copiedVerts = new float[lenVerts][][];
1328 fe3dec09 Leszek Koltunski
1329
        for(int i=0; i<lenVerts; i++)
1330
          {
1331 4b9d1df5 leszek
          float[][] v = vertsF[i];
1332 fe3dec09 Leszek Koltunski
          int len = v.length;
1333 4b9d1df5 leszek
          copiedVerts[i] = new float[len][2];
1334
1335
          for(int j=0; j<len; j++)
1336
            {
1337
            copiedVerts[i][j][0] = v[j][0];
1338
            copiedVerts[i][j][1] = v[j][1];
1339
            }
1340 fe3dec09 Leszek Koltunski
          }
1341
1342
        meshes[face] = new MeshMultigon(copiedVerts,bandsComputed,exIndex,exVertices);
1343
        }
1344 8aceea06 leszek
      else
1345
        {
1346 08bf6b98 leszek
        float[][] verts = sInfo.outerVertices[0];
1347 8aceea06 leszek
        int lenVerts = verts.length;
1348 7e9a35eb leszek
        float[][] copiedVerts = new float[lenVerts][2];
1349
1350
        for(int v=0; v<lenVerts; v++)
1351
          {
1352
          float[] ve = verts[v];
1353
          copiedVerts[v][0] = ve[0];
1354
          copiedVerts[v][1] = ve[1];
1355
          }
1356
1357 8aceea06 leszek
        meshes[face] = new MeshPolygon(copiedVerts,bandsComputed,exIndex,exVertices, convexXY[0], convexXY[1]);
1358
        }
1359 fe3dec09 Leszek Koltunski
1360 0b5d4a7b Leszek Koltunski
      meshes[face].setEffectAssociation(0,0,face);
1361 29b82486 Leszek Koltunski
      }
1362
1363
    MeshBase mesh = new MeshJoined(meshes);
1364
    Static3D center = new Static3D(0,0,0);
1365
1366
    for(int face=0; face<numFaces; face++)
1367
      {
1368
      fInfo = mNewFaceTransf.get(face);
1369
1370 57ef6378 Leszek Koltunski
      float vx = fInfo.vx;
1371
      float vy = fInfo.vy;
1372
      float vz = fInfo.vz;
1373
      float sc = fInfo.scale;
1374
      float qx = fInfo.qx;
1375
      float qy = fInfo.qy;
1376
      float qz = fInfo.qz;
1377
      float qw = fInfo.qw;
1378 29b82486 Leszek Koltunski
1379 846b69f3 Leszek Koltunski
      Static3D scale = new Static3D(sc,sc,sc);
1380 29b82486 Leszek Koltunski
      Static3D move3D= new Static3D(vx,vy,vz);
1381
      Static4D quat  = new Static4D(qx,qy,qz,qw);
1382
1383 0b5d4a7b Leszek Koltunski
      mesh.apply(new MatrixEffectScale(scale)           ,0,face);
1384
      mesh.apply(new MatrixEffectQuaternion(quat,center),0,face);
1385
      mesh.apply(new MatrixEffectMove(move3D)           ,0,face);
1386 29b82486 Leszek Koltunski
      }
1387
1388 18d97487 Leszek Koltunski
    correctComponents(mesh,numComponents);
1389 1fda81c4 leszek
    if( effects!=null ) applyVertexEffects(mesh,effects);
1390 29b82486 Leszek Koltunski
1391
    return mesh;
1392
    }
1393
  }