Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / helpers / FactoryBandagedCubit.java @ 96a68289

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 b1f0d55d Leszek Koltunski
  private float[] buildVertices(int[][] wall, int section)
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 b1f0d55d 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 b1f0d55d 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
                      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
                      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
                      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
                      vertices[3*i  ] = -vertices[3*i];
552 b1f0d55d Leszek Koltunski
                      vertices[3*i+2] = layer-dZ;
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
    for(int i=0; i<sections; i++)
571
      {
572
      float[] vertices = buildVertices(wall,i+1);
573 b8b71f52 Leszek Koltunski
      rotateAndMoveVertices(vertices,axis,layer);
574 a7c10d03 Leszek Koltunski
      list.add(vertices);
575 b8b71f52 Leszek Koltunski
/*
576
      int len = vertices.length/3;
577
      String w="";
578
579
      for(int j=0; j<len; j++)
580
        {
581
        w += ( "["+vertices[3*j]+" "+vertices[3*j+1]+" "+vertices[3*j+2]+"] ");
582
        }
583 96a68289 Leszek Koltunski
      android.util.Log.e("D", "axis: "+axis+" layer: "+layer+" vertices after: "+w);
584
 */
585 a7c10d03 Leszek Koltunski
      }
586
    }
587
588
///////////////////////////////////////////////////////////////////////////////////////////////////
589 786098dd Leszek Koltunski
590 e3302253 Leszek Koltunski
  private static boolean vertInFace(float[] vertex, float[] move, Static3D faceAxis, float dist)
591 786098dd Leszek Koltunski
    {
592
    final float MAX_ERROR = 0.01f;
593
594
    float x= faceAxis.get0();
595
    float y= faceAxis.get1();
596
    float z= faceAxis.get2();
597
598 e3302253 Leszek Koltunski
    float a = (vertex[0]+move[0])*x + (vertex[1]+move[1])*y + (vertex[2]+move[2])*z;
599 786098dd Leszek Koltunski
    float diff = a - dist;
600
601
    return diff>-MAX_ERROR && diff<MAX_ERROR;
602
    }
603
604
///////////////////////////////////////////////////////////////////////////////////////////////////
605 b1f0d55d Leszek Koltunski
// (vertices,indices) define a cubit face, i.e. a connected subset of the NxN grid.
606 786098dd Leszek Koltunski
// Return its 'diameter', i.e. max(width,height)
607
608
  private int faceDiameter(float[][] vertices, int[] indices)
609
    {
610 b1f0d55d Leszek Koltunski
    float maxX = -dX;
611
    float minX = +dX;
612
    float maxY = -dY;
613
    float minY = +dY;
614
    float maxZ = -dZ;
615
    float minZ = +dZ;
616 786098dd Leszek Koltunski
617
    for (int index : indices)
618
      {
619
      float[] v = vertices[index];
620
621
      if (v[0] > maxX) maxX = v[0];
622
      if (v[0] < minX) minX = v[0];
623
      if (v[1] > maxY) maxY = v[1];
624
      if (v[1] < minY) minY = v[1];
625
      if (v[2] > maxZ) maxZ = v[2];
626
      if (v[2] < minZ) minZ = v[2];
627
      }
628
629
    float diffX = maxX-minX;
630
    float diffY = maxY-minY;
631
    float diffZ = maxZ-minZ;
632
633
    float max = diffX>diffY ? Math.max(diffX,diffZ) : Math.max(diffY,diffZ);
634
635
    return (int)max;
636
    }
637
638
///////////////////////////////////////////////////////////////////////////////////////////////////
639
// return array of:
640 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
641 a7c10d03 Leszek Koltunski
642 29ad5fc9 Leszek Koltunski
  private int[] generateBandIndices(float[][] vertices, int[][] indices, float[] move)
643 a7c10d03 Leszek Koltunski
    {
644 786098dd Leszek Koltunski
    int numCubitFaces = indices.length;
645
    int[] bandIndices = new int[numCubitFaces];
646
647
    for(int cubitFace=0; cubitFace<numCubitFaces; cubitFace++)
648
      {
649
      bandIndices[cubitFace] = 0xffffffff;
650
      int numVertices = indices[cubitFace].length;
651
652
      for(int vertex=0; vertex<numVertices; vertex++)
653
        {
654 e3302253 Leszek Koltunski
        int vertBelongsBitmap = 0x00000000;
655 b1f0d55d Leszek Koltunski
        float[] vert = vertices[ indices[cubitFace][vertex] ];
656 e3302253 Leszek Koltunski
657 b1f0d55d Leszek Koltunski
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[0], dX) ) vertBelongsBitmap |= (1<<0);
658
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[1], dX) ) vertBelongsBitmap |= (1<<1);
659
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[2], dY) ) vertBelongsBitmap |= (1<<2);
660
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[3], dY) ) vertBelongsBitmap |= (1<<3);
661
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[4], dZ) ) vertBelongsBitmap |= (1<<4);
662
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[5], dZ) ) vertBelongsBitmap |= (1<<5);
663 786098dd Leszek Koltunski
664
        bandIndices[cubitFace] &= vertBelongsBitmap;
