Project

General

Profile

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

magiccube / src / main / java / org / distorted / magic / RubikRenderer.java @ 5974d2ae

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 5974d2ae Leszek Koltunski
    public static final int NODE_MESH_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 3c4a326c Leszek Koltunski
     if( mNewObject!=null )
136
       {
137
       mNewObject.savePreferences(editor);
138
       }
139 0333d81e Leszek Koltunski
     }
140
141
///////////////////////////////////////////////////////////////////////////////////////////////////
142
143
   void restorePreferences(SharedPreferences preferences)
144
     {
145 5bfc1b49 Leszek Koltunski
     mPreferences = preferences;
146 0333d81e Leszek Koltunski
     }
147
148 47ba5ddc Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
149
// no this will not race with onDrawFrame
150
151
   void finishRotation()
152
     {
153
     mFinishRotation = true;
154
     }
155
156
///////////////////////////////////////////////////////////////////////////////////////////////////
157
158 27a70eae Leszek Koltunski
   boolean createObject(RubikObjectList object)
159 47ba5ddc Leszek Koltunski
     {
160 27a70eae Leszek Koltunski
     if( mCanDrag && mCanRotate && object!=mNextObject )
161 47ba5ddc Leszek Koltunski
       {
162 27a70eae Leszek Koltunski
       mChangeObject = true;
163
       mNextObject = object;
164 47ba5ddc Leszek Koltunski
       return true;
165
       }
166
167
     return false;
168
     }
169
170
///////////////////////////////////////////////////////////////////////////////////////////////////
171
172 27a70eae Leszek Koltunski
   void scrambleObject(int num)
173 47ba5ddc Leszek Koltunski
     {
174
     if( mCanUI )
175
       {
176 27a70eae Leszek Koltunski
       mScrambleObject = true;
177
       mScrambleObjectNum = num;
178 47ba5ddc Leszek Koltunski
       }
179
     }
180
181
///////////////////////////////////////////////////////////////////////////////////////////////////
182
183 27a70eae Leszek Koltunski
   void solveObject()
184 47ba5ddc Leszek Koltunski
     {
185
     if( mCanUI )
186
       {
187 27a70eae Leszek Koltunski
       mSolveObject = true;
188 47ba5ddc Leszek Koltunski
       }
189
     }
190
191
///////////////////////////////////////////////////////////////////////////////////////////////////
192
193
   boolean canRotate()
194
     {
195
     return mCanRotate;
196
     }
197
198
///////////////////////////////////////////////////////////////////////////////////////////////////
199
200
   boolean canDrag()
201
     {
202
     return mCanDrag;
203
     }
204
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206
207
   void setQuatCurrentOnNextRender()
208
     {
209
     mSetQuatCurrent = true;
210
     }
211
212
///////////////////////////////////////////////////////////////////////////////////////////////////
213
214
   void setQuatAccumulatedOnNextRender()
215
     {
216
     mSetQuatAccumulated = true;
217
     }
218
219 0c52af30 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
220
// various things are done here delayed, 'after the next render' as not to be done mid-render and
221
// cause artifacts.
222
223 a7a7cc9c Leszek Koltunski
   @Override
224
   public void onDrawFrame(GL10 glUnused)
225
     {
226
     mScreen.render( System.currentTimeMillis() );
227
228
     if( mSetQuatCurrent )
229
       {
230
       mSetQuatCurrent = false;
231
       mView.setQuatCurrent();
232
       }
233
234
     if( mSetQuatAccumulated )
235
       {
236
       mSetQuatAccumulated = false;
237
       mView.setQuatAccumulated();
238
       }
239
240
     if( mFinishRotation )
241
       {
242
       mFinishRotation = false;
243
       mCanRotate      = false;
244
       mCanUI          = false;
245 27a70eae Leszek Koltunski
       mRotationFinishedID = mNewObject.finishRotationNow(this);
246 a7a7cc9c Leszek Koltunski
       }
247
248
     if( mRemoveRotation )
249
       {
250
       mRemoveRotation=false;
251 27a70eae Leszek Koltunski
       mNewObject.removeRotationNow();
252 a7a7cc9c Leszek Koltunski
253 27a70eae Leszek Koltunski
       boolean solved = mNewObject.isSolved();
254 a7a7cc9c Leszek Koltunski
255
       if( solved && !mIsSolved )
256
         {
257 0333d81e Leszek Koltunski
         if( RubikState.getCurrentState()==RubikState.SOLV )
258
           {
259
           RubikStateSolving solving = (RubikStateSolving)RubikState.SOLV.getStateClass();
260
           long time = solving.stopCounting();
261
           android.util.Log.e("renderer", "solving time: "+time+" milliseconds");
262
           }
263
264
         mCanDrag   = true;
265
         mCanRotate = false;
266
         mCanUI     = false;
267 a7a7cc9c Leszek Koltunski
         doEffectNow( BaseEffect.Type.WIN );
268
         }
269
       else
270
         {
271
         mCanRotate = true;
272
         mCanUI     = true;
273
         }
274
275
       mIsSolved = solved;
276
       }
277
278 27a70eae Leszek Koltunski
     if( mChangeObject )
279 a7a7cc9c Leszek Koltunski
       {
280 27a70eae Leszek Koltunski
       mChangeObject = false;
281
       mCanDrag      = false;
282
       mCanRotate    = false;
283
       mCanUI        = false;
284
       createObjectNow(mNextObject);
285 a7a7cc9c Leszek Koltunski
       doEffectNow( BaseEffect.Type.SIZECHANGE );
286
       }
287
288 27a70eae Leszek Koltunski
     if( mSolveObject )
289 a7a7cc9c Leszek Koltunski
       {
290 27a70eae Leszek Koltunski
       mSolveObject    = false;
291 a7a7cc9c Leszek Koltunski
       mCanDrag        = false;
292
       mCanRotate      = false;
293
       mCanUI          = false;
294
       doEffectNow( BaseEffect.Type.SOLVE );
295
       }
296
297 27a70eae Leszek Koltunski
     if( mScrambleObject )
298 a7a7cc9c Leszek Koltunski
       {
299 27a70eae Leszek Koltunski
       mScrambleObject = false;
300
       mCanDrag        = false;
301
       mCanRotate      = false;
302
       mCanUI          = false;
303 a7a7cc9c Leszek Koltunski
       doEffectNow( BaseEffect.Type.SCRAMBLE );
304
       }
305
     }
