Project

General

Profile

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

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

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.mesh.MeshBase;
19
import org.distorted.library.type.Static3D;
20
import org.distorted.objectlib.helpers.FactoryCubit;
21
import org.distorted.objectlib.helpers.ObjectFaceShape;
22
import org.distorted.objectlib.helpers.ObjectShape;
23
import org.distorted.objectlib.helpers.ObjectVertexEffects;
24

    
25
import java.util.ArrayList;
26
import java.util.Collections;
27
import java.util.Comparator;
28

    
29
///////////////////////////////////////////////////////////////////////////////////////////////////
30

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

    
37
    float[] vertices;
38
    float[] center;
39
    float[] normal;
40
    float centerCast;
41

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

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

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

    
62
      center[0] /= num;
63
      center[1] /= num;
64
      center[2] /= num;
65
      }
66

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

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

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

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

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

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

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

    
114
  private ArrayList<float[]> mTmpArray;
115
  private float[] mDist3D;
116
  private int[][] mFaceBelongsBitmap;
117
  private float[][] mCuts;
118
  private float[][] mRotAxis;
119
  private float[][] mDiaAxis;
120
  private float[][] mMinMax;
121

    
122
  BandagedElement[] mElements;
123
  ArrayList<float[][]> mVertexArray;
124

    
125
  int[][] mBandIndices;
126
  float[][][] mVertices;
127
  int[][][][] mIndices;
128
  float[][] mMove;
129
  int mNumElements;
130
  int mNumFaces;
131
  int mNumAxis;
132
  Static3D[] mNormals;
133

    
134
  int[] mNumLayers;
135

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

    
138
  FactoryBandaged()
139
    {
140

    
141
    }
142

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

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

    
156
///////////////////////////////////////////////////////////////////////////////////////////////////
157

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

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

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

    
171
      ret[i]=vertBelongsBitmap;
172
      }
173

    
174
    return ret;
175
    }
176

    
177
///////////////////////////////////////////////////////////////////////////////////////////////////
178
// (vertices,indices) define a single face of a set of connected elements.
179
// Return its 'diameter', i.e. the max distance (along any of its 'diameterAxis') between any two
180
// vertices of the face.
181

    
182
  private float faceDiameter(float[][] vertices, int[][] indices)
183
    {
184
    int num = mDiaAxis.length;
185

    
186
    for(int i=0; i<num; i++)
187
      {
188
      mMinMax[i][0] = Float.MAX_VALUE;
189
      mMinMax[i][1] =-Float.MAX_VALUE;
190
      }
191

    
192
    for (int[] ind : indices)
193
      for(int index : ind)
194
        {
195
        float[] v = vertices[index];
196

    
197
        for(int i=0; i<num; i++)
198
          {
199
          float[] mm = mMinMax[i];
200
          float[] ax = mDiaAxis[i];
201
          float dist = v[0]*ax[0] + v[1]*ax[1] + v[2]*ax[2];
202

    
203
          if ( dist > mm[1] ) mm[1] = dist;
204
          if ( dist < mm[0] ) mm[0] = dist;
205
          }
206
        }
207

    
208
    float maxDiff = 0;
209

    
210
    for(int i=0; i<num; i++)
211
      {
212
      float[] mm = mMinMax[i];
213
      float diff = mm[1]-mm[0];
214
      if( diff>maxDiff ) maxDiff = diff;
215
      }
216

    
217
    return maxDiff+0.01f; // this will be rounded down to nearest int; we don't want 1.9999 here
218
    }
219

    
220
///////////////////////////////////////////////////////////////////////////////////////////////////
221
// return array of:
222
// 0 if this is an inner face, 1 if its diameter is 1, 2 if diameter is 2, 3 if 3, etc
223
// but only up to 5 (because the number of bands is 6 - see createIrregularFaceShape() )
224

    
225
  int[] generateBandIndices(float[][] vertices, int[][][] indices, int[] belongs)
