Project

General

Profile

« Previous | Next » 

Revision b1f0d55d

Added by Leszek Koltunski over 3 years ago

Bandaged: generalize the FactoryBandagedCubit to be able to create bandaged cubits of any cuboid NxMxK where 1<=N,M,K<=5.

View differences:

src/main/java/org/distorted/objectlib/helpers/FactoryBandaged3x3Cubit.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
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
import org.distorted.library.mesh.MeshBase;
25
import org.distorted.library.type.Static3D;
26
import org.distorted.objectlib.touchcontrol.TouchControlHexahedron;
27

  
28
import static org.distorted.objectlib.main.TwistyObject.MESH_NICE;
29

  
30
///////////////////////////////////////////////////////////////////////////////////////////////////
31

  
32
public class FactoryBandaged3x3Cubit
33
  {
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
  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
  private static FactoryBandaged3x3Cubit mThis;
57
  private ArrayList<float[]> mVertexArray;
58
  private ArrayList<float[]> mTmpArray;
59
  private float[][][] mVertices;
60
  private int[][][] mIndices;
61
  private float[][] mMove;
62
  private final int[] mWall;
63
  private final int[][] mPoints;
64
  private final boolean[][][] mTmp;
65

  
66
///////////////////////////////////////////////////////////////////////////////////////////////////
67

  
68
  private FactoryBandaged3x3Cubit()
69
    {
70
    mWall= new int[9];
71
    mPoints = new int[4][4];
72
    mTmp = new boolean[3][3][3];
73
    }
74

  
75
///////////////////////////////////////////////////////////////////////////////////////////////////
76

  
77
  private float[][] getVertices(ArrayList<float[]> list, float[] move, int variant)
78
    {
79
    int numMoves = move.length/3;
80
    mMove[variant][0]=0.0f;
81
    mMove[variant][1]=0.0f;
82
    mMove[variant][2]=0.0f;
83

  
84
    for(int m=0; m<numMoves; m++)
85
      {
86
      mMove[variant][0] += move[3*m  ];
87
      mMove[variant][1] += move[3*m+1];
88
      mMove[variant][2] += move[3*m+2];
89
      }
90

  
91
    mMove[variant][0]/=numMoves;
92
    mMove[variant][1]/=numMoves;
93
    mMove[variant][2]/=numMoves;
94

  
95
    int total  = 0;
96
    int length = list.size();
97
    float[][] vertices = new float[length][];
98

  
99
    for( int i=0; i<length; i++ )
100
      {
101
      vertices[i] = list.get(i);
102
      total += vertices[i].length/3;
103
      }
104

  
105
    float[][] verts = new float[total][3];
106
    int pointer = 0;
107

  
108
    for(int i=0; i<length; i++)
109
      {
110
      int len = vertices[i].length/3;
111

  
112
      for(int j=0; j<len; j++)
113
        {
114
        verts[pointer][0] = vertices[i][3*j  ] - mMove[variant][0];
115
        verts[pointer][1] = vertices[i][3*j+1] - mMove[variant][1];
116
        verts[pointer][2] = vertices[i][3*j+2] - mMove[variant][2];
117
        pointer++;
118
        }
119
      }
120

  
121
    return verts;
122
    }
123

  
124
///////////////////////////////////////////////////////////////////////////////////////////////////
125

  
126
  private int[][] getIndices(ArrayList<float[]> list)
127
    {
128
    int indicesSoFar=0;
129
    int length = list.size();
130
    int[][] indices = new int[length][];
131

  
132
    for( int i=0; i<length; i++ )
133
      {
134
      float[] f = list.get(i);
135
      int len = f.length/3;
136
      int[] ind = new int[len];
137
      for(int j=0; j<len; j++) ind[j] = (indicesSoFar++);
138
      indices[i] = ind;
139
      }
140

  
141
    return indices;
142
    }
143

  
144
///////////////////////////////////////////////////////////////////////////////////////////////////
145

  
146
  private void markAllVertices(float[] vertex, float[][] vertices, int[][] indices, int pointer, int variant)
147
    {
148
    int lenI = indices.length;
149

  
150
    for(int index=0; index<lenI; index++)
151
      {
152
      int len = indices[index].length;
153

  
154
      for(int i=0; i<len; i++)
155
        {
156
        if( mIndices[variant][index][i] == -1 )
157
          {
158
          int ind = indices[index][i];
159
          float[] ver = vertices[ind];
160

  
161
          if( vertex[0]==ver[0] && vertex[1]==ver[1] && vertex[2]==ver[2] )
162
            {
163
            mIndices[variant][index][i] = pointer;
164
            }
165
          }
166
        }
167
      }
168
    }
169

  
170
///////////////////////////////////////////////////////////////////////////////////////////////////
171
// So far the 'vertices/indices' are stored inefficiently, with each vertex stored three times
172
// (each one normally is a corner of three faces) or even six times. Compress!
173
// Example of six times: the central vertex here:
174
//
175
// { 1.0f,  0.0f, -1.0f,
176
//   1.0f, -1.0f, -1.0f,
177
//   1.0f, -1.0f, +0.0f,
178
//   0.0f, -1.0f, -1.0f },
179

  
180
  private void compressVerticesAndIndices(int variant, float[][] vertices, int[][] indices)
181
    {
182
    if( mTmpArray==null ) mTmpArray = new ArrayList<>();
183

  
184
    int lenI = indices.length;
185
    int pointer=0;
186

  
187
    mIndices[variant] = new int[lenI][];
188

  
189
    for(int index=0; index<lenI; index++)
190
      {
191
      int len = indices[index].length;
192
      mIndices[variant][index] = new int[len];
193
      for(int i=0; i<len; i++) mIndices[variant][index][i] = -1;
194
      }
195

  
196
    for(int index=0; index<lenI; index++)
197
      {
198
      int len = indices[index].length;
199

  
200
      for(int i=0; i<len; i++)
201
        {
202
        if( mIndices[variant][index][i] == -1 )
203
          {
204
          int ind = indices[index][i];
205
          float[] ver = vertices[ind];
206
          mTmpArray.add(ver);
207
          markAllVertices(ver,vertices,indices,pointer,variant);
208
          pointer++;
209
          }
210
        }
211
      }
212

  
213
    int len = mTmpArray.size();
214
    mVertices[variant] = new float[len][];
215

  
216
    for(int i=0; i<len; i++)
217
      {
218
      mVertices[variant][i] = mTmpArray.remove(0);
219
      }
220
    }
221

  
222
///////////////////////////////////////////////////////////////////////////////////////////////////
223

  
224
  private boolean cubitExists(float[] pos, float x, float y, float z)
225
    {
226
    int len = pos.length/3;
227

  
228
    for(int i=0; i<len; i++)
229
      if( pos[3*i]==x && pos[3*i+1]==y && pos[3*i+2]==z ) return true;
230

  
231
    return false;
232
    }
233

  
234
///////////////////////////////////////////////////////////////////////////////////////////////////
235

  
236
  private void createRight0(ArrayList<float[]> list)
237
    {
238
    mWall[0] = (mTmp[0][2][2] && !mTmp[1][2][2]) ? WALL_MARKED:WALL_EMPTY;
239
    mWall[1] = (mTmp[0][2][1] && !mTmp[1][2][1]) ? WALL_MARKED:WALL_EMPTY;
240
    mWall[2] = (mTmp[0][2][0] && !mTmp[1][2][0]) ? WALL_MARKED:WALL_EMPTY;
241
    mWall[3] = (mTmp[0][1][2] && !mTmp[1][1][2]) ? WALL_MARKED:WALL_EMPTY;
242
    mWall[4] = (mTmp[0][1][1] && !mTmp[1][1][1]) ? WALL_MARKED:WALL_EMPTY;
243
    mWall[5] = (mTmp[0][1][0] && !mTmp[1][1][0]) ? WALL_MARKED:WALL_EMPTY;
244
    mWall[6] = (mTmp[0][0][2] && !mTmp[1][0][2]) ? WALL_MARKED:WALL_EMPTY;
245
    mWall[7] = (mTmp[0][0][1] && !mTmp[1][0][1]) ? WALL_MARKED:WALL_EMPTY;
246
    mWall[8] = (mTmp[0][0][0] && !mTmp[1][0][0]) ? WALL_MARKED:WALL_EMPTY;
247

  
248
    createVertices(list,mWall,AXIS_XP,0);
249
    }
250

  
251
///////////////////////////////////////////////////////////////////////////////////////////////////
252

  
253
  private void createRight1(ArrayList<float[]> list)
254
    {
255
    mWall[0] = (mTmp[1][2][2] && !mTmp[2][2][2]) ? WALL_MARKED:WALL_EMPTY;
256
    mWall[1] = (mTmp[1][2][1] && !mTmp[2][2][1]) ? WALL_MARKED:WALL_EMPTY;
257
    mWall[2] = (mTmp[1][2][0] && !mTmp[2][2][0]) ? WALL_MARKED:WALL_EMPTY;
258
    mWall[3] = (mTmp[1][1][2] && !mTmp[2][1][2]) ? WALL_MARKED:WALL_EMPTY;
259
    mWall[4] = (mTmp[1][1][1] && !mTmp[2][1][1]) ? WALL_MARKED:WALL_EMPTY;
260
    mWall[5] = (mTmp[1][1][0] && !mTmp[2][1][0]) ? WALL_MARKED:WALL_EMPTY;
261
    mWall[6] = (mTmp[1][0][2] && !mTmp[2][0][2]) ? WALL_MARKED:WALL_EMPTY;
262
    mWall[7] = (mTmp[1][0][1] && !mTmp[2][0][1]) ? WALL_MARKED:WALL_EMPTY;
263
    mWall[8] = (mTmp[1][0][0] && !mTmp[2][0][0]) ? WALL_MARKED:WALL_EMPTY;
264

  
265
    createVertices(list,mWall,AXIS_XP,1);
266
    }
267

  
268
///////////////////////////////////////////////////////////////////////////////////////////////////
269

  
270
  private void createRight2(ArrayList<float[]> list)
271
    {
272
    mWall[0] = mTmp[2][2][2] ? WALL_MARKED:WALL_EMPTY;
273
    mWall[1] = mTmp[2][2][1] ? WALL_MARKED:WALL_EMPTY;
274
    mWall[2] = mTmp[2][2][0] ? WALL_MARKED:WALL_EMPTY;
275
    mWall[3] = mTmp[2][1][2] ? WALL_MARKED:WALL_EMPTY;
276
    mWall[4] = mTmp[2][1][1] ? WALL_MARKED:WALL_EMPTY;
277
    mWall[5] = mTmp[2][1][0] ? WALL_MARKED:WALL_EMPTY;
278
    mWall[6] = mTmp[2][0][2] ? WALL_MARKED:WALL_EMPTY;
279
    mWall[7] = mTmp[2][0][1] ? WALL_MARKED:WALL_EMPTY;
280
    mWall[8] = mTmp[2][0][0] ? WALL_MARKED:WALL_EMPTY;
281

  
282
    createVertices(list,mWall,AXIS_XP,2);
283
    }
284

  
285
///////////////////////////////////////////////////////////////////////////////////////////////////
286

  
287
  private void createLeft0(ArrayList<float[]> list)
288
    {
289
    mWall[0] = mTmp[0][2][0] ? WALL_MARKED:WALL_EMPTY;
290
    mWall[1] = mTmp[0][2][1] ? WALL_MARKED:WALL_EMPTY;
291
    mWall[2] = mTmp[0][2][2] ? WALL_MARKED:WALL_EMPTY;
292
    mWall[3] = mTmp[0][1][0] ? WALL_MARKED:WALL_EMPTY;
293
    mWall[4] = mTmp[0][1][1] ? WALL_MARKED:WALL_EMPTY;
294
    mWall[5] = mTmp[0][1][2] ? WALL_MARKED:WALL_EMPTY;
295
    mWall[6] = mTmp[0][0][0] ? WALL_MARKED:WALL_EMPTY;
296
    mWall[7] = mTmp[0][0][1] ? WALL_MARKED:WALL_EMPTY;
297
    mWall[8] = mTmp[0][0][2] ? WALL_MARKED:WALL_EMPTY;
298

  
299
    createVertices(list,mWall,AXIS_XM,0);
300
    }
301

  
302
///////////////////////////////////////////////////////////////////////////////////////////////////
303

  
304
  private void createLeft1(ArrayList<float[]> list)
305
    {
306
    mWall[0] = (!mTmp[0][2][0] && mTmp[1][2][0]) ? WALL_MARKED:WALL_EMPTY;
307
    mWall[1] = (!mTmp[0][2][1] && mTmp[1][2][1]) ? WALL_MARKED:WALL_EMPTY;
308
    mWall[2] = (!mTmp[0][2][2] && mTmp[1][2][2]) ? WALL_MARKED:WALL_EMPTY;
309
    mWall[3] = (!mTmp[0][1][0] && mTmp[1][1][0]) ? WALL_MARKED:WALL_EMPTY;
310
    mWall[4] = (!mTmp[0][1][1] && mTmp[1][1][1]) ? WALL_MARKED:WALL_EMPTY;
311
    mWall[5] = (!mTmp[0][1][2] && mTmp[1][1][2]) ? WALL_MARKED:WALL_EMPTY;
312
    mWall[6] = (!mTmp[0][0][0] && mTmp[1][0][0]) ? WALL_MARKED:WALL_EMPTY;
313
    mWall[7] = (!mTmp[0][0][1] && mTmp[1][0][1]) ? WALL_MARKED:WALL_EMPTY;
314
    mWall[8] = (!mTmp[0][0][2] && mTmp[1][0][2]) ? WALL_MARKED:WALL_EMPTY;
315

  
316
    createVertices(list,mWall,AXIS_XM,1);
317
    }
318

  
319
///////////////////////////////////////////////////////////////////////////////////////////////////
320

  
321
  private void createLeft2(ArrayList<float[]> list)
322
    {
323
    mWall[0] = (!mTmp[1][2][0] && mTmp[2][2][0]) ? WALL_MARKED:WALL_EMPTY;
324
    mWall[1] = (!mTmp[1][2][1] && mTmp[2][2][1]) ? WALL_MARKED:WALL_EMPTY;
325
    mWall[2] = (!mTmp[1][2][2] && mTmp[2][2][2]) ? WALL_MARKED:WALL_EMPTY;
326
    mWall[3] = (!mTmp[1][1][0] && mTmp[2][1][0]) ? WALL_MARKED:WALL_EMPTY;
327
    mWall[4] = (!mTmp[1][1][1] && mTmp[2][1][1]) ? WALL_MARKED:WALL_EMPTY;
328
    mWall[5] = (!mTmp[1][1][2] && mTmp[2][1][2]) ? WALL_MARKED:WALL_EMPTY;
329
    mWall[6] = (!mTmp[1][0][0] && mTmp[2][0][0]) ? WALL_MARKED:WALL_EMPTY;
330
    mWall[7] = (!mTmp[1][0][1] && mTmp[2][0][1]) ? WALL_MARKED:WALL_EMPTY;
331
    mWall[8] = (!mTmp[1][0][2] && mTmp[2][0][2]) ? WALL_MARKED:WALL_EMPTY;
332

  
333
    createVertices(list,mWall,AXIS_XM,2);
334
    }
335

  
336
///////////////////////////////////////////////////////////////////////////////////////////////////
337

  
338
  private void createTop0(ArrayList<float[]> list)
339
    {
340
    mWall[0] = (mTmp[0][0][0] && !mTmp[0][1][0]) ? WALL_MARKED:WALL_EMPTY;
341
    mWall[1] = (mTmp[1][0][0] && !mTmp[1][1][0]) ? WALL_MARKED:WALL_EMPTY;
342
    mWall[2] = (mTmp[2][0][0] && !mTmp[2][1][0]) ? WALL_MARKED:WALL_EMPTY;
343
    mWall[3] = (mTmp[0][0][1] && !mTmp[0][1][1]) ? WALL_MARKED:WALL_EMPTY;
344
    mWall[4] = (mTmp[1][0][1] && !mTmp[1][1][1]) ? WALL_MARKED:WALL_EMPTY;
345
    mWall[5] = (mTmp[2][0][1] && !mTmp[2][1][1]) ? WALL_MARKED:WALL_EMPTY;
346
    mWall[6] = (mTmp[0][0][2] && !mTmp[0][1][2]) ? WALL_MARKED:WALL_EMPTY;
347
    mWall[7] = (mTmp[1][0][2] && !mTmp[1][1][2]) ? WALL_MARKED:WALL_EMPTY;
348
    mWall[8] = (mTmp[2][0][2] && !mTmp[2][1][2]) ? WALL_MARKED:WALL_EMPTY;
349

  
350
    createVertices(list,mWall,AXIS_YP,0);
351
    }
352

  
353
///////////////////////////////////////////////////////////////////////////////////////////////////
354

  
355
  private void createTop1(ArrayList<float[]> list)
356
    {
357
    mWall[0] = (mTmp[0][1][0] && !mTmp[0][2][0]) ? WALL_MARKED:WALL_EMPTY;
358
    mWall[1] = (mTmp[1][1][0] && !mTmp[1][2][0]) ? WALL_MARKED:WALL_EMPTY;
359
    mWall[2] = (mTmp[2][1][0] && !mTmp[2][2][0]) ? WALL_MARKED:WALL_EMPTY;
360
    mWall[3] = (mTmp[0][1][1] && !mTmp[0][2][1]) ? WALL_MARKED:WALL_EMPTY;
361
    mWall[4] = (mTmp[1][1][1] && !mTmp[1][2][1]) ? WALL_MARKED:WALL_EMPTY;
362
    mWall[5] = (mTmp[2][1][1] && !mTmp[2][2][1]) ? WALL_MARKED:WALL_EMPTY;
363
    mWall[6] = (mTmp[0][1][2] && !mTmp[0][2][2]) ? WALL_MARKED:WALL_EMPTY;
364
    mWall[7] = (mTmp[1][1][2] && !mTmp[1][2][2]) ? WALL_MARKED:WALL_EMPTY;
365
    mWall[8] = (mTmp[2][1][2] && !mTmp[2][2][2]) ? WALL_MARKED:WALL_EMPTY;
366

  
367
    createVertices(list,mWall,AXIS_YP,1);
368
    }
369

  
370
///////////////////////////////////////////////////////////////////////////////////////////////////
371

  
372
  private void createTop2(ArrayList<float[]> list)
373
    {
374
    mWall[0] = mTmp[0][2][0] ? WALL_MARKED:WALL_EMPTY;
375
    mWall[1] = mTmp[1][2][0] ? WALL_MARKED:WALL_EMPTY;
376
    mWall[2] = mTmp[2][2][0] ? WALL_MARKED:WALL_EMPTY;
377
    mWall[3] = mTmp[0][2][1] ? WALL_MARKED:WALL_EMPTY;
378
    mWall[4] = mTmp[1][2][1] ? WALL_MARKED:WALL_EMPTY;
379
    mWall[5] = mTmp[2][2][1] ? WALL_MARKED:WALL_EMPTY;
380
    mWall[6] = mTmp[0][2][2] ? WALL_MARKED:WALL_EMPTY;
381
    mWall[7] = mTmp[1][2][2] ? WALL_MARKED:WALL_EMPTY;
382
    mWall[8] = mTmp[2][2][2] ? WALL_MARKED:WALL_EMPTY;
383

  
384
    createVertices(list,mWall,AXIS_YP,2);
385
    }
386

  
387
///////////////////////////////////////////////////////////////////////////////////////////////////
388

  
389
  private void createBottom0(ArrayList<float[]> list)
390
    {
391
    mWall[0] = mTmp[0][0][2] ? WALL_MARKED:WALL_EMPTY;
392
    mWall[1] = mTmp[1][0][2] ? WALL_MARKED:WALL_EMPTY;
393
    mWall[2] = mTmp[2][0][2] ? WALL_MARKED:WALL_EMPTY;
394
    mWall[3] = mTmp[0][0][1] ? WALL_MARKED:WALL_EMPTY;
395
    mWall[4] = mTmp[1][0][1] ? WALL_MARKED:WALL_EMPTY;
396
    mWall[5] = mTmp[2][0][1] ? WALL_MARKED:WALL_EMPTY;
397
    mWall[6] = mTmp[0][0][0] ? WALL_MARKED:WALL_EMPTY;
398
    mWall[7] = mTmp[1][0][0] ? WALL_MARKED:WALL_EMPTY;
399
    mWall[8] = mTmp[2][0][0] ? WALL_MARKED:WALL_EMPTY;
400

  
401
    createVertices(list,mWall,AXIS_YM,0);
402
    }
403

  
404
///////////////////////////////////////////////////////////////////////////////////////////////////
405

  
406
  private void createBottom1(ArrayList<float[]> list)
407
    {
408
    mWall[0] = (mTmp[0][1][2] && !mTmp[0][0][2]) ? WALL_MARKED:WALL_EMPTY;
409
    mWall[1] = (mTmp[1][1][2] && !mTmp[1][0][2]) ? WALL_MARKED:WALL_EMPTY;
410
    mWall[2] = (mTmp[2][1][2] && !mTmp[2][0][2]) ? WALL_MARKED:WALL_EMPTY;
411
    mWall[3] = (mTmp[0][1][1] && !mTmp[0][0][1]) ? WALL_MARKED:WALL_EMPTY;
412
    mWall[4] = (mTmp[1][1][1] && !mTmp[1][0][1]) ? WALL_MARKED:WALL_EMPTY;
413
    mWall[5] = (mTmp[2][1][1] && !mTmp[2][0][1]) ? WALL_MARKED:WALL_EMPTY;
414
    mWall[6] = (mTmp[0][1][0] && !mTmp[0][0][0]) ? WALL_MARKED:WALL_EMPTY;
415
    mWall[7] = (mTmp[1][1][0] && !mTmp[1][0][0]) ? WALL_MARKED:WALL_EMPTY;
416
    mWall[8] = (mTmp[2][1][0] && !mTmp[2][0][0]) ? WALL_MARKED:WALL_EMPTY;
417

  
418
    createVertices(list,mWall,AXIS_YM,1);
419
    }
420

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

  
423
  private void createBottom2(ArrayList<float[]> list)
424
    {
425
    mWall[0] = (mTmp[0][2][2] && !mTmp[0][1][2]) ? WALL_MARKED:WALL_EMPTY;
426
    mWall[1] = (mTmp[1][2][2] && !mTmp[1][1][2]) ? WALL_MARKED:WALL_EMPTY;
427
    mWall[2] = (mTmp[2][2][2] && !mTmp[2][1][2]) ? WALL_MARKED:WALL_EMPTY;
428
    mWall[3] = (mTmp[0][2][1] && !mTmp[0][1][1]) ? WALL_MARKED:WALL_EMPTY;
429
    mWall[4] = (mTmp[1][2][1] && !mTmp[1][1][1]) ? WALL_MARKED:WALL_EMPTY;
430
    mWall[5] = (mTmp[2][2][1] && !mTmp[2][1][1]) ? WALL_MARKED:WALL_EMPTY;
431
    mWall[6] = (mTmp[0][2][0] && !mTmp[0][1][0]) ? WALL_MARKED:WALL_EMPTY;
432
    mWall[7] = (mTmp[1][2][0] && !mTmp[1][1][0]) ? WALL_MARKED:WALL_EMPTY;
433
    mWall[8] = (mTmp[2][2][0] && !mTmp[2][1][0]) ? WALL_MARKED:WALL_EMPTY;
434

  
435
    createVertices(list,mWall,AXIS_YM,2);
436
    }
437

  
438
///////////////////////////////////////////////////////////////////////////////////////////////////
439

  
440
  private void createFront0(ArrayList<float[]> list)
441
    {
442
    mWall[0] = (mTmp[0][2][0] && !mTmp[0][2][1]) ? WALL_MARKED:WALL_EMPTY;
443
    mWall[1] = (mTmp[1][2][0] && !mTmp[1][2][1]) ? WALL_MARKED:WALL_EMPTY;
444
    mWall[2] = (mTmp[2][2][0] && !mTmp[2][2][1]) ? WALL_MARKED:WALL_EMPTY;
445
    mWall[3] = (mTmp[0][1][0] && !mTmp[0][1][1]) ? WALL_MARKED:WALL_EMPTY;
446
    mWall[4] = (mTmp[1][1][0] && !mTmp[1][1][1]) ? WALL_MARKED:WALL_EMPTY;
447
    mWall[5] = (mTmp[2][1][0] && !mTmp[2][1][1]) ? WALL_MARKED:WALL_EMPTY;
448
    mWall[6] = (mTmp[0][0][0] && !mTmp[0][0][1]) ? WALL_MARKED:WALL_EMPTY;
449
    mWall[7] = (mTmp[1][0][0] && !mTmp[1][0][1]) ? WALL_MARKED:WALL_EMPTY;
450
    mWall[8] = (mTmp[2][0][0] && !mTmp[2][0][1]) ? WALL_MARKED:WALL_EMPTY;
451

  
452
    createVertices(list,mWall,AXIS_ZP,0);
453
    }
454

  
455
///////////////////////////////////////////////////////////////////////////////////////////////////
456

  
457
  private void createFront1(ArrayList<float[]> list)
458
    {
459
    mWall[0] = (mTmp[0][2][1] && !mTmp[0][2][2]) ? WALL_MARKED:WALL_EMPTY;
460
    mWall[1] = (mTmp[1][2][1] && !mTmp[1][2][2]) ? WALL_MARKED:WALL_EMPTY;
461
    mWall[2] = (mTmp[2][2][1] && !mTmp[2][2][2]) ? WALL_MARKED:WALL_EMPTY;
462
    mWall[3] = (mTmp[0][1][1] && !mTmp[0][1][2]) ? WALL_MARKED:WALL_EMPTY;
463
    mWall[4] = (mTmp[1][1][1] && !mTmp[1][1][2]) ? WALL_MARKED:WALL_EMPTY;
464
    mWall[5] = (mTmp[2][1][1] && !mTmp[2][1][2]) ? WALL_MARKED:WALL_EMPTY;
465
    mWall[6] = (mTmp[0][0][1] && !mTmp[0][0][2]) ? WALL_MARKED:WALL_EMPTY;
466
    mWall[7] = (mTmp[1][0][1] && !mTmp[1][0][2]) ? WALL_MARKED:WALL_EMPTY;
467
    mWall[8] = (mTmp[2][0][1] && !mTmp[2][0][2]) ? WALL_MARKED:WALL_EMPTY;
468

  
469
    createVertices(list,mWall,AXIS_ZP,1);
470
    }
471

  
472
///////////////////////////////////////////////////////////////////////////////////////////////////
473

  
474
  private void createFront2(ArrayList<float[]> list)
475
    {
476
    mWall[0] = mTmp[0][2][2] ? WALL_MARKED:WALL_EMPTY;
477
    mWall[1] = mTmp[1][2][2] ? WALL_MARKED:WALL_EMPTY;
478
    mWall[2] = mTmp[2][2][2] ? WALL_MARKED:WALL_EMPTY;
479
    mWall[3] = mTmp[0][1][2] ? WALL_MARKED:WALL_EMPTY;
480
    mWall[4] = mTmp[1][1][2] ? WALL_MARKED:WALL_EMPTY;
481
    mWall[5] = mTmp[2][1][2] ? WALL_MARKED:WALL_EMPTY;
482
    mWall[6] = mTmp[0][0][2] ? WALL_MARKED:WALL_EMPTY;
483
    mWall[7] = mTmp[1][0][2] ? WALL_MARKED:WALL_EMPTY;
484
    mWall[8] = mTmp[2][0][2] ? WALL_MARKED:WALL_EMPTY;
485

  
486
    createVertices(list,mWall,AXIS_ZP,2);
487
    }
488

  
489
///////////////////////////////////////////////////////////////////////////////////////////////////
490

  
491
  private void createBack0(ArrayList<float[]> list)
492
    {
493
    mWall[0] = mTmp[2][2][0] ? WALL_MARKED:WALL_EMPTY;
494
    mWall[1] = mTmp[1][2][0] ? WALL_MARKED:WALL_EMPTY;
495
    mWall[2] = mTmp[0][2][0] ? WALL_MARKED:WALL_EMPTY;
496
    mWall[3] = mTmp[2][1][0] ? WALL_MARKED:WALL_EMPTY;
497
    mWall[4] = mTmp[1][1][0] ? WALL_MARKED:WALL_EMPTY;
498
    mWall[5] = mTmp[0][1][0] ? WALL_MARKED:WALL_EMPTY;
499
    mWall[6] = mTmp[2][0][0] ? WALL_MARKED:WALL_EMPTY;
500
    mWall[7] = mTmp[1][0][0] ? WALL_MARKED:WALL_EMPTY;
501
    mWall[8] = mTmp[0][0][0] ? WALL_MARKED:WALL_EMPTY;
502

  
503
    createVertices(list,mWall,AXIS_ZM,0);
504
    }
505

  
506
///////////////////////////////////////////////////////////////////////////////////////////////////
507

  
508
  private void createBack1(ArrayList<float[]> list)
509
    {
510
    mWall[0] = (mTmp[2][2][1] && !mTmp[2][2][0]) ? WALL_MARKED:WALL_EMPTY;
511
    mWall[1] = (mTmp[1][2][1] && !mTmp[1][2][0]) ? WALL_MARKED:WALL_EMPTY;
512
    mWall[2] = (mTmp[0][2][1] && !mTmp[0][2][0]) ? WALL_MARKED:WALL_EMPTY;
513
    mWall[3] = (mTmp[2][1][1] && !mTmp[2][1][0]) ? WALL_MARKED:WALL_EMPTY;
514
    mWall[4] = (mTmp[1][1][1] && !mTmp[1][1][0]) ? WALL_MARKED:WALL_EMPTY;
515
    mWall[5] = (mTmp[0][1][1] && !mTmp[0][1][0]) ? WALL_MARKED:WALL_EMPTY;
516
    mWall[6] = (mTmp[2][0][1] && !mTmp[2][0][0]) ? WALL_MARKED:WALL_EMPTY;
517
    mWall[7] = (mTmp[1][0][1] && !mTmp[1][0][0]) ? WALL_MARKED:WALL_EMPTY;
518
    mWall[8] = (mTmp[0][0][1] && !mTmp[0][0][0]) ? WALL_MARKED:WALL_EMPTY;
519

  
520
    createVertices(list,mWall,AXIS_ZM,1);
521
    }
522

  
523
///////////////////////////////////////////////////////////////////////////////////////////////////
524

  
525
  private void createBack2(ArrayList<float[]> list)
526
    {
527
    mWall[0] = (mTmp[2][2][2] && !mTmp[2][2][1]) ? WALL_MARKED:WALL_EMPTY;
528
    mWall[1] = (mTmp[1][2][2] && !mTmp[1][2][1]) ? WALL_MARKED:WALL_EMPTY;
529
    mWall[2] = (mTmp[0][2][2] && !mTmp[0][2][1]) ? WALL_MARKED:WALL_EMPTY;
530
    mWall[3] = (mTmp[2][1][2] && !mTmp[2][1][1]) ? WALL_MARKED:WALL_EMPTY;
531
    mWall[4] = (mTmp[1][1][2] && !mTmp[1][1][1]) ? WALL_MARKED:WALL_EMPTY;
532
    mWall[5] = (mTmp[0][1][2] && !mTmp[0][1][1]) ? WALL_MARKED:WALL_EMPTY;
533
    mWall[6] = (mTmp[2][0][2] && !mTmp[2][0][1]) ? WALL_MARKED:WALL_EMPTY;
534
    mWall[7] = (mTmp[1][0][2] && !mTmp[1][0][1]) ? WALL_MARKED:WALL_EMPTY;
535
    mWall[8] = (mTmp[0][0][2] && !mTmp[0][0][1]) ? WALL_MARKED:WALL_EMPTY;
536

  
537
    createVertices(list,mWall,AXIS_ZM,2);
538
    }
539

  
540
///////////////////////////////////////////////////////////////////////////////////////////////////
541

  
542
  private void markNeighbours(int[] wall, int index, int section)
543
    {
544
    wall[index] = section;
545

  
546
    switch(index)
547
      {
548
      case 0: if( wall[1]==WALL_MARKED ) markNeighbours(wall,1,section);
549
              if( wall[3]==WALL_MARKED ) markNeighbours(wall,3,section);
550
              break;
551
      case 1: if( wall[0]==WALL_MARKED ) markNeighbours(wall,0,section);
552
              if( wall[2]==WALL_MARKED ) markNeighbours(wall,2,section);
553
              if( wall[4]==WALL_MARKED ) markNeighbours(wall,4,section);
554
              break;
555
      case 2: if( wall[1]==WALL_MARKED ) markNeighbours(wall,1,section);
556
              if( wall[5]==WALL_MARKED ) markNeighbours(wall,5,section);
557
              break;
558
      case 3: if( wall[0]==WALL_MARKED ) markNeighbours(wall,0,section);
559
              if( wall[4]==WALL_MARKED ) markNeighbours(wall,4,section);
560
              if( wall[6]==WALL_MARKED ) markNeighbours(wall,6,section);
561
              break;
562
      case 4: if( wall[1]==WALL_MARKED ) markNeighbours(wall,1,section);
563
              if( wall[3]==WALL_MARKED ) markNeighbours(wall,3,section);
564
              if( wall[5]==WALL_MARKED ) markNeighbours(wall,5,section);
565
              if( wall[7]==WALL_MARKED ) markNeighbours(wall,7,section);
566
              break;
567
      case 5: if( wall[2]==WALL_MARKED ) markNeighbours(wall,2,section);
568
              if( wall[4]==WALL_MARKED ) markNeighbours(wall,4,section);
569
              if( wall[8]==WALL_MARKED ) markNeighbours(wall,8,section);
570
              break;
571
      case 6: if( wall[3]==WALL_MARKED ) markNeighbours(wall,3,section);
572
              if( wall[7]==WALL_MARKED ) markNeighbours(wall,7,section);
573
              break;
574
      case 7: if( wall[4]==WALL_MARKED ) markNeighbours(wall,4,section);
575
              if( wall[6]==WALL_MARKED ) markNeighbours(wall,6,section);
576
              if( wall[8]==WALL_MARKED ) markNeighbours(wall,8,section);
577
              break;
578
      case 8: if( wall[5]==WALL_MARKED ) markNeighbours(wall,5,section);
579
              if( wall[7]==WALL_MARKED ) markNeighbours(wall,7,section);
580
              break;
581
      }
582
    }
583

  
584
///////////////////////////////////////////////////////////////////////////////////////////////////
585

  
586
  private int markSections(int[] wall)
587
    {
588
    int sections = 0;
589

  
590
    for(int i=0; i<9; i++)
591
      if( wall[i]==WALL_MARKED )
592
        {
593
        sections++;
594
        markNeighbours(wall,i,sections);
595
        }
596

  
597
    return sections;
598
    }
599

  
600
///////////////////////////////////////////////////////////////////////////////////////////////////
601
// return true iff exactly three or exactly one of the four values (x1,x2,x3,x4) are equal to 'value'.
602

  
603
  private boolean threeOrOne(int x1, int x2, int x3, int x4, int value)
604
    {
605
    if( x1==value ) return x2==value ? (x3==value)^(x4==value) : (x3==value)^(x4!=value);
606
    else            return x2==value ? (x3==value)^(x4!=value) : (x3==value)^(x4==value);
607
    }
608

  
609
///////////////////////////////////////////////////////////////////////////////////////////////////
610

  
611
  private int buildPoints(int[] wall, int section)
612
    {
613
    mPoints[0][0] = (wall[0]==section                   ) ? 0 : -1;
614
    mPoints[1][0] = (wall[0]==section)^(wall[1]==section) ? 0 : -1;
615
    mPoints[2][0] = (wall[1]==section)^(wall[2]==section) ? 0 : -1;
616
    mPoints[3][0] = (wall[2]==section                   ) ? 0 : -1;
617
    mPoints[0][1] = (wall[0]==section)^(wall[3]==section) ? 0 : -1;
618
    mPoints[1][1] = threeOrOne(wall[0],wall[1],wall[3],wall[4],section) ? 0 : -1;
619
    mPoints[2][1] = threeOrOne(wall[1],wall[2],wall[4],wall[5],section) ? 0 : -1;
620
    mPoints[3][1] = (wall[2]==section)^(wall[5]==section) ? 0 : -1;
621
    mPoints[0][2] = (wall[3]==section)^(wall[6]==section) ? 0 : -1;
622
    mPoints[1][2] = threeOrOne(wall[3],wall[4],wall[6],wall[7],section) ? 0 : -1;
623
    mPoints[2][2] = threeOrOne(wall[4],wall[5],wall[7],wall[8],section) ? 0 : -1;
624
    mPoints[3][2] = (wall[5]==section)^(wall[8]==section) ? 0 : -1;
625
    mPoints[0][3] = (wall[6]==section                   ) ? 0 : -1;
626
    mPoints[1][3] = (wall[6]==section)^(wall[7]==section) ? 0 : -1;
627
    mPoints[2][3] = (wall[7]==section)^(wall[8]==section) ? 0 : -1;
628
    mPoints[3][3] = (wall[8]==section                   ) ? 0 : -1;
629

  
630
    int numPoints=0;
631

  
632
    for(int i=0; i<4; i++)
633
      for(int j=0; j<4; j++)
634
        {
635
        if( mPoints[i][j]==0 ) numPoints++;
636
        }
637

  
638
    return numPoints;
639
    }
640

  
641
///////////////////////////////////////////////////////////////////////////////////////////////////
642

  
643
  private boolean isOddVertical(int x, int y)
644
    {
645
    int number = 0;
646

  
647
    for(int i=0; i<y; i++)
648
      if( mPoints[x][i]==0 ) number++;
649

  
650
    return (number%2)==0;
651
    }
652

  
653
///////////////////////////////////////////////////////////////////////////////////////////////////
654

  
655
  private boolean isOddHorizontal(int x, int y)
656
    {
657
    int number = 0;
658

  
659
    for(int i=0; i<x; i++)
660
      if( mPoints[i][y]==0 ) number++;
661

  
662
    return (number%2)==0;
663
    }
664

  
665
///////////////////////////////////////////////////////////////////////////////////////////////////
666

  
667
  private int moveUp(int x, int y)
668
    {
669
    for(int i=y-1; i>=0; i--)
670
      if( mPoints[x][i]==0 ) return i;
671

  
672
    android.util.Log.e("D", "moveUp error!");
673
    return 0;
674
    }
675

  
676
///////////////////////////////////////////////////////////////////////////////////////////////////
677

  
678
  private int moveDown(int x, int y)
679
    {
680
    for(int i=y+1; i<4; i++)
681
      if( mPoints[x][i]==0 ) return i;
682

  
683
    android.util.Log.e("D", "moveDown error!");
684
    return 0;
685
    }
686

  
687
///////////////////////////////////////////////////////////////////////////////////////////////////
688

  
689
  private int moveLeft(int x, int y)
690
    {
691
    for(int i=x-1; i>=0; i--)
692
      if( mPoints[i][y]==0 ) return i;
693

  
694
    android.util.Log.e("D", "moveLeft error!");
695
    return 0;
696
    }
697

  
698
///////////////////////////////////////////////////////////////////////////////////////////////////
699

  
700
  private int moveRight(int x, int y)
701
    {
702
    for(int i=x+1; i<4; i++)
703
      if( mPoints[i][y]==0 ) return i;
704

  
705
    android.util.Log.e("D", "moveRight error!");
706
    return 0;
707
    }
708

  
709
///////////////////////////////////////////////////////////////////////////////////////////////////
710

  
711
  private float[] buildVertices(int[] wall, int section)
712
    {
713
    int numPoints = buildPoints(wall,section);
714
    int numSections = numPoints/2;
715
    float[] vertices = new float[3*numPoints];
716
    int x=0,y=0,pointer=0;
717

  
718
    for(int i=0; i<4; i++)
719
      for(int j=0; j<4; j++)
720
        if( mPoints[i][j]==0 )
721
          {
722
          x = i;
723
          y = j;
724
          i = j = 4;
725
          }
726

  
727
    for(int s=0; s<numSections; s++)
728
      {
729
      vertices[6*pointer  ] = x-1.5f;
730
      vertices[6*pointer+1] = 1.5f-y;
731
      vertices[6*pointer+2] = 0.0f;
732

  
733
      y = isOddVertical(x,y) ? moveDown(x,y) : moveUp(x,y);
734

  
735
      vertices[6*pointer+3] = x-1.5f;
736
      vertices[6*pointer+4] = 1.5f-y;
737
      vertices[6*pointer+5] = 0.0f;
738

  
739
      x = isOddHorizontal(x,y) ? moveRight(x,y) : moveLeft(x,y);
740

  
741
      pointer++;
742
      }
743

  
744
    return vertices;
745
    }
746

  
747
///////////////////////////////////////////////////////////////////////////////////////////////////
748

  
749
  private void rotateAndMoveVertices(float[] vertices, int axis, int layer)
750
    {
751
    int i,len = vertices.length/3;
752

  
753
    switch(axis)
754
      {
755
      case AXIS_XP: for(i=0; i<len; i++)
756
                      {
757
                      vertices[3*i+2] = -vertices[3*i];
758
                      vertices[3*i  ] = layer-0.5f;
759
                      }
760
                    break;
761
      case AXIS_XM: for(i=0; i<len; i++)
762
                      {
763
                      vertices[3*i+2] = vertices[3*i];
764
                      vertices[3*i  ] = layer-1.5f;
765
                      }
766
                    break;
767
      case AXIS_YP: for(i=0; i<len; i++)
768
                      {
769
                      vertices[3*i+2] = -vertices[3*i+1];
770
                      vertices[3*i+1] = layer-0.5f;
771
                      }
772
                    break;
773
      case AXIS_YM: for(i=0; i<len; i++)
774
                      {
775
                      vertices[3*i+2] = vertices[3*i+1];
776
                      vertices[3*i+1] = layer-1.5f;
777
                      }
778
                    break;
779
      case AXIS_ZP: for(i=0; i<len; i++)
780
                      {
781
                      vertices[3*i+2] = layer-0.5f;
782
                      }
783
                    break;
784
      case AXIS_ZM: for(i=0; i<len; i++)
785
                      {
786
                      vertices[3*i  ] = -vertices[3*i];
787
                      vertices[3*i+2] = layer-1.5f;
788
                      }
789
                    break;
790
      }
791
    }
792

  
793
///////////////////////////////////////////////////////////////////////////////////////////////////
794
// 1. assume the 'wall' is in the XY plane
795
// 2. split the wall into individual connected regions and for each such region:
796
//   a. build the list of vertices (Z=0)
797
//   b. take the axis into consideration and rotate the vertices.
798
//   c. take layer into consideration and move the vertices.
799
//   d. add the resulting vertices to the list.
800

  
801
  private void createVertices(ArrayList<float[]> list, int[] wall, int axis, int layer)
802
    {
803
    int sections = markSections(wall);
804

  
805
    for(int i=0; i<sections; i++)
806
      {
807
      float[] vertices = buildVertices(wall,i+1);
808

  
809
      rotateAndMoveVertices(vertices,axis,layer);
810
      list.add(vertices);
811
/*
812
      int len = vertices.length/3;
813
      String w="";
814

  
815
      for(int j=0; j<len; j++)
816
        {
817
        w += ( "["+vertices[3*j]+" "+vertices[3*j+1]+" "+vertices[3*j+2]+"] ");
818
        }
819
      android.util.Log.e("D", i+" vertices after: "+w);
820
*/
821
      }
822
    }
823

  
824
///////////////////////////////////////////////////////////////////////////////////////////////////
825

  
826
  private static boolean vertInFace(float[] vertex, float[] move, Static3D faceAxis, float dist)
827
    {
828
    final float MAX_ERROR = 0.01f;
829

  
830
    float x= faceAxis.get0();
831
    float y= faceAxis.get1();
832
    float z= faceAxis.get2();
833

  
834
    float a = (vertex[0]+move[0])*x + (vertex[1]+move[1])*y + (vertex[2]+move[2])*z;
835
    float diff = a - dist;
836

  
837
    return diff>-MAX_ERROR && diff<MAX_ERROR;
838
    }
839

  
840
///////////////////////////////////////////////////////////////////////////////////////////////////
841
// (vertices,indices) define a cubit face, i.e. a connected subset of the 3x3 grid.
842
// Return its 'diameter', i.e. max(width,height)
843

  
844
  private int faceDiameter(float[][] vertices, int[] indices)
845
    {
846
    float maxX = -1.5f;
847
    float minX = +1.5f;
848
    float maxY = -1.5f;
849
    float minY = +1.5f;
850
    float maxZ = -1.5f;
851
    float minZ = +1.5f;
852

  
853
    for (int index : indices)
854
      {
855
      float[] v = vertices[index];
856

  
857
      if (v[0] > maxX) maxX = v[0];
858
      if (v[0] < minX) minX = v[0];
859
      if (v[1] > maxY) maxY = v[1];
860
      if (v[1] < minY) minY = v[1];
861
      if (v[2] > maxZ) maxZ = v[2];
862
      if (v[2] < minZ) minZ = v[2];
863
      }
864

  
865
    float diffX = maxX-minX;
866
    float diffY = maxY-minY;
867
    float diffZ = maxZ-minZ;
868

  
869
    float max = diffX>diffY ? Math.max(diffX,diffZ) : Math.max(diffY,diffZ);
870

  
871
    return (int)max;
872
    }
873

  
874
///////////////////////////////////////////////////////////////////////////////////////////////////
875
// return array of:
876
// 0 if this is an inner face, 1 if its diameter is 1, 2 if diameter is 2, 3 if 3.
877

  
878
  private int[] generateBandIndices(float[][] vertices, int[][] indices, float[] move)
879
    {
880
    int numCubitFaces = indices.length;
881
    int[] bandIndices = new int[numCubitFaces];
882

  
883
    for(int cubitFace=0; cubitFace<numCubitFaces; cubitFace++)
884
      {
885
      bandIndices[cubitFace] = 0xffffffff;
886
      int numVertices = indices[cubitFace].length;
887

  
888
      for(int vertex=0; vertex<numVertices; vertex++)
889
        {
890
        int vertBelongsBitmap = 0x00000000;
891

  
892
        for(int face=0; face<6; face++)
893
          {
894
          float[] vert = vertices[ indices[cubitFace][vertex] ];
895
          if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[face],1.5f) )
896
            {
897
            vertBelongsBitmap |= (1<<face);
898
            }
899
          }
900

  
901
        bandIndices[cubitFace] &= vertBelongsBitmap;
902
        }
903

  
904
      if( bandIndices[cubitFace]!=0 ) // outer face
905
        {
906
        bandIndices[cubitFace] = faceDiameter(vertices, indices[cubitFace]);
907
        }
908

  
909
      //android.util.Log.e("D", "cubit face "+cubitFace+" : "+bandIndices[cubitFace]);
910
      }
