Project

General

Profile

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

magiccube / src / main / java / org / distorted / magic / RubikRenderer.java @ ad9e8bb3

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.opengl.GLSurfaceView;
23

    
24
import org.distorted.effect.BaseEffect;
25
import org.distorted.library.effect.VertexEffectSink;
26
import org.distorted.library.main.DistortedEffects;
27
import org.distorted.library.main.DistortedLibrary;
28
import org.distorted.library.main.DistortedScreen;
29
import org.distorted.library.main.DistortedTexture;
30
import org.distorted.library.mesh.MeshFlat;
31
import org.distorted.library.message.EffectListener;
32
import org.distorted.object.RubikCube;
33
import org.distorted.object.RubikObject;
34
import org.distorted.uistate.RubikState;
35
import org.distorted.uistate.RubikStatePlay;
36

    
37
import javax.microedition.khronos.egl.EGLConfig;
38
import javax.microedition.khronos.opengles.GL10;
39

    
40
///////////////////////////////////////////////////////////////////////////////////////////////////
41

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

    
47
    private RubikSurfaceView mView;
48
    private DistortedScreen mScreen;
49
    private int mNextCubeSize, mScrambleCubeNum;
50
    private long mRotationFinishedID;
51
    private long[] mEffectID;
52
    private boolean mFinishRotation, mRemoveRotation, mSetQuatCurrent, mSetQuatAccumulated;
53
    private boolean mSizeChangeCube, mSolveCube, mScrambleCube;
54
    private boolean mCanRotate, mCanDrag, mCanUI;
55
    private boolean mIsSolved;
56
    private RubikCube mOldCube, mNewCube;
57
    private int mScreenWidth, mScreenHeight;
58
    private MeshFlat mMesh;
59

    
60
///////////////////////////////////////////////////////////////////////////////////////////////////
61

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

    
67
      mOldCube = null;
68
      mNewCube = null;
69

    
70
      mScreenWidth = mScreenHeight = 0;
71
      mScrambleCubeNum = 0;
72

    
73
      mFinishRotation     = false;
74
      mRemoveRotation     = false;
75
      mSetQuatCurrent     = false;
76
      mSetQuatAccumulated = false;
77
      mSizeChangeCube     = true;
78
      mSolveCube          = false;
79
      mScrambleCube       = false;
80

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

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

    
87
      mMesh= new MeshFlat(20,20);
88

    
89
      RubikStatePlay play = (RubikStatePlay) RubikState.PLAY.getStateClass();
90
      int size = play.getButton();
91
      mNextCubeSize = RubikObject.getObject(size).getObjectSize();
92
      }
93

    
94
///////////////////////////////////////////////////////////////////////////////////////////////////
95

    
96
   private void createCubeNow(int newSize)
97
     {
98
     if( mOldCube!=null ) mOldCube.releaseResources();
99
     mOldCube = mNewCube;
100

    
101
     DistortedTexture texture = new DistortedTexture(TEXTURE_SIZE,TEXTURE_SIZE);
102
     DistortedEffects effects = new DistortedEffects();
103

    
104
     mNewCube = new RubikCube(newSize, mView.getQuatCurrent(), mView.getQuatAccumulated(), texture, mMesh, effects);
105
     mNewCube.createTexture();
106

    
107
     if( mScreenWidth!=0 )
108
       {
109
       mNewCube.recomputeScaleFactor(mScreenWidth, mScreenHeight);
110
       }
111

    
112
     mIsSolved = true;
113
     }
114

    
115
///////////////////////////////////////////////////////////////////////////////////////////////////
116
// do all 'adjustable' effects (SizeChange, Solve, Scramble)
117

    
118
   private void doEffectNow(BaseEffect.Type type)
119
     {
120
     int index = type.ordinal();
121

    
122
     try
123
       {
124
       mEffectID[index] = type.startEffect(this);
125
       }
126
     catch( Exception ex )
127
       {
128
       android.util.Log.e("renderer", "exception starting effect: "+ex.getMessage());
129

    
130
       mCanUI     = true;
131
       mCanRotate = true;
132
       mCanDrag   = true;
133
       }
134
     }
135

    
136
///////////////////////////////////////////////////////////////////////////////////////////////////
137
// no this will not race with onDrawFrame
138

    
139
   void finishRotation()
140
     {
141
     mFinishRotation = true;
142
     }
143

    
144
///////////////////////////////////////////////////////////////////////////////////////////////////
145

    
146
   boolean createCube(int newSize)
147
     {
148
     if( mCanDrag && mCanRotate && (mNewCube==null || newSize != mNewCube.getSize()) )
149
       {
150
       mSizeChangeCube = true;
151
       mNextCubeSize = newSize;
152
       return true;
153
       }
154

    
155
     return false;
156
     }
157

    
158
///////////////////////////////////////////////////////////////////////////////////////////////////
159

    
160
   void scrambleCube(int num)
161
     {
162
     if( mCanUI )
163
       {
164
       mScrambleCube = true;
165
       mScrambleCubeNum = num;
166
       }
167
     }
168

    
169
///////////////////////////////////////////////////////////////////////////////////////////////////
170

    
171
   void solveCube()
172
     {
173
     if( mCanUI )
174
       {
175
       mSolveCube = true;
176
       }
177
     }
178

    
179
///////////////////////////////////////////////////////////////////////////////////////////////////
180

    
181
   boolean canRotate()
182
     {
183
     return mCanRotate;
184
     }
185

    
186
///////////////////////////////////////////////////////////////////////////////////////////////////
187

    
188
   boolean canDrag()
189
     {
190
     return mCanDrag;
191
     }
192

    
193
///////////////////////////////////////////////////////////////////////////////////////////////////
194

    
195
   void setQuatCurrentOnNextRender()
