Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / bandaged / FactoryBandaged.java @ 60cc43cc

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2023 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// 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
///////////////////////////////////////////////////////////////////////////////////////////////////
9

    
10
package org.distorted.objectlib.bandaged;
11

    
12
import static org.distorted.objectlib.main.TwistyObject.MESH_NICE;
13
import static org.distorted.objectlib.main.TwistyObject.SQ2;
14
import static org.distorted.objectlib.main.TwistyObject.SQ5;
15
import static org.distorted.objectlib.objects.TwistyBandagedCuboid.REGION_SIZE;
16
import static org.distorted.objectlib.objects.TwistyBandagedCuboid.STRENGTH;
17

    
18
import org.distorted.library.helpers.QuatHelper;
19
import org.distorted.library.mesh.MeshBase;
20
import org.distorted.library.type.Static3D;
21
import org.distorted.library.type.Static4D;
22
import org.distorted.objectlib.helpers.FactoryCubit;
23
import org.distorted.objectlib.helpers.ObjectFaceShape;
24
import org.distorted.objectlib.helpers.ObjectShape;
25
import org.distorted.objectlib.helpers.ObjectVertexEffects;
26

    
27
import java.util.ArrayList;
28
import java.util.Collections;
29
import java.util.Comparator;
30

    
31
///////////////////////////////////////////////////////////////////////////////////////////////////
32

    
33
abstract public class FactoryBandaged
34
  {
35
  private static class BandagedCubitFace
36
    {
37
    private static final float[] sortVect = new float[] { 1/(2*SQ2), SQ2/(2*SQ2), SQ5/(2*SQ2) };
38

    
39
    float[] vertices;
40
    float[] center;
41
    float[] normal;
42
    float centerCast;
43

    
44
    BandagedCubitFace(float[] verts)
45
      {
46
      vertices = verts;
47
      computeCenter();
48
      computeNormal();
49
      computeCenterCast();
50
      }
51

    
52
    private void computeCenter()
53
      {
54
      int num = vertices.length/3;
55
      center = new float[3];
56

    
57
      for(int v=0; v<num; v++)
58
        {
59
        center[0] += vertices[3*v  ];
60
        center[1] += vertices[3*v+1];
61
        center[2] += vertices[3*v+2];
62
        }
63

    
64
      center[0] /= num;
65
      center[1] /= num;
66
      center[2] /= num;
67
      }
68

    
69
    private void computeNormal()
70
      {
71
      normal = new float[3];
72

    
73
      float x1 = vertices[0];
74
      float y1 = vertices[1];
75
      float z1 = vertices[2];
76
      float x2 = vertices[3];
77
      float y2 = vertices[4];
78
      float z2 = vertices[5];
79
      float x3 = vertices[6];
80
      float y3 = vertices[7];
81
      float z3 = vertices[8];
82

    
83
      float v1x = x2-x1;
84
      float v1y = y2-y1;
85
      float v1z = z2-z1;
86
      float v2x = x3-x1;
87
      float v2y = y3-y1;
88
      float v2z = z3-z1;
89

    
90
      normal[0] = v1y*v2z - v2y*v1z;
91
      normal[1] = v1z*v2x - v2z*v1x;
92
      normal[2] = v1x*v2y - v2x*v1y;
93

    
94
      double len = normal[0]*normal[0] + normal[1]*normal[1] + normal[2]*normal[2];
95
      len = Math.sqrt(len);
96
      normal[0] /= len;
97
      normal[1] /= len;
98
      normal[2] /= len;
99
      }
100

    
101
    private void computeCenterCast()
102
      {
103
      centerCast = center[0]*sortVect[0] + center[1]*sortVect[1] + center[2]*sortVect[2];
104
      }
105
    }
106

    
107
  static class SortByCenterCast implements Comparator<BandagedCubitFace>
108
    {
109
    public int compare(BandagedCubitFace a, BandagedCubitFace b)
110
      {
111
      float diff = a.centerCast - b.centerCast;
112
      return diff>0 ? 1: diff==0 ? 0: -1;
113
      }
114
    }
115

    
116
  public static Static4D QUAT = new Static4D(0,0,0,1);
117

    
118
  private ArrayList<float[]> mTmpArray;
119
  private ArrayList<float[][]> mVertexArray;
120
  private BandagedElement[] mElements;
121
  private Static3D[] mNormals;
122
  private float[] mDist3D;
123
  private int[][] mFaceBelongsBitmap;
124
  private float[][] mDiaAxis;
125
  private float[][] mMinMax;
126
  private int mNumFaces;
127
  private int mNumElements;
128
  private float[][] mMove;
129
  private int[][][][] mIndices;
130
  private float[][][] mVertices;
131
  private int[][] mBandIndices;
132
  private int[] mNumLayers;
133
  private float[] mTmp;
134
  private float[][][] mAllPositions;
135

    
136
///////////////////////////////////////////////////////////////////////////////////////////////////
137

    
138
  FactoryBandaged()
139
    {
140

    
141
    }
142

    
143
///////////////////////////////////////////////////////////////////////////////////////////////////
144

    
145
  abstract Static3D[] getNormals();
146
  abstract float[][][] getPositions(int[] numLayers);
147
  abstract Static4D getElementQuat(int[] numLayers, int cubitIndex);
148
  abstract float[][] getDiameterAxis();
149
  abstract float[] getDist3D(int[] numLayers);
150
  abstract float[][] getBands(boolean iconMode, int[] numLayers);
151
  abstract int getElementVariant(int[] numLayers, float x, float y, float z);
152
  abstract int diameterMap(float diameter);
153
  abstract float[][] getVertices(int[] numLayers, int variant);
154
  abstract int[][] getIndices(int[] numLayers, int variant);
155
  abstract int getNumVariants(int[] numLayers);
156

    
157
///////////////////////////////////////////////////////////////////////////////////////////////////
158

    
159
  private int[] computeFaceBelongsBitmap(float[][] vertices, float[] move)
160
    {
161
    int numVerts = vertices.length;
162
    int[] ret = new int[numVerts];
163

    
164
    for(int i=0; i<numVerts; i++)
165
      {
166
      int vertBelongsBitmap=0x00000000;
167
      float[] vert=vertices[i];
168

    
169
      for(int j=0; j<mNumFaces; j++)
170
        if( vertInFace(vert, move, mNormals[j], mDist3D[j]) ) vertBelongsBitmap |= (1<<j);
171

    
172
      ret[i]=vertBelongsBitmap;
173
      }
174

    
175
    return ret;
176
    }
177

    
178
///////////////////////////////////////////////////////////////////////////////////////////////////
179

    
180
  private int getCubitIndex(float[][][] allPositions, int variant, float x, float y, float z)
181
    {
182
    int total = 0;
183
    for(int v=0; v<variant; v++) total += allPositions[v].length;
184

    
185
    float[][] pos = allPositions[variant];
186
    float minerror = Float.MAX_VALUE;
187
    int addition = -1;
188
    int num = pos.length;
189

    
190
    for(int n=0; n<num; n++)
191
      {
192
      float[] point = pos[n];
193
      float dx = point[0]-x;
194
      float dy = point[1]-y;
195
      float dz = point[2]-z;
196

    
197
      float diff = dx*dx + dy*dy + dz*dz;
198

    
199
      if( diff<minerror )
200
        {
201
        addition = n;
202
        minerror = diff;
203
        }
204
      }
205

    
206
    return total + addition;
207
    }
208

    
209
///////////////////////////////////////////////////////////////////////////////////////////////////
210
// (vertices,indices) define a single face of a set of connected elements.
211
// Return its 'diameter', i.e. the max distance (along any of its 'diameterAxis') between any two
212
// vertices of the face.
213

    
214
  private float faceDiameter(float[][] vertices, int[][] indices)
215
    {
216
    int num = mDiaAxis.length;
217

    
218
    for(int i=0; i<num; i++)
219
      {
220
      mMinMax[i][0] = Float.MAX_VALUE;
221
      mMinMax[i][1] =-Float.MAX_VALUE;
222
      }
223

    
224
    for (int[] ind : indices)
225
      for(int index : ind)
226
        {
227
        float[] v = vertices[index];
228

    
229
        for(int i=0; i<num; i++)
230
          {
231
          float[] mm = mMinMax[i];
232
          float[] ax = mDiaAxis[i];
233
          float dist = v[0]*ax[0] + v[1]*ax[1] + v[2]*ax[2];
234

    
235
          if ( dist > mm[1] ) mm[1] = dist;
236
          if ( dist < mm[0] ) mm[0] = dist;
237
          }
238
        }
239

    
240
    float maxDiff = 0;
241

    
242
    for(int i=0; i<num; i++)
243
      {
244
      float[] mm = mMinMax[i];
245
      float diff = mm[1]-mm[0];
246
      if( diff>maxDiff ) maxDiff = diff;
247
      }
248

    
249
    return maxDiff+0.01f; // this will be rounded down to nearest int; we don't want 1.9999 here
250
    }
251

    
252
///////////////////////////////////////////////////////////////////////////////////////////////////
253
// return array of:
254
// 0 if this is an inner face, 1 if its diameter is 1, 2 if diameter is 2, 3 if 3, etc
255
// but only up to 5 (because the number of bands is 6 - see createIrregularFaceShape() )
256

    
257
  private int[] generateBandIndices(float[][] vertices, int[][][] indices, int[] belongs)
258
    {
259
    int numCubitFaces = indices.length;
260
    int[] bandIndices = new int[numCubitFaces];
261

    
262
    for(int f=0; f<numCubitFaces; f++)
263
      {
264
      bandIndices[f] = 0xffffffff;
265
      for( int index : indices[f][0] ) bandIndices[f] &= belongs[index];
266

    
267
      if( bandIndices[f]!=0 ) // outer face
268
        {
269
        float diameter = faceDiameter(vertices, indices[f]);
270
        bandIndices[f] = diameterMap(diameter);
271
        }
272
      }
273

    
274
    return bandIndices;
275
    }
276

    
277
///////////////////////////////////////////////////////////////////////////////////////////////////
278

    
279
  private void computeMove(float[] pos, int variant)
280
    {
281
    int numMoves = pos.length/3;
282
    float[] m = mMove[variant];
283
    m[0]=0.0f;
284
    m[1]=0.0f;
285
    m[2]=0.0f;
286

    
287
    for(int i=0; i<numMoves; i++)
288
      {
289
      m[0] += pos[3*i  ];
290
      m[1] += pos[3*i+1];
291
      m[2] += pos[3*i+2];
292
      }
293

    
294
    m[0]/=numMoves;
295
    m[1]/=numMoves;
296
    m[2]/=numMoves;
297
    }
298

    
299
///////////////////////////////////////////////////////////////////////////////////////////////////
300

    
301
  private float[][] getVertices(ArrayList<float[][]> list, int variant)
302
    {
303
    int total  = 0;
304
    int length = list.size();
305
    float[][][] vertices = new float[length][][];
306

    
307
    for( int i=0; i<length; i++ )
308
      {
309
      vertices[i] = list.get(i);
310
      int len = vertices[i].length;
311
      for(int j=0; j<len; j++) total += vertices[i][j].length/3;
312
      }
313

    
314
    float[][] verts = new float[total][3];
315
    int pointer = 0;
316

    
317
    for(int i=0; i<length; i++)
318
      {
319
      int len = vertices[i].length;
320

    
321
      for(int j=0; j<len; j++)
322
        {
323
        float[] v = vertices[i][j];
324
        int l = v.length/3;
325

    
326
        for(int k=0; k<l; k++)
327
          {
328
          verts[pointer][0] = v[3*k  ] - mMove[variant][0];
329
          verts[pointer][1] = v[3*k+1] - mMove[variant][1];
330
          verts[pointer][2] = v[3*k+2] - mMove[variant][2];
331
          pointer++;
332
          }
333
        }
334
      }
335

    
336
    return verts;
337
    }
338

    
339
///////////////////////////////////////////////////////////////////////////////////////////////////
340

    
341
  private int[][][] getIndices(ArrayList<float[][]> list)
342
    {
343
    int indicesSoFar=0;
344
    int length = list.size();
345
    int[][][] indices = new int[length][][];
346

    
347
    for( int i=0; i<length; i++ )
348
      {
349
      float[][] face = list.get(i);
350
      int len = face.length;
351
      int[][] ind = new int[len][];
352

    
353
      for(int j=0; j<len; j++)
354
        {
355
        int l = face[j].length/3;
356
        ind[j] = new int[l];
357
        for(int k=0; k<l; k++) ind[j][k] = (indicesSoFar++);
358
        }
359

    
360
      indices[i] = ind;
361
      }
362

    
363
    return indices;
364
    }
365

    
366
///////////////////////////////////////////////////////////////////////////////////////////////////
367

    
368
  private void markAllVertices(float[] vertex, float[][] vertices, int[][][] indices, int pointer, int variant)
369
    {
370
    int numFaces = indices.length;
371

    
372
    for(int face=0; face<numFaces; face++)
373
      {
374
      int len = indices[face].length;
375

    
376
      for(int comp=0; comp<len; comp++)
377
        {
378
        int l = indices[face][comp].length;
379
        int[] in = mIndices[variant][face][comp];
380

    
381
        for(int v=0; v<l; v++)
382
          if( in[v]==-1 )
383
            {
384
            int ind=indices[face][comp][v];
385
            float[] ver=vertices[ind];
386
            if(vertex[0]==ver[0] && vertex[1]==ver[1] && vertex[2]==ver[2]) in[v]=pointer;
387
            }
388
        }
389
      }
390
    }
391

    
392
///////////////////////////////////////////////////////////////////////////////////////////////////
393
// So far the 'vertices/indices' are stored inefficiently, with each vertex stored three times
394
// (each one normally is a corner of three faces) or even six times. Compress!
395
// Example of six times: the central vertex here:
396
//
397
// { 1.0f,  0.0f, -1.0f,
398
//   1.0f, -1.0f, -1.0f,
399
//   1.0f, -1.0f, +0.0f,
400
//   0.0f, -1.0f, -1.0f },
401

    
402
  private void compressVerticesAndIndices(int variant, float[][] vertices, int[][][] indices)
403
    {
404
    if( mTmpArray==null ) mTmpArray = new ArrayList<>();
405

    
406
    int numFaces = indices.length;
407
    int pointer=0;
408

    
409
    mIndices[variant] = new int[numFaces][][];
410

    
411
    for(int face=0; face<numFaces;face++)
412
      {
413
      int len = indices[face].length;
414
      mIndices[variant][face] = new int[len][];
415

    
416
      for(int comp=0; comp<len; comp++)
417
        {
418
        int l = indices[face][comp].length;
419
        mIndices[variant][face][comp] = new int[l];
420
        for(int v=0; v<l; v++) mIndices[variant][face][comp][v] = -1;
421
        }
422
      }
423

    
424
    for(int face=0; face<numFaces; face++)
425
      {
426
      int len = indices[face].length;
427

    
428
      for(int comp=0; comp<len; comp++)
429
        {
430
        int l = indices[face][comp].length;
431

    
432
        for(int v=0; v<l; v++)
433
          {
434
          if( mIndices[variant][face][comp][v]==-1 )
435
            {
436
            int ind=indices[face][comp][v];
437
            float[] ver=vertices[ind];
438
            mTmpArray.add(ver);
439
            markAllVertices(ver, vertices, indices, pointer, variant);
440
            pointer++;
441
            }
442
          }
443
        }
444
      }
445

    
446
    int len = mTmpArray.size();
447
    mVertices[variant] = new float[len][];
448

    
449
    for(int i=0; i<len; i++)
450
      {
451
      mVertices[variant][i] = mTmpArray.remove(0);
452
      }
453
    }
454

    
455
///////////////////////////////////////////////////////////////////////////////////////////////////
456

    
457
  static boolean vertInFace(float[] vertex, float[] move, Static3D faceAxis, float dist)
458
    {
459
    final float MAX_ERROR = 0.01f;
460

    
461
    float x= faceAxis.get0();
462
    float y= faceAxis.get1();
463
    float z= faceAxis.get2();
464

    
465
    float a = (vertex[0]+move[0])*x + (vertex[1]+move[1])*y + (vertex[2]+move[2])*z;
466
    float diff = a - dist;
467

    
468
    return diff>-MAX_ERROR && diff<MAX_ERROR;
469
    }
470

    
471
///////////////////////////////////////////////////////////////////////////////////////////////////
472

    
473
  private void computeVectorFace(float[] prev, float[] curr, float[] next, float[] output)
474
    {
475
    float ax = prev[0]-curr[0];
476
    float ay = prev[1]-curr[1];
477
    float az = prev[2]-curr[2];
478

    
479
    float bx = next[0]-curr[0];
480
    float by = next[1]-curr[1];
481
    float bz = next[2]-curr[2];
482

    
483
    float lena = (float)Math.sqrt(ax*ax + ay*ay + az*az);
484
    float lenb = (float)Math.sqrt(bx*bx + by*by + bz*bz);
485

    
486
    ax /= lena;
487
    ay /= lena;
488
    az /= lena;
489

    
490
    bx /= lenb;
491
    by /= lenb;
492
    bz /= lenb;
493

    
494
    output[0] = ay*bz - az*by;
495
    output[1] = az*bx - ax*bz;
496
    output[2] = ax*by - ay*bx;
497

    
498
    output[3] = ax;
499
    output[4] = ay;
500
    output[5] = az;
501

    
502
    output[6] = bx;
503
    output[7] = by;
504
    output[8] = bz;
505
    }
506

    
507
///////////////////////////////////////////////////////////////////////////////////////////////////
508
// 'concave' vertices do not get pushed!
509

    
510
  private boolean vertexIsConcave(float[][] vecs, int numVecs)
511
    {
512
    for(int i=0; i<numVecs; i++)
513
      {
514
      float[] v1 = vecs[i];
515

    
516
      for(int j=0; j<numVecs; j++)
517
        {
518
        if( i==j ) continue;
519

    
520
        float[] v2 = vecs[j];
521

    
522
        float scalar1 = v1[0]*v2[3] + v1[1]*v2[4] + v1[2]*v2[5];
523
        float scalar2 = v1[0]*v2[6] + v1[1]*v2[7] + v1[2]*v2[8];
524

    
525
        if( scalar1<0 || scalar2<0 ) return true;
526
        }
527
      }
528

    
529
    return false;
530
    }
531

    
532
///////////////////////////////////////////////////////////////////////////////////////////////////
533

    
534
  private float[] computeVector(int index, float[][] vertices, int[][][] indices, int[] bandIndices)
535
    {
536
    int band=0;
537
    int numFaces = indices.length;
538
    int numBordering = 0;
539
    float x=0, y=0, z=0;
540

    
541
    float[][] vecs = new float[numFaces][9];
542
    int vecIndex = 0;
543

    
544
    for(int f=0; f<numFaces; f++)
545
      {
546
      int numComponentsInFace = indices[f].length;
547

    
548
      for(int c=0; c<numComponentsInFace; c++)
549
        {
550
        int[] ind = indices[f][c];
551
        int numVertsInComponent = ind.length;
552

    
553
        for(int v=0; v<numVertsInComponent; v++)
554
          {
555
          if(ind[v]==index)
556
            {
557
            int prev=v>0 ? v-1 : numVertsInComponent-1;
558
            int next=v<numVertsInComponent-1 ? v+1 : 0;
559

    
560
            int prevIndex=ind[prev];
561
            int currIndex=ind[v];
562
            int nextIndex=ind[next];
563

    
564
            float[] vec = vecs[vecIndex++];
565
            computeVectorFace(vertices[prevIndex], vertices[currIndex], vertices[nextIndex], vec);
566
            band|=bandIndices[f];
567
            v = numVertsInComponent;
568
            c = numComponentsInFace;
569
            numBordering++;
570

    
571
            x += vec[0];
572
            y += vec[1];
573
            z += vec[2];
574
            }
575
          }
576
        }
577
      }
578

    
579
    boolean concave = vertexIsConcave(vecs,vecIndex);
580

    
581
    return ( concave || band==0 || numBordering<3 ) ? null : new float[] { x/numBordering, y/numBordering, z/numBordering};
582
    }
583

    
584
///////////////////////////////////////////////////////////////////////////////////////////////////
585

    
586
  private float[][] generateVectors(float[][] vertices, int[][][] indices, int[] bandIndices)
587
    {
588
    int len = vertices.length;
589
    float[][] vectors = new float[len][];
590

    
591
    for(int i=0; i<len; i++)
592
      {
593
      vectors[i] = computeVector(i,vertices,indices,bandIndices);
594
      }
595

    
596
    return vectors;
597
    }
598

    
599
///////////////////////////////////////////////////////////////////////////////////////////////////
600

    
601
  private float[] buildFaceVertices(float[][] vertices, int[] indices, float[] pos, Static4D quat)
602
    {
603
    int num = indices.length;
604
    float[] ret = new float[3*num];
605

    
606
    for(int i=0; i<num; i++)
607
      {
608
      float[] v = vertices[indices[i]];
609
      QuatHelper.rotateVectorByQuat(mTmp,v[0],v[1],v[2],1,quat);
610

    
611
      ret[3*i  ] = mTmp[0] + pos[0];
612
      ret[3*i+1] = mTmp[1] + pos[1];
613
      ret[3*i+2] = mTmp[2] + pos[2];
614
      }
615

    
616
    return ret;
617
    }
618

    
619
///////////////////////////////////////////////////////////////////////////////////////////////////
620

    
621
  private void removeInternalWalls(ArrayList<BandagedCubitFace> list)
622
    {
623
    Collections.sort(list,new SortByCenterCast());
624

    
625
    int numElements = list.size();
626
    final float MAXDIFF = 0.01f;
627

    
628
    for(int e=0; e<numElements; e++)
629
      {
630
      int ne = e+1;
631
      BandagedCubitFace f1 = list.get(e);
632
      float[] center = f1.center;
633

    
634
      while( ne<numElements )
635
        {
636
        BandagedCubitFace f2 = list.get(ne);
637
        float diff = f2.centerCast-f1.centerCast;
638

    
639
        if( diff>-MAXDIFF && diff<MAXDIFF )
640
          {
641
          float[] c = f2.center;
642
          float dx = c[0]-center[0];
643
          float dy = c[1]-center[1];
644
          float dz = c[2]-center[2];
645

    
646
          float d = dx*dx + dy*dy + dz*dz;
647

    
648
          if( d>-MAXDIFF && d<MAXDIFF )
649
            {
650
            list.remove(ne);
651
            list.remove(e);
652
            numElements -= 2;
653
            e--;
654
            break;
655
            }
656
          }
657
        else break;
658

    
659
        ne++;
660
        }
661
      }
662
    }
663

    
664
///////////////////////////////////////////////////////////////////////////////////////////////////
665

    
666
  private float[][] getNextSection(ArrayList<BandagedCubitFace> list)
667
    {
668
    int numElements = list.size();
669
    if( numElements==0 ) return null;
670

    
671
    final float MAXDIFF = 0.01f;
672
    float[][] ret = new float[numElements][];
673
    BandagedCubitFace bcf = list.remove(0);
674
    float[] normal = bcf.normal;
675
    int removed = 1;
676

    
677
    ret[0] = bcf.vertices;
678

    
679
    for(int e=0; e<numElements-1; e++)
680
      {
681
      BandagedCubitFace f = list.get(e);
682
      float[] n = f.normal;
683

    
684
      float dx = n[0]-normal[0];
685
      float dy = n[1]-normal[1];
686
      float dz = n[2]-normal[2];
687

    
688
      float diff = dx*dx + dy*dy + dz*dz;
689

    
690
      if( diff>-MAXDIFF && diff<MAXDIFF )
691
        {
692
        list.remove(e);
693
        e--;
694
        numElements--;
695
        ret[removed++] = f.vertices;
696
        }
697
      }
698

    
699
    float[][] ret2 = new float[removed][];
700
    for(int i=0; i<removed; i++) ret2[i] = ret[i];
701

    
702
    return ret2;
703
    }
704

    
705
///////////////////////////////////////////////////////////////////////////////////////////////////
706

    
707
  private boolean isConnected(float[] face1, float[] face2)
708
    {
709
    float MAXDIFF = 0.01f;
710
    int l1 = face1.length/3;
711
    int l2 = face2.length/3;
712

    
713
    for(int i=0; i<l1; i++)
714
      {
715
      float x = face1[3*i  ];
716
      float y = face1[3*i+1];
717
      float z = face1[3*i+2];
718

    
719
      for(int j=0; j<l2; j++)
720
        {
721
        float dx = x-face2[3*j  ];
722
        float dy = y-face2[3*j+1];
723
        float dz = z-face2[3*j+2];
724

    
725
        if( dx*dx + dy*dy + dz*dz < MAXDIFF )
726
          {
727
          int inext = i==l1-1 ? 0 : i+1;
728
          int jprev = j==0 ? l2-1 : j-1;
729

    
730
          dx = face1[3*inext  ] - face2[3*jprev  ];
731
          dy = face1[3*inext+1] - face2[3*jprev+1];
732
          dz = face1[3*inext+2] - face2[3*jprev+2];
733

    
734
          if( dx*dx + dy*dy + dz*dz < MAXDIFF ) return true;
735

    
736
          int iprev = i==0 ? l1-1 : i-1;
737
          int jnext = j==l2-1 ? 0 : j+1;
738

    
739
          dx = face1[3*iprev  ] - face2[3*jnext  ];
740
          dy = face1[3*iprev+1] - face2[3*jnext+1];
741
          dz = face1[3*iprev+2] - face2[3*jnext+2];
742

    
743
          return dx*dx + dy*dy + dz*dz < MAXDIFF;
744
          }
745
        }
746
      }
747

    
748
    return false;
749
    }
750

    
751
///////////////////////////////////////////////////////////////////////////////////////////////////
752

    
753
  private float[][] getNextConnected(float[][] section, int nonNull)
754
    {
755
    float[][] ret = new float[nonNull][];
756
    int start,len = section.length;
757

    
758
    for(start=0; start<len; start++)
759
      if( section[start]!=null )
760
        {
761
        ret[0] = section[start];
762
        section[start] = null;
763
        break;
764
        }
765

    
766
    int firstUnverified = 0;
767
    int lastUnverified  = 0;
768
    start++;
769

    
770
    while( firstUnverified<=lastUnverified )
771
      {
772
      for(int i=start; i<len; i++)
773
        {
774
        if( section[i]!=null && isConnected(ret[firstUnverified],section[i]) )
775
          {
776
          lastUnverified++;
777
          ret[lastUnverified] = section[i];
778
          section[i] = null;
779
          }
780
        }
781
      firstUnverified++;
782
      }
783

    
784
    float[][] ret2 = new float[lastUnverified+1][];
785
    for(int i=0; i<=lastUnverified; i++) ret2[i] = ret[i];
786

    
787
    return ret2;
788
    }
789

    
790
///////////////////////////////////////////////////////////////////////////////////////////////////
791

    
792
  private void fillUpVertexArray()
793
    {
794
    ArrayList<BandagedCubitFace> list = new ArrayList<>();
795
    mTmp = new float[4];
796

    
797
    int numVariants = getNumVariants(mNumLayers);
798

    
799
    float[][][] verts = new float[numVariants][][];
800
    int[][][] inds    = new int[numVariants][][];
801

    
802
    for(int v=0; v<numVariants; v++)
803
      {
804
      verts[v] = getVertices(mNumLayers,v);
805
      inds[v]  = getIndices(mNumLayers,v);
806
      }
807

    
808
    for(int e=0; e<mNumElements; e++)
809
      {
810
      BandagedElement element = mElements[e];
811
      int variant = element.getVariant();
812
      float[] pos = element.getPos();
813
      Static4D quat = element.getQuat();
814

    
815
      for( int[] ind : inds[variant])
816
        {
817
        float[] vertices = buildFaceVertices(verts[variant],ind,pos,quat);
818
        BandagedCubitFace face = new BandagedCubitFace(vertices);
819
        list.add(face);
820
        }
821
      }
822

    
823
    removeInternalWalls(list);
824

    
825
    while(true)
826
      {
827
      float[][] section = getNextSection(list);
828

    
829
      if( section!=null )
830
        {
831
        int nonNull = section.length;
832

    
833
        while(nonNull>0)
834
          {
835
          float[][] connected = getNextConnected(section,nonNull);
836
          nonNull -= connected.length;
837
          mVertexArray.add(connected);
838
          }
839
        }
840
      else break;
841
      }
842
    }
843

    
844
///////////////////////////////////////////////////////////////////////////////////////////////////
845

    
846
  private boolean layersHaveChanged(int[] numLayers)
847
    {
848
    if( mNumLayers==null ) return true;
849

    
850
    int len = mNumLayers.length;
851

    
852
    for(int i=0; i<len; i++)
853
      if(mNumLayers[i]!=numLayers[i]) return true;
854

    
855
    return false;
856
    }
857

    
858
///////////////////////////////////////////////////////////////////////////////////////////////////
859
// PUBLIC API
860

    
861
  public void prepare(int numVariants, int[] numLayers)
862
    {
863
    if( mVertexArray==null ) mVertexArray = new ArrayList<>();
864
    mVertices= new float[numVariants][][];
865
    mIndices = new int[numVariants][][][];
866
    mMove = new float[numVariants][3];
867
    mBandIndices = new int[numVariants][];
868
    mFaceBelongsBitmap= new int[numVariants][];
869

    
870
    if( layersHaveChanged(numLayers) )
871
      {
872
      mAllPositions = getPositions(numLayers);
873
      }
874

    
875
    int num = numLayers.length;
876
    mNumLayers = new int[num];
877
    for(int l=0; l<num; l++) mNumLayers[l] = numLayers[l];
878

    
879
    mNormals   = getNormals();
880
    mNumFaces  = mNormals.length;
881
    mDist3D    = getDist3D(mNumLayers);
882
    mDiaAxis   = getDiameterAxis();
883
    mMinMax    = new float[mDiaAxis.length][2];
884
    }
885

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

    
888
  public Static4D getCubitQuat(float x, float y, float z)
889
    {
890
    int elementVariant = getElementVariant(mNumLayers, x,y,z);
891
    int cubitIndex = getCubitIndex(mAllPositions,elementVariant, x,y,z);
892
    return getElementQuat(mNumLayers, cubitIndex);
893
    }
894

    
895
///////////////////////////////////////////////////////////////////////////////////////////////////
896

    
897
  public ObjectShape createIrregularShape(int variant, float[] pos)
898
    {
899
    mVertexArray.clear();
900

    
901
    mNumElements = pos.length/3;
902
    mElements = new BandagedElement[mNumElements];
903

    
904
    for(int e=0; e<mNumElements; e++)
905
      {
906
      float x= pos[3*e  ];
907
      float y= pos[3*e+1];
908
      float z= pos[3*e+2];
909
      int elementVariant = getElementVariant(mNumLayers, x,y,z);
910
      int cubitIndex = getCubitIndex(mAllPositions,elementVariant, x,y,z);
911
      Static4D quat = getElementQuat(mNumLayers, cubitIndex);
912
      mElements[e] = new BandagedElement(pos, 3*e, elementVariant, quat);
913
      }
914

    
915
    fillUpVertexArray();
916

    
917
    computeMove(pos,variant);
918
    float[][] verts = getVertices(mVertexArray,variant);
919
    int[][][] inds  = getIndices(mVertexArray);
920

    
921
    compressVerticesAndIndices(variant,verts,inds);
922

    
923
    return new ObjectShape(mVertices[variant], mIndices[variant]);
924
    }
925

    
926
///////////////////////////////////////////////////////////////////////////////////////////////////
927

    
928
  public ObjectFaceShape createIrregularFaceShape(int variant, boolean iconMode)
929
    {
930
    float[][] bands = getBands(iconMode, mNumLayers);
931

    
932
    if( mBandIndices[variant]==null )
933
      {
934
      mFaceBelongsBitmap[variant] = computeFaceBelongsBitmap(mVertices[variant], mMove[variant]);
935
      mBandIndices[variant] = generateBandIndices(mVertices[variant], mIndices[variant], mFaceBelongsBitmap[variant]);
936
      }
937

    
938
    return new ObjectFaceShape(bands,mBandIndices[variant],null);
939
    }
940

    
941
///////////////////////////////////////////////////////////////////////////////////////////////////
942

    
943
  public ObjectVertexEffects createVertexEffects(int variant, boolean roundCorners)
944
    {
945
    float[][] vertVec= generateVectors(mVertices[variant], mIndices[variant], mBandIndices[variant]);
946
    int numEffects   = mVertices[variant].length;
947
    float S          = STRENGTH;
948
    float[] region   = {0,0,0,REGION_SIZE};
949
    String[] names   = new String[numEffects];
950
    float[][] regions= new float[numEffects][];
951
    boolean[] uses   = new boolean[numEffects];
952
    float[][] vars   = new float[numEffects][];
953

    
954
    for(int i=0; i<numEffects; i++)
955
      {
956
      float[] v = vertVec[i];
957

    
958
      if( v!=null )
959
        {
960
        names[i]  = FactoryCubit.NAME;
961
        regions[i]= region;
962
        uses[i]   = roundCorners;
963
        vars[i]   = new float[] { 0, S*v[0], S*v[1], S*v[2], 1 };
964
        }
965
      }
966

    
967
    return new ObjectVertexEffects(names,vars,mVertices[variant],regions,uses);
968
    }
969

    
970
///////////////////////////////////////////////////////////////////////////////////////////////////
971

    
972
  public MeshBase createMesh(float[] pos, int[] numLayers, boolean iconMode, boolean roundCorners)
973
    {
974
    prepare(1,numLayers);
975
    ObjectShape shape           = createIrregularShape(0,pos);
976
    ObjectFaceShape face        = createIrregularFaceShape(0,iconMode);
977
    ObjectVertexEffects effects = createVertexEffects(0,roundCorners);
978
    int numFaces                = shape.getNumFaces();
979

    
980
    FactoryCubit factory = FactoryCubit.getInstance();
981
    factory.clear();
982
    factory.createNewFaceTransform(shape,null);
983
    return factory.createRoundedSolid(shape,face,effects,MESH_NICE,numFaces);
984
    }
985
  }
(7-7/11)