Project

General

Profile

« Previous | Next » 

Revision 5718b29d

Added by Leszek Koltunski 9 months ago

Carve out another, 2nd layer from TwistyObject: everything related to creating its Mesh.

View differences:

src/main/java/org/distorted/objectlib/helpers/ObjectShape.java
12 12
import org.distorted.library.helpers.QuatHelper;
13 13
import org.distorted.library.type.Static3D;
14 14
import org.distorted.library.type.Static4D;
15
import org.distorted.objectlib.main.TwistyObject;
15
import org.distorted.objectlib.main.TwistyObjectWithMesh;
16 16

  
17 17
///////////////////////////////////////////////////////////////////////////////////////////////////
18 18

  
......
121 121

  
122 122
///////////////////////////////////////////////////////////////////////////////////////////////////
123 123

  
124
  public int getNumFaces()
125
    {
126
    return mNumFaces;
127
    }
128

  
129
///////////////////////////////////////////////////////////////////////////////////////////////////
130

  
131
  public boolean isMultigon()
132
    {
133
    return mFacesMultigon;
134
    }
135

  
136
///////////////////////////////////////////////////////////////////////////////////////////////////
137

  
138
  public float[][] getVertices()
139
    {
140
    return mVertices;
141
    }
142

  
143
///////////////////////////////////////////////////////////////////////////////////////////////////
144

  
145
  public int[][] getVertIndices()
146
    {
147
    return mVertIndices;
148
    }
149

  
150
///////////////////////////////////////////////////////////////////////////////////////////////////
151

  
152
  public int[][][] getMultigonIndices()
153
    {
154
    return mMultigonIndices;
155
    }
156

  
157
///////////////////////////////////////////////////////////////////////////////////////////////////
158

  
159
  public float[] getFirstVertexInFace(int face)
160
    {
161
    if( mFacesMultigon )
162
      {
163
      int[][][] indices=getMultigonIndices();
164
      int vertIndex=indices[face][0][0];
165
      return getVertices()[vertIndex];
166
      }
167
    else
168
      {
169
      int[][] indices=getVertIndices();
170
      int vertIndex=indices[face][0];
171
      return getVertices()[vertIndex];
172
      }
173
    }
124
  public int getNumFaces()               { return mNumFaces; }
125
  public boolean isMultigon()            { return mFacesMultigon; }
126
  public float[][] getVertices()         { return mVertices; }
127
  public int[][] getVertIndices()        { return mVertIndices; }
128
  public int[][][] getMultigonIndices()  { return mMultigonIndices; }
174 129

  
175 130
///////////////////////////////////////////////////////////////////////////////////////////////////
176 131

  
......
375 330

  
376 331
///////////////////////////////////////////////////////////////////////////////////////////////////
377 332

  
378
  public static int[][] computeColors(ObjectShape[] shapes, float[][] moves, Static4D[] quats, TwistyObject object)
333
  public static int[][] computeColors(ObjectShape[] shapes, float[][] moves, Static4D[] quats, TwistyObjectWithMesh object)
