Project

General

Profile

Download (13.2 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / bandaged / BandagedObject.java @ afd7e804

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2023 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9

    
10
package org.distorted.bandaged;
11

    
12
import static org.distorted.objectlib.main.TwistyObject.COLOR_BLUE;
13
import static org.distorted.objectlib.main.TwistyObject.COLOR_GREEN;
14
import static org.distorted.objectlib.main.TwistyObject.COLOR_ORANGE;
15
import static org.distorted.objectlib.main.TwistyObject.COLOR_RED;
16
import static org.distorted.objectlib.main.TwistyObject.COLOR_WHITE;
17
import static org.distorted.objectlib.main.TwistyObject.COLOR_YELLOW;
18

    
19
import org.distorted.library.main.DistortedNode;
20
import org.distorted.library.main.DistortedScreen;
21
import org.distorted.library.mesh.MeshBase;
22
import org.distorted.library.type.Static3D;
23
import org.distorted.library.type.Static4D;
24
import org.distorted.objectlib.helpers.FactoryBandagedCubit;
25
import org.distorted.objectlib.main.InitData;
26
import org.distorted.objectlib.main.TwistyObject;
27
import org.distorted.objectlib.objects.TwistyBandagedCuboid;
28
import org.distorted.objectlib.shape.ShapeHexahedron;
29
import org.distorted.objectlib.touchcontrol.TouchControlHexahedron;
30

    
31
///////////////////////////////////////////////////////////////////////////////////////////////////
32

    
33
public class BandagedObject
34
{
35
    private final DistortedScreen mScreen;
36
    private final float[] mPos;
37
    private final int[] mSize;
38
    private final float mDist2D;
39

    
40
    private BandagedCubit[] mCubits;
41
    private int mMax;
42
    private int mNumCubits;
43

    
44
///////////////////////////////////////////////////////////////////////////////////////////////////
45

    
46
   BandagedObject(DistortedScreen screen)
47
     {
48
     mScreen = screen;
49
     mPos = new float[3];
50
     mSize = new int[3];
51
     mDist2D = getDist2D();
52
     }
53

    
54
///////////////////////////////////////////////////////////////////////////////////////////////////
55

    
56
   int[] getSize()
57
     {
58
     return mSize;
59
     }
60

    
61
///////////////////////////////////////////////////////////////////////////////////////////////////
62

    
63
   void resetObject(float scale)
64
     {
65
     for(int c=0; c<mNumCubits; c++)
66
       {
67
       if( !mCubits[c].isAttached() )
68
         {
69
         mCubits[c].attach();
70
         mScreen.attach(mCubits[c].getNode());
71
         }
72
       if( mCubits[c].getPosition().length>3 )
73
         {
74
         mCubits[c].reset(scale);
75
         }
76
       mCubits[c].setUnmarked();
77
       }
78
     }
79

    
80
///////////////////////////////////////////////////////////////////////////////////////////////////
81

    
82
   private boolean isAdjacent(float[] pos1, float[] pos2)
83
     {
84
     int len1 = pos1.length/3;
85
     int len2 = pos2.length/3;
86

    
87
     for(int i=0; i<len1; i++)
88
       for(int j=0; j<len2; j++)
89
         {
90
         float d0 = pos1[3*i  ] - pos2[3*j  ];
91
         float d1 = pos1[3*i+1] - pos2[3*j+1];
92
         float d2 = pos1[3*i+2] - pos2[3*j+2];
93

    
94
         if( d0*d0 + d1*d1 + d2*d2 == 1 ) return true;
95
         }
96

    
97
     return false;
98
     }
99

    
100
///////////////////////////////////////////////////////////////////////////////////////////////////
101

    
102
   private int computeNumCubits(int x, int y, int z)
103
     {
104
     return ( x<=1 || y<=1 || z<=1 ) ? x*y*z : x*y*z-(x-2)*(y-2)*(z-2);
105
     }
106

    
107
///////////////////////////////////////////////////////////////////////////////////////////////////
108

    
109
   float getMaxSize()
110
     {
111
     return mMax;
112
     }
113

    
114
///////////////////////////////////////////////////////////////////////////////////////////////////
115

    
116
   float[][] getCubitPositions()
117
     {
118
     int numAttached = 0;
119

    
120
     for(int i=0; i<mNumCubits; i++)
121
       if( mCubits[i].isAttached() ) numAttached++;
122

    
123
     float[][] pos = new float[numAttached][];
124
     int attached=0;
125

    
126
     for(int i=0; i<mNumCubits; i++)
127
       if( mCubits[i].isAttached() )
128
         {
129
         pos[attached++] = mCubits[i].getPosition();
130
         }
131

    
132
     return pos;
133
     }
134

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

    
137
   TwistyObject createObject(int mode, float size)
138
     {
139
     float[][] pos = getCubitPositions();
140
     InitData data = new InitData( mSize,pos);
141
     return new TwistyBandagedCuboid( TwistyObject.MESH_NICE, mode, ShapeHexahedron.DEFAULT_ROT, new Static3D(0,0,0), size, data, null );
142
     }
143

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

    
146
   void tryConnectingCubits(int index1, int index2, float scale)
147
     {
148
     if( index1!=index2 )
149
       {
150
       float[] pos1 = mCubits[index1].getPosition();
151
       float[] pos2 = mCubits[index2].getPosition();
152

    
153
       if( isAdjacent(pos1,pos2) )
154
         {
155
         mCubits[index2].join(pos1,scale);
156
         mCubits[index1].detach();
157
         mScreen.detach(mCubits[index1].getNode());
158
         }
159
       }
160
     }
161

    
162
///////////////////////////////////////////////////////////////////////////////////////////////////
163

    
164
   void attachCubits(float scale)
165
     {
166
     for(int i=0; i<mNumCubits; i++)
167
       {
168
       mCubits[i].scaleMove(scale);
169
       DistortedNode node = mCubits[i].getNode();
170
       mScreen.attach(node);
171
       }
172
     }
173

    
174
///////////////////////////////////////////////////////////////////////////////////////////////////
175

    
176
   void attachAndMarkCubits(float scale, int touched)
177
     {
178
     for(int i=0; i<mNumCubits; i++)
179
       {
180
       if( mCubits[i].isAttached() )
181
         {
182
         mCubits[i].scaleMove(scale);
183
         if( touched==i ) mCubits[i].setMarked();
184
         else             mCubits[i].setUnmarked();
185
         DistortedNode node = mCubits[i].getNode();
186
         mScreen.attach(node);
187
         }
188
       }
189
     }
190

    
191
///////////////////////////////////////////////////////////////////////////////////////////////////
192

    
193
   boolean tryChangeObject(int x, int y, int z)
194
     {
195
     if( mSize[0]!=x || mSize[1]!=y || mSize[2]!=z )
196
       {
197
       mSize[0] = x;
198
       mSize[1] = y;
199
       mSize[2] = z;
200
       mMax = x>y ? Math.max(x,z) : Math.max(y,z);
201
       mNumCubits = computeNumCubits(x,y,z);
202
       return true;
203
       }
204

    
205
     return false;
206
     }
207

    
208
///////////////////////////////////////////////////////////////////////////////////////////////////
209

    
210
   int computeProjectionAngle()
211
     {
212
     float quot1 = mSize[2]/ (float)mSize[0];
213
     float quot2 = mSize[2]/ (float)mSize[1];
214
     float quot3 = mSize[0]/ (float)mSize[2];
215
     float quot4 = mSize[0]/ (float)mSize[1];
216

    
217
     float quot5 = Math.max(quot1,quot2);
218
     float quot6 = Math.max(quot3,quot4);
219
     float quot7 = Math.max(quot5,quot6);
220

    
221
          if( quot7<=1.0f ) return 120;
222
     else if( quot7<=1.5f ) return 90;
223
     else if( quot7<=2.0f ) return 60;
224
     else                   return 30;
225
     }
226

    
227
///////////////////////////////////////////////////////////////////////////////////////////////////
228

    
229
   void scaleCubits(float scale)
230
     {
231
     for(int i=0; i<mNumCubits; i++) mCubits[i].scaleMove(scale);
232
     }
233

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

    
236
   void recreateCubits(Static4D quatT, Static4D quatA, Static3D scale)
237
     {
238
     if( mCubits==null )
239
        {
240
        createCubits(quatT,quatA,scale);
241
        }
242
      else
243
        {
244
        for(int i=0; i<mNumCubits; i++) mCubits[i].recreateBitmap();
245
        }
246
     }
247

    
248
///////////////////////////////////////////////////////////////////////////////////////////////////
249

    
250
   float[] getDist3D()
251
     {
252
     float max = getMaxSize();
253

    
254
     float x = 0.5f*(mSize[0]/max);
255
     float y = 0.5f*(mSize[1]/max);
256
     float z = 0.5f*(mSize[2]/max);
257

    
258
     return new float[] {x,x,y,y,z,z};
259
     }
260

    
261

    
262
///////////////////////////////////////////////////////////////////////////////////////////////////
263

    
264
   float getDist2D()
265
     {
266
     return 0.5f;
267
     }
268

    
269
///////////////////////////////////////////////////////////////////////////////////////////////////
270
// (x,y,z) ==
271
//
272
// ( 1,0,0) --> 0
273
// (-1,0,0) --> 1
274
// (0, 1,0) --> 2
275
// (0,-1,0) --> 3
276
// (0,0, 1) --> 4
277
// (0,0,-1) --> 5
278

    
279
   int computeMapsIndex(float[] faceAxis)
280
      {
281
      float x = faceAxis[0];
282
      float y = faceAxis[1];
283
      float z = faceAxis[2];
284

    
285
      int ix = x>0 ? (int)(x+0.5f) : (int)(x-0.5f);
286
      int iy = y>0 ? (int)(y+0.5f) : (int)(y-0.5f);
287
      int iz = z>0 ? (int)(z+0.5f) : (int)(z-0.5f);
288

    
289
      if( ix== 1 ) return 0;
290
      if( ix==-1 ) return 1;
291
      if( iy== 1 ) return 2;
292
      if( iy==-1 ) return 3;
293
      if( iz== 1 ) return 4;
294
      if( iz==-1 ) return 5;
295

    
296
      return 0;
297
      }
298

    
299
///////////////////////////////////////////////////////////////////////////////////////////////////
300

    
301
   MeshBase createMesh(float[] pos, boolean round)
302
      {
303
      FactoryBandagedCubit factory = FactoryBandagedCubit.getInstance();
304
      int[] size = getSize();
305
      return factory.createMesh(pos,size[0],size[1],size[2],false,round);
306
      }
307

    
308
///////////////////////////////////////////////////////////////////////////////////////////////////
309

    
310
   int[] getColors()
311
     {
312
     return new int[]
313
         {
314
           COLOR_YELLOW, COLOR_WHITE,
315
           COLOR_BLUE  , COLOR_GREEN,
316
           COLOR_RED   , COLOR_ORANGE
317
         };
318
     }
319

    
320
///////////////////////////////////////////////////////////////////////////////////////////////////
321

    
322
   void createCubits(Static4D quatT, Static4D quatA, Static3D scale)
323
     {
324
     mCubits = new BandagedCubit[mNumCubits];
325
     int c=0;
326
     int sx = mSize[0];
327
     int sy = mSize[1];
328
     int sz = mSize[2];
329

    
330
     float begX = 0.5f*(1-sx);
331
     float begY = 0.5f*(1-sy);
332
     float begZ = 0.5f*(1-sz);
333

    
334
     for(int x=0; x<sx; x++)
335
       for(int y=0; y<sy; y++)
336
          for(int z=0; z<sz; z++)
337
            if( x==0 || x==sx-1 || y==0 || y==sy-1 || z==0 || z==sz-1 )
338
              {
339
              float[] pos = new float[] { begX+x,begY+y,begZ+z };
340
              mCubits[c] = new BandagedCubit(this,pos,quatT,quatA,scale,false);
341
              c++;
342
              }
343
    }
344

    
345
///////////////////////////////////////////////////////////////////////////////////////////////////
346

    
347
  Static3D[] getFaceAxis()
348
    {
349
    return TouchControlHexahedron.FACE_AXIS;
350
    }
351

    
352
///////////////////////////////////////////////////////////////////////////////////////////////////
353

    
354
  void touchCubit(int index)
355
    {
356
    if( index>=0 && index<mNumCubits && mCubits[index]!=null ) mCubits[index].setMarked();
357
    }
358

    
359
///////////////////////////////////////////////////////////////////////////////////////////////////
360

    
361
  void untouchCubit(int index)
362
    {
363
    if( index>=0 && index<mNumCubits && mCubits[index]!=null ) mCubits[index].setUnmarked();
364
    }
365

    
366
///////////////////////////////////////////////////////////////////////////////////////////////////
367

    
368
  void stretchPoint(int face, float[] output)
369
    {
370
    float max = getMaxSize();
371

    
372
    switch(face/2)
373
      {
374
      case 0: output[0] *= (max/mSize[2]); output[1] *= (max/mSize[1]); break;
375
      case 1: output[0] *= (max/mSize[0]); output[1] *= (max/mSize[2]); break;
376
      case 2: output[0] *= (max/mSize[0]); output[1] *= (max/mSize[1]); break;
377
      }
378
    }
379

    
380
///////////////////////////////////////////////////////////////////////////////////////////////////
381

    
382
  int whichCubitTouched(int face, float pointX, float pointY)
383
    {
384
    float x = mSize[0];
385
    float y = mSize[1];
386
    float z = mSize[2];
387

    
388
    switch(face)
389
      {
390
      case 0: mPos[0] = (x-1)/2;
391
              mPos[1] = (int)( y*pointY+y/2)-(y-1)/2;
392
              mPos[2] = (int)(-z*pointX-z/2)+(z-1)/2;
393
              break;
394
      case 1: mPos[0] =-(x-1)/2;
395
              mPos[1] = (int)( y*pointY+y/2)-(y-1)/2;
396
              mPos[2] = (int)( z*pointX+z/2)-(z-1)/2;
397
              break;
398
      case 2: mPos[0] = (int)( x*pointX+x/2)-(x-1)/2;
399
              mPos[1] = (y-1)/2;
400
              mPos[2] = (int)(-z*pointY-z/2)+(z-1)/2;
401
              break;
402
      case 3: mPos[0] = (int)( x*pointX+x/2)-(x-1)/2;
403
              mPos[1] =-(y-1)/2;
404
              mPos[2] = (int)( z*pointY+z/2)-(z-1)/2;
405
              break;
406
      case 4: mPos[0] = (int)( x*pointX+x/2)-(x-1)/2;
407
              mPos[1] = (int)( y*pointY+y/2)-(y-1)/2;
408
              mPos[2] = (z-1)/2;
409
              break;
410
      case 5: mPos[0] = (int)(-x*pointX-x/2)+(x-1)/2;
411
              mPos[1] = (int)( y*pointY+y/2)-(y-1)/2;
412
              mPos[2] =-(z-1)/2;
413
              break;
414
      }
415

    
416
    for(int c=0; c<mNumCubits; c++)
417
      if( mCubits[c].isAttached() )
418
        {
419
        float[] pos = mCubits[c].getPosition();
420
        int len = pos.length/3;
421

    
422
        for(int p=0; p<len; p++)
423
          if( pos[3*p]==mPos[0] && pos[3*p+1]==mPos[1] && pos[3*p+2]==mPos[2] ) return c;
424
        }
425

    
426
    android.util.Log.e("D", "whichCubitTouched: IMPOSSIBLE!!");
427
    return -1;
428
    }
429

    
430
///////////////////////////////////////////////////////////////////////////////////////////////////
431

    
432
  boolean isInsideFace(int face, float[] p)
433
    {
434
    return ( p[0]<=mDist2D && p[0]>=-mDist2D && p[1]<=mDist2D && p[1]>=-mDist2D );
435
    }
436
}
(9-9/14)