665
        }
666
667
      if( bandIndices[cubitFace]!=0 ) // outer face
668
        {
669
        bandIndices[cubitFace] = faceDiameter(vertices, indices[cubitFace]);
670
        }
671 e3302253 Leszek Koltunski
672
      //android.util.Log.e("D", "cubit face "+cubitFace+" : "+bandIndices[cubitFace]);
673 786098dd Leszek Koltunski
      }
674 b8b71f52 Leszek Koltunski
675
    return bandIndices;
676 a7c10d03 Leszek Koltunski
    }
677
678
///////////////////////////////////////////////////////////////////////////////////////////////////
679
680 db758bd0 Leszek Koltunski
  private int[] generateCornerIndices(float[][] vertices, boolean roundCorners)
681 a7c10d03 Leszek Koltunski
    {
682 b8b71f52 Leszek Koltunski
    int len = vertices.length;
683 db758bd0 Leszek Koltunski
    int val = roundCorners ? 0 : -1;
684 b8b71f52 Leszek Koltunski
    int[] cornerIndices = new int[len];
685 db758bd0 Leszek Koltunski
    for(int i=0; i<len; i++) cornerIndices[i] = val;
686 b8b71f52 Leszek Koltunski
    return cornerIndices;
687 a7c10d03 Leszek Koltunski
    }
688
689 b8b71f52 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
690 a7c10d03 Leszek Koltunski
691 5987822f Leszek Koltunski
  private int computeVectorFace(float[] prev, float[] curr, float[] next)
692
    {
693
    float ax = prev[0]-curr[0];
694
    float ay = prev[1]-curr[1];
695
    float az = prev[2]-curr[2];
696
697
    float bx = next[0]-curr[0];
698
    float by = next[1]-curr[1];
699
    float bz = next[2]-curr[2];
700
701
    float lena = (float)Math.sqrt(ax*ax + ay*ay + az*az);
702
    float lenb = (float)Math.sqrt(bx*bx + by*by + bz*bz);
703
704
    ax /= lena;
705
    ay /= lena;
706
    az /= lena;
707
708
    bx /= lenb;
709
    by /= lenb;
710
    bz /= lenb;
711
712
    float cx = ax + bx + ay*bz-az*by;
713
    float cy = ay + by + az*bx-ax*bz;
714
    float cz = az + bz + ax*by-ay*bx;
715
716
    return (cx<0 ? 0:4) + (cy<0 ? 0:2) + (cz<0 ? 0:1);
717
    }
718
719
///////////////////////////////////////////////////////////////////////////////////////////////////
720
721
  private float[] computeVector(int index, float[][] vertices, int[][] indices, int[] bandIndices)
722
    {
723
    int band=0;
724
    int len = indices.length;
725
    int vector=-1;
726
727
    for(int i=0; i<len; i++)
728
      {
729
      int len2 = indices[i].length;
730
731
      for(int j=0; j<len2; j++)
732
        {
733
        if( indices[i][j]==index )
734
          {
735
          int prev = j>0 ? j-1 : len2-1;
736
          int next = j<len2-1 ? j+1 : 0;
737
738
          int prevIndex = indices[i][prev];
739
          int currIndex = indices[i][j];
740
          int nextIndex = indices[i][next];
741
742
          int newVector = computeVectorFace(vertices[prevIndex],vertices[currIndex],vertices[nextIndex]);
743
          if( vector!=-1 && vector!=newVector ) return null;
744
745
          vector = newVector;
746
          band |= bandIndices[i];
747
          }
748
        }
749
      }
750
751
    return band==0 ? null : VECTOR[vector];
752
    }
753
754
///////////////////////////////////////////////////////////////////////////////////////////////////
755
756
  private float[][] generateVectors(float[][] vertices, int[][] indices, int[] bandIndices)
757 a7c10d03 Leszek Koltunski
    {
758 b8b71f52 Leszek Koltunski
    int len = vertices.length;
759 5987822f Leszek Koltunski
    float[][] vectors = new float[len][];
760
761
    for(int i=0; i<len; i++)
762
      {
763
      vectors[i] = computeVector(i,vertices,indices,bandIndices);
764
      }
765
766
    return vectors;
767
    }
768
769
///////////////////////////////////////////////////////////////////////////////////////////////////
770
771
  private float[][] generateCenters(float[][] vertices, float[][] vectors)
