Project

General

Profile

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

magiccube / src / main / java / org / distorted / magic / RubikRenderer.java @ 74686c71

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