Project

General

Profile

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

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

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

    
20
package org.distorted.magic;
21

    
22
import android.content.SharedPreferences;
23
import android.opengl.GLSurfaceView;
24

    
25
import org.distorted.effect.BaseEffect;
26
import org.distorted.library.effect.VertexEffectSink;
27
import org.distorted.library.main.DistortedLibrary;
28
import org.distorted.library.main.DistortedScreen;
29
import org.distorted.library.message.EffectListener;
30
import org.distorted.object.RubikObject;
31
import org.distorted.object.RubikObjectList;
32
import org.distorted.uistate.RubikState;
33
import org.distorted.uistate.RubikStateSolving;
34

    
35
import javax.microedition.khronos.egl.EGLConfig;
36
import javax.microedition.khronos.opengles.GL10;
37

    
38
///////////////////////////////////////////////////////////////////////////////////////////////////
39

    
40
public class RubikRenderer implements GLSurfaceView.Renderer, EffectListener
41
{
42
    static final float CAMERA_DISTANCE = 0.6f;  // 0.6 of the length of min(scrHeight,scrWidth)
43
    public static final int NODE_MESH_SIZE = 600;
44

    
45
    private RubikSurfaceView mView;
46
    private DistortedScreen mScreen;
47
    private RubikObjectList mNextObject;
48
    private int mScrambleObjectNum;
49
    private long mRotationFinishedID;
50
    private long[] mEffectID;
51
    private boolean mFinishRotation, mRemoveRotation, mSetQuatCurrent, mSetQuatAccumulated;
52
    private boolean mChangeObject, mSolveObject, mScrambleObject;
53
    private boolean mCanRotate, mCanDrag, mCanUI;
54
    private boolean mIsSolved;
55
    private RubikObject mOldObject, mNewObject;
56
    private int mScreenWidth, mScreenHeight;
57
    private SharedPreferences mPreferences;
58

    
59
///////////////////////////////////////////////////////////////////////////////////////////////////
60

    
61
    RubikRenderer(RubikSurfaceView v)
62
      {
63
      mView = v;
64
      mScreen = new DistortedScreen();
65

    
66
      mOldObject = null;
67
      mNewObject = null;
68

    
69
      mScreenWidth = mScreenHeight = 0;
70
      mScrambleObjectNum = 0;
71

    
72
      mFinishRotation     = false;
73
      mRemoveRotation     = false;
74
      mSetQuatCurrent     = false;
75
      mSetQuatAccumulated = false;
76
      mChangeObject       = false;
77
      mSolveObject        = false;
78
      mScrambleObject     = false;
79

    
80
      mCanRotate   = true;
81
      mCanDrag     = true;
82
      mCanUI       = true;
83

    
84
      mEffectID = new long[BaseEffect.Type.LENGTH];
85
      }
86

    
87
///////////////////////////////////////////////////////////////////////////////////////////////////
88

    
89
   private void createObjectNow(RubikObjectList object)
90
     {
91
     boolean firstTime = (mNewObject==null);
92

    
93
     if( mOldObject!=null ) mOldObject.releaseResources();
94
     mOldObject = mNewObject;
95

    
96
     mNewObject = object.create(mView.getQuatCurrent(), mView.getQuatAccumulated());
97
     mNewObject.createTexture();
98
     mView.setMovement(object.getObjectMovementClass());
99

    
100
     if( firstTime ) mNewObject.restorePreferences(mPreferences);
101

    
102
     if( mScreenWidth!=0 )
103
       {
104
       mNewObject.recomputeScaleFactor(mScreenWidth, mScreenHeight);
105
       }
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
     try
118
       {
119
       mEffectID[index] = type.startEffect(this);
120
       }
121
     catch( Exception ex )
122
       {
123
       android.util.Log.e("renderer", "exception starting effect: "+ex.getMessage());
124

    
125
       mCanUI     = true;
126
       mCanRotate = true;
127
       mCanDrag   = true;
128
       }
129
     }
130

    
131
///////////////////////////////////////////////////////////////////////////////////////////////////
132

    
133
   void savePreferences(SharedPreferences.Editor editor)
134
     {
135
     if( mNewObject!=null )
136
       {
137
       mNewObject.savePreferences(editor);
138
       }
139
     }
140

    
141
///////////////////////////////////////////////////////////////////////////////////////////////////
142

    
143
   void restorePreferences(SharedPreferences preferences)
144
     {
145
     mPreferences = preferences;
146
     }
147

    
148
///////////////////////////////////////////////////////////////////////////////////////////////////
149
// no this will not race with onDrawFrame
150

    
151
   void finishRotation()
152
     {
153
     mFinishRotation = true;
154
     }
155

    
156
///////////////////////////////////////////////////////////////////////////////////////////////////
157

    
158
   boolean createObject(RubikObjectList object)
159
     {
160
     if( mCanDrag && mCanRotate && object!=mNextObject )
161
       {
162
       mChangeObject = true;
163
       mNextObject = object;
164
       return true;
165
       }
166

    
167
     return false;
168
     }
169

    
170
///////////////////////////////////////////////////////////////////////////////////////////////////
171

    
172
   void scrambleObject(int num)
173
     {
174
     if( mCanUI )
175
       {
176
       mScrambleObject = true;
177
       mScrambleObjectNum = num;
178
       }
179
     }
180

    
181
///////////////////////////////////////////////////////////////////////////////////////////////////
182

    
183
   void solveObject()
184
     {
185
     if( mCanUI )
186
       {
187
       mSolveObject = true;
188
       }
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
///////////////////////////////////////////////////////////////////////////////////////////////////
220
// various things are done here delayed, 'after the next render' as not to be done mid-render and
221
// cause artifacts.
222

    
223
   @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
       mRotationFinishedID = mNewObject.finishRotationNow(this);
246
       }
247

    
248
     if( mRemoveRotation )
249
       {
250
       mRemoveRotation=false;
251
       mNewObject.removeRotationNow();
252

    
253
       boolean solved = mNewObject.isSolved();
254

    
255
       if( solved && !mIsSolved )
256
         {
257
         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
         doEffectNow( BaseEffect.Type.WIN );
268
         }
269
       else
270
         {
271
         mCanRotate = true;
272
         mCanUI     = true;
273
         }
274

    
275
       mIsSolved = solved;
276
       }
277

    
278
     if( mChangeObject )
279
       {
280
       mChangeObject = false;
281
       mCanDrag      = false;
282
       mCanRotate    = false;
283
       mCanUI        = false;
284
       createObjectNow(mNextObject);
285
       doEffectNow( BaseEffect.Type.SIZECHANGE );
286
       }
287

    
288
     if( mSolveObject )
289
       {
290
       mSolveObject    = false;
291
       mCanDrag        = false;
292
       mCanRotate      = false;
293
       mCanUI          = false;
294
       doEffectNow( BaseEffect.Type.SOLVE );
295
       }
296

    
297
     if( mScrambleObject )
298
       {
299
       mScrambleObject = false;
300
       mCanDrag        = false;
301
       mCanRotate      = false;
302
       mCanUI          = false;
303
       doEffectNow( BaseEffect.Type.SCRAMBLE );
304
       }
305
     }
