Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / helpers / FactoryBandagedCuboid.java @ 4a9f01f9

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 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.helpers;
11

    
12
import java.util.ArrayList;
13

    
14
import org.distorted.library.type.Static3D;
15
import org.distorted.objectlib.touchcontrol.TouchControlHexahedron;
16

    
17
///////////////////////////////////////////////////////////////////////////////////////////////////
18

    
19
public class FactoryBandagedCuboid extends FactoryBandaged
20
  {
21
  private static final int WALL_MARKED=0;
22
  private static final int WALL_EMPTY =-1;
23

    
24
  private static final int AXIS_XP = 0;
25
  private static final int AXIS_XM = 1;
26
  private static final int AXIS_YP = 2;
27
  private static final int AXIS_YM = 3;
28
  private static final int AXIS_ZP = 4;
29
  private static final int AXIS_ZM = 5;
30

    
31
  private static FactoryBandagedCuboid mThis;
32

    
33
  private int mMax;
34
  private int[][] mWall;
35

    
36
///////////////////////////////////////////////////////////////////////////////////////////////////
37

    
38
  private FactoryBandagedCuboid()
39
    {
40

    
41
    }
42

    
43
///////////////////////////////////////////////////////////////////////////////////////////////////
44

    
45
  private void displayWall(String tmp)
46
    {
47
    StringBuilder sb = new StringBuilder();
48

    
49
    for(int i=0; i<mMax; i++)
50
      {
51
      for(int j=0; j<mMax; j++)
52
        {
53
        sb.append(mWall[i][j]);
54
        sb.append(' ');
55
        }
56
      sb.append("  -  ");
57
      }
58

    
59
    android.util.Log.e("D", tmp+" : "+sb);
60
    }
61

    
62
///////////////////////////////////////////////////////////////////////////////////////////////////
63

    
64
  private void createRight(int x, ArrayList<float[][]> list)
65
    {
66
    for(int i=0; i<mMax; i++)
67
      for(int j=0; j<mMax; j++) mWall[i][j] = WALL_EMPTY;
68

    
69
    for(int i=0; i<mNumElements; i++)
70
      {
71
      int[] row = mElements[i].getRotRow();
72

    
73
      if( row[0]==x )
74
        {
75
        int y = mNumLayers[1]-1-row[2];
76
        int z = mNumLayers[2]-1-row[4];
77
        mWall[z][y] = elementExists(x+1,row[2],row[4]) ? WALL_EMPTY : WALL_MARKED;
78
        }
79
      }
80

    
81
    createVertices(list,mWall,AXIS_XP,x);
82
    }
83

    
84
///////////////////////////////////////////////////////////////////////////////////////////////////
85

    
86
  private void createLeft(int x, ArrayList<float[][]> list)
87
    {
88
    for(int i=0; i<mMax; i++)
89
      for(int j=0; j<mMax; j++) mWall[i][j] = WALL_EMPTY;
90

    
91
    for(int i=0; i<mNumElements; i++)
92
      {
93
      int[] row = mElements[i].getRotRow();
94

    
95
      if( row[0]==x )
96
        {
97
        int y = mNumLayers[1]-1-row[2];
98
        int z = row[4];
99
        mWall[z][y] = elementExists(x-1,row[2],row[4]) ? WALL_EMPTY : WALL_MARKED;
100
        }
101
      }
102

    
103
    createVertices(list,mWall,AXIS_XM,x);
104
    }
105

    
106
///////////////////////////////////////////////////////////////////////////////////////////////////
107

    
108
  private void createTop(int y, ArrayList<float[][]> list)
109
    {
110
    for(int i=0; i<mMax; i++)
111
      for(int j=0; j<mMax; j++) mWall[i][j] = WALL_EMPTY;
112

    
113
    for(int i=0; i< mNumElements; i++)
114
      {
115
      int[] row = mElements[i].getRotRow();
116

    
117
      if( row[2]==y )
118
        {
119
        int x = row[0];
120
        int z = row[4];
121
        mWall[x][z] = elementExists(row[0],y+1,row[4]) ? WALL_EMPTY : WALL_MARKED;
122
        }
123
      }
124

    
125
    createVertices(list,mWall,AXIS_YP,y);
126
    }
127

    
128
///////////////////////////////////////////////////////////////////////////////////////////////////
129

    
130
  private void createBottom(int y, ArrayList<float[][]> list)
131
    {
132
    for(int i=0; i<mMax; i++)
133
      for(int j=0; j<mMax; j++) mWall[i][j] = WALL_EMPTY;
134

    
135
    for(int i=0; i<mNumElements; i++)
136
      {
137
      int[] row = mElements[i].getRotRow();
138

    
139
      if( row[2]==y )
140
        {
141
        int x = row[0];
142
        int z = mNumLayers[2]-1-row[4];
143
        mWall[x][z] = elementExists(row[0],y-1,row[4]) ? WALL_EMPTY : WALL_MARKED;
144
        }
145
      }
146

    
147
    createVertices(list,mWall,AXIS_YM,y);
148
    }
149

    
150
///////////////////////////////////////////////////////////////////////////////////////////////////
151

    
152
  private void createFront(int z, ArrayList<float[][]> list)
153
    {
154
    for(int i=0; i<mMax; i++)
155
      for(int j=0; j<mMax; j++) mWall[i][j] = WALL_EMPTY;
156

    
157
    for(int i=0; i<mNumElements; i++)
158
      {
159
      int[] row = mElements[i].getRotRow();
160

    
161
      if( row[4]==z )
162
        {
163
        int x = row[0];
164
        int y = mNumLayers[1]-1-row[2];
165
        mWall[x][y] = elementExists(row[0],row[2],z+1) ? WALL_EMPTY : WALL_MARKED;
166
        }
167
      }
168

    
169
    createVertices(list,mWall,AXIS_ZP,z);
170
    }
171

    
172
///////////////////////////////////////////////////////////////////////////////////////////////////
173

    
174
  private void createBack(int z, ArrayList<float[][]> list)
175
    {
176
    for(int i=0; i<mMax; i++)
177
      for(int j=0; j<mMax; j++) mWall[i][j] = WALL_EMPTY;
178

    
179
    for(int i=0; i<mNumElements; i++)
180
      {
181
      int[] row = mElements[i].getRotRow();
182

    
183
      if( row[4]==z )
184
        {
185
        int x = mNumLayers[0]-1-row[0];
186
        int y = mNumLayers[1]-1-row[2];
187
        mWall[x][y] = elementExists(row[0],row[2],z-1) ? WALL_EMPTY : WALL_MARKED;
188
        }
189
      }
190

    
191
    createVertices(list,mWall,AXIS_ZM,z);
192
    }
193

    
194
///////////////////////////////////////////////////////////////////////////////////////////////////
195

    
196
  private void markNeighbours(int[][] wall, int x, int y, int section)
197
    {
198
    wall[x][y] = section;
199

    
200
    if( x  >   0 && wall[x-1][y]==WALL_MARKED ) markNeighbours(wall,x-1,y,section);
201
    if( x+1<mMax && wall[x+1][y]==WALL_MARKED ) markNeighbours(wall,x+1,y,section);
202
    if( y  >   0 && wall[x][y-1]==WALL_MARKED ) markNeighbours(wall,x,y-1,section);
203
    if( y+1<mMax && wall[x][y+1]==WALL_MARKED ) markNeighbours(wall,x,y+1,section);
204
    }
205

    
206
///////////////////////////////////////////////////////////////////////////////////////////////////
207

    
208
  private int markSections(int[][] wall)
209
    {
210
    int sections = 0;
211

    
212
    for(int x=0; x<mMax; x++)
213
      for(int y=0; y<mMax; y++)
214
        if( wall[x][y]==WALL_MARKED )
215
          {
216
          sections++;
217
          markNeighbours(wall,x,y,sections);
218
          }
219

    
220
    return sections;
221
    }
222

    
223
///////////////////////////////////////////////////////////////////////////////////////////////////
224

    
225
  private float[][] buildVertices(int[][] wall, int section, float dx, float dy)
226
    {
227
    int numMarked = howManyMarked(wall,section);
228
    float[][] vertices = new float[numMarked][];
229
    int curr=0;
230

    
231
    for(int x=0; x<mMax; x++)
232
      for(int y=0; y<mMax; y++)
233
        if( wall[x][y]==section )
234
          {
235
          vertices[curr] = new float[12];
236

    
237
          vertices[curr][ 0] = x-dx;
238
          vertices[curr][ 1] = dy-y;
239
          vertices[curr][ 2] = 0.0f;
240

    
241
          vertices[curr][ 3] = x-dx;
242
          vertices[curr][ 4] = dy-y-1;
243
          vertices[curr][ 5] = 0.0f;
244

    
245
          vertices[curr][ 6] = x-dx+1;
246
          vertices[curr][ 7] = dy-y-1;
247
          vertices[curr][ 8] = 0.0f;
248

    
249
          vertices[curr][ 9] = x-dx+1;
250
          vertices[curr][10] = dy-y;
251
          vertices[curr][11] = 0.0f;
252

    
253
          curr++;
254
          }
255

    
256
    return vertices;
257
    }
258

    
259
///////////////////////////////////////////////////////////////////////////////////////////////////
260

    
261
  private int howManyMarked(int[][] wall, int section)
262
    {
263
    int numMarked=0;
264

    
265
    for(int x=0; x<mMax; x++)
266
      for(int y=0; y<mMax; y++)
267
        if( wall[x][y]==section ) numMarked++;
268

    
269
    return numMarked;
270
    }
271

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

    
274
  private void rotateAndMoveVertices(float[][] vertices, int axis, int layer)
275
    {
276
    int i,len = vertices.length;
277

    
278
    switch(axis)
279
      {
280
      case AXIS_XP: for(i=0; i<len; i++)
281
                      {
282
                      int l = vertices[i].length/3;
283
                      float x = layer - mNumLayers[0]/2.0f + 1.0f;
284

    
285
                      for(int j=0; j<l; j++)
286
                        {
287
                        vertices[i][3*j+2] = -vertices[i][3*j];
288
                        vertices[i][3*j]   = x;
289
                        }
290
                      }
291
                    break;
292
      case AXIS_XM: for(i=0; i<len; i++)
293
                      {
294
                      int l = vertices[i].length/3;
295
                      float x = layer - mNumLayers[0]/2.0f;
296

    
297
                      for(int j=0; j<l; j++)
298
                        {
299
                        vertices[i][3*j+2] = vertices[i][3*j];
300
                        vertices[i][3*j]   = x;
301
                        }
302
                      }
303
                    break;
304
      case AXIS_YP: for(i=0; i<len; i++)
305
                      {
306
                      int l = vertices[i].length/3;
307
                      float y = layer - mNumLayers[1]/2.0f + 1.0f;
308

    
309
                      for(int j=0; j<l; j++)
310
                        {
311
                        vertices[i][3*j+2] = -vertices[i][3*j+1];
312
                        vertices[i][3*j+1] = y;
313
                        }
314
                      }
315
                    break;
316
      case AXIS_YM: for(i=0; i<len; i++)
317
                      {
318
                      int l = vertices[i].length/3;
319
                      float y = layer - mNumLayers[1]/2.0f;
320

    
321
                      for(int j=0; j<l; j++)
322
                        {
323
                        vertices[i][3*j+2] = vertices[i][3*j+1];
324
                        vertices[i][3*j+1] = y;
325
                        }
326
                      }
327
                    break;
328
      case AXIS_ZP: for(i=0; i<len; i++)
329
                      {
330
                      int l = vertices[i].length/3;
331
                      float z = layer - mNumLayers[2]/2.0f + 1.0f;
332

    
333
                      for(int j=0; j<l; j++)
334
                        {
335
                        vertices[i][3*j+2] = z;
336
                        }
337
                      }
338
                    break;
339
      case AXIS_ZM: for(i=0; i<len; i++)
340
                      {
341
                      int l = vertices[i].length/3;
342
                      float z = layer - mNumLayers[2]/2.0f;
343

    
344
                      for(int j=0; j<l; j++)
345
                        {
346
                        vertices[i][3*j+2] = z;
347
                        vertices[i][3*j]   = -vertices[i][3*j];
348
                        }
349
                      }
350
                    break;
351
      }
352
    }
353

    
354
///////////////////////////////////////////////////////////////////////////////////////////////////
355
// 1. assume the 'wall' is in the XY plane
356
// 2. split the wall into individual connected regions and for each such region:
357
//   a. build the list of vertices (Z=0)
358
//   b. take the axis into consideration and rotate the vertices.
359
//   c. take layer into consideration and move the vertices.
360
//   d. add the resulting vertices to the list.
361

    
362
  private void createVertices(ArrayList<float[][]> list, int[][] wall, int axis, int layer)
363
    {
364
    int sections = markSections(wall);
365

    
366
    float dx = (axis==AXIS_XP || axis==AXIS_XM) ? mNumLayers[2]/2.0f : mNumLayers[0]/2.0f;
367
    float dy = (axis==AXIS_YP || axis==AXIS_YM) ? mNumLayers[2]/2.0f : mNumLayers[1]/2.0f;
368

    
369
    for(int i=0; i<sections; i++)
370
      {
371
      float[][] vertices = buildVertices(wall,i+1,dx,dy);
372
      rotateAndMoveVertices(vertices,axis,layer);
373
      list.add(vertices);
374
      }
375
    }
376

    
377
///////////////////////////////////////////////////////////////////////////////////////////////////
378
// (vertices,indices) define a cubit face, i.e. a connected subset of the NxN grid.
379
// Return its 'diameter', i.e. max(width,height)
380

    
381
  public float faceDiameter(float[][] vertices, int[][] indices)
382
    {
383
    float maxX = -Float.MAX_VALUE;
384
    float minX =  Float.MAX_VALUE;
385
    float maxY = -Float.MAX_VALUE;
386
    float minY =  Float.MAX_VALUE;
387
    float maxZ = -Float.MAX_VALUE;
388
    float minZ =  Float.MAX_VALUE;
389

    
390
    for (int[] ind : indices)
391
      for(int index : ind)
392
        {
393
        float[] v = vertices[index];
394

    
395
        if (v[0] > maxX) maxX = v[0];
396
        if (v[0] < minX) minX = v[0];
397
        if (v[1] > maxY) maxY = v[1];
398
        if (v[1] < minY) minY = v[1];
399
        if (v[2] > maxZ) maxZ = v[2];
400
        if (v[2] < minZ) minZ = v[2];
401
        }
402

    
403
    float diffX = maxX-minX;
404
    float diffY = maxY-minY;
405
    float diffZ = maxZ-minZ;
406

    
407
    return diffX>diffY ? Math.max(diffX,diffZ) : Math.max(diffY,diffZ);
408
    }
409

    
410
///////////////////////////////////////////////////////////////////////////////////////////////////
411
// PUBLIC API
412

    
413
  public static FactoryBandagedCuboid getInstance()
414
    {
415
    if( mThis==null ) mThis = new FactoryBandagedCuboid();
416
    return mThis;
417
    }
418

    
419
///////////////////////////////////////////////////////////////////////////////////////////////////
420

    
421
  public float[][] getCuts(int[] numLayers)
422
    {
423
    int numFaces = 6;
424
    float[][] cuts = new float[numFaces][];
425

    
426
    for(int axis=0; axis<numFaces; axis++)
427
      {
428
      int len = numLayers[axis/2];
429
      float start = 1-len*0.5f;
430

    
431
      if( len>=2 )
432
        {
433
        cuts[axis] = new float[len-1];
434
        for(int i=0; i<len-1; i++) cuts[axis][i] = start+i;
435
        }
436
      }
437

    
438
    return cuts;
439
    }
440

    
441
///////////////////////////////////////////////////////////////////////////////////////////////////
442

    
443
  public Static3D[] getNormals()
444
    {
445
    return TouchControlHexahedron.FACE_AXIS;
446
    }
447

    
448
///////////////////////////////////////////////////////////////////////////////////////////////////
449

    
450
  public float[] getDist3D()
451
    {
452
    float dx = mNumLayers[0]/2.0f;
453
    float dy = mNumLayers[1]/2.0f;
454
    float dz = mNumLayers[2]/2.0f;
455

    
456
    return new float[] {dx,dx,dy,dy,dz,dz};
457
    }
458

    
459
///////////////////////////////////////////////////////////////////////////////////////////////////
460

    
461
  public void prepareSubclass(int numVariants, int[] numLayers)
462
    {
463
    int x = numLayers[0];
464
    int y = numLayers[1];
465
    int z = numLayers[2];
466

    
467
    mMax = x>y ? Math.max(x,z) : Math.max(y,z);
468
    mWall = new int[mMax][mMax];
469
    }
470

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

    
473
  public float[][] getBands(boolean iconMode)
474
    {
475
    float height= iconMode ? 0.001f : 0.048f;
476
    int[] angle = {60,50,40,32,28,23};
477
    float R     = 0.2f;
478
    float S     = 0.5f;
479
    int extraI  = 0;
480
    int extraV  = 0;
481

    
482
    int sum = mNumLayers[0]+mNumLayers[1]+mNumLayers[2];
483
    int numVertA= sum>=19 ? 3 : (sum>=16 ? 4:5);
484
    int numVertI= sum>=13 ? 2 : 3;
485

    
486
    return new float[][] { {  0.001f,angle[0],R,S,numVertI,extraV,extraI},
487
                           {height  ,angle[1],R,S,numVertA,extraV,extraI},
488
                           {height/2,angle[2],R,S,numVertA,extraV,extraI},
489
                           {height/3,angle[3],R,S,numVertA,extraV,extraI},
490
                           {height/4,angle[4],R,S,numVertA,extraV,extraI},
491
                           {height/5,angle[5],R,S,numVertA,extraV,extraI} };
492
    }
493

    
494
///////////////////////////////////////////////////////////////////////////////////////////////////
495

    
496
  public void fillUpVertexArray()
497
    {
498
    int numX = mNumLayers[0];
499
    int numY = mNumLayers[1];
500
    int numZ = mNumLayers[2];
501

    
502
    for(int x=0; x<numX; x++) createRight (x,mVertexArray);
503
    for(int x=0; x<numX; x++) createLeft  (x,mVertexArray);
504
    for(int y=0; y<numY; y++) createTop   (y,mVertexArray);
505
    for(int y=0; y<numY; y++) createBottom(y,mVertexArray);
506
    for(int z=0; z<numZ; z++) createFront (z,mVertexArray);
507
    for(int z=0; z<numZ; z++) createBack  (z,mVertexArray);
508
    }
509
  }
(4-4/17)