226
    {
227
    int numCubitFaces = indices.length;
228
    int[] bandIndices = new int[numCubitFaces];
229

    
230
    for(int f=0; f<numCubitFaces; f++)
231
      {
232
      bandIndices[f] = 0xffffffff;
233
      for( int index : indices[f][0] ) bandIndices[f] &= belongs[index];
234

    
235
      if( bandIndices[f]!=0 ) // outer face
236
        {
237
        float diameter = faceDiameter(vertices, indices[f]);
238
        bandIndices[f] = diameterMap(diameter);
239
        }
240
      }
241

    
242
    return bandIndices;
243
    }
244

    
245
///////////////////////////////////////////////////////////////////////////////////////////////////
246

    
247
  void computeMove(float[] pos, int variant)
248
    {
249
    int numMoves = pos.length/3;
250
    float[] m = mMove[variant];
251
    m[0]=0.0f;
252
    m[1]=0.0f;
253
    m[2]=0.0f;
254

    
255
    for(int i=0; i<numMoves; i++)
256
      {
257
      m[0] += pos[3*i  ];
258
      m[1] += pos[3*i+1];
259
      m[2] += pos[3*i+2];
260
      }
261

    
262
    m[0]/=numMoves;
263
    m[1]/=numMoves;
264
    m[2]/=numMoves;
265
    }
266

    
267
///////////////////////////////////////////////////////////////////////////////////////////////////
268

    
269
  float[][] getVertices(ArrayList<float[][]> list, int variant)
270
    {
271
    int total  = 0;
272
    int length = list.size();
273
    float[][][] vertices = new float[length][][];
274

    
275
    for( int i=0; i<length; i++ )
276
      {
277
      vertices[i] = list.get(i);
278
      int len = vertices[i].length;
279
      for(int j=0; j<len; j++) total += vertices[i][j].length/3;
280
      }
281

    
282
    float[][] verts = new float[total][3];
283
    int pointer = 0;
284

    
285
    for(int i=0; i<length; i++)
286
      {
287
      int len = vertices[i].length;
288

    
289
      for(int j=0; j<len; j++)
290
        {
291
        float[] v = vertices[i][j];
292
        int l = v.length/3;
293

    
294
        for(int k=0; k<l; k++)
295
          {
296
          verts[pointer][0] = v[3*k  ] - mMove[variant][0];
297
          verts[pointer][1] = v[3*k+1] - mMove[variant][1];
298
          verts[pointer][2] = v[3*k+2] - mMove[variant][2];
299
          pointer++;
300
          }
301
        }
302
      }
303

    
304
    return verts;
305
    }
306

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

    
309
  int[][][] getIndices(ArrayList<float[][]> list)
310
    {
311
    int indicesSoFar=0;
312
    int length = list.size();
313
    int[][][] indices = new int[length][][];
314

    
315
    for( int i=0; i<length; i++ )
316
      {
317
      float[][] face = list.get(i);
318
      int len = face.length;
319
      int[][] ind = new int[len][];
320

    
321
      for(int j=0; j<len; j++)
322
        {
323
        int l = face[j].length/3;
324
        ind[j] = new int[l];
325
        for(int k=0; k<l; k++) ind[j][k] = (indicesSoFar++);
326
        }
327

    
328
      indices[i] = ind;
329
      }
330

    
331
    return indices;
332
    }
333

    
334
///////////////////////////////////////////////////////////////////////////////////////////////////
335

    
336
  private void markAllVertices(float[] vertex, float[][] vertices, int[][][] indices, int pointer, int variant)
337
    {
338
    int numFaces = indices.length;
339

    
340
    for(int face=0; face<numFaces; face++)
341
      {
342
      int len = indices[face].length;
343

    
344
      for(int comp=0; comp<len; comp++)
345
        {
346
        int l = indices[face][comp].length;
347
        int[] in = mIndices[variant][face][comp];
348

    
349
        for(int v=0; v<l; v++)
350
          if( in[v]==-1 )
351
            {
352
            int ind=indices[face][comp][v];
353
            float[] ver=vertices[ind];
354
            if(vertex[0]==ver[0] && vertex[1]==ver[1] && vertex[2]==ver[2]) in[v]=pointer;
355
            }
356
        }
357
      }
358
    }
359

    
360
///////////////////////////////////////////////////////////////////////////////////////////////////
361
// So far the 'vertices/indices' are stored inefficiently, with each vertex stored three times
362
// (each one normally is a corner of three faces) or even six times. Compress!
363
// Example of six times: the central vertex here:
364
//
365
// { 1.0f,  0.0f, -1.0f,
366
//   1.0f, -1.0f, -1.0f,
367
//   1.0f, -1.0f, +0.0f,
368
//   0.0f, -1.0f, -1.0f },
369

    
370
  void compressVerticesAndIndices(int variant, float[][] vertices, int[][][] indices)
371
    {
372
    if( mTmpArray==null ) mTmpArray = new ArrayList<>();
373

    
374
    int numFaces = indices.length;
375
    int pointer=0;
376

    
377
    mIndices[variant] = new int[numFaces][][];
378

    
379
    for(int face=0; face<numFaces;face++)
380
      {
381
      int len = indices[face].length;
382
      mIndices[variant][face] = new int[len][];
383

    
384
      for(int comp=0; comp<len; comp++)
385
        {
386
        int l = indices[face][comp].length;
387
        mIndices[variant][face][comp] = new int[l];
388
        for(int v=0; v<l; v++) mIndices[variant][face][comp][v] = -1;
389
        }
390
      }
391

    
392
    for(int face=0; face<numFaces; face++)
393
      {
394
      int len = indices[face].length;
395

    
396
      for(int comp=0; comp<len; comp++)
397
        {
398
        int l = indices[face][comp].length;
399

    
400
        for(int v=0; v<l; v++)
401
          {
402
          if( mIndices[variant][face][comp][v]==-1 )
403
            {
404
            int ind=indices[face][comp][v];
405
            float[] ver=vertices[ind];
406
            mTmpArray.add(ver);
407
            markAllVertices(ver, vertices, indices, pointer, variant);
408
            pointer++;
409
            }
410
          }
411
        }
412
      }
413

    
414
    int len = mTmpArray.size();
415
    mVertices[variant] = new float[len][];
416

    
417
    for(int i=0; i<len; i++)
418
      {
419
      mVertices[variant][i] = mTmpArray.remove(0);
420
      }
421
    }
422

    
423
///////////////////////////////////////////////////////////////////////////////////////////////////
424

    
425
  static boolean vertInFace(float[] vertex, float[] move, Static3D faceAxis, float dist)
426
    {
427
    final float MAX_ERROR = 0.01f;
428

    
429
    float x= faceAxis.get0();
430
    float y= faceAxis.get1();
431
    float z= faceAxis.get2();
432

    
433
    float a = (vertex[0]+move[0])*x + (vertex[1]+move[1])*y + (vertex[2]+move[2])*z;
434
    float diff = a - dist;
435

    
436
    return diff>-MAX_ERROR && diff<MAX_ERROR;
437
    }
438

    
439
///////////////////////////////////////////////////////////////////////////////////////////////////
440

    
441
  private void computeVectorFace(float[] prev, float[] curr, float[] next, float[] output)
442
    {
443
    float ax = prev[0]-curr[0];
444
    float ay = prev[1]-curr[1];
445
    float az = prev[2]-curr[2];
446

    
447
    float bx = next[0]-curr[0];
448
    float by = next[1]-curr[1];
449
    float bz = next[2]-curr[2];
450

    
451
    float lena = (float)Math.sqrt(ax*ax + ay*ay + az*az);
452
    float lenb = (float)Math.sqrt(bx*bx + by*by + bz*bz);
453

    
454
    ax /= lena;
455
    ay /= lena;
456
    az /= lena;
457

    
458
    bx /= lenb;
459
    by /= lenb;
460
    bz /= lenb;
461

    
462
    output[0] = ay*bz - az*by;
463
    output[1] = az*bx - ax*bz;
464
    output[2] = ax*by - ay*bx;
465

    
466
    output[3] = ax;
467
    output[4] = ay;
468
    output[5] = az;
469

    
470
    output[6] = bx;
471
    output[7] = by;
472
    output[8] = bz;
473
    }