196
     {
197
     mSetQuatCurrent = true;
198
     }
199

    
200
///////////////////////////////////////////////////////////////////////////////////////////////////
201

    
202
   void setQuatAccumulatedOnNextRender()
203
     {
204
     mSetQuatAccumulated = true;
205
     }
206

    
207
///////////////////////////////////////////////////////////////////////////////////////////////////
208
// various things are done here delayed, 'after the next render' as not to be done mid-render and
209
// cause artifacts.
210

    
211
   @Override
212
   public void onDrawFrame(GL10 glUnused)
213
     {
214
     mScreen.render( System.currentTimeMillis() );
215

    
216
     if( mSetQuatCurrent )
217
       {
218
       mSetQuatCurrent = false;
219
       mView.setQuatCurrent();
220
       }
221

    
222
     if( mSetQuatAccumulated )
223
       {
224
       mSetQuatAccumulated = false;
225
       mView.setQuatAccumulated();
226
       }
227

    
228
     if( mFinishRotation )
229
       {
230
       mFinishRotation = false;
231
       mCanRotate      = false;
232
       mCanUI          = false;
233
       mRotationFinishedID = mNewCube.finishRotationNow(this);
234
       }
235

    
236
     if( mRemoveRotation )
237
       {
238
       mRemoveRotation=false;
239
       mNewCube.removeRotationNow();
240

    
241
       boolean solved = mNewCube.isSolved();
242

    
243
       if( solved && !mIsSolved )
244
         {
245
         mCanDrag        = true;
246
         mCanRotate      = false;
247
         mCanUI          = false;
248
         doEffectNow( BaseEffect.Type.WIN );
249
         }
250
       else
251
         {
252
         mCanRotate = true;
253
         mCanUI     = true;
254
         }
255

    
256
       mIsSolved = solved;
257
       }
258

    
259
     if( mSizeChangeCube )
260
       {
261
       mSizeChangeCube = false;
262
       mCanDrag        = false;
263
       mCanRotate      = false;
264
       mCanUI          = false;
265
       createCubeNow(mNextCubeSize);
266
       doEffectNow( BaseEffect.Type.SIZECHANGE );
267
       }
268

    
269
     if( mSolveCube )
270
       {
271
       mSolveCube      = false;
272
       mCanDrag        = false;
273
       mCanRotate      = false;
274
       mCanUI          = false;
275
       doEffectNow( BaseEffect.Type.SOLVE );
276
       }
277

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

    
288
///////////////////////////////////////////////////////////////////////////////////////////////////
289

    
290
   @Override
291
   public void onSurfaceChanged(GL10 glUnused, int width, int height)
292
      {
293
      if( mNewCube!=null ) mNewCube.createTexture();
294

    
295
      double halfFOVInRadians = Math.atan( 1.0f/(2*CAMERA_DISTANCE) );
296
      float fovInDegrees = (float)(2*halfFOVInRadians*(180/Math.PI));
297

    
298
      mScreen.setProjection( fovInDegrees, 0.1f);
299
      mScreen.resize(width, height);
300
      mView.setScreenSize(width,height);
301

    
302
      if( mNewCube!=null )
303
        {
304
        mNewCube.recomputeScaleFactor(width,height);
305
        }
306

    
307
      mScreenHeight = height;
308
      mScreenWidth  = width;
309
      }
310

    
311
///////////////////////////////////////////////////////////////////////////////////////////////////
312

    
313
   @Override
314
   public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
315
      {
316
      VertexEffectSink.enable();
317
      BaseEffect.Type.enableEffects();
318

    
319
      try
320
        {
321
        DistortedLibrary.onCreate(mView.getContext());
322
        }
323
      catch(Exception ex)
324
        {
325
        android.util.Log.e("Rubik", ex.getMessage() );
326
        }
327
      }
328

    
329
///////////////////////////////////////////////////////////////////////////////////////////////////
330
// PUBLIC API
331
///////////////////////////////////////////////////////////////////////////////////////////////////
332

    
333
   public void effectFinished(final long effectID)
334
     {
335
     if( effectID == mRotationFinishedID )
336
       {
337
       mRemoveRotation = true;
338
       }
339
     else
340
       {
341
       for(int i=0; i<BaseEffect.Type.LENGTH; i++)
342
         {
343
         if( effectID == mEffectID[i] )
344
           {
345
           mCanRotate   = true;
346
           mCanDrag     = true;
347
           mCanUI       = true;
348

    
349
           if( i==BaseEffect.Type.SCRAMBLE.ordinal() )
350
             {
351
             final RubikActivity act = (RubikActivity)mView.getContext();
352

    
353
             act.runOnUiThread(new Runnable()
354
               {
355
               @Override
356
               public void run()
357
                 {
358
                 RubikState.switchState( act, RubikState.SOLV);
359
                 }
360
               });
361
             }
362
           break;
363
           }
364
         }
365
       }
366
     }
367

    
368
///////////////////////////////////////////////////////////////////////////////////////////////////
369

    
370
   public RubikCube getCube()
371
     {
372
     return mNewCube;
373
     }
374

    
375
///////////////////////////////////////////////////////////////////////////////////////////////////
376

    
377
   public RubikCube getOldCube()
378
     {
379
     return mOldCube;
380
     }
381

    
382
///////////////////////////////////////////////////////////////////////////////////////////////////
383

    
384
   public DistortedScreen getScreen()
385
     {
386
     return mScreen;
387
     }
388

    
389
///////////////////////////////////////////////////////////////////////////////////////////////////
390

    
391
   public int getNumScrambles()
392
     {
393
     return mScrambleCubeNum;
394
     }
395
}
(2-2/3)