Project

General

Profile

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

magiccube / src / main / java / org / distorted / magic / RubikRenderer.java @ 5bfc1b49

1 0c52af30 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 Leszek Koltunski                                                               //
3
//                                                                                               //
4 fdec60a3 Leszek Koltunski
// This file is part of Magic Cube.                                                              //
5 0c52af30 Leszek Koltunski
//                                                                                               //
6 fdec60a3 Leszek Koltunski
// Magic Cube is free software: you can redistribute it and/or modify                            //
7 0c52af30 Leszek Koltunski
// 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 fdec60a3 Leszek Koltunski
// Magic Cube is distributed in the hope that it will be useful,                                 //
12 0c52af30 Leszek Koltunski
// 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 fdec60a3 Leszek Koltunski
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18 0c52af30 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
19
20
package org.distorted.magic;
21
22 0333d81e Leszek Koltunski
import android.content.SharedPreferences;
23 0c52af30 Leszek Koltunski
import android.opengl.GLSurfaceView;
24
25 64975793 Leszek Koltunski
import org.distorted.effect.BaseEffect;
26 0c52af30 Leszek Koltunski
import org.distorted.library.effect.VertexEffectSink;
27 9208e27b Leszek Koltunski
import org.distorted.library.main.DistortedEffects;
28 e1111500 Leszek Koltunski
import org.distorted.library.main.DistortedLibrary;
29 0c52af30 Leszek Koltunski
import org.distorted.library.main.DistortedScreen;
30 9208e27b Leszek Koltunski
import org.distorted.library.main.DistortedTexture;
31 39fb9047 Leszek Koltunski
import org.distorted.library.mesh.MeshFlat;
32 0c52af30 Leszek Koltunski
import org.distorted.library.message.EffectListener;
33 beb325a0 Leszek Koltunski
import org.distorted.object.RubikCube;
34 4f9f99a2 Leszek Koltunski
import org.distorted.object.RubikObject;
35 211b48f2 Leszek Koltunski
import org.distorted.uistate.RubikState;
36
import org.distorted.uistate.RubikStatePlay;
37 0333d81e Leszek Koltunski
import org.distorted.uistate.RubikStateSolving;
38 0c52af30 Leszek Koltunski
39
import javax.microedition.khronos.egl.EGLConfig;
40
import javax.microedition.khronos.opengles.GL10;
41
42
///////////////////////////////////////////////////////////////////////////////////////////////////
43
44 9208e27b Leszek Koltunski
public class RubikRenderer implements GLSurfaceView.Renderer, EffectListener
45 0c52af30 Leszek Koltunski
{
46 0fd3ac1f Leszek Koltunski
    static final float CAMERA_DISTANCE = 0.6f;  // 0.6 of the length of min(scrHeight,scrWidth)
47 123d6172 Leszek Koltunski
    public static final int TEXTURE_SIZE = 600;
48 0c52af30 Leszek Koltunski
49
    private RubikSurfaceView mView;
50
    private DistortedScreen mScreen;
51 3b12e641 Leszek Koltunski
    private int mNextCubeSize, mScrambleCubeNum;
52 64975793 Leszek Koltunski
    private long mRotationFinishedID;
53
    private long[] mEffectID;
54 05fa94d9 Leszek Koltunski
    private boolean mFinishRotation, mRemoveRotation, mSetQuatCurrent, mSetQuatAccumulated;
55 408d4676 Leszek Koltunski
    private boolean mSizeChangeCube, mSolveCube, mScrambleCube;
56 45686da2 Leszek Koltunski
    private boolean mCanRotate, mCanDrag, mCanUI;
57 47ba5ddc Leszek Koltunski
    private boolean mIsSolved;
58 434f2f5a Leszek Koltunski
    private RubikCube mOldCube, mNewCube;
59 d1484aba Leszek Koltunski
    private int mScreenWidth, mScreenHeight;
60 39fb9047 Leszek Koltunski
    private MeshFlat mMesh;
61 5bfc1b49 Leszek Koltunski
    private SharedPreferences mPreferences;
62 9208e27b Leszek Koltunski
63 0c52af30 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
64
65
    RubikRenderer(RubikSurfaceView v)
66
      {
67
      mView = v;
68
      mScreen = new DistortedScreen();
69
70 434f2f5a Leszek Koltunski
      mOldCube = null;
71
      mNewCube = null;
72
73 d1484aba Leszek Koltunski
      mScreenWidth = mScreenHeight = 0;
74 3b12e641 Leszek Koltunski
      mScrambleCubeNum = 0;
75 d1484aba Leszek Koltunski
76 05fa94d9 Leszek Koltunski
      mFinishRotation     = false;
77
      mRemoveRotation     = false;
78
      mSetQuatCurrent     = false;
79
      mSetQuatAccumulated = false;
80
      mSizeChangeCube     = true;
81
      mSolveCube          = false;
82
      mScrambleCube       = false;
83 0c52af30 Leszek Koltunski
84 2ecf0c21 Leszek Koltunski
      mCanRotate   = true;
85
      mCanDrag     = true;
86 45686da2 Leszek Koltunski
      mCanUI       = true;
87 9208e27b Leszek Koltunski
88 64975793 Leszek Koltunski
      mEffectID = new long[BaseEffect.Type.LENGTH];
89
90 39fb9047 Leszek Koltunski
      mMesh= new MeshFlat(20,20);
91 211b48f2 Leszek Koltunski
92
      RubikStatePlay play = (RubikStatePlay) RubikState.PLAY.getStateClass();
93
      int size = play.getButton();
94 4f9f99a2 Leszek Koltunski
      mNextCubeSize = RubikObject.getObject(size).getObjectSize();
95 0c52af30 Leszek Koltunski
      }
96
97 47ba5ddc Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
98
99
   private void createCubeNow(int newSize)
100
     {
101 5bfc1b49 Leszek Koltunski
     boolean firstTime = (mOldCube==null && mNewCube==null);
102
103 47ba5ddc Leszek Koltunski
     if( mOldCube!=null ) mOldCube.releaseResources();
104
     mOldCube = mNewCube;
105
106
     DistortedTexture texture = new DistortedTexture(TEXTURE_SIZE,TEXTURE_SIZE);
107
     DistortedEffects effects = new DistortedEffects();
108
109
     mNewCube = new RubikCube(newSize, mView.getQuatCurrent(), mView.getQuatAccumulated(), texture, mMesh, effects);
110
     mNewCube.createTexture();
111 5bfc1b49 Leszek Koltunski
     if( firstTime ) mNewCube.restorePreferences(mPreferences);
112 47ba5ddc Leszek Koltunski
113
     if( mScreenWidth!=0 )
114
       {
115 beb325a0 Leszek Koltunski
       mNewCube.recomputeScaleFactor(mScreenWidth, mScreenHeight);
116 47ba5ddc Leszek Koltunski
       }
117
118
     mIsSolved = true;
119
     }
120
121
///////////////////////////////////////////////////////////////////////////////////////////////////
122
// do all 'adjustable' effects (SizeChange, Solve, Scramble)
123
124
   private void doEffectNow(BaseEffect.Type type)
125
     {
126
     int index = type.ordinal();
127
128 beb325a0 Leszek Koltunski
     try
129
       {
130
       mEffectID[index] = type.startEffect(this);
131
       }
132
     catch( Exception ex )
133 47ba5ddc Leszek Koltunski
       {
134 beb325a0 Leszek Koltunski
       android.util.Log.e("renderer", "exception starting effect: "+ex.getMessage());
135
136 47ba5ddc Leszek Koltunski
       mCanUI     = true;
137
       mCanRotate = true;
138
       mCanDrag   = true;
139
       }
140
     }
141
142 0333d81e Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
143
144
   void savePreferences(SharedPreferences.Editor editor)
145
     {
146 5bfc1b49 Leszek Koltunski
     mNewCube.savePreferences(editor);
147 0333d81e Leszek Koltunski
     }
148
149
///////////////////////////////////////////////////////////////////////////////////////////////////
150
151
   void restorePreferences(SharedPreferences preferences)
152
     {
153 5bfc1b49 Leszek Koltunski
     mPreferences = preferences;
154 0333d81e Leszek Koltunski
     }
155
156 47ba5ddc Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
157
// no this will not race with onDrawFrame
158
159
   void finishRotation()
160
     {
161
     mFinishRotation = true;
162
     }
163
164
///////////////////////////////////////////////////////////////////////////////////////////////////
165
166
   boolean createCube(int newSize)
167
     {
168
     if( mCanDrag && mCanRotate && (mNewCube==null || newSize != mNewCube.getSize()) )
169
       {
170
       mSizeChangeCube = true;
171
       mNextCubeSize = newSize;
172
       return true;
173
       }
174
175
     return false;
176
     }
177
178
///////////////////////////////////////////////////////////////////////////////////////////////////
179
180
   void scrambleCube(int num)
181
     {
182
     if( mCanUI )
183
       {
184
       mScrambleCube = true;
185
       mScrambleCubeNum = num;
186
       }
187
     }
188
189
///////////////////////////////////////////////////////////////////////////////////////////////////
190
191
   void solveCube()
192
     {
193
     if( mCanUI )
194
       {
195
       mSolveCube = true;
196
       }
197
     }
198
199
///////////////////////////////////////////////////////////////////////////////////////////////////
200
201
   boolean canRotate()
202
     {
203
     return mCanRotate;
204
     }
205
206
///////////////////////////////////////////////////////////////////////////////////////////////////
207
208
   boolean canDrag()
209
     {
210
     return mCanDrag;
211
     }
212
213
///////////////////////////////////////////////////////////////////////////////////////////////////
214
215
   void setQuatCurrentOnNextRender()
216
     {
217
     mSetQuatCurrent = true;
218
     }
219
220
///////////////////////////////////////////////////////////////////////////////////////////////////
221
222
   void setQuatAccumulatedOnNextRender()
223
     {
224
     mSetQuatAccumulated = true;
225
     }
226
227 0c52af30 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
228
// various things are done here delayed, 'after the next render' as not to be done mid-render and
229
// cause artifacts.
230
231 a7a7cc9c Leszek Koltunski
   @Override
232
   public void onDrawFrame(GL10 glUnused)
233
     {
234
     mScreen.render( System.currentTimeMillis() );
235
236
     if( mSetQuatCurrent )
237
       {
238
       mSetQuatCurrent = false;
239
       mView.setQuatCurrent();
240
       }
241
242
     if( mSetQuatAccumulated )
243
       {
244
       mSetQuatAccumulated = false;
245
       mView.setQuatAccumulated();
246
       }
247
248
     if( mFinishRotation )
249
       {
250
       mFinishRotation = false;
251
       mCanRotate      = false;
252
       mCanUI          = false;
253
       mRotationFinishedID = mNewCube.finishRotationNow(this);
254
       }
255
256
     if( mRemoveRotation )
257
       {
258
       mRemoveRotation=false;
259
       mNewCube.removeRotationNow();
260
261
       boolean solved = mNewCube.isSolved();
262
263
       if( solved && !mIsSolved )
264
         {
265 0333d81e Leszek Koltunski
         if( RubikState.getCurrentState()==RubikState.SOLV )
266
           {
267
           RubikStateSolving solving = (RubikStateSolving)RubikState.SOLV.getStateClass();
268
           long time = solving.stopCounting();
269
           android.util.Log.e("renderer", "solving time: "+time+" milliseconds");
270
           }
271
272
         mCanDrag   = true;
273
         mCanRotate = false;
274
         mCanUI     = false;
275 a7a7cc9c Leszek Koltunski
         doEffectNow( BaseEffect.Type.WIN );
276
         }
277
       else
278
         {
279
         mCanRotate = true;
280
         mCanUI     = true;
281
         }
282
283
       mIsSolved = solved;
284
       }
285
286
     if( mSizeChangeCube )
287
       {
288
       mSizeChangeCube = false;
289
       mCanDrag        = false;
290
       mCanRotate      = false;
291
       mCanUI          = false;
292
       createCubeNow(mNextCubeSize);
293
       doEffectNow( BaseEffect.Type.SIZECHANGE );
294
       }
295
296
     if( mSolveCube )
297
       {
298
       mSolveCube      = false;
299
       mCanDrag        = false;
300
       mCanRotate      = false;
301
       mCanUI          = false;
302
       doEffectNow( BaseEffect.Type.SOLVE );
303
       }
304
305
     if( mScrambleCube )
306
       {
307
       mScrambleCube = false;
308
       mCanDrag      = false;
309
       mCanRotate    = false;
310
       mCanUI        = false;
311
       doEffectNow( BaseEffect.Type.SCRAMBLE );
312
       }
313
     }
314 0c52af30 Leszek Koltunski
315
///////////////////////////////////////////////////////////////////////////////////////////////////
316 aa8b36aa Leszek Koltunski
317
   @Override
318
   public void onSurfaceChanged(GL10 glUnused, int width, int height)
319
      {
320
      if( mNewCube!=null ) mNewCube.createTexture();
321
322 123d6172 Leszek Koltunski
      double halfFOVInRadians = Math.atan( 1.0f/(2*CAMERA_DISTANCE) );
323
      float fovInDegrees = (float)(2*halfFOVInRadians*(180/Math.PI));
324 beb325a0 Leszek Koltunski
325
      mScreen.setProjection( fovInDegrees, 0.1f);
326 aa8b36aa Leszek Koltunski
      mScreen.resize(width, height);
327 123d6172 Leszek Koltunski
      mView.setScreenSize(width,height);
328 aa8b36aa Leszek Koltunski
329 beb325a0 Leszek Koltunski
      if( mNewCube!=null )
330
        {
331 123d6172 Leszek Koltunski
        mNewCube.recomputeScaleFactor(width,height);
332 beb325a0 Leszek Koltunski
        }
333 aa8b36aa Leszek Koltunski
334
      mScreenHeight = height;
335
      mScreenWidth  = width;
336
      }
337
338
///////////////////////////////////////////////////////////////////////////////////////////////////
339
340
   @Override
341
   public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
342
      {
343
      VertexEffectSink.enable();
344 64975793 Leszek Koltunski
      BaseEffect.Type.enableEffects();
345 aa8b36aa Leszek Koltunski
346
      try
347
        {
348
        DistortedLibrary.onCreate(mView.getContext());
349
        }
350
      catch(Exception ex)
351
        {
352
        android.util.Log.e("Rubik", ex.getMessage() );
353
        }
354
      }
355
356 ad9e8bb3 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
357
// PUBLIC API
358 aa8b36aa Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
359 0c52af30 Leszek Koltunski
360 f647630d Leszek Koltunski
   public void effectFinished(final long effectID)
361 0c52af30 Leszek Koltunski
     {
362 45686da2 Leszek Koltunski
     if( effectID == mRotationFinishedID )
363 434f2f5a Leszek Koltunski
       {
364
       mRemoveRotation = true;
365
       }
366 45686da2 Leszek Koltunski
     else
367 3b12e641 Leszek Koltunski
       {
368 45686da2 Leszek Koltunski
       for(int i=0; i<BaseEffect.Type.LENGTH; i++)
369
         {
370
         if( effectID == mEffectID[i] )
371
           {
372
           mCanRotate   = true;
373
           mCanDrag     = true;
374
           mCanUI       = true;
375 ad9e8bb3 Leszek Koltunski
376
           if( i==BaseEffect.Type.SCRAMBLE.ordinal() )
377
             {
378
             final RubikActivity act = (RubikActivity)mView.getContext();
379
380
             act.runOnUiThread(new Runnable()
381
               {
382
               @Override
383
               public void run()
384
                 {
385
                 RubikState.switchState( act, RubikState.SOLV);
386
                 }
387
               });
388
             }
389 45686da2 Leszek Koltunski
           break;
390
           }
391
         }
392 3b12e641 Leszek Koltunski
       }
393 34747dd1 Leszek Koltunski
     }
394 f291130e Leszek Koltunski
395 0c52af30 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
396
397 64975793 Leszek Koltunski
   public RubikCube getCube()
398 8197c92d Leszek Koltunski
     {
399 64975793 Leszek Koltunski
     return mNewCube;
400 8197c92d Leszek Koltunski
     }
401
402
///////////////////////////////////////////////////////////////////////////////////////////////////
403
404 64975793 Leszek Koltunski
   public RubikCube getOldCube()
405 8197c92d Leszek Koltunski
     {
406 64975793 Leszek Koltunski
     return mOldCube;
407 8197c92d Leszek Koltunski
     }
408
409 434f2f5a Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
410
411 64975793 Leszek Koltunski
   public DistortedScreen getScreen()
412 434f2f5a Leszek Koltunski
     {
413 64975793 Leszek Koltunski
     return mScreen;
414 434f2f5a Leszek Koltunski
     }
415
416 8197c92d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
417
418 64975793 Leszek Koltunski
   public int getNumScrambles()
419 8197c92d Leszek Koltunski
     {
420 64975793 Leszek Koltunski
     return mScrambleCubeNum;
421 8197c92d Leszek Koltunski
     }
422 0c52af30 Leszek Koltunski
}