Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / helpers / FactoryBandagedCubit.java @ 630cf5ce

1 a7c10d03 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is free software: you can redistribute it and/or modify                            //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Magic Cube is distributed in the hope that it will be useful,                                 //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19
20
package org.distorted.objectlib.helpers;
21
22
import java.util.ArrayList;
23
24 12aa6192 Leszek Koltunski
import org.distorted.library.mesh.MeshBase;
25 786098dd Leszek Koltunski
import org.distorted.library.type.Static3D;
26
import org.distorted.objectlib.touchcontrol.TouchControlHexahedron;
27
28 12aa6192 Leszek Koltunski
import static org.distorted.objectlib.main.TwistyObject.MESH_NICE;
29
30 786098dd Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
31
32 b1f0d55d Leszek Koltunski
public class FactoryBandagedCubit
33 a7c10d03 Leszek Koltunski
  {
34
  private static final int WALL_MARKED=0;
35
  private static final int WALL_EMPTY =-1;
36
37
  private static final int AXIS_XP = 0;
38
  private static final int AXIS_XM = 1;
39
  private static final int AXIS_YP = 2;
40
  private static final int AXIS_YM = 3;
41
  private static final int AXIS_ZP = 4;
42
  private static final int AXIS_ZM = 5;
43
44 5987822f Leszek Koltunski
  private static final float[][] VECTOR =
45
      {
46
          {-1.0f,-1.0f,-1.0f},
47
          {-1.0f,-1.0f,+1.0f},
48
          {-1.0f,+1.0f,-1.0f},
49
          {-1.0f,+1.0f,+1.0f},
50
          {+1.0f,-1.0f,-1.0f},
51
          {+1.0f,-1.0f,+1.0f},
52
          {+1.0f,+1.0f,-1.0f},
53
          {+1.0f,+1.0f,+1.0f}
54
      };
55
56 b1f0d55d Leszek Koltunski
  private static FactoryBandagedCubit mThis;
57 a7c10d03 Leszek Koltunski
  private ArrayList<float[]> mVertexArray;
58 b442e28c Leszek Koltunski
  private ArrayList<float[]> mTmpArray;
59 a7c10d03 Leszek Koltunski
  private float[][][] mVertices;
60
  private int[][][] mIndices;
61 29ad5fc9 Leszek Koltunski
  private float[][] mMove;
62 b1f0d55d Leszek Koltunski
63
  private int mX, mY, mZ, mMax;
64
  private float dX, dY, dZ;
65
  private int[][] mWall;
66
  private int[][] mPoints;
67
  private boolean[][][] mTmp;
68 a7c10d03 Leszek Koltunski
69
///////////////////////////////////////////////////////////////////////////////////////////////////
70
71 b1f0d55d Leszek Koltunski
  private FactoryBandagedCubit()
72 a7c10d03 Leszek Koltunski
    {
73 b1f0d55d Leszek Koltunski
74 a7c10d03 Leszek Koltunski
    }
75
76
///////////////////////////////////////////////////////////////////////////////////////////////////
77
78 29ad5fc9 Leszek Koltunski
  private float[][] getVertices(ArrayList<float[]> list, float[] move, int variant)
79 a7c10d03 Leszek Koltunski
    {
80 b8b71f52 Leszek Koltunski
    int numMoves = move.length/3;
81 29ad5fc9 Leszek Koltunski
    mMove[variant][0]=0.0f;
82
    mMove[variant][1]=0.0f;
83
    mMove[variant][2]=0.0f;
84 b8b71f52 Leszek Koltunski
85
    for(int m=0; m<numMoves; m++)
86
      {
87 29ad5fc9 Leszek Koltunski
      mMove[variant][0] += move[3*m  ];
88
      mMove[variant][1] += move[3*m+1];
89
      mMove[variant][2] += move[3*m+2];
90 b8b71f52 Leszek Koltunski
      }
91
92 29ad5fc9 Leszek Koltunski
    mMove[variant][0]/=numMoves;
93
    mMove[variant][1]/=numMoves;
94
    mMove[variant][2]/=numMoves;
95 b8b71f52 Leszek Koltunski
96
    int total  = 0;
97 a7c10d03 Leszek Koltunski
    int length = list.size();
98
    float[][] vertices = new float[length][];
99 b8b71f52 Leszek Koltunski
100
    for( int i=0; i<length; i++ )
101
      {
102
      vertices[i] = list.get(i);
103
      total += vertices[i].length/3;
104
      }
105
106
    float[][] verts = new float[total][3];
107
    int pointer = 0;
108
109
    for(int i=0; i<length; i++)
110
      {
111
      int len = vertices[i].length/3;
112
113
      for(int j=0; j<len; j++)
114
        {
115 29ad5fc9 Leszek Koltunski
        verts[pointer][0] = vertices[i][3*j  ] - mMove[variant][0];
116
        verts[pointer][1] = vertices[i][3*j+1] - mMove[variant][1];
117
        verts[pointer][2] = vertices[i][3*j+2] - mMove[variant][2];
118 b8b71f52 Leszek Koltunski
        pointer++;
119
        }
120
      }
121
122
    return verts;
123 a7c10d03 Leszek Koltunski
    }
124
125
///////////////////////////////////////////////////////////////////////////////////////////////////
126
127
  private int[][] getIndices(ArrayList<float[]> list)
128
    {
129
    int indicesSoFar=0;
130
    int length = list.size();
131
    int[][] indices = new int[length][];
132
133
    for( int i=0; i<length; i++ )
134
      {
135
      float[] f = list.get(i);
136 b8b71f52 Leszek Koltunski
      int len = f.length/3;
137 a7c10d03 Leszek Koltunski
      int[] ind = new int[len];
138
      for(int j=0; j<len; j++) ind[j] = (indicesSoFar++);
139
      indices[i] = ind;
140
      }
141
142
    return indices;
143
    }
144
145 b442e28c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
146
147
  private void markAllVertices(float[] vertex, float[][] vertices, int[][] indices, int pointer, int variant)
148
    {
149
    int lenI = indices.length;
150
151
    for(int index=0; index<lenI; index++)
152
      {
153
      int len = indices[index].length;
154
155
      for(int i=0; i<len; i++)
156
        {
157
        if( mIndices[variant][index][i] == -1 )
158
          {
159
          int ind = indices[index][i];
160
          float[] ver = vertices[ind];
161
162
          if( vertex[0]==ver[0] && vertex[1]==ver[1] && vertex[2]==ver[2] )
163
            {
164
            mIndices[variant][index][i] = pointer;
165
            }
166
          }
167
        }
168
      }
169
    }
170
171
///////////////////////////////////////////////////////////////////////////////////////////////////
172
// So far the 'vertices/indices' are stored inefficiently, with each vertex stored three times
173 5987822f Leszek Koltunski
// (each one normally is a corner of three faces) or even six times. Compress!
174 b442e28c Leszek Koltunski
// Example of six times: the central vertex here:
175
//
176
// { 1.0f,  0.0f, -1.0f,
177
//   1.0f, -1.0f, -1.0f,
178
//   1.0f, -1.0f, +0.0f,
179
//   0.0f, -1.0f, -1.0f },
180
181
  private void compressVerticesAndIndices(int variant, float[][] vertices, int[][] indices)
182
    {
183
    if( mTmpArray==null ) mTmpArray = new ArrayList<>();
184
185
    int lenI = indices.length;
186
    int pointer=0;
187
188
    mIndices[variant] = new int[lenI][];
189
190
    for(int index=0; index<lenI; index++)
191
      {
192
      int len = indices[index].length;
193
      mIndices[variant][index] = new int[len];
194
      for(int i=0; i<len; i++) mIndices[variant][index][i] = -1;
195
      }
196
197
    for(int index=0; index<lenI; index++)
198
      {
199
      int len = indices[index].length;
200
201
      for(int i=0; i<len; i++)
202
        {
203
        if( mIndices[variant][index][i] == -1 )
204
          {
205
          int ind = indices[index][i];
206
          float[] ver = vertices[ind];
207
          mTmpArray.add(ver);
208
          markAllVertices(ver,vertices,indices,pointer,variant);
209
          pointer++;
210
          }
211
        }
212
      }
213
214
    int len = mTmpArray.size();
215
    mVertices[variant] = new float[len][];
216
217
    for(int i=0; i<len; i++)
218
      {
219
      mVertices[variant][i] = mTmpArray.remove(0);
220
      }
221
    }
222
223 a7c10d03 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
224
225
  private boolean cubitExists(float[] pos, float x, float y, float z)
226
    {
227
    int len = pos.length/3;
228
229
    for(int i=0; i<len; i++)
230
      if( pos[3*i]==x && pos[3*i+1]==y && pos[3*i+2]==z ) return true;
231
232
    return false;
233
    }
234
235
///////////////////////////////////////////////////////////////////////////////////////////////////
236
237 b1f0d55d Leszek Koltunski
  private void createRight(int x, ArrayList<float[]> list)
238 a7c10d03 Leszek Koltunski
    {
239 b1f0d55d Leszek Koltunski
    for(int y=0; y<mMax; y++)
240
      for(int z=0; z<mMax; z++)
241
        {
242
        boolean b = (y<mY && z<mZ) && ( mTmp[x][mY-1-y][mZ-1-z] && (x+1>=mX || !mTmp[x+1][mY-1-y][mZ-1-z]) );
243
        mWall[z][y] = b ? WALL_MARKED : WALL_EMPTY;
244
        }
245 a7c10d03 Leszek Koltunski
246 b1f0d55d Leszek Koltunski
    createVertices(list,mWall,AXIS_XP,x);
247 a7c10d03 Leszek Koltunski
    }
248
249
///////////////////////////////////////////////////////////////////////////////////////////////////
250
251 b1f0d55d Leszek Koltunski
  private void createLeft(int x, ArrayList<float[]> list)
252 a7c10d03 Leszek Koltunski
    {
253 b1f0d55d Leszek Koltunski
    for(int y=0; y<mMax; y++)
254
      for(int z=0; z<mMax; z++)
255
        {
256
        boolean b = (y<mY && z<mZ) && ( mTmp[x][mY-1-y][z] && (x<1 || !mTmp[x-1][mY-1-y][z]) );
257
        mWall[z][y] = b ? WALL_MARKED : WALL_EMPTY;
258
        }
259 a7c10d03 Leszek Koltunski
260 b1f0d55d Leszek Koltunski
    createVertices(list,mWall,AXIS_XM,x);
261 a7c10d03 Leszek Koltunski
    }
262
263
///////////////////////////////////////////////////////////////////////////////////////////////////
264
265 b1f0d55d Leszek Koltunski
  private void createTop(int y, ArrayList<float[]> list)
266 a7c10d03 Leszek Koltunski
    {
267 b1f0d55d Leszek Koltunski
    for(int z=0; z<mMax; z++)
268
      for(int x=0; x<mMax; x++)
269
        {
270
        boolean b = (x<mX && z<mZ) && ( mTmp[x][y][z] && (y+1>=mY || !mTmp[x][y+1][z]) );
271
        mWall[x][z] = b ? WALL_MARKED : WALL_EMPTY;
272
        }
273 a7c10d03 Leszek Koltunski
274 b1f0d55d Leszek Koltunski
    createVertices(list,mWall,AXIS_YP,y);
275 a7c10d03 Leszek Koltunski
    }
276
277
///////////////////////////////////////////////////////////////////////////////////////////////////
278
279 b1f0d55d Leszek Koltunski
  private void createBottom(int y, ArrayList<float[]> list)
280 a7c10d03 Leszek Koltunski
    {
281 b1f0d55d Leszek Koltunski
    for(int z=0; z<mMax; z++)
282
      for(int x=0; x<mMax; x++)
283
        {
284
        boolean b = (x<mX && z<mZ) && ( mTmp[x][y][mZ-1-z] && (y<1 || !mTmp[x][y-1][mZ-1-z]) );
285
        mWall[x][z] = b ? WALL_MARKED : WALL_EMPTY;
286
        }
287 a7c10d03 Leszek Koltunski
288 b1f0d55d Leszek Koltunski
    createVertices(list,mWall,AXIS_YM,y);
289 a7c10d03 Leszek Koltunski
    }
290
291
///////////////////////////////////////////////////////////////////////////////////////////////////
292
293 b1f0d55d Leszek Koltunski
  private void createFront(int z, ArrayList<float[]> list)
294 a7c10d03 Leszek Koltunski
    {
295 b1f0d55d Leszek Koltunski
    for(int y=0; y<mMax; y++)
296
      for(int x=0; x<mMax; x++)
297
        {
298
        boolean b = (x<mX && y<mY) && ( mTmp[x][mY-1-y][z] && (z+1>=mZ || !mTmp[x][mY-1-y][z+1]) );
299
        mWall[x][y] = b ? WALL_MARKED : WALL_EMPTY;
300
        }
301 a7c10d03 Leszek Koltunski
302 b1f0d55d Leszek Koltunski
    createVertices(list,mWall,AXIS_ZP,z);
303 a7c10d03 Leszek Koltunski
    }
304
305
///////////////////////////////////////////////////////////////////////////////////////////////////
306
307 b1f0d55d Leszek Koltunski
  private void createBack(int z, ArrayList<float[]> list)
308 a7c10d03 Leszek Koltunski
    {
309 b1f0d55d Leszek Koltunski
    for(int y=0; y<mMax; y++)
310
      for(int x=0; x<mMax; x++)
311
        {
312
        boolean b = (x<mX && y<mY) && ( mTmp[mX-1-x][mY-1-y][z] && (z<1 || !mTmp[mX-1-x][mY-1-y][z-1]) );
313
        mWall[x][y] = b ? WALL_MARKED : WALL_EMPTY;
314
        }
315 a7c10d03 Leszek Koltunski
316 b1f0d55d Leszek Koltunski
    createVertices(list,mWall,AXIS_ZM,z);
317 a7c10d03 Leszek Koltunski
    }
318
319
///////////////////////////////////////////////////////////////////////////////////////////////////
320
321 b1f0d55d Leszek Koltunski
  private void markNeighbours(int[][] wall, int x, int y, int section)
322 a7c10d03 Leszek Koltunski
    {
323 b1f0d55d Leszek Koltunski
    wall[x][y] = section;
324 a7c10d03 Leszek Koltunski
325 b1f0d55d Leszek Koltunski
    if( x  >   0 && wall[x-1][y]==WALL_MARKED ) markNeighbours(wall,x-1,y,section);
326
    if( x+1<mMax && wall[x+1][y]==WALL_MARKED ) markNeighbours(wall,x+1,y,section);
327
    if( y  >   0 && wall[x][y-1]==WALL_MARKED ) markNeighbours(wall,x,y-1,section);
328
    if( y+1<mMax && wall[x][y+1]==WALL_MARKED ) markNeighbours(wall,x,y+1,section);
329 a7c10d03 Leszek Koltunski
    }
330
331
///////////////////////////////////////////////////////////////////////////////////////////////////
332
333 b1f0d55d Leszek Koltunski
  private int markSections(int[][] wall)
334 a7c10d03 Leszek Koltunski
    {
335
    int sections = 0;
336
337 b1f0d55d Leszek Koltunski
    for(int x=0; x<mMax; x++)
338
      for(int y=0; y<mMax; y++)
339
        if( wall[x][y]==WALL_MARKED )
340
          {
341
          sections++;
342
          markNeighbours(wall,x,y,sections);
343
          }
344 a7c10d03 Leszek Koltunski
345
    return sections;
346
    }
347
348
///////////////////////////////////////////////////////////////////////////////////////////////////
349 b8b71f52 Leszek Koltunski
// return true iff exactly three or exactly one of the four values (x1,x2,x3,x4) are equal to 'value'.
350 a7c10d03 Leszek Koltunski
351 b8b71f52 Leszek Koltunski
  private boolean threeOrOne(int x1, int x2, int x3, int x4, int value)
352 a7c10d03 Leszek Koltunski
    {
353 b8b71f52 Leszek Koltunski
    if( x1==value ) return x2==value ? (x3==value)^(x4==value) : (x3==value)^(x4!=value);
354
    else            return x2==value ? (x3==value)^(x4!=value) : (x3==value)^(x4==value);
355
    }
356
357
///////////////////////////////////////////////////////////////////////////////////////////////////
358
359
  private boolean isOddVertical(int x, int y)
360
    {
361
    int number = 0;
362
363
    for(int i=0; i<y; i++)
364
      if( mPoints[x][i]==0 ) number++;
365
366
    return (number%2)==0;
367
    }
368
369
///////////////////////////////////////////////////////////////////////////////////////////////////
370
371
  private boolean isOddHorizontal(int x, int y)
372
    {
373
    int number = 0;
374
375
    for(int i=0; i<x; i++)
376
      if( mPoints[i][y]==0 ) number++;
377
378
    return (number%2)==0;
379
    }
380
381
///////////////////////////////////////////////////////////////////////////////////////////////////
382
383
  private int moveUp(int x, int y)
384
    {
385
    for(int i=y-1; i>=0; i--)
386
      if( mPoints[x][i]==0 ) return i;
387
388
    android.util.Log.e("D", "moveUp error!");
389
    return 0;
390 a7c10d03 Leszek Koltunski
    }
391
392
///////////////////////////////////////////////////////////////////////////////////////////////////
393
394 b8b71f52 Leszek Koltunski
  private int moveDown(int x, int y)
395 a7c10d03 Leszek Koltunski
    {
396 b1f0d55d Leszek Koltunski
    for(int i=y+1; i<=mMax; i++)
397 b8b71f52 Leszek Koltunski
      if( mPoints[x][i]==0 ) return i;
398 a7c10d03 Leszek Koltunski
399 b8b71f52 Leszek Koltunski
    android.util.Log.e("D", "moveDown error!");
400
    return 0;
401 a7c10d03 Leszek Koltunski
    }
402
403
///////////////////////////////////////////////////////////////////////////////////////////////////
404
405 b8b71f52 Leszek Koltunski
  private int moveLeft(int x, int y)
406 a7c10d03 Leszek Koltunski
    {
407 b8b71f52 Leszek Koltunski
    for(int i=x-1; i>=0; i--)
408
      if( mPoints[i][y]==0 ) return i;
409 a7c10d03 Leszek Koltunski
410 b8b71f52 Leszek Koltunski
    android.util.Log.e("D", "moveLeft error!");
411
    return 0;
412
    }
413
414
///////////////////////////////////////////////////////////////////////////////////////////////////
415
416
  private int moveRight(int x, int y)
417
    {
418 b1f0d55d Leszek Koltunski
    for(int i=x+1; i<=mMax; i++)
419 b8b71f52 Leszek Koltunski
      if( mPoints[i][y]==0 ) return i;
420
421
    android.util.Log.e("D", "moveRight error!");
422
    return 0;
423
    }
424
425
///////////////////////////////////////////////////////////////////////////////////////////////////
426
427 630cf5ce Leszek Koltunski
  private float[] buildVertices(int[][] wall, int section, float dx, float dy)
428 b8b71f52 Leszek Koltunski
    {
429
    int numPoints = buildPoints(wall,section);
430
    int numSections = numPoints/2;
431
    float[] vertices = new float[3*numPoints];
432
    int x=0,y=0,pointer=0;
433
434 b1f0d55d Leszek Koltunski
    for(int i=0; i<=mMax; i++)
435
      for(int j=0; j<=mMax; j++)
436 b8b71f52 Leszek Koltunski
        if( mPoints[i][j]==0 )
437
          {
438
          x = i;
439
          y = j;
440 b1f0d55d Leszek Koltunski
          i = j = mMax+1;
441 b8b71f52 Leszek Koltunski
          }
442
443
    for(int s=0; s<numSections; s++)
444
      {
445 630cf5ce Leszek Koltunski
      vertices[6*pointer  ] = x-dx;
446
      vertices[6*pointer+1] = dy-y;
447 b8b71f52 Leszek Koltunski
      vertices[6*pointer+2] = 0.0f;
448
449
      y = isOddVertical(x,y) ? moveDown(x,y) : moveUp(x,y);
450
451 630cf5ce Leszek Koltunski
      vertices[6*pointer+3] = x-dx;
452
      vertices[6*pointer+4] = dy-y;
453 b8b71f52 Leszek Koltunski
      vertices[6*pointer+5] = 0.0f;
454
455
      x = isOddHorizontal(x,y) ? moveRight(x,y) : moveLeft(x,y);
456
457
      pointer++;
458
      }
459
460
    return vertices;
461
    }
462
463 b1f0d55d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
464
465
  private int buildPoints(int[][] wall, int section)
466
    {
467
    int numPoints=0;
468
    boolean thereIsCorner;
469
470
    for(int x=0; x<=mMax; x++)
471
      for(int y=0; y<=mMax; y++)
472
        {
473
        if( y==0 )
474
          {
475
               if( x==   0 ) thereIsCorner = (wall[     0][0]==section);
476
          else if( x==mMax ) thereIsCorner = (wall[mMax-1][0]==section);
477
          else               thereIsCorner = (wall[x-1][0]==section)^(wall[x][0]==section);
478
          }
479
        else if( y==mMax )
480
          {
481
               if( x==   0 ) thereIsCorner = (wall[     0][mMax-1]==section);
482
          else if( x==mMax ) thereIsCorner = (wall[mMax-1][mMax-1]==section);
483
          else               thereIsCorner = (wall[x-1][mMax-1]==section)^(wall[x][mMax-1]==section);
484
          }
485
        else if( x==0 )
486
          {
487
          thereIsCorner = (wall[0][y-1]==section)^(wall[0][y]==section);
488
          }
489
        else if( x==mMax )
490
          {
491
          thereIsCorner = (wall[mMax-1][y-1]==section)^(wall[mMax-1][y]==section);
492
          }
493
        else
494
          {
495
          thereIsCorner = threeOrOne(wall[x-1][y-1],wall[x-1][y],wall[x][y-1],wall[x][y],section);
496
          }
497
498
        if( thereIsCorner )
499
          {
500
          mPoints[x][y] = 0;
501
          numPoints++;
502
          }
503
        else
504
          {
505
          mPoints[x][y] =-1;
506
          }
507
        }
508
509
    return numPoints;
510
    }
511
512 b8b71f52 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
513
514
  private void rotateAndMoveVertices(float[] vertices, int axis, int layer)
515
    {
516
    int i,len = vertices.length/3;
517
518
    switch(axis)
519
      {
520
      case AXIS_XP: for(i=0; i<len; i++)
521
                      {
522 630cf5ce Leszek Koltunski
                      vertices[3*i+2] =-vertices[3*i  ];
523 b1f0d55d Leszek Koltunski
                      vertices[3*i  ] = layer-(dX-1.0f);
524 b8b71f52 Leszek Koltunski
                      }
525
                    break;
526
      case AXIS_XM: for(i=0; i<len; i++)
527
                      {
528 630cf5ce Leszek Koltunski
                      vertices[3*i+2] = vertices[3*i  ];
529 b1f0d55d Leszek Koltunski
                      vertices[3*i  ] = layer-dX;
530 b8b71f52 Leszek Koltunski
                      }
531
                    break;
532
      case AXIS_YP: for(i=0; i<len; i++)
533
                      {
534 630cf5ce Leszek Koltunski
                      vertices[3*i+2] =-vertices[3*i+1];
535 b1f0d55d Leszek Koltunski
                      vertices[3*i+1] = layer-(dY-1.0f);
536 b8b71f52 Leszek Koltunski
                      }
537
                    break;
538
      case AXIS_YM: for(i=0; i<len; i++)
539
                      {
540
                      vertices[3*i+2] = vertices[3*i+1];
541 b1f0d55d Leszek Koltunski
                      vertices[3*i+1] = layer-dY;
542 b8b71f52 Leszek Koltunski
                      }
543
                    break;
544
      case AXIS_ZP: for(i=0; i<len; i++)
545
                      {
546 b1f0d55d Leszek Koltunski
                      vertices[3*i+2] = layer-(dZ-1.0f);
547 b8b71f52 Leszek Koltunski
                      }
548
                    break;
549
      case AXIS_ZM: for(i=0; i<len; i++)
550
                      {
551 b1f0d55d Leszek Koltunski
                      vertices[3*i+2] = layer-dZ;
552 630cf5ce Leszek Koltunski
                      vertices[3*i  ] =-vertices[3*i  ];
553 b8b71f52 Leszek Koltunski
                      }
554
                    break;
555
      }
556 a7c10d03 Leszek Koltunski
    }
557
558
///////////////////////////////////////////////////////////////////////////////////////////////////
559
// 1. assume the 'wall' is in the XY plane
560
// 2. split the wall into individual connected regions and for each such region:
561
//   a. build the list of vertices (Z=0)
562
//   b. take the axis into consideration and rotate the vertices.
563
//   c. take layer into consideration and move the vertices.
564
//   d. add the resulting vertices to the list.
565
566 b1f0d55d Leszek Koltunski
  private void createVertices(ArrayList<float[]> list, int[][] wall, int axis, int layer)
567 a7c10d03 Leszek Koltunski
    {
568
    int sections = markSections(wall);
569
570 630cf5ce Leszek Koltunski
    float dx = (axis==AXIS_XP || axis==AXIS_XM) ? dZ : dX;
571
    float dy = (axis==AXIS_YP || axis==AXIS_YM) ? dZ : dY;
572
573 a7c10d03 Leszek Koltunski
    for(int i=0; i<sections; i++)
574
      {
575 630cf5ce Leszek Koltunski
      float[] vertices = buildVertices(wall,i+1,dx,dy);
576
577 b8b71f52 Leszek Koltunski
      rotateAndMoveVertices(vertices,axis,layer);
578 a7c10d03 Leszek Koltunski
      list.add(vertices);
579 b8b71f52 Leszek Koltunski
/*
580
      int len = vertices.length/3;
581
      String w="";
582
583
      for(int j=0; j<len; j++)
584
        {
585
        w += ( "["+vertices[3*j]+" "+vertices[3*j+1]+" "+vertices[3*j+2]+"] ");
586
        }
587 630cf5ce Leszek Koltunski
      android.util.Log.e("D", "1 section: "+i+" axis: "+axis+" layer: "+layer+" vertices after: "+w);
588
*/
589 a7c10d03 Leszek Koltunski
      }
590
    }
591
592
///////////////////////////////////////////////////////////////////////////////////////////////////
593 786098dd Leszek Koltunski
594 e3302253 Leszek Koltunski
  private static boolean vertInFace(float[] vertex, float[] move, Static3D faceAxis, float dist)
595 786098dd Leszek Koltunski
    {
596
    final float MAX_ERROR = 0.01f;
597
598
    float x= faceAxis.get0();
599
    float y= faceAxis.get1();
600
    float z= faceAxis.get2();
601
602 e3302253 Leszek Koltunski
    float a = (vertex[0]+move[0])*x + (vertex[1]+move[1])*y + (vertex[2]+move[2])*z;
603 786098dd Leszek Koltunski
    float diff = a - dist;
604
605
    return diff>-MAX_ERROR && diff<MAX_ERROR;
606
    }
607
608
///////////////////////////////////////////////////////////////////////////////////////////////////
609 b1f0d55d Leszek Koltunski
// (vertices,indices) define a cubit face, i.e. a connected subset of the NxN grid.
610 786098dd Leszek Koltunski
// Return its 'diameter', i.e. max(width,height)
611
612
  private int faceDiameter(float[][] vertices, int[] indices)
613
    {
614 b1f0d55d Leszek Koltunski
    float maxX = -dX;
615
    float minX = +dX;
616
    float maxY = -dY;
617
    float minY = +dY;
618
    float maxZ = -dZ;
619
    float minZ = +dZ;
620 786098dd Leszek Koltunski
621
    for (int index : indices)
622
      {
623
      float[] v = vertices[index];
624
625
      if (v[0] > maxX) maxX = v[0];
626
      if (v[0] < minX) minX = v[0];
627
      if (v[1] > maxY) maxY = v[1];
628
      if (v[1] < minY) minY = v[1];
629
      if (v[2] > maxZ) maxZ = v[2];
630
      if (v[2] < minZ) minZ = v[2];
631
      }
632
633
    float diffX = maxX-minX;
634
    float diffY = maxY-minY;
635
    float diffZ = maxZ-minZ;
636
637
    float max = diffX>diffY ? Math.max(diffX,diffZ) : Math.max(diffY,diffZ);
638
639
    return (int)max;
640
    }
641
642
///////////////////////////////////////////////////////////////////////////////////////////////////
643
// return array of:
644 b1f0d55d Leszek Koltunski
// 0 if this is an inner face, 1 if its diameter is 1, 2 if diameter is 2, 3 if 3, etc
645 a7c10d03 Leszek Koltunski
646 29ad5fc9 Leszek Koltunski
  private int[] generateBandIndices(float[][] vertices, int[][] indices, float[] move)
647 a7c10d03 Leszek Koltunski
    {
648 786098dd Leszek Koltunski
    int numCubitFaces = indices.length;
649
    int[] bandIndices = new int[numCubitFaces];
650
651
    for(int cubitFace=0; cubitFace<numCubitFaces; cubitFace++)
652
      {
653
      bandIndices[cubitFace] = 0xffffffff;
654
      int numVertices = indices[cubitFace].length;
655
656
      for(int vertex=0; vertex<numVertices; vertex++)
657
        {
658 e3302253 Leszek Koltunski
        int vertBelongsBitmap = 0x00000000;
659 b1f0d55d Leszek Koltunski
        float[] vert = vertices[ indices[cubitFace][vertex] ];
660 e3302253 Leszek Koltunski
661 b1f0d55d Leszek Koltunski
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[0], dX) ) vertBelongsBitmap |= (1<<0);
662
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[1], dX) ) vertBelongsBitmap |= (1<<1);
663
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[2], dY) ) vertBelongsBitmap |= (1<<2);
664
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[3], dY) ) vertBelongsBitmap |= (1<<3);
665
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[4], dZ) ) vertBelongsBitmap |= (1<<4);
666
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[5], dZ) ) vertBelongsBitmap |= (1<<5);
667 786098dd Leszek Koltunski
668
        bandIndices[cubitFace] &= vertBelongsBitmap;
669
        }
670
671
      if( bandIndices[cubitFace]!=0 ) // outer face
672
        {
673
        bandIndices[cubitFace] = faceDiameter(vertices, indices[cubitFace]);
674
        }
675 e3302253 Leszek Koltunski
676
      //android.util.Log.e("D", "cubit face "+cubitFace+" : "+bandIndices[cubitFace]);
677 786098dd Leszek Koltunski
      }
678 b8b71f52 Leszek Koltunski
679
    return bandIndices;
680 a7c10d03 Leszek Koltunski
    }
681
682
///////////////////////////////////////////////////////////////////////////////////////////////////
683
684 db758bd0 Leszek Koltunski
  private int[] generateCornerIndices(float[][] vertices, boolean roundCorners)
685 a7c10d03 Leszek Koltunski
    {
686 b8b71f52 Leszek Koltunski
    int len = vertices.length;
687 db758bd0 Leszek Koltunski
    int val = roundCorners ? 0 : -1;
688 b8b71f52 Leszek Koltunski
    int[] cornerIndices = new int[len];
689 db758bd0 Leszek Koltunski
    for(int i=0; i<len; i++) cornerIndices[i] = val;
690 b8b71f52 Leszek Koltunski
    return cornerIndices;
691 a7c10d03 Leszek Koltunski
    }