306 0c52af30 Leszek Koltunski
307
///////////////////////////////////////////////////////////////////////////////////////////////////
308 aa8b36aa Leszek Koltunski
309
   @Override
310
   public void onSurfaceChanged(GL10 glUnused, int width, int height)
311
      {
312 27a70eae Leszek Koltunski
      if( mNewObject!=null ) mNewObject.createTexture();
313 aa8b36aa Leszek Koltunski
314 123d6172 Leszek Koltunski
      double halfFOVInRadians = Math.atan( 1.0f/(2*CAMERA_DISTANCE) );
315
      float fovInDegrees = (float)(2*halfFOVInRadians*(180/Math.PI));
316 beb325a0 Leszek Koltunski
317
      mScreen.setProjection( fovInDegrees, 0.1f);
318 aa8b36aa Leszek Koltunski
      mScreen.resize(width, height);
319 123d6172 Leszek Koltunski
      mView.setScreenSize(width,height);
320 aa8b36aa Leszek Koltunski
321 27a70eae Leszek Koltunski
      if( mNewObject!=null )
322 beb325a0 Leszek Koltunski
        {
323 27a70eae Leszek Koltunski
        mNewObject.recomputeScaleFactor(width,height);
324 beb325a0 Leszek Koltunski
        }
325 aa8b36aa Leszek Koltunski
326
      mScreenHeight = height;
327
      mScreenWidth  = width;
328
      }
329
330
///////////////////////////////////////////////////////////////////////////////////////////////////
331
332
   @Override
333
   public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
334
      {
335
      VertexEffectSink.enable();
336 64975793 Leszek Koltunski
      BaseEffect.Type.enableEffects();
337 aa8b36aa Leszek Koltunski
338
      try
339
        {
340
        DistortedLibrary.onCreate(mView.getContext());
341
        }
342
      catch(Exception ex)
343
        {
344
        android.util.Log.e("Rubik", ex.getMessage() );
345
        }
346
      }
347
348 ad9e8bb3 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
349
// PUBLIC API
350 aa8b36aa Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
351 0c52af30 Leszek Koltunski
352 f647630d Leszek Koltunski
   public void effectFinished(final long effectID)
353 0c52af30 Leszek Koltunski
     {
354 45686da2 Leszek Koltunski
     if( effectID == mRotationFinishedID )
355 434f2f5a Leszek Koltunski
       {
356
       mRemoveRotation = true;
357
       }
358 45686da2 Leszek Koltunski
     else
359 3b12e641 Leszek Koltunski
       {
360 45686da2 Leszek Koltunski
       for(int i=0; i<BaseEffect.Type.LENGTH; i++)
361
         {
362
         if( effectID == mEffectID[i] )
363
           {
364
           mCanRotate   = true;
365
           mCanDrag     = true;
366
           mCanUI       = true;
367 ad9e8bb3 Leszek Koltunski
368
           if( i==BaseEffect.Type.SCRAMBLE.ordinal() )
369
             {
370
             final RubikActivity act = (RubikActivity)mView.getContext();
371
372
             act.runOnUiThread(new Runnable()
373
               {
374
               @Override
375
               public void run()
376
                 {
377
                 RubikState.switchState( act, RubikState.SOLV);
378
                 }
379
               });
380
             }
381 45686da2 Leszek Koltunski
           break;
382
           }
383
         }
384 3b12e641 Leszek Koltunski
       }
385 34747dd1 Leszek Koltunski
     }
386 f291130e Leszek Koltunski
387 0c52af30 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
388
389 27a70eae Leszek Koltunski
   public RubikObject getObject()
390 8197c92d Leszek Koltunski
     {
391 27a70eae Leszek Koltunski
     return mNewObject;
392 8197c92d Leszek Koltunski
     }
393
394
///////////////////////////////////////////////////////////////////////////////////////////////////
395
396 27a70eae Leszek Koltunski
   public RubikObject getOldObject()
397 8197c92d Leszek Koltunski
     {
398 27a70eae Leszek Koltunski
     return mOldObject;
399 8197c92d Leszek Koltunski
     }
400
401 434f2f5a Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
402
403 64975793 Leszek Koltunski
   public DistortedScreen getScreen()
404 434f2f5a Leszek Koltunski
     {
405 64975793 Leszek Koltunski
     return mScreen;
406 434f2f5a Leszek Koltunski
     }
407
408 8197c92d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
409
410 64975793 Leszek Koltunski
   public int getNumScrambles()
411 8197c92d Leszek Koltunski
     {
412 27a70eae Leszek Koltunski
     return mScrambleObjectNum;
413 8197c92d Leszek Koltunski
     }
414 0c52af30 Leszek Koltunski
}