911

  
912
    return bandIndices;
913
    }
914

  
915
///////////////////////////////////////////////////////////////////////////////////////////////////
916

  
917
  private int[] generateCornerIndices(float[][] vertices, boolean roundCorners)
918
    {
919
    int len = vertices.length;
920
    int val = roundCorners ? 0 : -1;
921
    int[] cornerIndices = new int[len];
922
    for(int i=0; i<len; i++) cornerIndices[i] = val;
923
    return cornerIndices;
924
    }
925

  
926
///////////////////////////////////////////////////////////////////////////////////////////////////
927

  
928
  private int computeVectorFace(float[] prev, float[] curr, float[] next)
929
    {
930
    float ax = prev[0]-curr[0];
931
    float ay = prev[1]-curr[1];
932
    float az = prev[2]-curr[2];
933

  
934
    float bx = next[0]-curr[0];
935
    float by = next[1]-curr[1];
936
    float bz = next[2]-curr[2];
937

  
938
    float lena = (float)Math.sqrt(ax*ax + ay*ay + az*az);
939
    float lenb = (float)Math.sqrt(bx*bx + by*by + bz*bz);
940

  
941
    ax /= lena;
942
    ay /= lena;
943
    az /= lena;
944

  
945
    bx /= lenb;
946
    by /= lenb;
947
    bz /= lenb;
948

  
949
    float cx = ax + bx + ay*bz-az*by;
950
    float cy = ay + by + az*bx-ax*bz;
951
    float cz = az + bz + ax*by-ay*bx;
952

  
953
    return (cx<0 ? 0:4) + (cy<0 ? 0:2) + (cz<0 ? 0:1);
954
    }
