Project

General

Profile

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

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

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

    
135
///////////////////////////////////////////////////////////////////////////////////////////////////
136

    
137
  FactoryBandaged()
138
    {
139

    
140
    }
141

    
142
///////////////////////////////////////////////////////////////////////////////////////////////////
143

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

    
154
///////////////////////////////////////////////////////////////////////////////////////////////////
155

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

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

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

    
169
      ret[i]=vertBelongsBitmap;
170
      }
171

    
172
    return ret;
173
    }
174

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

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

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

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

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

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

    
206
    float maxDiff = 0;
207

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

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

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

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

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

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

    
240
    return bandIndices;
241
    }
242

    
243
///////////////////////////////////////////////////////////////////////////////////////////////////
244

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

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

    
260
    m[0]/=numMoves;
261
    m[1]/=numMoves;
262
    m[2]/=numMoves;
263
    }
264

    
265
///////////////////////////////////////////////////////////////////////////////////////////////////
266

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

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

    
280
    float[][] verts = new float[total][3];
281
    int pointer = 0;
282

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

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

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

    
302
    return verts;
303
    }
304

    
305
///////////////////////////////////////////////////////////////////////////////////////////////////
306

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

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

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

    
326
      indices[i] = ind;
327
      }
328

    
329
    return indices;
330
    }
331

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

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

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

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

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

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

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

    
372
    int numFaces = indices.length;
373
    int pointer=0;
374

    
375
    mIndices[variant] = new int[numFaces][][];
376

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

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

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

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

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

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

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

    
421
///////////////////////////////////////////////////////////////////////////////////////////////////
422

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

    
427
    float x= faceAxis.get0();
428
    float y= faceAxis.get1();
429
    float z= faceAxis.get2();
430

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

    
434
    return diff>-MAX_ERROR && diff<MAX_ERROR;
435
    }
436

    
437
///////////////////////////////////////////////////////////////////////////////////////////////////
438

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

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

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

    
452
    ax /= lena;
453
    ay /= lena;
454
    az /= lena;
455

    
456
    bx /= lenb;
457
    by /= lenb;
458
    bz /= lenb;
459

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

    
464
    output[3] = ax;
465
    output[4] = ay;
466
    output[5] = az;
467

    
468
    output[6] = bx;
469
    output[7] = by;
470
    output[8] = bz;
471
    }
472

    
473
///////////////////////////////////////////////////////////////////////////////////////////////////
474
// 'concave' vertices do not get pushed!
475

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

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

    
486
        float[] v2 = vecs[j];
487

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

    
491
        if( scalar1<0 || scalar2<0 ) return true;
492
        }
493
      }
494

    
495
    return false;
496
    }
497

    
498
///////////////////////////////////////////////////////////////////////////////////////////////////
499

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

    
507
    float[][] vecs = new float[numFaces][9];
508
    int vecIndex = 0;
509

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

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

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

    
526
            int prevIndex=ind[prev];
527
            int currIndex=ind[v];
528
            int nextIndex=ind[next];
529

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

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

    
545
    boolean concave = vertexIsConcave(vecs,vecIndex);
546

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

    
550
///////////////////////////////////////////////////////////////////////////////////////////////////
551

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

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

    
562
    return vectors;
563
    }
564

    
565
///////////////////////////////////////////////////////////////////////////////////////////////////
566

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

    
572
    for(int i=0; i<num; i++)
573
      {
574
      float[] v = vertices[indices[i]];
575
      QuatHelper.rotateVectorByQuat(mTmp,v[0],v[1],v[2],1,quat);
576

    
577
      ret[3*i  ] = mTmp[0] + pos[0];
578
      ret[3*i+1] = mTmp[1] + pos[1];
579
      ret[3*i+2] = mTmp[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
    mTmp = new float[4];
762

    
763
    for(int e=0; e<mNumElements; e++)
764
      {
765
      BandagedElement element = mElements[e];
766
      int variant = element.getVariant();
767
      float[] pos = element.getPos();
768
      Static4D quat = element.getQuat();
769

    
770
      float[][] verts = getVertices(mNumLayers,variant);
771
      int[][] inds = getIndices(mNumLayers,variant);
772

    
773
      for( int[] ind : inds)
774
        {
775
        float[] vertices = buildFaceVertices(verts,ind,pos,quat);
776
        BandagedCubitFace face = new BandagedCubitFace(vertices);
777
        list.add(face);
778
        }
779
      }
780

    
781
    removeInternalWalls(list);
782

    
783
    while(true)
784
      {
785
      float[][] section = getNextSection(list);
786

    
787
      if( section!=null )
788
        {
789
        int nonNull = section.length;
790

    
791
        while(nonNull>0)
792
          {
793
          float[][] connected = getNextConnected(section,nonNull);
794
          nonNull -= connected.length;
795
          mVertexArray.add(connected);
796
          }
797
        }
798
      else break;
799
      }
800
    }
801

    
802
///////////////////////////////////////////////////////////////////////////////////////////////////
803
// PUBLIC API
804

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

    
814
    mNumLayers = numLayers;
815
    mNormals   = getNormals();
816
    mNumFaces  = mNormals.length;
817
    mDist3D    = getDist3D(mNumLayers);
818
    mDiaAxis   = getDiameterAxis();
819
    mMinMax    = new float[mDiaAxis.length][2];
820
    }
821

    
822
///////////////////////////////////////////////////////////////////////////////////////////////////
823

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

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

    
837
    fillUpVertexArray();
838

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

    
843
    compressVerticesAndIndices(variant,verts,inds);
844

    
845
    return new ObjectShape(mVertices[variant], mIndices[variant]);
846
    }
847

    
848
///////////////////////////////////////////////////////////////////////////////////////////////////
849

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

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

    
860
    return new ObjectFaceShape(bands,mBandIndices[variant],null);
861
    }
862

    
863
///////////////////////////////////////////////////////////////////////////////////////////////////
864

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

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

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

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

    
892
///////////////////////////////////////////////////////////////////////////////////////////////////
893

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

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