306

    
307
///////////////////////////////////////////////////////////////////////////////////////////////////
308

    
309
   @Override
310
   public void onSurfaceChanged(GL10 glUnused, int width, int height)
311
      {
312
      if( mNewObject!=null ) mNewObject.createTexture();
313

    
314
      double halfFOVInRadians = Math.atan( 1.0f/(2*CAMERA_DISTANCE) );
315
      float fovInDegrees = (float)(2*halfFOVInRadians*(180/Math.PI));
316

    
317
      mScreen.setProjection( fovInDegrees, 0.1f);
318
      mScreen.resize(width, height);
319
      mView.setScreenSize(width,height);
320

    
321
      if( mNewObject!=null )
322
        {
323
        mNewObject.recomputeScaleFactor(width,height);
324
        }
325

    
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
      BaseEffect.Type.enableEffects();
337

    
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
///////////////////////////////////////////////////////////////////////////////////////////////////
349
// PUBLIC API
350
///////////////////////////////////////////////////////////////////////////////////////////////////
351

    
352
   public void effectFinished(final long effectID)
353
     {
354
     if( effectID == mRotationFinishedID )
355
       {
356
       mRemoveRotation = true;
357
       }
358
     else
359
       {
360
       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

    
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
           break;
382
           }
383
         }
384
       }
385
     }
386

    
387
///////////////////////////////////////////////////////////////////////////////////////////////////
388

    
389
   public RubikObject getObject()
390
     {
391
     return mNewObject;
392
     }
393

    
394
///////////////////////////////////////////////////////////////////////////////////////////////////
395

    
396
   public RubikObject getOldObject()
397
     {
398
     return mOldObject;
399
     }
400

    
401
///////////////////////////////////////////////////////////////////////////////////////////////////
402

    
403
   public DistortedScreen getScreen()
404
     {
405
     return mScreen;
406
     }
407

    
408
///////////////////////////////////////////////////////////////////////////////////////////////////
409

    
410
   public int getNumScrambles()
411
     {
412
     return mScrambleObjectNum;
413
     }
414
}
(2-2/3)