955

  
956
///////////////////////////////////////////////////////////////////////////////////////////////////
957

  
958
  private float[] computeVector(int index, float[][] vertices, int[][] indices, int[] bandIndices)
959
    {
960
    int band=0;
961
    int len = indices.length;
962
    int vector=-1;
963

  
964
    for(int i=0; i<len; i++)
965
      {
966
      int len2 = indices[i].length;
967

  
968
      for(int j=0; j<len2; j++)
969
        {
970
        if( indices[i][j]==index )
971
          {
972
          int prev = j>0 ? j-1 : len2-1;
973
          int next = j<len2-1 ? j+1 : 0;
974

  
975
          int prevIndex = indices[i][prev];
976
          int currIndex = indices[i][j];
977
          int nextIndex = indices[i][next];
978

  
979
          int newVector = computeVectorFace(vertices[prevIndex],vertices[currIndex],vertices[nextIndex]);
980
          if( vector!=-1 && vector!=newVector ) return null;
981

  
982
          vector = newVector;
983
          band |= bandIndices[i];
984
          }
985
        }
986
      }
987

  
988
    return band==0 ? null : VECTOR[vector];
989
    }
990

  
991
///////////////////////////////////////////////////////////////////////////////////////////////////
992

  
993
  private float[][] generateVectors(float[][] vertices, int[][] indices, int[] bandIndices)
994
    {
995
    int len = vertices.length;
996
    float[][] vectors = new float[len][];
997

  
998
    for(int i=0; i<len; i++)
999
      {
1000
      vectors[i] = computeVector(i,vertices,indices,bandIndices);
1001
      }
1002

  
1003
    return vectors;
1004
    }
1005

  
1006
///////////////////////////////////////////////////////////////////////////////////////////////////
1007

  
1008
  private float[][] generateCenters(float[][] vertices, float[][] vectors)
1009
    {
1010
    int pointer=0,total=0;
1011
    int len = vertices.length;
1012

  
1013
    for( float[] vector : vectors )
1014
      {
1015
      if( vector!=null ) total++;
1016
      }
1017

  
1018
    float[][] centers = new float[total][3];
1019

  
1020
    for( int i=0; i<len; i++ )
1021
      {
1022
      if( vectors[i]!=null )
1023
        {
1024
        centers[pointer][0] = vertices[i][0]+vectors[i][0];
1025
        centers[pointer][1] = vertices[i][1]+vectors[i][1];
1026
        centers[pointer][2] = vertices[i][2]+vectors[i][2];
1027
        pointer++;
1028
        }
1029
      }
1030

  
1031
    return centers;
1032
    }
1033

  
1034
///////////////////////////////////////////////////////////////////////////////////////////////////
1035

  
1036
  private int[] generateCenterIndices(float[][] vectors)