474

    
475
///////////////////////////////////////////////////////////////////////////////////////////////////
476
// 'concave' vertices do not get pushed!
477

    
478
  private boolean vertexIsConcave(float[][] vecs, int numVecs)
479
    {
480
    for(int i=0; i<numVecs; i++)
481
      {
482
      float[] v1 = vecs[i];
483

    
484
      for(int j=0; j<numVecs; j++)
485
        {
486
        if( i==j ) continue;
487

    
488
        float[] v2 = vecs[j];
489

    
490
        float scalar1 = v1[0]*v2[3] + v1[1]*v2[4] + v1[2]*v2[5];
491
        float scalar2 = v1[0]*v2[6] + v1[1]*v2[7] + v1[2]*v2[8];
492

    
493
        if( scalar1<0 || scalar2<0 ) return true;
494
        }
495
      }
496

    
497
    return false;
498
    }
499

    
500
///////////////////////////////////////////////////////////////////////////////////////////////////
501

    
502
  private float[] computeVector(int index, float[][] vertices, int[][][] indices, int[] bandIndices)
503
    {
504
    int band=0;
505
    int numFaces = indices.length;
506
    int numBordering = 0;
507
    float x=0, y=0, z=0;
508

    
509
    float[][] vecs = new float[numFaces][9];
510
    int vecIndex = 0;
511

    
512
    for(int f=0; f<numFaces; f++)
513
      {
514
      int numComponentsInFace = indices[f].length;
515

    
516
      for(int c=0; c<numComponentsInFace; c++)
517
        {
518
        int[] ind = indices[f][c];
519
        int numVertsInComponent = ind.length;
520

    
521
        for(int v=0; v<numVertsInComponent; v++)
522
          {
523
          if(ind[v]==index)
524
            {
525
            int prev=v>0 ? v-1 : numVertsInComponent-1;
526
            int next=v<numVertsInComponent-1 ? v+1 : 0;
527

    
528
            int prevIndex=ind[prev];
529
            int currIndex=ind[v];
530
            int nextIndex=ind[next];
531

    
532
            float[] vec = vecs[vecIndex++];
533
            computeVectorFace(vertices[prevIndex], vertices[currIndex], vertices[nextIndex], vec);
534
            band|=bandIndices[f];
535
            v = numVertsInComponent;
536
            c = numComponentsInFace;
537
            numBordering++;
538

    
539
            x += vec[0];
540
            y += vec[1];
541
            z += vec[2];
542
            }
543
          }
544
        }
545
      }
546

    
547
    boolean concave = vertexIsConcave(vecs,vecIndex);
548

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

    
552
///////////////////////////////////////////////////////////////////////////////////////////////////
553

    
554
  private float[][] generateVectors(float[][] vertices, int[][][] indices, int[] bandIndices)
555
    {
556
    int len = vertices.length;
557
    float[][] vectors = new float[len][];
558

    
559
    for(int i=0; i<len; i++)
560
      {
561
      vectors[i] = computeVector(i,vertices,indices,bandIndices);
562
      }
563

    
564
    return vectors;
565
    }
566

    
567
///////////////////////////////////////////////////////////////////////////////////////////////////
568

    
569
  private float[] buildFaceVertices(float[][] vertices, int[] indices, float[] pos)
570
    {
571
    int num = indices.length;
572
    float[] ret = new float[3*num];
573

    
574
    for(int i=0; i<num; i++)
575
      {
576
      float[] v = vertices[indices[i]];
577
      ret[3*i  ] = v[0] + pos[0];
578
      ret[3*i+1] = v[1] + pos[1];
579
      ret[3*i+2] = v[2] + pos[2];
580
      }
581

    
582
    return ret;
583
    }
584

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

    
587
  private void removeInternalWalls(ArrayList<BandagedCubitFace> list)
588
    {
589
    Collections.sort(list,new SortByCenterCast());
590

    
591
    int numElements = list.size();
592
    final float MAXDIFF = 0.01f;
593

    
594
    for(int e=0; e<numElements; e++)
595
      {
596
      int ne = e+1;
597
      BandagedCubitFace f1 = list.get(e);
598
      float[] center = f1.center;
599

    
600
      while( ne<numElements )
601
        {
602
        BandagedCubitFace f2 = list.get(ne);
603
        float diff = f2.centerCast-f1.centerCast;
604

    
605
        if( diff>-MAXDIFF && diff<MAXDIFF )
606
          {
607
          float[] c = f2.center;
608
          float dx = c[0]-center[0];
609
          float dy = c[1]-center[1];
610
          float dz = c[2]-center[2];
611

    
612
          float d = dx*dx + dy*dy + dz*dz;
613

    
614
          if( d>-MAXDIFF && d<MAXDIFF )
615
            {
616
            list.remove(ne);
617
            list.remove(e);
618
            numElements -= 2;
619
            e--;
620
            break;
621
            }
622
          }
623
        else break;
624

    
625
        ne++;
626
        }
627
      }
628
    }
629

    
630
///////////////////////////////////////////////////////////////////////////////////////////////////
631

    
632
  private float[][] getNextSection(ArrayList<BandagedCubitFace> list)
633
    {
634
    int numElements = list.size();
635
    if( numElements==0 ) return null;
636

    
637
    final float MAXDIFF = 0.01f;
638
    float[][] ret = new float[numElements][];
639
    BandagedCubitFace bcf = list.remove(0);
640
    float[] normal = bcf.normal;
641
    int removed = 1;
642

    
643
    ret[0] = bcf.vertices;
644

    
645
    for(int e=0; e<numElements-1; e++)
646
      {
647
      BandagedCubitFace f = list.get(e);
648
      float[] n = f.normal;
649

    
650
      float dx = n[0]-normal[0];
651
      float dy = n[1]-normal[1];
652
      float dz = n[2]-normal[2];
653

    
654
      float diff = dx*dx + dy*dy + dz*dz;
655

    
656
      if( diff>-MAXDIFF && diff<MAXDIFF )
657
        {
658
        list.remove(e);
659
        e--;
660
        numElements--;
661
        ret[removed++] = f.vertices;
662
        }
663
      }
664

    
665
    float[][] ret2 = new float[removed][];
666
    for(int i=0; i<removed; i++) ret2[i] = ret[i];
667

    
668
    return ret2;
669
    }
670

    
671
///////////////////////////////////////////////////////////////////////////////////////////////////
672

    
673
  private boolean isConnected(float[] face1, float[] face2)
674
    {
675
    float MAXDIFF = 0.01f;
676
    int l1 = face1.length/3;
677
    int l2 = face2.length/3;
678

    
679
    for(int i=0; i<l1; i++)
680
      {
681
      float x = face1[3*i  ];
682
      float y = face1[3*i+1];
683
      float z = face1[3*i+2];
684

    
685
      for(int j=0; j<l2; j++)
686
        {
687
        float dx = x-face2[3*j  ];
688
        float dy = y-face2[3*j+1];
689
        float dz = z-face2[3*j+2];
690

    
691
        if( dx*dx + dy*dy + dz*dz < MAXDIFF )
692
          {
693
          int inext = i==l1-1 ? 0 : i+1;
694
          int jprev = j==0 ? l2-1 : j-1;
695

    
696
          dx = face1[3*inext  ] - face2[3*jprev  ];
697
          dy = face1[3*inext+1] - face2[3*jprev+1];
698
          dz = face1[3*inext+2] - face2[3*jprev+2];
699

    
700
          if( dx*dx + dy*dy + dz*dz < MAXDIFF ) return true;
701

    
702
          int iprev = i==0 ? l1-1 : i-1;
703
          int jnext = j==l2-1 ? 0 : j+1;
704

    
705
          dx = face1[3*iprev  ] - face2[3*jnext  ];
706
          dy = face1[3*iprev+1] - face2[3*jnext+1];
707
          dz = face1[3*iprev+2] - face2[3*jnext+2];
708

    
709
          return dx*dx + dy*dy + dz*dz < MAXDIFF;
710
          }
711
        }
712
      }
713

    
714
    return false;
715
    }
716

    
717
///////////////////////////////////////////////////////////////////////////////////////////////////
718

    
719
  private float[][] getNextConnected(float[][] section, int nonNull)
720
    {
721
    float[][] ret = new float[nonNull][];
722
    int start,len = section.length;
723

    
724
    for(start=0; start<len; start++)
725
      if( section[start]!=null )
726
        {
727
        ret[0] = section[start];
728
        section[start] = null;
729
        break;
730
        }
731

    
732
    int firstUnverified = 0;
733
    int lastUnverified  = 0;
734
    start++;
735

    
736
    while( firstUnverified<=lastUnverified )
737
      {
738
      for(int i=start; i<len; i++)
739
        {
740
        if( section[i]!=null && isConnected(ret[firstUnverified],section[i]) )
741
          {
742
          lastUnverified++;
743
          ret[lastUnverified] = section[i];
744
          section[i] = null;
745
          }
746
        }
747
      firstUnverified++;
748
      }
749

    
750
    float[][] ret2 = new float[lastUnverified+1][];
751
    for(int i=0; i<=lastUnverified; i++) ret2[i] = ret[i];
752

    
753
    return ret2;
754
    }
755

    
756
///////////////////////////////////////////////////////////////////////////////////////////////////
757

    
758
  private void fillUpVertexArray()
759
    {
760
    ArrayList<BandagedCubitFace> list = new ArrayList<>();
761

    
762
    for(int e=0; e<mNumElements; e++)
763
      {
764
      int variant = mElements[e].getVariant();
765
      float[][] verts = getVertices(variant);
766
      int[][] inds = getIndices(variant);
767
      float[] pos = mElements[e].getPos();
768

    
769
      for( int[] ind : inds)
770
        {
771
        float[] vertices = buildFaceVertices(verts,ind,pos);
772
        BandagedCubitFace face = new BandagedCubitFace(vertices);
773
        list.add(face);
774
        }
775
      }
776

    
777
    removeInternalWalls(list);
778

    
779
    while(true)
780
      {
781
      float[][] section = getNextSection(list);
782

    
783
      if( section!=null )
784
        {
785
        int nonNull = section.length;
786

    
787
        while(nonNull>0)
788
          {
789
          float[][] connected = getNextConnected(section,nonNull);
790
          nonNull -= connected.length;
791
          mVertexArray.add(connected);
792
          }
793
        }
794
      else break;
795
      }
796
    }
797

    
798
///////////////////////////////////////////////////////////////////////////////////////////////////
799
// PUBLIC API
800

    
801
  public void prepare(int numVariants, int[] numLayers)
802
    {
803
    if( mVertexArray==null ) mVertexArray = new ArrayList<>();
804
    mVertices= new float[numVariants][][];
805
    mIndices = new int[numVariants][][][];
806
    mMove = new float[numVariants][3];
807
    mBandIndices = new int[numVariants][];
808
    mFaceBelongsBitmap= new int[numVariants][];
809

    
810
    mNumLayers = numLayers;
811
    mNormals   = getNormals();
812
    mNumFaces  = mNormals.length;
813
    mDist3D    = getDist3D();
814
    mCuts      = getCuts(numLayers);
815
    mRotAxis   = getRotAxis();
816
    mNumAxis   = mRotAxis.length;
817
    mDiaAxis   = getDiameterAxis();
818
    mMinMax    = new float[mDiaAxis.length][2];
819
    }
820

    
821
///////////////////////////////////////////////////////////////////////////////////////////////////
822

    
823
  public ObjectShape createIrregularShape(int variant, float[] pos)
824
    {
825
    mVertexArray.clear();
826

    
827
    mNumElements = pos.length/3;
828
    mElements = new BandagedElement[mNumElements];
829
    for(int i=0; i<mNumElements; i++)
830
      {
831
      int elementVariant = getElementVariant(pos[3*i],pos[3*i+1],pos[3*i+2]);
832
      mElements[i] = new BandagedElement(pos, 3*i, mRotAxis, mCuts,elementVariant);
833
      }
834

    
835
    fillUpVertexArray();
836

    
837
    computeMove(pos,variant);
838
    float[][] verts = getVertices(mVertexArray,variant);
839
    int[][][] inds  = getIndices(mVertexArray);
840

    
841
    compressVerticesAndIndices(variant,verts,inds);
842

    
843
    return new ObjectShape(mVertices[variant], mIndices[variant]);
844
    }
845

    
846
///////////////////////////////////////////////////////////////////////////////////////////////////
847

    
848
  public ObjectFaceShape createIrregularFaceShape(int variant, boolean iconMode)
849
    {
850
    float[][] bands = getBands(iconMode);
851

    
852
    if( mBandIndices[variant]==null )
853
      {
854
      mFaceBelongsBitmap[variant] = computeFaceBelongsBitmap(mVertices[variant], mMove[variant]);
855
      mBandIndices[variant] = generateBandIndices(mVertices[variant], mIndices[variant], mFaceBelongsBitmap[variant]);
856
      }
857

    
858
    return new ObjectFaceShape(bands,mBandIndices[variant],null);
859
    }
860

    
861
///////////////////////////////////////////////////////////////////////////////////////////////////
862

    
863
  public ObjectVertexEffects createVertexEffects(int variant, boolean roundCorners)
864
    {
865
    float[][] vertVec= generateVectors(mVertices[variant], mIndices[variant], mBandIndices[variant]);
866
    int numEffects   = mVertices[variant].length;
867
    float S          = STRENGTH;
868
    float[] region   = {0,0,0,REGION_SIZE};
869
    String[] names   = new String[numEffects];
870
    float[][] regions= new float[numEffects][];
871
    boolean[] uses   = new boolean[numEffects];
872
    float[][] vars   = new float[numEffects][];
873

    
874
    for(int i=0; i<numEffects; i++)
875
      {
876
      float[] v = vertVec[i];
877

    
878
      if( v!=null )
879
        {
880
        names[i]  = FactoryCubit.NAME;
881
        regions[i]= region;
882
        uses[i]   = roundCorners;
883
        vars[i]   = new float[] { 0, S*v[0], S*v[1], S*v[2], 1 };
884
        }
885
      }
886

    
887
    return new ObjectVertexEffects(names,vars,mVertices[variant],regions,uses);
888
    }
889

    
890
///////////////////////////////////////////////////////////////////////////////////////////////////
891

    
892
  public MeshBase createMesh(float[] pos, int[] numLayers, boolean iconMode, boolean roundCorners)
893
    {
894
    prepare(1,numLayers);
895
    ObjectShape shape           = createIrregularShape(0,pos);
896
    ObjectFaceShape face        = createIrregularFaceShape(0,iconMode);
897
    ObjectVertexEffects effects = createVertexEffects(0,roundCorners);
898
    int numFaces                = shape.getNumFaces();
899

    
900
    FactoryCubit factory = FactoryCubit.getInstance();
901
    factory.clear();
902
    factory.createNewFaceTransform(shape,null);
903
    return factory.createRoundedSolid(shape,face,effects,MESH_NICE,numFaces);
904
    }
905
  }
(7-7/11)