379 334
    {
380 335
    int numCubits = moves.length;
381 336
    int[][] colors = new int[numCubits][];
src/main/java/org/distorted/objectlib/main/TwistyObject.java
1 1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
2
// Copyright 2024 Leszek Koltunski                                                               //
3 3
//                                                                                               //
4 4
// This file is part of Magic Cube.                                                              //
5 5
//                                                                                               //
......
9 9

  
10 10
package org.distorted.objectlib.main;
11 11

  
12
import java.io.DataInputStream;
13
import java.io.IOException;
14 12
import java.io.InputStream;
15 13
import java.util.Random;
16 14

  
......
22 20
import org.distorted.library.effect.MatrixEffectMove;
23 21
import org.distorted.library.effect.MatrixEffectQuaternion;
24 22
import org.distorted.library.effect.MatrixEffectScale;
25
import org.distorted.library.effect.VertexEffectQuaternion;
26
import org.distorted.library.effect.VertexEffectSink;
27
import org.distorted.library.main.DistortedEffects;
28 23
import org.distorted.library.main.DistortedLibrary;
29 24
import org.distorted.library.main.DistortedNode;
30 25
import org.distorted.library.main.DistortedTexture;
31
import org.distorted.library.helpers.QuatHelper;
32
import org.distorted.library.mesh.MeshBase;
33
import org.distorted.library.mesh.MeshFile;
34
import org.distorted.library.mesh.MeshJoined;
35 26
import org.distorted.library.message.EffectListener;
36
import org.distorted.library.type.Static1D;
37 27
import org.distorted.library.type.Static3D;
38 28
import org.distorted.library.type.Static4D;
39 29

  
40 30
import org.distorted.objectlib.helpers.FactoryCubit;
41 31
import org.distorted.objectlib.helpers.FactorySticker;
42
import org.distorted.objectlib.helpers.ObjectFaceShape;
43 32
import org.distorted.objectlib.helpers.ObjectLibInterface;
44
import org.distorted.objectlib.helpers.ObjectShape;
45 33
import org.distorted.objectlib.helpers.ObjectSticker;
46 34
import org.distorted.objectlib.helpers.ObjectStickerOverride;
47
import org.distorted.objectlib.helpers.ObjectVertexEffects;
48 35
import org.distorted.objectlib.helpers.OperatingSystemInterface;
49 36
import org.distorted.objectlib.json.JsonReader;
50 37
import org.distorted.objectlib.metadata.Metadata;
......
59 46

  
60 47
///////////////////////////////////////////////////////////////////////////////////////////////////
61 48

  
62
public abstract class TwistyObject extends TwistyObjectTheoretical
49
public abstract class TwistyObject extends TwistyObjectWithMesh
63 50
  {
64 51
  public static final int MODE_ICON = 0;
65 52
  public static final int MODE_NORM = 1;
......
70 57
  private static final int DEFAULT_TEXTURE_HEIGHT = 256;
71 58
  private static final int DEFAULT_TEXTURE_ROWS   = 8;
72 59

  
73
  public static final float SQ2 = (float)Math.sqrt(2);
74
  public static final float SQ3 = (float)Math.sqrt(3);
75
  public static final float SQ5 = (float)Math.sqrt(5);
76
  public static final float SQ6 = (float)Math.sqrt(6);
77

  
78 60
  private static final float MAX_SIZE_CHANGE = 1.35f;
79 61
  private static final float MIN_SIZE_CHANGE = 0.75f;
80 62

  
81
  private static final Static3D CENTER = new Static3D(0,0,0);
82

  
83 63
  protected float[][][][] mStickerCoords;
84 64

  
85 65
  private int[][] mStickerVariants;
86 66
  private float[] mStickerScales;
87
  private Static4D[] mOrigQuat;
88 67
  private TwistyObjectSolved mSolved;
89
  private MeshBase[] mMeshes;
90 68
  private int mNumFaceColors, mNumTextures, mNumOverrides;
91
  private int mNumCubitFaces, mNumStickerTypes;
92
  private Static4D[] mMixupModeQuats;
93
  private boolean mIsInMixupMode;
69
  private int mNumStickerTypes;
94 70
  private Static4D mQuat;
95
  private int[] mNumLayers;
96 71
  private float mSize;
97
  private DistortedEffects mEffects;
98 72
  private Static3D mObjectScale;
99 73
  private DistortedTexture mTexture;
100 74
  private float mInitScreenRatio;
101 75
  private float mObjectScreenRatio;
102 76
  private int mNumTexRows, mNumTexCols, mTexHeight;
103
  private MeshBase mMesh;
104 77
  private ObjectScrambler mScrambler;
105 78
  private TouchControl mTouchControl;
106 79
  private DistortedNode mNode;
107 80
  private ObjectLibInterface mInterface;
108 81
  private Bitmap mBitmap;
109 82
  private ObjectSticker[] mStickers;
110
  private ObjectShape[] mShapes;
111
  private int mNumCubitVariants;
112
  private int[][] mCubitFaceColors;
113
  private int[][] mVariantFaceIsOuter;
114 83
  private int mIconMode;
115 84
  private Metadata mMetadata;
116 85
  private ObjectStickerOverride[] mStickerOverrides;
117 86
  private boolean mError;
118 87
  private String mErrorString;
119
  private int mMaxNumLayers;
120 88
  private TwistyLayerRotations mRotation;
121 89
  private int[] mColorTable;
122 90
  private int[] mOriginalColorTable;
......
166 134

  
167 135
  private void initialize(int iconMode, Static4D quat, Static3D move, float scale, InitAssets asset, boolean fromJSON)
168 136
    {
169
    Static3D[] axis = getRotationAxis();
170
    int[][] angles = getBasicAngles();
171
    Static3D[] faceAxis = getFaceAxis();
172
    float[][] positions = getCubitPositions(mNumLayers);
173
    float[][] cuts = getCuts(mNumLayers);
174
    int[][] minCubits = getMinimalCubiesInRow();
175

  
176
    int numCubits = positions.length;
177
    float[][] offsets = new float[numCubits][];
178
    int[] types = new int[numCubits];
179

  
180
    for(int c=0; c<numCubits; c++)
181
      {
182
      offsets[c] = getCubitRowOffset(c);
183
      types[c] = getCubitRotationType(c);
184
      }
185

  
186
    super.initialize(axis, angles, positions, cuts, minCubits, offsets, types, faceAxis);
137
    super.initialize(asset,fromJSON);
187 138

  
188 139
    mIconMode = iconMode;
189 140
    mQuat = quat;
190 141
    mInitScreenRatio = getScreenRatio();
191 142
    mCubitQuats = new int[mNumCubits];
192 143

  
193
    mMaxNumLayers = -1;
194
    for(int i=0; i<mNumAxis; i++)
195
      {
196
      if( mMaxNumLayers<mNumLayers[i] ) mMaxNumLayers = mNumLayers[i];
197
      }
198

  
199 144
    mOriginalColorTable = getColorTable();
200 145
    mNumFaceColors = mOriginalColorTable.length;
201 146
    mColorTable = new int[mNumFaceColors];
......
214 159
    mObjectScale = new Static3D(scale,scale,scale);
215 160
    setObjectRatioNow(scale,720);
216 161

  
217
    mEffects = new DistortedEffects();
218
    createQuaternionEffects();
219

  
220 162
    mRotation = new TwistyLayerRotations(this,mAxis,mNumLayers,getGhostAngle(),mEffects);
221 163

  
222 164
    MatrixEffectScale scaleEffect = new MatrixEffectScale(mObjectScale);
......
225 167

  
226 168
    InputStream meshStream = asset!=null ? asset.getMeshStream(): null;
227 169
    boolean fromDMESH = (meshStream!=null);
228
    getQuatsAndShapes(fromDMESH,fromJSON);
229
    createMesh(meshStream,fromDMESH);
230 170
    setUpTextures(fromDMESH,fromJSON);
231 171

  
232 172
    int index = getSolvedFunctionIndex();
......
239 179
    mEffects.apply(moveEffect);
240 180

  
241 181
    mNode = new DistortedNode(mTexture,mEffects,mMesh);
242

  
243
    for(int c=0; c<mNumCubits; c++) setCubitQuat(c,0);
244 182
    }
245 183

  
246 184
///////////////////////////////////////////////////////////////////////////////////////////////////
......
267 205
    return ImplementedTablebasesList.createPacked(os,shortName);
268 206
    }
269 207

  
270
///////////////////////////////////////////////////////////////////////////////////////////////////
271

  
272
  private void createQuaternionEffects()
273
    {
274
    if( mNumQuats<=ObjectControl.MAX_QUATS )
275
      {
276
      mIsInMixupMode = false;
277

  
278
      for( int q=0; q<mNumQuats; q++)
279
        {
280
        VertexEffectQuaternion vq = new VertexEffectQuaternion(mObjectQuats[q],CENTER);
281
        vq.setMeshAssociation(0,q);
282
        mEffects.apply(vq);
283
        }
284
      }
285
    else if( mNumCubits<=ObjectControl.MAX_QUATS )
286
      {
287
      mIsInMixupMode = true;
288
      mMixupModeQuats = new Static4D[mNumCubits];
289

  
290
      for( int q=0; q<mNumCubits; q++)
291
        {
292
        mMixupModeQuats[q] = new Static4D(mObjectQuats[0]);
293
        VertexEffectQuaternion vq = new VertexEffectQuaternion(mMixupModeQuats[q],CENTER);
294
        vq.setMeshAssociation(0,q);
295
        mEffects.apply(vq);
296
        }
297
      }
298
    else
299
      {
300
      android.util.Log.e("D", "object has too many quaternions ("+mNumQuats+") or too many cubits ("+mNumCubits+")");
301
      }
302
    }
303

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

  
306
  private Static3D getPos(float[] origPos)
307
    {
308
    int len = origPos.length/3;
309
    float sumX = 0.0f;
310
    float sumY = 0.0f;
311
    float sumZ = 0.0f;
312

  
313
    for(int i=0; i<len; i++)
314
      {
315
      sumX += origPos[3*i  ];
316
      sumY += origPos[3*i+1];
317
      sumZ += origPos[3*i+2];
318
      }
319

  
320
    sumX /= len;
321
    sumY /= len;
322
    sumZ /= len;
323

  
324
    return new Static3D(sumX,sumY,sumZ);
325
    }
326

  
327
///////////////////////////////////////////////////////////////////////////////////////////////////
328

  
329
  private void createOuterFaces()
330
    {
331
    for(int v=0; v<mNumCubitVariants; v++)
332
      {
333
      int numFaces = mShapes[v].getNumFaces();
334
      mVariantFaceIsOuter[v] = new int[numFaces];
335
      }
336

  
337
    for( int cubit=0; cubit<mNumCubits; cubit++)
338
      {
339
      int variant = getCubitVariant(cubit,mNumLayers);
340
      int numFaces = mShapes[variant].getNumFaces();
341

  
342
      for(int face=0; face<numFaces; face++)
343
        if( getDefaultCubitFaceColor(cubit,face)>=0 )
344
          {
345
          mVariantFaceIsOuter[variant][face] = 1;
346
          }
347
      }
348
    }
349

  
350
///////////////////////////////////////////////////////////////////////////////////////////////////
351

  
352
  private void getQuatsAndShapes(boolean fromDMESH, boolean fromJSON)
353
    {
354
    mNumCubitVariants = getNumCubitVariants(mNumLayers);
355

  
356
    if( !fromDMESH || !fromJSON )
357
      {
358
      FactoryCubit factory = FactoryCubit.getInstance();
359
      factory.clear();
360

  
361
      mShapes = new ObjectShape[mNumCubitVariants];
362
      for(int v=0; v<mNumCubitVariants; v++) mShapes[v] = getObjectShape(v);
363
      mNumCubitFaces = ObjectShape.computeNumComponents(mShapes);
364
      mVariantFaceIsOuter = new int[mNumCubitVariants][];
365

  
366
      mOrigQuat = new Static4D[mNumCubits];
367
      for(int i=0; i<mNumCubits; i++) mOrigQuat[i] = getCubitQuats(i,mNumLayers);
368

  
369
      if( !fromJSON )
370
        {
371
        mCubitFaceColors = ObjectShape.computeColors(mShapes,mCubitPos,mOrigQuat,this);
372
        createOuterFaces();
373
        }
374

  
375
      if( fromDMESH )
376
        {
377
        for(int i=0; i<mNumCubitVariants; i++) factory.createNewFaceTransform(mShapes[i], mVariantFaceIsOuter[i]);
378
        }
379
      }
380
    }
381

  
382
///////////////////////////////////////////////////////////////////////////////////////////////////
383

  
384
  private void createMesh(InputStream stream, boolean fromDMESH)
385
    {
386
    if( fromDMESH )
387
      {
388
      DataInputStream dos = new DataInputStream(stream);
389
      mMesh = new MeshFile(dos);
390

  
391
      try
392
        {
393
        stream.close();
394
        }
395
      catch(IOException e)
396
        {
397
        android.util.Log.e("meshFile", "Error closing InputStream: "+e);
398
        }
399
      }
400
    else
401
      {
402
      MeshBase[] cubitMesh = new MeshBase[mNumCubits];
403

  
404
      for(int i=0; i<mNumCubits; i++)
405
        {
406
        cubitMesh[i] = createCubitMesh(i,mNumLayers,mNumCubitFaces);
407
        Static3D pos = getPos(mCubitPos[i]);
408
        cubitMesh[i].apply(new MatrixEffectMove(pos),1,0);
409
        }
410

  
411
      mMesh = new MeshJoined(cubitMesh);
412

  
413
      float pillowCoeff = getPillowCoeff();
414

  
415
      if( pillowCoeff!=1.0f )
416
        {
417
        float radius = getCircumscribedRadius();
418
        Static1D coeff = new Static1D(pillowCoeff);
419
        Static4D region= new Static4D(0,0,0,radius);
420
        VertexEffectSink sink = new VertexEffectSink(coeff,CENTER,region);
421
        mMesh.apply(sink);
422
        }
423
      }
424
    }
425

  
426
///////////////////////////////////////////////////////////////////////////////////////////////////
427

  
428
  private MeshBase createCubitMesh(int cubit, int[] numLayers, int numComponents)
429
    {
430
    int variant = getCubitVariant(cubit,numLayers);
431

  
432
    if( mMeshes==null ) mMeshes = new MeshBase[mNumCubitVariants];
433

  
434
    if( mMeshes[variant]==null )
435
      {
436
      ObjectFaceShape faceShape = getObjectFaceShape(variant);
437
      ObjectVertexEffects effects = getVertexEffects(variant);
438
      FactoryCubit factory = FactoryCubit.getInstance();
439
      factory.createNewFaceTransform(mShapes[variant],mVariantFaceIsOuter[variant]);
440
      mMeshes[variant] = factory.createRoundedSolid(mShapes[variant],faceShape,effects,numComponents);
441
      }
442

  
443
    MeshBase mesh = mMeshes[variant].copy(true);
444
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( mOrigQuat[cubit], CENTER );
445
    mesh.apply(quat,0xffffffff,0);
446

  
447
    return mesh;
448
    }
449

  
450 208
///////////////////////////////////////////////////////////////////////////////////////////////////
451 209

  
452 210
  private void figureOutBitmapDimensions(int numTextures)
......
476 234
    if( fromJSON )
477 235
      {
478 236
      mNumStickerTypes = getNumStickerTypes();
479
      mNumCubitFaces = getNumCubitFaces();
480 237
      }
481 238
    else
482 239
      {
......
541 298
    return ScrambleEdgeGenerator.getScramblingAlgorithms(mBasicAngles);
542 299
    }
543 300

  
544
///////////////////////////////////////////////////////////////////////////////////////////////////
545

  
546
  void rotateAllCubits(int axisIndex, int rowBitmap, int angle)
547
    {
548
    super.rotateAllCubits(axisIndex,rowBitmap,angle);
549
    for(int i=0; i<mNumCubits; i++) setCubitQuat(i,getCubitQuatIndex(i));
550
    }
551

  
552
///////////////////////////////////////////////////////////////////////////////////////////////////
553

  
554
  private boolean sticksOut(Static3D[] faceAxis, float[] dist, float x, float y, float z )
555
    {
556
    final float MAXERR = 0.05f;
557
    int numAxis = dist.length;
558

  
559
    for(int i=0; i<numAxis; i++)
560
      {
561
      Static3D ax = faceAxis[i];
562
      float len = ax.get0()*x + ax.get1()*y + ax.get2()*z;
563
      if( len>mSize*dist[i]+MAXERR ) return true;
564
      }
565

  
566
    return false;
567
    }
568

  
569
///////////////////////////////////////////////////////////////////////////////////////////////////
570

  
571
  private boolean doesNotStickOut(int variant, float px, float py, float pz, float[] tmp, Static4D quat)
572
    {
573
    float[][] vertices = mShapes[variant].getVertices();
574
    Static3D[] axis = getFaceAxis();
575
    float[] dist3D = getDist3D(mNumLayers);
576

  
577
    for( float[] vertex : vertices)
578
      {
579
      float x = vertex[0];
580
      float y = vertex[1];
581
      float z = vertex[2];
582

  
583
      QuatHelper.rotateVectorByQuat(tmp, x, y, z, 1, quat);
584

  
585
      float mx = tmp[0] + px;
586
      float my = tmp[1] + py;
587
      float mz = tmp[2] + pz;
588

  
589
      if( sticksOut(axis, dist3D, mx,my,mz) ) return false;
590
      }
591

  
592
    return true;
593
    }
594

  
595
///////////////////////////////////////////////////////////////////////////////////////////////////
596

  
597
  private float computeAvg(float[] pos, int offset)
598
    {
599
    int len = pos.length/3;
600
    float ret=0.0f;
601
    for(int i=0; i<len; i++) ret += pos[3*i+offset];
602
    ret /= len;
603

  
604
    return ret;
605
    }
606

  
607
///////////////////////////////////////////////////////////////////////////////////////////////////
608

  
609
  protected void displayCubitQuats()
610
    {
611
    StringBuilder builder = new StringBuilder();
612
    float[] tmp = new float[4];
613
    float ERR = 0.01f;
614

  
615
    for(int cubit=0; cubit<mNumCubits; cubit++)
616
      {
617
      builder.append(cubit);
618
      builder.append(" : ");
619

  
620
      int refCubit,variant = getCubitVariant(cubit,mNumLayers);
621

  
622
      for(refCubit=0; refCubit<mNumCubits; refCubit++)
623
        {
624
        if( getCubitVariant(refCubit,mNumLayers)==variant ) break;
625
        }
626

  
627
      float[] curpos = mCubitPos[cubit];
628
      float[] refpos = mCubitPos[refCubit];
629
      float refX = computeAvg(refpos,0);
630
      float refY = computeAvg(refpos,1);
631
      float refZ = computeAvg(refpos,2);
632
      float curX = computeAvg(curpos,0);
633
      float curY = computeAvg(curpos,1);
634
      float curZ = computeAvg(curpos,2);
635

  
636
      for(int quat=0; quat<mNumQuats; quat++)
637
        {
638
        QuatHelper.rotateVectorByQuat(tmp,refX,refY,refZ,0,mObjectQuats[quat]);
639

  
640
        float dx = tmp[0]-curX;
641
        float dy = tmp[1]-curY;
642
        float dz = tmp[2]-curZ;
643

  
644
        if( dx>-ERR && dx<ERR && dy>-ERR && dy<ERR && dz>-ERR && dz<ERR )
645
          {
646
          if( doesNotStickOut(variant,curX,curY,curZ,tmp,mObjectQuats[quat]) )
647
            {
648
            builder.append(quat);
649
            builder.append(',');
650
            }
651
          else
652
            {
653
            android.util.Log.e("D", "cubit: "+cubit+" quat: "+quat+" : center correct, but shape sticks out");
654
            }
655
          }
656
        }
657

  
658
      builder.append('\n');
659
      }
660

  
661
    android.util.Log.e("D", "cubitQuats: \n"+builder );
662
    }
663

  
664
///////////////////////////////////////////////////////////////////////////////////////////////////
665

  
666
  public int getCubitRotationType(int cubit)
667
    {
668
    return TwistyObjectTheoreticalCubit.TYPE_NORMAL;
669
    }
670

  
671
///////////////////////////////////////////////////////////////////////////////////////////////////
672

  
673
  public float[] getCubitRowOffset(int cubitIndex)
674
    {
675
    return null;
676
    }
677

  
678 301
///////////////////////////////////////////////////////////////////////////////////////////////////
679 302

  
680 303
  public int[][] getSolvedQuats()
......
686 309

  
687 310
  protected int[][] getOldSolvedQuats()
688 311
    {
689
    return mSolved.getSolvedQuats(mNumLayers,mNumCubitFaces,mCubitFaceColors);
312
    return mSolved.getSolvedQuats(mNumLayers,mNumCubitFaces);
690 313
    }
691 314

  
692 315
///////////////////////////////////////////////////////////////////////////////////////////////////
......
709 332
    return ObjectScrambler.SCRAMBLING_ALGORITHMS;
710 333
    }
711 334

  
712
///////////////////////////////////////////////////////////////////////////////////////////////////
713

  
714
  public int[][] getMinimalCubiesInRow()
715
    {
716
    return null;
717
    }
718

  
719 335
///////////////////////////////////////////////////////////////////////////////////////////////////
720 336

  
721 337
  void setLibInterface(ObjectLibInterface inter)
......
829 445
    return puzzleFace;
830 446
    }
831 447

  
832
///////////////////////////////////////////////////////////////////////////////////////////////////
833

  
834
  public int getCubitFaceMap(int cubit, int face)
835
    {
836
    int numFaces = mCubitFaceColors[cubit].length;
837
    int puzzleFace = face<numFaces ? mCubitFaceColors[cubit][face] : -1;
838
    return puzzleFace<0 ? -1 : puzzleFace;
839
    }
840

  
841
///////////////////////////////////////////////////////////////////////////////////////////////////
842
// this would return the REAL value of outer; the 'getCubitFaceColor()>=0' returns if the face is
843
// colored, which for example in case of Container (which has colored internal faces) is not the
844
// same thing
845

  
846
  boolean faceIsOuter(int cubit, int face)
847
    {
848
    if( mCubitFaceColors==null )
849
      {
850
      if( mShapes==null )
851
        {
852
        mShapes = new ObjectShape[mNumCubitVariants];
853
        }
854

  
855
      if( mShapes[0]==null )
856
        {
857
        for(int v=0; v<mNumCubitVariants; v++) mShapes[v] = getObjectShape(v);
858
        }
859

  
860
      if( mOrigQuat==null )
861
        {
862
        mOrigQuat = new Static4D[mNumCubits];
863
        }
864

  
865
      if( mOrigQuat[0]==null )
866
        {
867
        for(int c=0; c<mNumCubits; c++) mOrigQuat[c] = getCubitQuats(c,mNumLayers);
868
        }
869

  
870
      mCubitFaceColors = ObjectShape.computeColors(mShapes,mCubitPos,mOrigQuat,this);
871
      }
872

  
873
    return mCubitFaceColors[cubit][face]>=0;
874
    }
875

  
876 448
///////////////////////////////////////////////////////////////////////////////////////////////////
877 449

  
878 450
  void resetAllTextureMaps()
......
936 508
    super.releaseResources();
937 509

  
938 510
    mTexture.markForDeletion();
939
    mMesh.markForDeletion();
940
    mEffects.markForDeletion();
941 511

  
942 512
    if( mBitmap!=null )
943 513
      {
......
946 516
      }
947 517
    }
948 518

  
949
///////////////////////////////////////////////////////////////////////////////////////////////////
950

  
951
  int computeAssociation(int cubit)
952
    {
953
    int result = 0, accumulativeShift = 0;
954

  
955
    for(int axis=0; axis<mNumAxis; axis++)
956
      {
957
      int rotRow = getCubitRotRow(cubit,axis);
958
      result += (rotRow<<accumulativeShift);
959
      accumulativeShift += mMaxNumLayers;
960
      }
961

  
962
    return result;
963
    }
964

  
965
///////////////////////////////////////////////////////////////////////////////////////////////////
966

  
967
  private void setCubitQuat(int cubit, int equAssociation)
968
    {
969
    int andAssociation = computeAssociation(cubit);
970

  
971
    if( !mIsInMixupMode )
972
      {
973
      mMesh.setEffectAssociation(cubit,andAssociation,equAssociation);
974
      }
975
    else
976
      {
977
      mMesh.setEffectAssociation(cubit,andAssociation,cubit);
978
      Static4D tmp = mObjectQuats[equAssociation];
979
      mMixupModeQuats[cubit].set(tmp);
980
      }
981
    }
982

  
983 519
///////////////////////////////////////////////////////////////////////////////////////////////////
984 520

  
985 521
  private int numberOfDifferentColors(int[] table)
......
1032 568
  synchronized void restorePreferences(OperatingSystemInterface os)
1033 569
    {
1034 570
    String key = getShortName();
1035
    boolean error = super.restorePreferences(key,os);
1036

  
1037
    if( error )
1038
      {
1039
      for(int c=0; c<mNumCubits; c++) setCubitQuat(c,0);
1040
      }
1041
    else
1042
      {
1043
      for(int c=0; c<mNumCubits; c++)
1044
        {
1045
        int q = getCubitQuatIndex(c);
1046
        setCubitQuat(c, q);
1047
        }
1048
      }
1049

  
571
    super.restorePreferences(key,os);
1050 572
    restoreSti(key,os);
1051 573
    }
1052 574

  
......
1145 667
    return 1-A*cos;
1146 668
    }
1147 669

  
1148
///////////////////////////////////////////////////////////////////////////////////////////////////
1149
// Radius of the sphere circumscribed on the puzzle. Needed for pillowing.
1150
//
1151
// This won't work correctly for pillowing off-center puzzles (e.g. mirrors) - for those we'd need
1152
// to introduce the concept of a 'sink center' as well.
1153
//
1154
// public because needed in TouchControlShapemod
1155

  
1156
  public float getCircumscribedRadius()
1157
    {
1158
    switch( getCategory() )
1159
      {
1160
      case Metadata.CATEGORY_SHAPE_TET: return (SQ6/4)*mSize;
1161
      case Metadata.CATEGORY_SHAPE_HEX: return (SQ3/2)*mSize;
1162
      case Metadata.CATEGORY_SHAPE_OCT: return (SQ2/2)*mSize;
1163
      case Metadata.CATEGORY_SHAPE_DOD: return (SQ3/2)*((SQ5+1)/2)*mSize;
1164
      case Metadata.CATEGORY_SHAPE_BAL: return 0.50f*mSize;
1165
      case Metadata.CATEGORY_SHAPE_ICO: return 0; // no pillowed icosahedra
1166
      case Metadata.CATEGORY_SHAPE_BAR: return 0; // no pillowed barrels
1167
      }
1168

  
1169
    return 0.0f;
1170
    }
1171

  
1172 670
///////////////////////////////////////////////////////////////////////////////////////////////////
1173 671
// might be overridden in subclasses which want per-edge radii
1174 672

  
......
1268 766

  
1269 767
    }
1270 768

  
1271
///////////////////////////////////////////////////////////////////////////////////////////////////
1272
// Return the 'surface' the given face of the given cubit is on. (px,py,pz) is the pre-computed
1273
// center of the cubit (so we don't have to keep re-computing this per each face)
1274
// If the face is not external, return null.
1275
//
1276
// This is needed by the TwistyObjectSolved's method2 detecting if the object is in a solved state.
1277
//
1278
// What is a 'surface' ? For objects with flat monochromatic external walls, it is simply a 4-tuple
1279
// [(nx,ny,nz),d] (normal vector + distance from origin) describing a 3D plane this face is part of.
1280
// Exceptions are objects with curved external walls (ATM Masterball & Penrose Cubes): it is a union
1281
// of several surfaces which together define the bent, monochromatic wall. I.e. Penrose Cube has 3
1282
// surfaces (blue, yellow and red), each defined by 3 planes (think before the bending effect!)
1283
//
1284
// This is the default which simply returns the single plane. If some puzzle has more complicated
1285
// surfaces, it needs to override this method.
1286
//
1287
// We never need to test if a given point is part of a given surface (see TwistyObjectSurface!) - we
1288
// only need to be able to rotate the surface by quats and test if two surfaces are the same. Thus:
1289
// it is possible to provide some artificial surfaces - for example, in case of the Penrose, the
1290
// three surfaces can be only the single 'middle' plane [the one on the bend].
1291

  
1292
  public float[] getMonochromaticSurface(int variant, int cubitIndex, int faceIndex, float px, float py, float pz)
1293
    {
1294
    if( !faceIsOuter(cubitIndex,faceIndex) ) return null;
1295

  
1296
    Static4D cubitQuat = getCubitQuats(cubitIndex,mNumLayers);
1297

  
1298
    float[] normal   = new float[4];
1299
    float[] intPoint = new float[3];
1300
    float[] rotPoint = new float[4];
1301
    float[] surface  = new float[4];
1302

  
1303
    ObjectShape objShape = mShapes[variant];
1304
    objShape.getFacePoint(faceIndex,intPoint);
1305
    objShape.getFaceNormal(faceIndex,normal);
1306

  
1307
    QuatHelper.rotateVectorByQuat(rotPoint,intPoint[0],intPoint[1],intPoint[2],1,cubitQuat);
1308
    QuatHelper.rotateVectorByQuat(surface,normal[0],normal[1],normal[2],0,cubitQuat);
1309

  
1310
    float x = rotPoint[0] + px;
1311
    float y = rotPoint[1] + py;
1312
    float z = rotPoint[2] + pz;
1313
    surface[3] = x*surface[0] + y*surface[1] + z*surface[2];
1314

  
1315
    return surface;
1316
    }
1317

  
1318
///////////////////////////////////////////////////////////////////////////////////////////////////
1319

  
1320
  public int[][] getVariantFaceIsOuter()
1321
    {
1322
    return mVariantFaceIsOuter;
1323
    }
1324

  
1325 769
///////////////////////////////////////////////////////////////////////////////////////////////////
1326 770

  
1327 771
  public int getInternalColor()
......
1506 950
    mEffects.abortById(effectID);
1507 951
    }
1508 952

  
1509
///////////////////////////////////////////////////////////////////////////////////////////////////
1510

  
1511
  public MeshBase getObjectMesh()
1512
    {
1513
    return mMesh;
1514
    }
1515

  
1516
///////////////////////////////////////////////////////////////////////////////////////////////////
1517

  
1518
  public DistortedEffects getObjectEffects()
1519
    {
1520
    return mEffects;
1521
    }
1522

  
1523 953
///////////////////////////////////////////////////////////////////////////////////////////////////
1524 954

  
1525 955
  public ObjectStickerOverride[] getStickerOverrides()
......
1555 985
    return (mNumTexRows-1-y)*mNumTexCols + x;
1556 986
    }
1557 987

  
1558
///////////////////////////////////////////////////////////////////////////////////////////////////
1559

  
1560
  public int[] getNumLayers()
1561
    {
1562
    return mNumLayers;
1563
    }
1564

  
1565
///////////////////////////////////////////////////////////////////////////////////////////////////
1566

  
1567
  public synchronized void solve()
1568
    {
1569
    super.solve();
1570
    for(int i=0; i<mNumCubits; i++) setCubitQuat(i,0);
1571
    }
1572

  
1573 988
///////////////////////////////////////////////////////////////////////////////////////////////////
1574 989

  
1575 990
  public Bitmap getStickerBitmap()
......
1606 1021
    return builder.toString();
1607 1022
    }
1608 1023

  
1609
///////////////////////////////////////////////////////////////////////////////////////////////////
1610
// this is here only so it can be overridden in TwistyJSON so that we can get this from JSON.
1611

  
1612
  public int getNumCubitFaces()
1613
    {
1614
    return 0;
1615
    }
1616

  
1617
///////////////////////////////////////////////////////////////////////////////////////////////////
1618
// 1.0 - i.e. no pillowing - by default.
1619
// The coeff is really param of the 'sink' vertex effect - if it is not equal to 1.0, we apply the
1620
// sink effect [centered at (0,0,0)] to the whole mesh as the last step of composing it.
1621

  
1622
  public float getPillowCoeff()
1623
    {
1624
    return 1.0f;
1625
    }
1626

  
1627 1024
///////////////////////////////////////////////////////////////////////////////////////////////////
1628 1025

  
1629 1026
  public TouchControl getTouchControl()
......
1687 1084
  public boolean isSubmittable()              { return mCurrentColorSchemeSubmittable; }
1688 1085

  
1689 1086
///////////////////////////////////////////////////////////////////////////////////////////////////
1690
  // for JSON only
1087

  
1691 1088
  public abstract int getTouchControlType();
1692 1089
  public abstract int getTouchControlSplit();
1693 1090
  public abstract boolean[][] getLayerRotatable(int[] numLayers);
1694 1091
  public abstract int[][][] getEnabled();
1695
  public abstract float[] getDist3D(int[] numLayers);
1696
  public abstract Static3D[] getFaceAxis();
1697 1092
  public abstract int[][] getScrambleEdges();
1698
  public abstract float[][] getCuts(int[] numLayers);
1699 1093
  public abstract float getStickerRadius();
1700 1094
  public abstract float getStickerStroke();
1701 1095
  public abstract float[][][] getStickerAngles();
1702
  public abstract int getCubitVariant(int cubit, int[] numLayers);
1703
  public abstract ObjectShape getObjectShape(int variant);
1704
  public abstract ObjectFaceShape getObjectFaceShape(int variant);
1705
  public abstract ObjectVertexEffects getVertexEffects(int variant);
1706
  public abstract int getNumCubitVariants(int[] numLayers);
1707
  public abstract float[][] getCubitPositions(int[] numLayers);
1708
  public abstract Static4D getCubitQuats(int cubit, int[] numLayers);
1709 1096
  public abstract float getScreenRatio();
1710 1097
  public abstract int[] getColorTable();
1711 1098
  public abstract String getShortName();
1712 1099
  public abstract String printColor(int color);
1713

  
1714
  // not only for JSON
1715
  public abstract Static3D[] getRotationAxis();
1716
  public abstract int[][] getBasicAngles();
1717 1100
  public abstract int getNumPuzzleFaces();
1718 1101
  public abstract int getFOV();
1719 1102
  public abstract String[][] getTutorials();
src/main/java/org/distorted/objectlib/main/TwistyObjectOld.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 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.main;
11

  
12
import static org.distorted.objectlib.touchcontrol.TouchControl.TC_BALL;
13
import static org.distorted.objectlib.touchcontrol.TouchControl.TC_BARREL;
14
import static org.distorted.objectlib.touchcontrol.TouchControl.TC_CHANGING_MIRROR;
15
import static org.distorted.objectlib.touchcontrol.TouchControl.TC_CHANGING_SHAPEMOD;
16
import static org.distorted.objectlib.touchcontrol.TouchControl.TC_CHANGING_SQUARE;
17
import static org.distorted.objectlib.touchcontrol.TouchControl.TC_CUBOID;
18
import static org.distorted.objectlib.touchcontrol.TouchControl.TC_DODECAHEDRON;
19
import static org.distorted.objectlib.touchcontrol.TouchControl.TC_HEXAHEDRON;
20
import static org.distorted.objectlib.touchcontrol.TouchControl.TC_ICOSAHEDRON;
21
import static org.distorted.objectlib.touchcontrol.TouchControl.TC_OCTAHEDRON;
22
import static org.distorted.objectlib.touchcontrol.TouchControl.TC_TETRAHEDRON;
23

  
24
import android.graphics.Bitmap;
25
import android.graphics.Canvas;
26
import android.graphics.Paint;
27

  
28
import org.distorted.library.effect.Effect;
29
import org.distorted.library.effect.MatrixEffectMove;
30
import org.distorted.library.effect.MatrixEffectQuaternion;
31
import org.distorted.library.effect.MatrixEffectScale;
32
import org.distorted.library.effect.VertexEffectQuaternion;
33
import org.distorted.library.effect.VertexEffectSink;
34
import org.distorted.library.helpers.QuatHelper;
35
import org.distorted.library.main.DistortedEffects;
36
import org.distorted.library.main.DistortedLibrary;
37
import org.distorted.library.main.DistortedNode;
38
import org.distorted.library.main.DistortedTexture;
39
import org.distorted.library.mesh.MeshBase;
40
import org.distorted.library.mesh.MeshFile;
41
import org.distorted.library.mesh.MeshJoined;
42
import org.distorted.library.message.EffectListener;
43
import org.distorted.library.type.Static1D;
44
import org.distorted.library.type.Static3D;
45
import org.distorted.library.type.Static4D;
46
import org.distorted.objectlib.helpers.FactoryCubit;
47
import org.distorted.objectlib.helpers.FactorySticker;
48
import org.distorted.objectlib.helpers.ObjectFaceShape;
49
import org.distorted.objectlib.helpers.ObjectLibInterface;
50
import org.distorted.objectlib.helpers.ObjectShape;
51
import org.distorted.objectlib.helpers.ObjectSticker;
52
import org.distorted.objectlib.helpers.ObjectStickerOverride;
53
import org.distorted.objectlib.helpers.ObjectVertexEffects;
54
import org.distorted.objectlib.helpers.OperatingSystemInterface;
55
import org.distorted.objectlib.json.JsonReader;
56
import org.distorted.objectlib.metadata.Metadata;
57
import org.distorted.objectlib.scrambling.ObjectScrambler;
58
import org.distorted.objectlib.scrambling.ScrambleEdgeGenerator;
59
import org.distorted.objectlib.signature.ObjectSignature;
60
import org.distorted.objectlib.tablebases.ImplementedTablebasesList;
61
import org.distorted.objectlib.tablebases.TablebasesAbstract;
62
import org.distorted.objectlib.touchcontrol.TouchControl;
63
import org.distorted.objectlib.touchcontrol.TouchControlBall;
64
import org.distorted.objectlib.touchcontrol.TouchControlBarrel;
65
import org.distorted.objectlib.touchcontrol.TouchControlCuboids;
66
import org.distorted.objectlib.touchcontrol.TouchControlDodecahedron;
67
import org.distorted.objectlib.touchcontrol.TouchControlHexahedron;
68
import org.distorted.objectlib.touchcontrol.TouchControlIcosahedron;
69
import org.distorted.objectlib.touchcontrol.TouchControlMirror;
70
import org.distorted.objectlib.touchcontrol.TouchControlOctahedron;
71
import org.distorted.objectlib.touchcontrol.TouchControlShapemod;
72
import org.distorted.objectlib.touchcontrol.TouchControlSquare;
73
import org.distorted.objectlib.touchcontrol.TouchControlTetrahedron;
74

  
75
import java.io.DataInputStream;
76
import java.io.IOException;
77
import java.io.InputStream;
78
import java.util.Random;
79

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

  
82
public abstract class TwistyObjectOld extends TwistyObjectTheoretical
83
  {
84
/*
85
  public static final int MODE_ICON = 0;
86
  public static final int MODE_NORM = 1;
87

  
88
  public static final int COLOR_STROKE   = 0xff000000;
89
  public static final int COLOR_INTERNAL = 0xff000000;
90

  
91
  private static final int DEFAULT_TEXTURE_HEIGHT = 256;
92
  private static final int DEFAULT_TEXTURE_ROWS   = 8;
93

  
94
  public static final float SQ2 = (float)Math.sqrt(2);
95
  public static final float SQ3 = (float)Math.sqrt(3);
96
  public static final float SQ5 = (float)Math.sqrt(5);
97
  public static final float SQ6 = (float)Math.sqrt(6);
98

  
99
  private static final float MAX_SIZE_CHANGE = 1.35f;
100
  private static final float MIN_SIZE_CHANGE = 0.75f;
101

  
102
  private static final Static3D CENTER = new Static3D(0,0,0);
103

  
104
  protected float[][][][] mStickerCoords;
105

  
106
  private int[][] mStickerVariants;
107
  private float[] mStickerScales;
108
  private Static4D[] mOrigQuat;
109
  private TwistyObjectSolved mSolved;
110
  private MeshBase[] mMeshes;
111
  private int mNumFaceColors, mNumTextures, mNumOverrides;
112
  private int mNumCubitFaces, mNumStickerTypes;
113
  private Static4D[] mMixupModeQuats;
114
  private boolean mIsInMixupMode;
115
  private Static4D mQuat;
116
  private int[] mNumLayers;
117
  private float mSize;
118
  private DistortedEffects mEffects;
119
  private Static3D mObjectScale;
120
  private DistortedTexture mTexture;
121
  private float mInitScreenRatio;
122
  private float mObjectScreenRatio;
123
  private int mNumTexRows, mNumTexCols, mTexHeight;
124
  private MeshBase mMesh;
125
  private ObjectScrambler mScrambler;
126
  private TouchControl mTouchControl;
127
  private DistortedNode mNode;
128
  private ObjectLibInterface mInterface;
129
  private Bitmap mBitmap;
130
  private ObjectSticker[] mStickers;
131
  private ObjectShape[] mShapes;
132
  private int mNumCubitVariants;
133
  private int[][] mCubitFaceColors;
134
  private int[][] mVariantFaceIsOuter;
135
  private int mIconMode;
136
  private Metadata mMetadata;
137
  private ObjectStickerOverride[] mStickerOverrides;
138
  private boolean mError;
139
  private String mErrorString;
140
  private int mMaxNumLayers;
141
  private TwistyLayerRotations mRotation;
142
  private int[] mColorTable;
143
  private int[] mOriginalColorTable;
144
  private float mTextureBorderMultiplier, mTextureCornerMultiplier;
145
  private boolean mCurrentColorSchemeSubmittable;
146
  private int[] mCubitQuats;
147

  
148
///////////////////////////////////////////////////////////////////////////////////////////////////
149

  
150
  TwistyObjectOld(int iconMode, Static4D quat, Static3D move, float scale, InitAssets asset)
151
    {
152
    try
153
      {
154
      InputStream jsonStream = asset!=null ? asset.getJsonStream(): null;
155
      JsonReader reader = new JsonReader();
156
      reader.parseJsonFile(jsonStream);
157
      setReader(reader);
158
      mNumLayers = reader.getNumLayers();
159
      mSize      = reader.getSize();
160
      mMetadata  = null;
161
      initialize(iconMode,quat,move,scale,asset,true);
162
      if( asset!=null ) asset.close();
163
      mError = false;
164
      mErrorString=null;
165
      }
166
    catch(Exception ex)
167
      {
168
      mError = true;
169
      mErrorString = ex.getMessage();
170
      }
171
    }
172

  
173
///////////////////////////////////////////////////////////////////////////////////////////////////
174

  
175
  public TwistyObjectOld(int iconMode, float size, Static4D quat, Static3D move, float scale, Metadata meta, InitAssets asset)
176
    {
177
    mNumLayers = meta.getNumLayers();
178
    mSize      = size;
179
    mMetadata  = meta;
180
    initialize(iconMode,quat,move,scale,asset,false);
181
    if( asset!=null ) asset.close();
182
    mError = false;
183
    mErrorString = null;
184
    }
185

  
186
///////////////////////////////////////////////////////////////////////////////////////////////////
187

  
188
  private void initialize(int iconMode, Static4D quat, Static3D move, float scale, InitAssets asset, boolean fromJSON)
189
    {
190
    Static3D[] axis = getRotationAxis();
191
    int[][] angles = getBasicAngles();
192
    Static3D[] faceAxis = getFaceAxis();
193
    float[][] positions = getCubitPositions(mNumLayers);
194
    float[][] cuts = getCuts(mNumLayers);
195
    int[][] minCubits = getMinimalCubiesInRow();
196

  
197
    int numCubits = positions.length;
198
    float[][] offsets = new float[numCubits][];
199
    int[] types = new int[numCubits];
200

  
201
    for(int c=0; c<numCubits; c++)
202
      {
203
      offsets[c] = getCubitRowOffset(c);
204
      types[c] = getCubitRotationType(c);
205
      }
206

  
207
    super.initialize(axis, angles, positions, cuts, minCubits, offsets, types, faceAxis);
208

  
209
    mIconMode = iconMode;
210
    mQuat = quat;
211
    mInitScreenRatio = getScreenRatio();
212
    mCubitQuats = new int[mNumCubits];
213

  
214
    mMaxNumLayers = -1;
215
    for(int i=0; i<mNumAxis; i++)
216
      {
217
      if( mMaxNumLayers<mNumLayers[i] ) mMaxNumLayers = mNumLayers[i];
218
      }
219

  
220
    mOriginalColorTable = getColorTable();
221
    mNumFaceColors = mOriginalColorTable.length;
222
    mColorTable = new int[mNumFaceColors];
223
    recreateFaceColors();
224
    mTextureBorderMultiplier = 1.0f;
225
    mTextureCornerMultiplier = 1.0f;
226

  
227
    int scramblingType = getScrambleType();
228
    int[][] edges = getScrambleEdges();
229
    int[][] algorithms = getScrambleAlgorithms();
230

  
231
    OperatingSystemInterface os = asset==null ? null : asset.getOS();
232
    TablebasesAbstract tablebase = os!=null ? getTablebase(os) : null;
233
    mScrambler = new ObjectScrambler(scramblingType,mNumAxis,mNumLayers,algorithms,edges,tablebase);
234

  
235
    mObjectScale = new Static3D(scale,scale,scale);
236
    setObjectRatioNow(scale,720);
237

  
238
    mEffects = new DistortedEffects();
239
    createQuaternionEffects();
240

  
241
    mRotation = new TwistyLayerRotations(this,mAxis,mNumLayers,getGhostAngle(),mEffects);
242

  
243
    MatrixEffectScale scaleEffect = new MatrixEffectScale(mObjectScale);
244
    MatrixEffectQuaternion quatEffect = new MatrixEffectQuaternion(mQuat, CENTER);
245
    MatrixEffectMove moveEffect = new MatrixEffectMove(move);
246

  
247
    InputStream meshStream = asset!=null ? asset.getMeshStream(): null;
248
    boolean fromDMESH = (meshStream!=null);
249
    getQuatsAndShapes(fromDMESH,fromJSON);
250
    createMesh(meshStream,fromDMESH);
251
    setUpTextures(fromDMESH,fromJSON);
252

  
253
    int index = getSolvedFunctionIndex();
254
    mSolved = new TwistyObjectSolved(this,mCubitPos,index);
255
    mSolved.setupSolvedQuats(getSolvedQuats());
256
    mSolved.setPuzzleFaceColor(mColorTable);
257

  
258
    mEffects.apply(quatEffect);
259
    mEffects.apply(scaleEffect);
260
    mEffects.apply(moveEffect);
261

  
262
    mNode = new DistortedNode(mTexture,mEffects,mMesh);
263

  
264
    for(int c=0; c<mNumCubits; c++) setCubitQuat(c,0);
265
    }
266

  
267
///////////////////////////////////////////////////////////////////////////////////////////////////
268

  
269
  public void recreateFaceColors()
270
    {
271
    for(int i=0; i<mNumFaceColors; i++) mColorTable[i] = mOriginalColorTable[i];
272
    mCurrentColorSchemeSubmittable = true;
273
    }
274

  
275
///////////////////////////////////////////////////////////////////////////////////////////////////
276
// in degrees so that everything can be treated modulo 360
277

  
278
  public int getGhostAngle()
279
    {
280
    return 0;
281
    }
282

  
283
///////////////////////////////////////////////////////////////////////////////////////////////////
284

  
285
  private TablebasesAbstract getTablebase(OperatingSystemInterface os)
286
    {
287
    String shortName = getShortName();
288
    return ImplementedTablebasesList.createPacked(os,shortName);
289
    }
290

  
291
///////////////////////////////////////////////////////////////////////////////////////////////////
292

  
293
  private void createQuaternionEffects()
294
    {
295
    if( mNumQuats<=ObjectControl.MAX_QUATS )
296
      {
297
      mIsInMixupMode = false;
298

  
299
      for( int q=0; q<mNumQuats; q++)
300
        {
301
        VertexEffectQuaternion vq = new VertexEffectQuaternion(mObjectQuats[q],CENTER);
302
        vq.setMeshAssociation(0,q);
303
        mEffects.apply(vq);
304
        }
305
      }
306
    else if( mNumCubits<=ObjectControl.MAX_QUATS )
307
      {
308
      mIsInMixupMode = true;
309
      mMixupModeQuats = new Static4D[mNumCubits];
310

  
311
      for( int q=0; q<mNumCubits; q++)
312
        {
313
        mMixupModeQuats[q] = new Static4D(mObjectQuats[0]);
314
        VertexEffectQuaternion vq = new VertexEffectQuaternion(mMixupModeQuats[q],CENTER);
315
        vq.setMeshAssociation(0,q);
316
        mEffects.apply(vq);
317
        }
318
      }
319
    else
320
      {
321
      android.util.Log.e("D", "object has too many quaternions ("+mNumQuats+") or too many cubits ("+mNumCubits+")");
322
      }
323
    }
324

  
325
///////////////////////////////////////////////////////////////////////////////////////////////////
326

  
327
  private Static3D getPos(float[] origPos)
328
    {
329
    int len = origPos.length/3;
330
    float sumX = 0.0f;
331
    float sumY = 0.0f;
332
    float sumZ = 0.0f;
333

  
334
    for(int i=0; i<len; i++)
335
      {
336
      sumX += origPos[3*i  ];
337
      sumY += origPos[3*i+1];
338
      sumZ += origPos[3*i+2];
339
      }
340

  
341
    sumX /= len;
342
    sumY /= len;
343
    sumZ /= len;
344

  
345
    return new Static3D(sumX,sumY,sumZ);
346
    }
347

  
348
///////////////////////////////////////////////////////////////////////////////////////////////////
349

  
350
  private void createOuterFaces()
351
    {
352
    for(int v=0; v<mNumCubitVariants; v++)
353
      {
354
      int numFaces = mShapes[v].getNumFaces();
355
      mVariantFaceIsOuter[v] = new int[numFaces];
356
      }
357

  
358
    for( int cubit=0; cubit<mNumCubits; cubit++)
359
      {
360
      int variant = getCubitVariant(cubit,mNumLayers);
361
      int numFaces = mShapes[variant].getNumFaces();
362

  
363
      for(int face=0; face<numFaces; face++)
364
        if( getDefaultCubitFaceColor(cubit,face)>=0 )
365
          {
366
          mVariantFaceIsOuter[variant][face] = 1;
367
          }
368
      }
369
    }
370

  
371
///////////////////////////////////////////////////////////////////////////////////////////////////
372

  
373
  private void getQuatsAndShapes(boolean fromDMESH, boolean fromJSON)
374
    {
375
    mNumCubitVariants = getNumCubitVariants(mNumLayers);
376

  
377
    if( !fromDMESH || !fromJSON )
378
      {
379
      FactoryCubit factory = FactoryCubit.getInstance();
380
      factory.clear();
381

  
382
      mShapes = new ObjectShape[mNumCubitVariants];
383
      for(int v=0; v<mNumCubitVariants; v++) mShapes[v] = getObjectShape(v);
384
      mNumCubitFaces = ObjectShape.computeNumComponents(mShapes);
385
      mVariantFaceIsOuter = new int[mNumCubitVariants][];
386

  
387
      mOrigQuat = new Static4D[mNumCubits];
388
      for(int i=0; i<mNumCubits; i++) mOrigQuat[i] = getCubitQuats(i,mNumLayers);
389

  
390
      if( !fromJSON )
391
        {
392
        mCubitFaceColors = ObjectShape.computeColors(mShapes,mCubitPos,mOrigQuat,this);
393
        createOuterFaces();
394
        }
395

  
396
      if( fromDMESH )
397
        {
398
        for(int i=0; i<mNumCubitVariants; i++) factory.createNewFaceTransform(mShapes[i], mVariantFaceIsOuter[i]);
399
        }
400
      }
401
    }
402

  
403
///////////////////////////////////////////////////////////////////////////////////////////////////
404

  
405
  private void createMesh(InputStream stream, boolean fromDMESH)
406
    {
407
    if( fromDMESH )
408
      {
409
      DataInputStream dos = new DataInputStream(stream);
410
      mMesh = new MeshFile(dos);
411

  
412
      try
413
        {
414
        stream.close();
415
        }
416
      catch(IOException e)
417
        {
418
        android.util.Log.e("meshFile", "Error closing InputStream: "+e);
419
        }
420
      }
421
    else
422
      {
423
      MeshBase[] cubitMesh = new MeshBase[mNumCubits];
424

  
425
      for(int i=0; i<mNumCubits; i++)
426
        {
427
        cubitMesh[i] = createCubitMesh(i,mNumLayers,mNumCubitFaces);
428
        Static3D pos = getPos(mCubitPos[i]);
429
        cubitMesh[i].apply(new MatrixEffectMove(pos),1,0);
430
        }
431

  
432
      mMesh = new MeshJoined(cubitMesh);
433

  
434
      float pillowCoeff = getPillowCoeff();
435

  
436
      if( pillowCoeff!=1.0f )
437
        {
438
        float radius = getCircumscribedRadius();
439
        Static1D coeff = new Static1D(pillowCoeff);
440
        Static4D region= new Static4D(0,0,0,radius);
441
        VertexEffectSink sink = new VertexEffectSink(coeff,CENTER,region);
442
        mMesh.apply(sink);
443
        }
444
      }
445
    }
446

  
447
///////////////////////////////////////////////////////////////////////////////////////////////////
448

  
449
  private MeshBase createCubitMesh(int cubit, int[] numLayers, int numComponents)
450
    {
451
    int variant = getCubitVariant(cubit,numLayers);
452

  
453
    if( mMeshes==null ) mMeshes = new MeshBase[mNumCubitVariants];
454

  
455
    if( mMeshes[variant]==null )
456
      {
457
      ObjectFaceShape faceShape = getObjectFaceShape(variant);
458
      ObjectVertexEffects effects = getVertexEffects(variant);
459
      FactoryCubit factory = FactoryCubit.getInstance();
460
      factory.createNewFaceTransform(mShapes[variant],mVariantFaceIsOuter[variant]);
461
      mMeshes[variant] = factory.createRoundedSolid(mShapes[variant],faceShape,effects,numComponents);
462
      }
463

  
464
    MeshBase mesh = mMeshes[variant].copy(true);
465
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( mOrigQuat[cubit], CENTER );
466
    mesh.apply(quat,0xffffffff,0);
467

  
468
    return mesh;
469
    }
470

  
471
///////////////////////////////////////////////////////////////////////////////////////////////////
472

  
473
  private void figureOutBitmapDimensions(int numTextures)
474
    {
475
    int maxSize = DistortedLibrary.getMaxTextureSize();
476

  
477
    mTexHeight  = DEFAULT_TEXTURE_HEIGHT;
478

  
479
    while(true)
480
      {
481
      mNumTexCols = DEFAULT_TEXTURE_ROWS;
482
      mNumTexRows = numTextures/mNumTexCols + 1;
483

  
484
      if( mNumTexRows*mTexHeight <= maxSize &&
485
          mNumTexCols*mTexHeight <= maxSize  ) break;
486

  
487
      mTexHeight/=2;
488
      }
489
    }
490

  
491
///////////////////////////////////////////////////////////////////////////////////////////////////
492

  
493
  private void setUpTextures(boolean fromDMESH, boolean fromJSON)
494
    {
495
    mTexture = new DistortedTexture();
496

  
497
    if( fromJSON )
498
      {
499
      mNumStickerTypes = getNumStickerTypes();
500
      mNumCubitFaces = getNumCubitFaces();
501
      }
502
    else
503
      {
504
      FactoryCubit factory = FactoryCubit.getInstance();
505
      mStickerCoords   = factory.getStickerCoords();
506
      mStickerVariants = factory.getStickerVariants();
507
      mStickerScales   = factory.getStickerScales();
508
      adjustStickerCoords();
509
      mNumStickerTypes = (mStickerCoords==null ? 0 : mStickerCoords.length);
510
      }
511

  
512
    mStickerOverrides = getStickerOverrides();
513
    mNumOverrides = mStickerOverrides==null ? 0 : mStickerOverrides.length;
514

  
515
    mNumTextures= mNumFaceColors*mNumStickerTypes + mNumOverrides;
516
    figureOutBitmapDimensions(mNumTextures);
517
    if( mNumTexCols*mNumTexRows < mNumTextures+1 ) mNumTexRows++;
518

  
519
    if( !fromDMESH || shouldResetTextureMaps() ) resetAllTextureMaps();
520
    else overrideCubitFaceColor();
521

  
522
    setTexture();
523
    }
524

  
525
///////////////////////////////////////////////////////////////////////////////////////////////////
526

  
527
  public Metadata getMetadata()
528
    {
529
    return mMetadata;
530
    }
531

  
532
///////////////////////////////////////////////////////////////////////////////////////////////////
533

  
534
  public boolean isInIconMode()
535
    {
536
    return mIconMode==MODE_ICON;
537
    }
538

  
539
///////////////////////////////////////////////////////////////////////////////////////////////////
540

  
541
  public int getVariantStickerShape(int variant, int face)
542
    {
543
    if( variant <mStickerVariants.length )
544
      {
545
      int[] var = mStickerVariants[variant];
546
      return face>=var.length ? -1 : var[face];
547
      }
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff