Project

General

Profile

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

examples / src / main / java / org / distorted / examples / rubik / RubikCube.java @ 6e18bd32

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// Distorted 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
// Distorted 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 Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.examples.rubik;
21

    
22
import java.util.Random;
23

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

    
28
import org.distorted.library.effect.MatrixEffectMove;
29
import org.distorted.library.effect.MatrixEffectQuaternion;
30
import org.distorted.library.effect.MatrixEffectRotate;
31
import org.distorted.library.effect.MatrixEffectScale;
32
import org.distorted.library.effect.VertexEffectSink;
33
import org.distorted.library.main.DistortedEffects;
34
import org.distorted.library.main.DistortedNode;
35
import org.distorted.library.main.DistortedScreen;
36
import org.distorted.library.main.DistortedTexture;
37
import org.distorted.library.mesh.MeshCubes;
38
import org.distorted.library.message.EffectListener;
39
import org.distorted.library.type.Dynamic1D;
40
import org.distorted.library.type.Static1D;
41
import org.distorted.library.type.Static3D;
42
import org.distorted.library.type.Static4D;
43

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

    
46
class RubikCube
47
{
48
    private static final int VECTX = 0;  //
49
    private static final int VECTY = 1;  // don't change this
50
    private static final int VECTZ = 2;  //
51

    
52
    private static final int ROTATION_MILLISEC = 1500;
53
    private static final int TEXTURE_SIZE = 100;
54

    
55
    private static final Static3D VectX = new Static3D(1,0,0);
56
    private static final Static3D VectY = new Static3D(0,1,0);
57
    private static final Static3D VectZ = new Static3D(0,0,1);
58

    
59
    private DistortedNode[][][] mNodes;
60
    private MeshCubes[][][] mCubes;
61
    private DistortedEffects[][][] mEffects;
62
    private Static3D[][][] mRotationAxis;
63
    private Dynamic1D[][][] mRotationAngle;
64
    private DistortedTexture mTexture;
65

    
66
    private int mSize;
67

    
68
    private Random mRnd = new Random(0);
69

    
70
///////////////////////////////////////////////////////////////////////////////////////////////////
71

    
72
    RubikCube(int size, Static3D move, Static3D scale)
73
      {
74
      mSize = size;
75

    
76
      mTexture = new DistortedTexture(TEXTURE_SIZE,TEXTURE_SIZE);
77

    
78
      mNodes          = new DistortedNode[mSize][mSize][mSize];
79
      mCubes          = new MeshCubes[mSize][mSize][mSize];
80
      mEffects        = new DistortedEffects[mSize][mSize][mSize];
81
      mRotationAxis   = new Static3D[mSize][mSize][mSize];
82
      mRotationAngle  = new Dynamic1D[mSize][mSize][mSize];
83

    
84
      Static3D[][][] cubeVectors = new Static3D[mSize][mSize][mSize];
85

    
86
      Static3D center = new Static3D(TEXTURE_SIZE*0.5f, TEXTURE_SIZE*0.5f, TEXTURE_SIZE*0.5f);
87
      Static4D region = new Static4D(0,0,0, TEXTURE_SIZE*0.72f);
88

    
89
      VertexEffectSink        sinkEffect = new VertexEffectSink( new Static1D(getSinkStrength()), center, region );
90
      MatrixEffectMove        moveEffect = new MatrixEffectMove(move);
91
      MatrixEffectScale      scaleEffect = new MatrixEffectScale(scale);
92
      MatrixEffectQuaternion  quatEffect = new MatrixEffectQuaternion( initializeQuat(), center);
93

    
94
      // 3x2 bitmap = 6 squares:
95
      //
96
      // RED     GREEN   BLUE
97
      // YELLOW  WHITE   BROWN
98

    
99
      final float ze = 0.0f;
100
      final float ot = 1.0f/3.0f;
101
      final float tt = 2.0f/3.0f;
102
      final float oh = 1.0f/2.0f;
103
      final float of = 1.0f/40.0f;
104

    
105
      final Static4D mapFront = new Static4D(ze,oh, ze+ot,oh+oh);
106
      final Static4D mapBack  = new Static4D(tt,ze, tt+ot,ze+oh);
107
      final Static4D mapLeft  = new Static4D(ot,ze, ot+ot,ze+oh);
108
      final Static4D mapRight = new Static4D(ze,ze, ze+ot,ze+oh);
109
      final Static4D mapTop   = new Static4D(tt,oh, tt+ot,oh+oh);
110
      final Static4D mapBottom= new Static4D(ot,oh, ot+ot,oh+oh);
111

    
112
      final Static4D mapBlack = new Static4D(ze,ze, ze+of,ze+of);
113

    
114
      Static4D tmpFront, tmpBack, tmpLeft, tmpRight, tmpTop, tmpBottom;
115
      float nc = 0.5f*(mSize-1);
116
      int vertices = (int)(24.0f/mSize + 2.0f);
117

    
118
      for(int x = 0; x< mSize; x++)
119
        for(int y = 0; y< mSize; y++)
120
          for(int z = 0; z< mSize; z++)
121
            {
122
            if( x==0 || x==mSize-1 || y==0 || y==mSize-1 || z==0 || z==mSize-1 ) // only the external walls
123
              {
124
              tmpLeft  = (x==       0 ? mapLeft  :mapBlack);
125
              tmpRight = (x== mSize-1 ? mapRight :mapBlack);
126
              tmpFront = (z== mSize-1 ? mapFront :mapBlack);
127
              tmpBack  = (z==       0 ? mapBack  :mapBlack);
128
              tmpTop   = (y== mSize-1 ? mapTop   :mapBlack);
129
              tmpBottom= (y==       0 ? mapBottom:mapBlack);
130

    
131
              mCubes[x][y][z]           = new MeshCubes(vertices,vertices,vertices, tmpFront, tmpBack, tmpLeft, tmpRight, tmpTop, tmpBottom);
132
              cubeVectors[x][y][z]      = new Static3D( TEXTURE_SIZE*(x-nc), TEXTURE_SIZE*(y-nc), TEXTURE_SIZE*(z-nc) );
133
              mRotationAngle[x][y][z]   = new Dynamic1D();
134
              mRotationAxis[x][y][z]    = new Static3D(1,0,0);
135

    
136
              mRotationAngle[x][y][z].add(new Static1D(0.0f));
137
              mRotationAngle[x][y][z].add(new Static1D(0.0f));
138

    
139
              mEffects[x][y][z] = new DistortedEffects();
140
              mEffects[x][y][z].apply(sinkEffect);
141
              mEffects[x][y][z].apply(moveEffect);
142
              mEffects[x][y][z].apply(scaleEffect);
143
              mEffects[x][y][z].apply(quatEffect);
144
              mEffects[x][y][z].apply( new MatrixEffectRotate( mRotationAngle[x][y][z], mRotationAxis[x][y][z], center));
145
              mEffects[x][y][z].apply( new MatrixEffectMove(cubeVectors[x][y][z]) );
146
              }
147
            }
148
      }
149

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

    
152
    void attachToScreen(DistortedScreen screen)
153
      {
154
      for(int x=0; x<mSize; x++)
155
        for(int y=0; y<mSize; y++)
156
          for(int z=0; z<mSize; z++)
157
            {
158
            if( x==0 || x==mSize-1 || y==0 || y==mSize-1 || z==0 || z==mSize-1 )
159
              {
160
              mNodes[x][y][z] = new DistortedNode(mTexture,mEffects[x][y][z],mCubes[x][y][z]);
161
              screen.attach(mNodes[x][y][z]);
162
              }
163
            }
164
      }
165

    
166
///////////////////////////////////////////////////////////////////////////////////////////////////
167
// all DistortedTextures, DistortedNodes, DistortedFramebuffers, DistortedScreens and all types of
168
// Meshes HAVE TO be markedForDeletion when they are no longer needed- otherwise we have a major
169
// memory leak.
170

    
171
    void releaseResources()
172
      {
173
      mTexture.markForDeletion();
174

    
175
      for(int x=0; x<mSize; x++)
176
        for(int y=0; y<mSize; y++)
177
          for(int z=0; z<mSize; z++)
178
            {
179
            if( x==0 || x==mSize-1 || y==0 || y==mSize-1 || z==0 || z==mSize-1 )
180
              {
181
              mCubes[x][y][z].markForDeletion();
182
              mNodes[x][y][z].markForDeletion();
183
              }
184
            }
185
      }
186

    
187
///////////////////////////////////////////////////////////////////////////////////////////////////
188

    
189
    void addRotation(EffectListener listener)
190
      {
191
      mRnd.setSeed(System.currentTimeMillis());
192

    
193
      int vector = mRnd.nextInt(3);
194
      int rotRow = mRnd.nextInt(mSize);
195

    
196
      boolean first = true;
197
      Static3D axis = VectX;
198

    
199
      switch(vector)
200
        {
201
        case VECTX: axis = VectX; break;
202
        case VECTY: axis = VectY; break;
203
        case VECTZ: axis = VectZ; break;
204
        }
205

    
206
      for(int x=0; x<mSize; x++)
207
        for(int y=0; y<mSize; y++)
208
          for(int z=0; z<mSize; z++)
209
            if( x==0 || x==mSize-1 || y==0 || y==mSize-1 || z==0 || z==mSize-1 )
210
              {
211
              if( belongsToRotation(x,y,z,vector,rotRow) )
212
                {
213
                mRotationAxis[x][y][z].set(axis);
214
                mRotationAngle[x][y][z].makeRunNowFor(ROTATION_MILLISEC);
215
                mRotationAngle[x][y][z].setPoint(1,90.0f);
216

    
217
                if( first )
218
                  {
219
                  first = false;
220
                  mEffects[x][y][z].registerForMessages(listener);
221
                  }
222
                }
223
              }
224
      }
225

    
226
///////////////////////////////////////////////////////////////////////////////////////////////////
227
// Initial rotation of the cube. Something semi-random that looks good.
228

    
229
   private Static4D initializeQuat()
230
     {
231
     return new Static4D(-0.25189602f,0.3546389f,0.009657208f,0.90038127f);
232
     }
233

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

    
236
    private boolean belongsToRotation(int x, int y, int z, int vector, int row)
237
      {
238
      switch(vector)
239
        {
240
        case VECTX: return x==row;
241
        case VECTY: return y==row;
242
        case VECTZ: return z==row;
243
        }
244

    
245
      return false;
246
      }
247

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

    
250
    private float getSinkStrength()
251
      {
252
      switch(mSize)
253
        {
254
        case 1 : return 1.1f;
255
        case 2 : return 1.5f;
256
        case 3 : return 1.8f;
257
        case 4 : return 2.0f;
258
        default: return 3.0f - 4.0f/mSize;
259
        }
260
      }
261

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

    
264
    void createTexture()
265
      {
266
      Bitmap bitmap;
267

    
268
      final int S = 128;
269
      final int W = 3*S;
270
      final int H = 2*S;
271
      final int R = S/10;
272
      final int M = S/20;
273

    
274
      Paint paint = new Paint();
275
      bitmap = Bitmap.createBitmap(W,H, Bitmap.Config.ARGB_8888);
276
      Canvas canvas = new Canvas(bitmap);
277

    
278
      paint.setAntiAlias(true);
279
      paint.setTextAlign(Paint.Align.CENTER);
280
      paint.setStyle(Paint.Style.FILL);
281

    
282
      // 3x2 bitmap = 6 squares:
283
      //
284
      // RED     GREEN   BLUE
285
      // YELLOW  WHITE   BROWN
286

    
287
      paint.setColor(0xff000000);                                  // BLACK BACKGROUND
288
      canvas.drawRect(0, 0, W, H, paint);                          //
289

    
290
      paint.setColor(0xffff0000);                                  // RED
291
      canvas.drawRoundRect(    M,   M,   S-M,   S-M, R, R, paint); //
292
      paint.setColor(0xff00ff00);                                  // GREEN
293
      canvas.drawRoundRect(  S+M,   M, 2*S-M,   S-M, R, R, paint); //
294
      paint.setColor(0xff0000ff);                                  // BLUE
295
      canvas.drawRoundRect(2*S+M,   M, 3*S-M,   S-M, R, R, paint); //
296
      paint.setColor(0xffffff00);                                  // YELLOW
297
      canvas.drawRoundRect(    M, S+M,   S-M, 2*S-M, R, R, paint); //
298
      paint.setColor(0xffffffff);                                  // WHITE
299
      canvas.drawRoundRect(  S+M, S+M, 2*S-M, 2*S-M, R, R, paint); //
300
      paint.setColor(0xffb5651d);                                  // BROWN
301
      canvas.drawRoundRect(2*S+M, S+M, 3*S-M, 2*S-M, R, R, paint); //
302

    
303
      mTexture.setTexture(bitmap);
304
      }
305

    
306
///////////////////////////////////////////////////////////////////////////////////////////////////
307

    
308
    float getTextureSize()
309
      {
310
      return TEXTURE_SIZE;
311
      }
312

    
313
///////////////////////////////////////////////////////////////////////////////////////////////////
314

    
315
    int getSize()
316
      {
317
      return mSize;
318
      }
319
}
(2-2/4)