1037
    {
1038
    int pointer=0;
1039
    int len = vectors.length;
1040
    int[] centerIndices = new int[len];
1041

  
1042
    for(int i=0; i<len; i++)
1043
      {
1044
      if( vectors[i]==null )
1045
        {
1046
        centerIndices[i] = -1;
1047
        }
1048
      else
1049
        {
1050
        centerIndices[i] = pointer;
1051
        pointer++;
1052
        }
1053
      }
1054

  
1055
    return centerIndices;
1056
    }
1057

  
1058
///////////////////////////////////////////////////////////////////////////////////////////////////
1059
// PUBLIC API
1060

  
1061
  public static FactoryBandaged3x3Cubit getInstance()
1062
    {
1063
    if( mThis==null ) mThis = new FactoryBandaged3x3Cubit();
1064
    return mThis;
1065
    }
1066

  
1067
///////////////////////////////////////////////////////////////////////////////////////////////////
1068

  
1069
  public void prepare(int numVariants)
1070
    {
1071
    if( mVertexArray==null ) mVertexArray = new ArrayList<>();
1072
    mVertices= new float[numVariants][][];
1073
    mIndices = new int[numVariants][][];
1074
    mMove = new float[numVariants][3];
1075
    }
1076

  
1077
///////////////////////////////////////////////////////////////////////////////////////////////////
1078

  
1079
  public ObjectShape createIrregularShape(int variant, float[] pos)
1080
    {
1081
    mVertexArray.clear();
1082

  
1083
    for(int x=0; x<3; x++)
1084
      for(int y=0; y<3; y++)
1085
        for(int z=0; z<3; z++)
1086
          {
1087
          mTmp[x][y][z] = cubitExists(pos,x-1.0f,y-1.0f,z-1.0f);
1088
          }
1089

  
1090
    createRight0(mVertexArray);
1091
    createRight1(mVertexArray);
1092
    createRight2(mVertexArray);
1093

  
1094
    createLeft0(mVertexArray);
1095
    createLeft1(mVertexArray);
1096
    createLeft2(mVertexArray);
1097

  
1098
    createTop0(mVertexArray);
1099
    createTop1(mVertexArray);
1100
    createTop2(mVertexArray);
1101

  
1102
    createBottom0(mVertexArray);
1103
    createBottom1(mVertexArray);
1104
    createBottom2(mVertexArray);
1105

  
1106
    createFront0(mVertexArray);
1107
    createFront1(mVertexArray);
1108
    createFront2(mVertexArray);
1109

  
1110
    createBack0(mVertexArray);
1111
    createBack1(mVertexArray);
1112
    createBack2(mVertexArray);
1113

  
1114
    float[][] verts = getVertices(mVertexArray,pos,variant);
1115
    int[][] inds    = getIndices(mVertexArray);
1116

  
1117
    compressVerticesAndIndices(variant,verts,inds);
1118

  
1119
    return new ObjectShape(mVertices[variant], mIndices[variant]);
1120
    }
1121

  
1122
///////////////////////////////////////////////////////////////////////////////////////////////////
1123

  
1124
  private void debug(float[][] vert, int[][] ind)
1125
    {
1126
    String vv="VERTICES: ";
1127
    for (float[] floats : vert)
1128
      {
1129
      vv += "\n";
1130
      int lenV2 = floats.length / 3;
1131

  
1132
      for (int v2 = 0; v2 < lenV2; v2++)
1133
        {
1134
        vv += " {";
1135
        vv += (floats[3 * v2] + " ");
1136
        vv += (floats[3 * v2 + 1] + " ");
1137
        vv += (floats[3 * v2 + 2] + " ");
1138
        vv += "}";
1139
        }
1140
      }
1141
    android.util.Log.e("D", vv);
1142

  
1143
    String ii="INDICES: ";
1144
    for (int[] ints : ind)
1145
      {
1146
      ii += "\n";
1147
      int lenI2 = ints.length;
1148

  
1149
      for (int i2 = 0; i2 < lenI2; i2++)
1150
        {
1151
        ii += (ints[i2] + " ");
1152
        }
1153
      }
1154
    android.util.Log.e("D", ii);
1155
    }
1156

  
1157
///////////////////////////////////////////////////////////////////////////////////////////////////
1158

  
1159
  public ObjectFaceShape createIrregularFaceShape(int variant, boolean iconMode, boolean roundCorners)