692
693 b8b71f52 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
694 a7c10d03 Leszek Koltunski
695 5987822f Leszek Koltunski
  private int computeVectorFace(float[] prev, float[] curr, float[] next)
696
    {
697
    float ax = prev[0]-curr[0];
698
    float ay = prev[1]-curr[1];
699
    float az = prev[2]-curr[2];
700
701
    float bx = next[0]-curr[0];
702
    float by = next[1]-curr[1];
703
    float bz = next[2]-curr[2];
704
705
    float lena = (float)Math.sqrt(ax*ax + ay*ay + az*az);
706
    float lenb = (float)Math.sqrt(bx*bx + by*by + bz*bz);
707
708
    ax /= lena;
709
    ay /= lena;
710
    az /= lena;
711
712
    bx /= lenb;
713
    by /= lenb;
714
    bz /= lenb;
715
716
    float cx = ax + bx + ay*bz-az*by;
717
    float cy = ay + by + az*bx-ax*bz;
718
    float cz = az + bz + ax*by-ay*bx;
719
720
    return (cx<0 ? 0:4) + (cy<0 ? 0:2) + (cz<0 ? 0:1);
721
    }
722
723
///////////////////////////////////////////////////////////////////////////////////////////////////
724
725
  private float[] computeVector(int index, float[][] vertices, int[][] indices, int[] bandIndices)
726
    {
727
    int band=0;
728
    int len = indices.length;
729
    int vector=-1;
730
731
    for(int i=0; i<len; i++)
732
      {
733
      int len2 = indices[i].length;
734
735
      for(int j=0; j<len2; j++)
736
        {
737
        if( indices[i][j]==index )
738
          {
739
          int prev = j>0 ? j-1 : len2-1;
740
          int next = j<len2-1 ? j+1 : 0;
741
742
          int prevIndex = indices[i][prev];
743
          int currIndex = indices[i][j];
744
          int nextIndex = indices[i][next];
745
746
          int newVector = computeVectorFace(vertices[prevIndex],vertices[currIndex],vertices[nextIndex]);
747
          if( vector!=-1 && vector!=newVector ) return null;
748
749
          vector = newVector;
750
          band |= bandIndices[i];
751
          }
752
        }
753
      }
754
755
    return band==0 ? null : VECTOR[vector];
756
    }
757
758
///////////////////////////////////////////////////////////////////////////////////////////////////
759
760
  private float[][] generateVectors(float[][] vertices, int[][] indices, int[] bandIndices)
761 a7c10d03 Leszek Koltunski
    {
762 b8b71f52 Leszek Koltunski
    int len = vertices.length;
763 5987822f Leszek Koltunski
    float[][] vectors = new float[len][];
764
765
    for(int i=0; i<len; i++)
766
      {
767
      vectors[i] = computeVector(i,vertices,indices,bandIndices);
768
      }
769
770
    return vectors;
771
    }
772
773
///////////////////////////////////////////////////////////////////////////////////////////////////
774
775
  private float[][] generateCenters(float[][] vertices, float[][] vectors)
776
    {
777
    int pointer=0,total=0;
778
    int len = vertices.length;
779
780
    for( float[] vector : vectors )
781
      {
782
      if( vector!=null ) total++;
783
      }
784
785
    float[][] centers = new float[total][3];
786
787
    for( int i=0; i<len; i++ )
788
      {
789
      if( vectors[i]!=null )
790
        {
791
        centers[pointer][0] = vertices[i][0]+vectors[i][0];
792
        centers[pointer][1] = vertices[i][1]+vectors[i][1];
793
        centers[pointer][2] = vertices[i][2]+vectors[i][2];
794
        pointer++;
795
        }
796
      }
797
798
    return centers;
799 a7c10d03 Leszek Koltunski
    }
800
801
///////////////////////////////////////////////////////////////////////////////////////////////////
802
803 5987822f Leszek Koltunski
  private int[] generateCenterIndices(float[][] vectors)
804 a7c10d03 Leszek Koltunski
    {
805 5987822f Leszek Koltunski
    int pointer=0;
806
    int len = vectors.length;
807
    int[] centerIndices = new int[len];
808
809
    for(int i=0; i<len; i++)
810
      {
811
      if( vectors[i]==null )
812
        {
813
        centerIndices[i] = -1;
814
        }
815
      else
816
        {
817
        centerIndices[i] = pointer;
818
        pointer++;
819
        }
820
      }
821
822
    return centerIndices;
823 a7c10d03 Leszek Koltunski
    }
824
825
///////////////////////////////////////////////////////////////////////////////////////////////////
826
// PUBLIC API
827
828 b1f0d55d Leszek Koltunski
  public static FactoryBandagedCubit getInstance()
829 a7c10d03 Leszek Koltunski
    {
830 b1f0d55d Leszek Koltunski
    if( mThis==null ) mThis = new FactoryBandagedCubit();
831 a7c10d03 Leszek Koltunski
    return mThis;
832
    }
833
834
///////////////////////////////////////////////////////////////////////////////////////////////////
835
836 52e3d46b Leszek Koltunski
  public void prepare(int numVariants, int x, int y, int z)
837 a7c10d03 Leszek Koltunski
    {
838
    if( mVertexArray==null ) mVertexArray = new ArrayList<>();
839
    mVertices= new float[numVariants][][];
840
    mIndices = new int[numVariants][][];
841 29ad5fc9 Leszek Koltunski
    mMove = new float[numVariants][3];
842 b1f0d55d Leszek Koltunski
843 52e3d46b Leszek Koltunski
    mX = x;
844
    mY = y;
845
    mZ = z;
846 b1f0d55d Leszek Koltunski
847
    dX = mX/2.0f;
848
    dY = mY/2.0f;
849
    dZ = mZ/2.0f;
850
851
    mMax = mX>mY ? Math.max(mX,mZ) : Math.max(mY,mZ);
852
853
    mWall   = new int[mMax][mMax];
854
    mPoints = new int[mMax+1][mMax+1];
855
    mTmp    = new boolean[mX][mY][mZ];
856 a7c10d03 Leszek Koltunski
    }
857
858
///////////////////////////////////////////////////////////////////////////////////////////////////
859
860
  public ObjectShape createIrregularShape(int variant, float[] pos)
861
    {
862 786098dd Leszek Koltunski
    mVertexArray.clear();
863
864 96a68289 Leszek Koltunski
    float begX = 0.5f*(1-mX);
865
    float begY = 0.5f*(1-mY);
866
    float begZ = 0.5f*(1-mZ);
867
868 b1f0d55d Leszek Koltunski
    for(int x=0; x<mX; x++)
869
      for(int y=0; y<mY; y++)
870 96a68289 Leszek Koltunski
        for(int z=0; z<mZ; z++) mTmp[x][y][z] = cubitExists(pos,begX+x,begY+y,begZ+z);
871 a7c10d03 Leszek Koltunski
872 b1f0d55d Leszek Koltunski
    for(int x=0; x<mX; x++) createRight (x,mVertexArray);
873
    for(int x=0; x<mX; x++) createLeft  (x,mVertexArray);
874
    for(int y=0; y<mY; y++) createTop   (y,mVertexArray);
875
    for(int y=0; y<mY; y++) createBottom(y,mVertexArray);
876
    for(int z=0; z<mZ; z++) createFront (z,mVertexArray);
877
    for(int z=0; z<mZ; z++) createBack  (z,mVertexArray);
878 a7c10d03 Leszek Koltunski
879 b442e28c Leszek Koltunski
    float[][] verts = getVertices(mVertexArray,pos,variant);
880
    int[][] inds    = getIndices(mVertexArray);
881 b8b71f52 Leszek Koltunski
882 b442e28c Leszek Koltunski
    compressVerticesAndIndices(variant,verts,inds);
883 b8b71f52 Leszek Koltunski
884 b442e28c Leszek Koltunski
    return new ObjectShape(mVertices[variant], mIndices[variant]);
885 b8b71f52 Leszek Koltunski
    }
886
887 b442e28c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
888 a7c10d03 Leszek Koltunski
889 b442e28c Leszek Koltunski
  private void debug(float[][] vert, int[][] ind)
890 b8b71f52 Leszek Koltunski
    {
891 b442e28c Leszek Koltunski
    String vv="VERTICES: ";
892
    for (float[] floats : vert)
893
      {
894
      vv += "\n";
895
      int lenV2 = floats.length / 3;
896
897
      for (int v2 = 0; v2 < lenV2; v2++)
898
        {
899
        vv += " {";
900
        vv += (floats[3 * v2] + " ");
901
        vv += (floats[3 * v2 + 1] + " ");
902
        vv += (floats[3 * v2 + 2] + " ");
903
        vv += "}";
904
        }
905
      }
906
    android.util.Log.e("D", vv);
907
908
    String ii="INDICES: ";
909
    for (int[] ints : ind)
910
      {
911
      ii += "\n";
912
      int lenI2 = ints.length;
913
914
      for (int i2 = 0; i2 < lenI2; i2++)
915
        {
916
        ii += (ints[i2] + " ");
917
        }
918
      }
919
    android.util.Log.e("D", ii);
920 a7c10d03 Leszek Koltunski
    }
921
922
///////////////////////////////////////////////////////////////////////////////////////////////////
923
924 db758bd0 Leszek Koltunski
  public ObjectFaceShape createIrregularFaceShape(int variant, boolean iconMode, boolean roundCorners)
925 a7c10d03 Leszek Koltunski
    {
926 01a68e12 Leszek Koltunski
    float height   = iconMode ? 0.001f : 0.048f;
927 3bf19410 Leszek Koltunski
    int angle      = 60;
928
    float R        = 0.2f;
929 3ece88b8 Leszek Koltunski
    float S        = 0.5f;
930 3bf19410 Leszek Koltunski
    int numVertices= 5;
931 3ece88b8 Leszek Koltunski
    int extraI     = 0;
932
    int extraV     = 0;
933 b0638b61 Leszek Koltunski
934 5987822f Leszek Koltunski
    float[][] corners   = { {0.02f,0.12f} };
935 3bf19410 Leszek Koltunski
    float[][] bands     = { {  0.001f,angle,R,S,numVertices,extraV,extraI},
936
                            {height/1,angle,R,S,numVertices,extraV,extraI},
937
                            {height/2,angle,R,S,numVertices,extraV,extraI},
938
                            {height/3,angle,R,S,numVertices,extraV,extraI} };
939 a7c10d03 Leszek Koltunski
940 29ad5fc9 Leszek Koltunski
    int[] bandIndices   = generateBandIndices(mVertices[variant], mIndices[variant], mMove[variant]);
941 db758bd0 Leszek Koltunski
    int[] cornerIndices = generateCornerIndices(mVertices[variant], roundCorners);
942 5987822f Leszek Koltunski
    float[][] vertexVec = generateVectors(mVertices[variant], mIndices[variant], bandIndices);
943
    float[][] centers   = generateCenters(mVertices[variant], vertexVec);
944
    int[] centerIndices = generateCenterIndices(vertexVec);
945 a7c10d03 Leszek Koltunski
946
    return new ObjectFaceShape(bands,bandIndices,corners,cornerIndices,centers,centerIndices,null);
947
    }
948 12aa6192 Leszek Koltunski
949
///////////////////////////////////////////////////////////////////////////////////////////////////
950
951 52e3d46b Leszek Koltunski
  public MeshBase createMesh(float[] pos, int x, int y, int z, boolean iconMode, boolean roundCorners)
952 12aa6192 Leszek Koltunski
    {
953 52e3d46b Leszek Koltunski
    prepare(1,x,y,z);
954 12aa6192 Leszek Koltunski
    ObjectShape shape    = createIrregularShape(0,pos);
955 db758bd0 Leszek Koltunski
    ObjectFaceShape face = createIrregularFaceShape(0,iconMode,roundCorners);
956 12aa6192 Leszek Koltunski
    int[][] indices      = shape.getVertIndices();
957
    int numComponents    = indices.length;
958
959
    FactoryCubit factory = FactoryCubit.getInstance();
960 1c55e462 Leszek Koltunski
    factory.clear();
961 12aa6192 Leszek Koltunski
    factory.createNewFaceTransform(shape,null);
962
    return factory.createRoundedSolid(shape,face,MESH_NICE,numComponents);
963
    }
964 a7c10d03 Leszek Koltunski
  }