Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / bandaged / BandagedObject.java @ 6777e712

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.objectlib.bandaged;
11

    
12
import android.graphics.Bitmap;
13
import android.graphics.Canvas;
14
import android.graphics.Paint;
15

    
16
import org.distorted.library.helpers.QuatHelper;
17
import org.distorted.library.main.DistortedNode;
18
import org.distorted.library.main.DistortedScreen;
19
import org.distorted.library.main.DistortedTexture;
20
import org.distorted.library.mesh.MeshBase;
21
import org.distorted.library.type.Static3D;
22
import org.distorted.library.type.Static4D;
23
import org.distorted.objectlib.helpers.FactoryCubit;
24
import org.distorted.objectlib.main.TwistyObject;
25

    
26
///////////////////////////////////////////////////////////////////////////////////////////////////
27

    
28
public abstract class BandagedObject
29
{
30
    private static final float[] mTmp = new float[4];
31

    
32
    private final DistortedScreen mScreen;
33
    private final float[][] mFaceAxis;
34
    private BandagedCubit[] mCubits;
35
    private final float[][] mRotAxis;
36
    private Bitmap mBitmap;
37
    private Static4D[] mTextureMaps;
38

    
39
    float[][] mCuts;
40
    final int[] mSize;
41
    final float mDist2D;
42

    
43
    int mMax;
44
    int mNumCubits;
45
    int mMinSize, mMaxSize;
46

    
47
///////////////////////////////////////////////////////////////////////////////////////////////////
48

    
49
   BandagedObject(DistortedScreen screen, int minSize, int maxSize)
50
     {
51
     mScreen = screen;
52
     mRotAxis = getRotAxis();
53
     mDist2D = getDist2D();
54

    
55
     Static3D[] axis = getFaceAxis();
56
     int numAxis = axis.length;
57
     mFaceAxis = new float[numAxis][];
58
     for(int i=0; i<numAxis; i++) mFaceAxis[i] = new float[] { axis[i].get0(), axis[i].get1(), axis[i].get2() };
59

    
60
     int numRot= mRotAxis.length;
61
     mSize = new int[numRot];
62
     for(int a=0; a<numRot; a++) mSize[a] = minSize;
63

    
64
     mMinSize = minSize;
65
     mMaxSize = maxSize;
66
     }
67

    
68
///////////////////////////////////////////////////////////////////////////////////////////////////
69

    
70
   abstract float[][] getRotAxis();
71
   abstract float getDist2D();
72
   abstract int[] getColors();
73
   abstract float[][][] getPositions();
74
   abstract boolean isAdjacent(float x1, float y1, float z1, float x2, float y2, float z2 );
75
   abstract MeshBase createMesh(float[] pos, boolean round);
76

    
77
   public abstract TwistyObject createObject(int mode, float scale );
78
   public abstract float[] getDist3D();
79
   public abstract int computeProjectionAngle();
80
   public abstract boolean tryChangeObject(int x, int y, int z);
81
   public abstract boolean isInsideFace(int face, float[] p);
82
   public abstract Static3D[] getFaceAxis();
83
   public abstract float getScreenRatio();
84

    
85
///////////////////////////////////////////////////////////////////////////////////////////////////
86

    
87
  private void createBitmap(int[] colors)
88
    {
89
    final int NUM = colors.length;
90
    final int SIZE= 32;
91

    
92
    mTextureMaps = new Static4D[NUM];
93

    
94
    Paint paint = new Paint();
95
    paint.setStyle(Paint.Style.FILL);
96
    mBitmap = Bitmap.createBitmap( NUM*SIZE, SIZE, Bitmap.Config.ARGB_4444);
97
    Canvas canvas = new Canvas(mBitmap);
98

    
99
    for(int color=0; color<NUM; color++)
100
      {
101
      paint.setColor(colors[color]);
102
      canvas.drawRect(color*SIZE, 0, (color+1)*SIZE, SIZE, paint);
103
      mTextureMaps[color] = new Static4D( ((float)color)/NUM, 0.0f, 1.0f/NUM, 1.0f );
104
      }
105
    }
106

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

    
109
  void resetTextureMaps(MeshBase mesh)
110
    {
111
    FactoryCubit fact = FactoryCubit.getInstance();
112
    int numComponents = mesh.getNumTexComponents();
113
    Static4D[] maps = new Static4D[numComponents];
114

    
115
    if( mTextureMaps==null || mBitmap==null )
116
      {
117
      createBitmap(getColors());
118
      }
119

    
120
    for(int i=0; i<numComponents; i++)
121
      {
122
      Static4D q = fact.getQuaternion(i);
123
      QuatHelper.rotateVectorByQuat(mTmp,0,0,1,0,q);
124
      int index = computeMapsIndex(mTmp);
125
      maps[i] = mTextureMaps[index];
126
      }
127

    
128
    mesh.setTextureMap(maps,0);
129
    }
130

    
131
///////////////////////////////////////////////////////////////////////////////////////////////////
132

    
133
  private float getRotRow(int ax, float d)
134
    {
135
    float[] cuts = mCuts[ax];
136
    int numCuts = cuts==null ? 0 : cuts.length;
137
    for(int c=0; c<numCuts; c++) if( d<=cuts[c] ) return c;
138
    return numCuts;
139
    }
140

    
141
///////////////////////////////////////////////////////////////////////////////////////////////////
142

    
143
  float[][] getRotRows(float[] pos)
144
    {
145
    int num = pos.length/3;
146
    int numAx = mRotAxis.length;
147
    float[][] ret = new float[num][numAx];
148

    
149
    for(int p=0; p<num; p++)
150
      for(int a=0; a<numAx; a++)
151
        {
152
        float[] ax = mRotAxis[a];
153
        float x = pos[3*p];
154
        float y = pos[3*p+1];
155
        float z = pos[3*p+2];
156
        float d = ax[0]*x + ax[1]*y + ax[2]*z;
157
        ret[p][a] = getRotRow(a,d);
158
        }
159

    
160
    return ret;
161
    }
162

    
163
///////////////////////////////////////////////////////////////////////////////////////////////////
164

    
165
  public void createCubits(Static4D quatT, Static4D quatA, Static3D scale)
166
    {
167
    mCubits = new BandagedCubit[mNumCubits];
168
    float[][][] pos = getPositions();
169
    int c=0;
170

    
171
    for(float[][] po : pos)
172
      for(float[] p : po)
173
        mCubits[c++] = new BandagedCubit(this, p, quatT, quatA, scale, false);
174
    }
175

    
176
///////////////////////////////////////////////////////////////////////////////////////////////////
177

    
178
  int computeMapsIndex(float[] faceAx)
179
    {
180
    int min=-1, numAxis = mFaceAxis.length;
181
    float error = Float.MAX_VALUE;
182
    float x = faceAx[0];
183
    float y = faceAx[1];
184
    float z = faceAx[2];
185

    
186
    for(int i=0; i<numAxis; i++)
187
      {
188
      float[] ax = mFaceAxis[i];
189
      float dx = x-ax[0];
190
      float dy = y-ax[1];
191
      float dz = z-ax[2];
192

    
193
      float diff = dx*dx + dy*dy + dz*dz;
194

    
195
      if( error>diff )
196
        {
197
        error = diff;
198
        min = i;
199
        }
200
      }
201

    
202
    return min;
203
    }
204

    
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206

    
207
  public void resetObject(float scale)
208
    {
209
    for(int c=0; c<mNumCubits; c++)
210
      {
211
      if( !mCubits[c].isAttached() )
212
        {
213
        mCubits[c].attach();
214
        mScreen.attach(mCubits[c].getNode());
215
        }
216
      if( mCubits[c].getPosition().length>3 )
217
        {
218
        mCubits[c].reset(scale);
219
        }
220
      mCubits[c].setUnmarked();
221
      }
222
    }
223

    
224
///////////////////////////////////////////////////////////////////////////////////////////////////
225

    
226
  public float getMaxSize()
227
    {
228
    return mMax;
229
    }
230

    
231
///////////////////////////////////////////////////////////////////////////////////////////////////
232

    
233
  float[][] getCubitPositions()
234
    {
235
    int numAttached = 0;
236

    
237
    for(int i=0; i<mNumCubits; i++)
238
      if( mCubits[i].isAttached() ) numAttached++;
239

    
240
    float[][] pos = new float[numAttached][];
241
    int attached=0;
242

    
243
    for(int i=0; i<mNumCubits; i++)
244
      if( mCubits[i].isAttached() )
245
        pos[attached++] = mCubits[i].getPosition();
246

    
247
    return pos;
248
    }
249

    
250
///////////////////////////////////////////////////////////////////////////////////////////////////
251

    
252
  public void tryConnectingCubits(int index1, int index2, float scale)
253
    {
254
    if( index1!=index2 )
255
      {
256
      float[] pos1 = mCubits[index1].getPosition();
257
      float[] pos2 = mCubits[index2].getPosition();
258

    
259
      if( isAdjacent(pos1,pos2) )
260
        {
261
        mCubits[index2].join(pos1,scale);
262
        mCubits[index1].detach();
263
        mScreen.detach(mCubits[index1].getNode());
264
        }
265
      }
266
    }
267

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

    
270
  public void attachCubits(float scale)
271
    {
272
    for(int i=0; i<mNumCubits; i++)
273
      {
274
      mCubits[i].scaleMove(scale);
275
      DistortedNode node = mCubits[i].getNode();
276
      mScreen.attach(node);
277
      }
278
    }
279

    
280
///////////////////////////////////////////////////////////////////////////////////////////////////
281

    
282
  public void attachAndMarkCubits(float scale, int touched)
283
    {
284
    for(int i=0; i<mNumCubits; i++)
285
      {
286
      if( mCubits[i].isAttached() )
287
        {
288
        mCubits[i].scaleMove(scale);
289
        if( touched==i ) mCubits[i].setMarked();
290
        else             mCubits[i].setUnmarked();
291
        DistortedNode node = mCubits[i].getNode();
292
        mScreen.attach(node);
293
        }
294
      }
295
    }
296

    
297
///////////////////////////////////////////////////////////////////////////////////////////////////
298

    
299
  public void scaleCubits(float scale)
300
    {
301
    for(int i=0; i<mNumCubits; i++) mCubits[i].scaleMove(scale);
302
    }
303

    
304
///////////////////////////////////////////////////////////////////////////////////////////////////
305

    
306
  public void recreateCubits(Static4D quatT, Static4D quatA, Static3D scale)
307
    {
308
    if( mCubits==null )
309
      {
310
      createCubits(quatT,quatA,scale);
311
      }
312
    else
313
      {
314
      for(int i=0; i<mNumCubits; i++)
315
        {
316
        DistortedTexture tex = mCubits[i].getTexture();
317
        recreateBitmap(tex);
318
        }
319
      }
320
    }
321

    
322
///////////////////////////////////////////////////////////////////////////////////////////////////
323

    
324
  void recreateBitmap(DistortedTexture tex)
325
    {
326
    if( mBitmap==null ) createBitmap(getColors());
327
    tex.setTextureAlreadyInverted(mBitmap);
328
    }
329

    
330
///////////////////////////////////////////////////////////////////////////////////////////////////
331

    
332
  public void touchCubit(int index)
333
    {
334
    if( index>=0 && index<mNumCubits && mCubits[index]!=null ) mCubits[index].setMarked();
335
    }
336

    
337
///////////////////////////////////////////////////////////////////////////////////////////////////
338

    
339
  public void untouchCubit(int index)
340
    {
341
    if( index>=0 && index<mNumCubits && mCubits[index]!=null ) mCubits[index].setUnmarked();
342
    }
343

    
344
///////////////////////////////////////////////////////////////////////////////////////////////////
345

    
346
  public int whichCubitTouched(float[] point3D)
347
    {
348
    float x = point3D[0]*mMax;
349
    float y = point3D[1]*mMax;
350
    float z = point3D[2]*mMax;
351

    
352
    int numAxis = mRotAxis.length;
353
    float[] rotRow = new float[numAxis];
354

    
355
    for(int a=0; a<numAxis; a++)
356
      {
357
      float[] ax = mRotAxis[a];
358
      float d = ax[0]*x + ax[1]*y + ax[2]*z;
359
      rotRow[a] = getRotRow(a,d);
360
      }
361

    
362
    int diff = Integer.MAX_VALUE;
363
    int currBest = -1;
364

    
365
    for(int c=0; c<mNumCubits; c++)
366
      if( mCubits[c].isAttached() )
367
        {
368
        float[][] cubitRotRow = mCubits[c].getRotRow();
369

    
370
        for(float[] row : cubitRotRow)
371
          {
372
          int currDiff = 0;
373

    
374
          for(int a=0; a<numAxis; a++)
375
            {
376
            float d = rotRow[a]-row[a];
377
            currDiff += d*d;
378
            }
379

    
380
          if( currDiff<diff )
381
            {
382
            diff = currDiff;
383
            currBest = c;
384
            }
385
          }
386
        }
387

    
388
    return currBest;
389
    }
390

    
391
///////////////////////////////////////////////////////////////////////////////////////////////////
392

    
393
  boolean isAdjacent(float[] pos1, float[] pos2)
394
     {
395
     int len1 = pos1.length/3;
396
     int len2 = pos2.length/3;
397

    
398
     for(int i=0; i<len1; i++)
399
       {
400
       float x1 = pos1[3*i  ];
401
       float y1 = pos1[3*i+1];
402
       float z1 = pos1[3*i+2];
403

    
404
       for(int j=0; j<len2; j++)
405
         {
406
         float x2 = pos2[3*j  ];
407
         float y2 = pos2[3*j+1];
408
         float z2 = pos2[3*j+2];
409

    
410
         if( isAdjacent(x1,y1,z1,x2,y2,z2) ) return true;
411
         }
412
       }
413

    
414
     return false;
415
     }
416
}
(3-3/15)