772
    {
773
    int pointer=0,total=0;
774
    int len = vertices.length;
775
776
    for( float[] vector : vectors )
777
      {
778
      if( vector!=null ) total++;
779
      }
780
781
    float[][] centers = new float[total][3];
782
783
    for( int i=0; i<len; i++ )
784
      {
785
      if( vectors[i]!=null )
786
        {
787
        centers[pointer][0] = vertices[i][0]+vectors[i][0];
788
        centers[pointer][1] = vertices[i][1]+vectors[i][1];
789
        centers[pointer][2] = vertices[i][2]+vectors[i][2];
790
        pointer++;
791
        }
792
      }
793
794
    return centers;
795 a7c10d03 Leszek Koltunski
    }
796
797
///////////////////////////////////////////////////////////////////////////////////////////////////
798
799 5987822f Leszek Koltunski
  private int[] generateCenterIndices(float[][] vectors)
800 a7c10d03 Leszek Koltunski
    {
801 5987822f Leszek Koltunski
    int pointer=0;
802
    int len = vectors.length;
803
    int[] centerIndices = new int[len];
804
805
    for(int i=0; i<len; i++)
806
      {
807
      if( vectors[i]==null )
808
        {
809
        centerIndices[i] = -1;
810
        }
811
      else
812
        {
813
        centerIndices[i] = pointer;
814
        pointer++;
815
        }
816
      }
817
818
    return centerIndices;
819 a7c10d03 Leszek Koltunski
    }
820
821
///////////////////////////////////////////////////////////////////////////////////////////////////
822
// PUBLIC API
823
824 b1f0d55d Leszek Koltunski
  public static FactoryBandagedCubit getInstance()
825 a7c10d03 Leszek Koltunski
    {
826 b1f0d55d Leszek Koltunski
    if( mThis==null ) mThis = new FactoryBandagedCubit();
827 a7c10d03 Leszek Koltunski
    return mThis;
828
    }
829
830
///////////////////////////////////////////////////////////////////////////////////////////////////
831
832 52e3d46b Leszek Koltunski
  public void prepare(int numVariants, int x, int y, int z)
833 a7c10d03 Leszek Koltunski
    {
834
    if( mVertexArray==null ) mVertexArray = new ArrayList<>();
835
    mVertices= new float[numVariants][][];
836
    mIndices = new int[numVariants][][];
837 29ad5fc9 Leszek Koltunski
    mMove = new float[numVariants][3];
838 b1f0d55d Leszek Koltunski
839 52e3d46b Leszek Koltunski
    mX = x;
840
    mY = y;
841
    mZ = z;
842 b1f0d55d Leszek Koltunski
843
    dX = mX/2.0f;
844
    dY = mY/2.0f;
845
    dZ = mZ/2.0f;
846
847
    mMax = mX>mY ? Math.max(mX,mZ) : Math.max(mY,mZ);
848
849
    mWall   = new int[mMax][mMax];
850
    mPoints = new int[mMax+1][mMax+1];
851
    mTmp    = new boolean[mX][mY][mZ];
852 a7c10d03 Leszek Koltunski
    }
853
854
///////////////////////////////////////////////////////////////////////////////////////////////////
855
856
  public ObjectShape createIrregularShape(int variant, float[] pos)
857
    {
858 786098dd Leszek Koltunski
    mVertexArray.clear();
859
860 96a68289 Leszek Koltunski
    float begX = 0.5f*(1-mX);
861
    float begY = 0.5f*(1-mY);
862
    float begZ = 0.5f*(1-mZ);
863
864 b1f0d55d Leszek Koltunski
    for(int x=0; x<mX; x++)
865
      for(int y=0; y<mY; y++)
866 96a68289 Leszek Koltunski
        for(int z=0; z<mZ; z++) mTmp[x][y][z] = cubitExists(pos,begX+x,begY+y,begZ+z);
867 a7c10d03 Leszek Koltunski
868 b1f0d55d Leszek Koltunski
    for(int x=0; x<mX; x++) createRight (x,mVertexArray);
869
    for(int x=0; x<mX; x++) createLeft  (x,mVertexArray);
870
    for(int y=0; y<mY; y++) createTop   (y,mVertexArray);
871
    for(int y=0; y<mY; y++) createBottom(y,mVertexArray);
872
    for(int z=0; z<mZ; z++) createFront (z,mVertexArray);
873
    for(int z=0; z<mZ; z++) createBack  (z,mVertexArray);
874 a7c10d03 Leszek Koltunski
875 b442e28c Leszek Koltunski
    float[][] verts = getVertices(mVertexArray,pos,variant);
876
    int[][] inds    = getIndices(mVertexArray);
877 b8b71f52 Leszek Koltunski
878 b442e28c Leszek Koltunski
    compressVerticesAndIndices(variant,verts,inds);
879 b8b71f52 Leszek Koltunski
880 b442e28c Leszek Koltunski
    return new ObjectShape(mVertices[variant], mIndices[variant]);
881 b8b71f52 Leszek Koltunski
    }
882
883 b442e28c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
884 a7c10d03 Leszek Koltunski
885 b442e28c Leszek Koltunski
  private void debug(float[][] vert, int[][] ind)
886 b8b71f52 Leszek Koltunski
    {
887 b442e28c Leszek Koltunski
    String vv="VERTICES: ";
888
    for (float[] floats : vert)
889
      {
890
      vv += "\n";
891
      int lenV2 = floats.length / 3;
892
893
      for (int v2 = 0; v2 < lenV2; v2++)
894
        {
895
        vv += " {";
896
        vv += (floats[3 * v2] + " ");
897
        vv += (floats[3 * v2 + 1] + " ");
898
        vv += (floats[3 * v2 + 2] + " ");
899
        vv += "}";
900
        }
901
      }
902
    android.util.Log.e("D", vv);
903
904
    String ii="INDICES: ";
905
    for (int[] ints : ind)
906
      {
907
      ii += "\n";
908
      int lenI2 = ints.length;
909
910
      for (int i2 = 0; i2 < lenI2; i2++)
911
        {
912
        ii += (ints[i2] + " ");
913
        }
914
      }
915
    android.util.Log.e("D", ii);
916 a7c10d03 Leszek Koltunski
    }
917
918
///////////////////////////////////////////////////////////////////////////////////////////////////
919
920 db758bd0 Leszek Koltunski
  public ObjectFaceShape createIrregularFaceShape(int variant, boolean iconMode, boolean roundCorners)
921 a7c10d03 Leszek Koltunski
    {
922 01a68e12 Leszek Koltunski
    float height   = iconMode ? 0.001f : 0.048f;
923 3bf19410 Leszek Koltunski
    int angle      = 60;
924
    float R        = 0.2f;
925 3ece88b8 Leszek Koltunski
    float S        = 0.5f;
926 3bf19410 Leszek Koltunski
    int numVertices= 5;
927 3ece88b8 Leszek Koltunski
    int extraI     = 0;
928
    int extraV     = 0;
929 b0638b61 Leszek Koltunski
930 5987822f Leszek Koltunski
    float[][] corners   = { {0.02f,0.12f} };
931 3bf19410 Leszek Koltunski
    float[][] bands     = { {  0.001f,angle,R,S,numVertices,extraV,extraI},
932
                            {height/1,angle,R,S,numVertices,extraV,extraI},
933
                            {height/2,angle,R,S,numVertices,extraV,extraI},
934
                            {height/3,angle,R,S,numVertices,extraV,extraI} };
935 a7c10d03 Leszek Koltunski
936 29ad5fc9 Leszek Koltunski
    int[] bandIndices   = generateBandIndices(mVertices[variant], mIndices[variant], mMove[variant]);
937 db758bd0 Leszek Koltunski
    int[] cornerIndices = generateCornerIndices(mVertices[variant], roundCorners);
938 5987822f Leszek Koltunski
    float[][] vertexVec = generateVectors(mVertices[variant], mIndices[variant], bandIndices);
939
    float[][] centers   = generateCenters(mVertices[variant], vertexVec);
940
    int[] centerIndices = generateCenterIndices(vertexVec);
941 a7c10d03 Leszek Koltunski
942
    return new ObjectFaceShape(bands,bandIndices,corners,cornerIndices,centers,centerIndices,null);
943
    }
944 12aa6192 Leszek Koltunski
945
///////////////////////////////////////////////////////////////////////////////////////////////////
946
947 52e3d46b Leszek Koltunski
  public MeshBase createMesh(float[] pos, int x, int y, int z, boolean iconMode, boolean roundCorners)
948 12aa6192 Leszek Koltunski
    {
949 52e3d46b Leszek Koltunski
    prepare(1,x,y,z);
950 12aa6192 Leszek Koltunski
    ObjectShape shape    = createIrregularShape(0,pos);
951 db758bd0 Leszek Koltunski
    ObjectFaceShape face = createIrregularFaceShape(0,iconMode,roundCorners);
952 12aa6192 Leszek Koltunski
    int[][] indices      = shape.getVertIndices();
953
    int numComponents    = indices.length;
954
955
    FactoryCubit factory = FactoryCubit.getInstance();
956 1c55e462 Leszek Koltunski
    factory.clear();
957 12aa6192 Leszek Koltunski
    factory.createNewFaceTransform(shape,null);
958
    return factory.createRoundedSolid(shape,face,MESH_NICE,numComponents);
959
    }
960 a7c10d03 Leszek Koltunski
  }