1160
    {
1161
    float height   = iconMode ? 0.001f : 0.048f;
1162
    int angle      = 60;
1163
    float R        = 0.2f;
1164
    float S        = 0.5f;
1165
    int numVertices= 5;
1166
    int extraI     = 0;
1167
    int extraV     = 0;
1168

  
1169
    float[][] corners   = { {0.02f,0.12f} };
1170
    float[][] bands     = { {  0.001f,angle,R,S,numVertices,extraV,extraI},
1171
                            {height/1,angle,R,S,numVertices,extraV,extraI},
1172
                            {height/2,angle,R,S,numVertices,extraV,extraI},
1173
                            {height/3,angle,R,S,numVertices,extraV,extraI} };
1174

  
1175
    int[] bandIndices   = generateBandIndices(mVertices[variant], mIndices[variant], mMove[variant]);
1176
    int[] cornerIndices = generateCornerIndices(mVertices[variant], roundCorners);
1177
    float[][] vertexVec = generateVectors(mVertices[variant], mIndices[variant], bandIndices);
1178
    float[][] centers   = generateCenters(mVertices[variant], vertexVec);
1179
    int[] centerIndices = generateCenterIndices(vertexVec);
1180

  
1181
    return new ObjectFaceShape(bands,bandIndices,corners,cornerIndices,centers,centerIndices,null);
1182
    }
1183

  
1184
///////////////////////////////////////////////////////////////////////////////////////////////////
1185

  
1186
  public MeshBase createMesh(float[] pos, boolean iconMode, boolean roundCorners)
1187
    {
1188
    prepare(1);
1189
    ObjectShape shape    = createIrregularShape(0,pos);
1190
    ObjectFaceShape face = createIrregularFaceShape(0,iconMode,roundCorners);
1191
    int[][] indices      = shape.getVertIndices();
1192
    int numComponents    = indices.length;
1193

  
1194
    FactoryCubit factory = FactoryCubit.getInstance();
1195
    factory.clear();
1196
    factory.createNewFaceTransform(shape,null);
1197
    return factory.createRoundedSolid(shape,face,MESH_NICE,numComponents);
1198
    }
1199
  }
src/main/java/org/distorted/objectlib/helpers/FactoryBandagedCubit.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
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
import org.distorted.library.mesh.MeshBase;
25
import org.distorted.library.type.Static3D;
26
import org.distorted.objectlib.touchcontrol.TouchControlHexahedron;
27

  
28
import static org.distorted.objectlib.main.TwistyObject.MESH_NICE;
29

  
30
///////////////////////////////////////////////////////////////////////////////////////////////////
31

  
32
public class FactoryBandagedCubit
33
  {
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
  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
  private static FactoryBandagedCubit mThis;
57
  private ArrayList<float[]> mVertexArray;
58
  private ArrayList<float[]> mTmpArray;
59
  private float[][][] mVertices;
60
  private int[][][] mIndices;
61
  private float[][] mMove;
62

  
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

  
69
///////////////////////////////////////////////////////////////////////////////////////////////////
70

  
71
  private FactoryBandagedCubit()
72
    {
73

  
74
    }
75

  
76
///////////////////////////////////////////////////////////////////////////////////////////////////
77

  
78
  private float[][] getVertices(ArrayList<float[]> list, float[] move, int variant)
79
    {
80
    int numMoves = move.length/3;
81
    mMove[variant][0]=0.0f;
82
    mMove[variant][1]=0.0f;
83
    mMove[variant][2]=0.0f;
84

  
85
    for(int m=0; m<numMoves; m++)
86
      {
87
      mMove[variant][0] += move[3*m  ];
88
      mMove[variant][1] += move[3*m+1];
89
      mMove[variant][2] += move[3*m+2];
90
      }
91

  
92
    mMove[variant][0]/=numMoves;
93
    mMove[variant][1]/=numMoves;
94
    mMove[variant][2]/=numMoves;
95

  
96
    int total  = 0;
97
    int length = list.size();
98
    float[][] vertices = new float[length][];
99

  
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
        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
        pointer++;
119
        }
120
      }
121

  
122
    return verts;
123
    }
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
      int len = f.length/3;
137
      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
///////////////////////////////////////////////////////////////////////////////////////////////////
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
// (each one normally is a corner of three faces) or even six times. Compress!
174
// 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
///////////////////////////////////////////////////////////////////////////////////////////////////
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
  private void createRight(int x, ArrayList<float[]> list)
238
    {
239
    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

  
246
    createVertices(list,mWall,AXIS_XP,x);
247
    }
248

  
249
///////////////////////////////////////////////////////////////////////////////////////////////////
250

  
251
  private void createLeft(int x, ArrayList<float[]> list)
252
    {
253
    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

  
260
    createVertices(list,mWall,AXIS_XM,x);
261
    }
262

  
263
///////////////////////////////////////////////////////////////////////////////////////////////////
264

  
265
  private void createTop(int y, ArrayList<float[]> list)
266
    {
267
    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

  
274
    createVertices(list,mWall,AXIS_YP,y);
275
    }
276

  
277
///////////////////////////////////////////////////////////////////////////////////////////////////
278

  
279
  private void createBottom(int y, ArrayList<float[]> list)
280
    {
281
    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]) );
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff