Project

General

Profile

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

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

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
import android.opengl.GLSurfaceView;
23
24 64975793 Leszek Koltunski
import org.distorted.effect.BaseEffect;
25 0c52af30 Leszek Koltunski
import org.distorted.library.effect.VertexEffectSink;
26 9208e27b Leszek Koltunski
import org.distorted.library.main.DistortedEffects;
27 e1111500 Leszek Koltunski
import org.distorted.library.main.DistortedLibrary;
28 0c52af30 Leszek Koltunski
import org.distorted.library.main.DistortedScreen;
29 9208e27b Leszek Koltunski
import org.distorted.library.main.DistortedTexture;
30 39fb9047 Leszek Koltunski
import org.distorted.library.mesh.MeshFlat;
31 0c52af30 Leszek Koltunski
import org.distorted.library.message.EffectListener;
32
33
import javax.microedition.khronos.egl.EGLConfig;
34
import javax.microedition.khronos.opengles.GL10;
35
36
///////////////////////////////////////////////////////////////////////////////////////////////////
37
38 9208e27b Leszek Koltunski
public class RubikRenderer implements GLSurfaceView.Renderer, EffectListener
39 0c52af30 Leszek Koltunski
{
40
    private static final float CUBE_SCREEN_RATIO = 0.5f;
41
    private static final float CAMERA_DISTANCE   = 0.6f;  // 0.6 of the length of max(scrHeight,scrWidth)
42 9208e27b Leszek Koltunski
    public  static final int TEXTURE_SIZE = 600;
43 0c52af30 Leszek Koltunski
44
    private RubikSurfaceView mView;
45
    private DistortedScreen mScreen;
46
    private float mCubeSizeInScreenSpace;
47 3b12e641 Leszek Koltunski
    private int mNextCubeSize, mScrambleCubeNum;
48 64975793 Leszek Koltunski
    private long mRotationFinishedID;
49
    private long[] mEffectID;
50 05fa94d9 Leszek Koltunski
    private boolean mFinishRotation, mRemoveRotation, mSetQuatCurrent, mSetQuatAccumulated;
51 408d4676 Leszek Koltunski
    private boolean mSizeChangeCube, mSolveCube, mScrambleCube;
52 45686da2 Leszek Koltunski
    private boolean mCanRotate, mCanDrag, mCanUI;
53 47ba5ddc Leszek Koltunski
    private boolean mIsSolved;
54 434f2f5a Leszek Koltunski
    private RubikCube mOldCube, mNewCube;
55 d1484aba Leszek Koltunski
    private int mScreenWidth, mScreenHeight;
56 39fb9047 Leszek Koltunski
    private MeshFlat mMesh;
57 9208e27b Leszek Koltunski
58 0c52af30 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
59
60
    RubikRenderer(RubikSurfaceView v)
61
      {
62
      mView = v;
63
64
      mScreen = new DistortedScreen();
65
66 434f2f5a Leszek Koltunski
      mOldCube = null;
67
      mNewCube = null;
68
69 d1484aba Leszek Koltunski
      mScreenWidth = mScreenHeight = 0;
70 3b12e641 Leszek Koltunski
      mScrambleCubeNum = 0;
71 d1484aba Leszek Koltunski
72 05fa94d9 Leszek Koltunski
      mFinishRotation     = false;
73
      mRemoveRotation     = false;
74
      mSetQuatCurrent     = false;
75
      mSetQuatAccumulated = false;
76
      mSizeChangeCube     = true;
77
      mSolveCube          = false;
78
      mScrambleCube       = 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
86 39fb9047 Leszek Koltunski
      mMesh= new MeshFlat(20,20);
87 05fa94d9 Leszek Koltunski
      mNextCubeSize = RubikActivity.getSize();
88 0c52af30 Leszek Koltunski
      }
89
90 47ba5ddc Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
91
92
   private float computeFOV(float cameraDistance, int screenHeight)
93
     {
94
     double halfFOVInRadians = Math.atan( screenHeight/(2*cameraDistance) );
95
     return (float)(2*halfFOVInRadians*(180/Math.PI));
96
     }
97
98
///////////////////////////////////////////////////////////////////////////////////////////////////
99
100
   private void recomputeScaleFactor(int screenWidth, int screenHeight)
101
     {
102
     mCubeSizeInScreenSpace = CUBE_SCREEN_RATIO*(screenWidth>screenHeight ? screenHeight:screenWidth);
103
104
     if( mNewCube!=null )
105
       {
106
       mNewCube.recomputeScaleFactor(screenWidth, screenHeight, mCubeSizeInScreenSpace);
107
       }
108
     }
109
110
///////////////////////////////////////////////////////////////////////////////////////////////////
111
112
   private void createCubeNow(int newSize)
113
     {
114
     if( mOldCube!=null ) mOldCube.releaseResources();
115
     mOldCube = mNewCube;
116
117
     DistortedTexture texture = new DistortedTexture(TEXTURE_SIZE,TEXTURE_SIZE);
118
     DistortedEffects effects = new DistortedEffects();
119
120
     mNewCube = new RubikCube(newSize, mView.getQuatCurrent(), mView.getQuatAccumulated(), texture, mMesh, effects);
121
     mNewCube.createTexture();
122
123
     if( mScreenWidth!=0 )
124
       {
125
       recomputeScaleFactor(mScreenWidth,mScreenHeight);
126
       }
127
128
     mIsSolved = true;
129
     }
130
131
///////////////////////////////////////////////////////////////////////////////////////////////////
132
// do all 'adjustable' effects (SizeChange, Solve, Scramble)
133
134
   private void doEffectNow(BaseEffect.Type type)
135
     {
136
     int index = type.ordinal();
137
138
     mEffectID[index] = type.startEffect(this);
139
140
     if( mEffectID[index] < 0 )
141
       {
142
       mCanUI     = true;
143
       mCanRotate = true;
144
       mCanDrag   = true;
145
       }
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 createCube(int newSize)
159
     {
160
     if( mCanDrag && mCanRotate && (mNewCube==null || newSize != mNewCube.getSize()) )
161
       {
162
       mSizeChangeCube = true;
163
       mNextCubeSize = newSize;
164
       return true;
165
       }
166
167
     return false;
168
     }
169
170
///////////////////////////////////////////////////////////////////////////////////////////////////
171
172
   void scrambleCube(int num)
173
     {
174
     if( mCanUI )
175
       {
176
       mScrambleCube = true;
177
       mScrambleCubeNum = num;
178
       }
179
     }
180
181
///////////////////////////////////////////////////////////////////////////////////////////////////
182
183
   void solveCube()
184
     {
185
     if( mCanUI )
186
       {
187
       mSolveCube = true;
188
       }
189
     }
190
191
///////////////////////////////////////////////////////////////////////////////////////////////////
192
193
   float returnCubeSizeInScreenSpace()
194
     {
195
     return mCubeSizeInScreenSpace;
196
     }
197
198
///////////////////////////////////////////////////////////////////////////////////////////////////
199
200
   boolean canRotate()
201
     {
202
     return mCanRotate;
203
     }
204
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206
207
   boolean canDrag()
208
     {
209
     return mCanDrag;
210
     }
211
212
///////////////////////////////////////////////////////////////////////////////////////////////////
213
214
   void setQuatCurrentOnNextRender()
215
     {
216
     mSetQuatCurrent = true;
217
     }
218
219
///////////////////////////////////////////////////////////////////////////////////////////////////
220
221
   void setQuatAccumulatedOnNextRender()
222
     {
223
     mSetQuatAccumulated = true;
224
     }
225
226
///////////////////////////////////////////////////////////////////////////////////////////////////
227
// PUBLIC API
228 0c52af30 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
229
// various things are done here delayed, 'after the next render' as not to be done mid-render and
230
// cause artifacts.
231
232 a7a7cc9c Leszek Koltunski
   @Override
233
   public void onDrawFrame(GL10 glUnused)
234
     {
235
     mScreen.render( System.currentTimeMillis() );
236
237
     if( mSetQuatCurrent )
238
       {
239
       mSetQuatCurrent = false;
240
       mView.setQuatCurrent();
241
       }
242
243
     if( mSetQuatAccumulated )
244
       {
245
       mSetQuatAccumulated = false;
246
       mView.setQuatAccumulated();
247
       }
248
249
     if( mFinishRotation )
250
       {
251
       mFinishRotation = false;
252
       mCanRotate      = false;
253
       mCanUI          = false;
254
       mRotationFinishedID = mNewCube.finishRotationNow(this);
255
       }
256
257
     if( mRemoveRotation )
258
       {
259
       mRemoveRotation=false;
260
       mNewCube.removeRotationNow();
261
262
       boolean solved = mNewCube.isSolved();
263
264
       if( solved && !mIsSolved )
265
         {
266
         mCanDrag        = false;
267
         mCanRotate      = false;
268
         mCanUI          = false;
269
         doEffectNow( BaseEffect.Type.WIN );
270
         }
271
       else
272
         {
273
         mCanRotate = true;
274
         mCanUI     = true;
275
         }
276
277
       mIsSolved = solved;
278
       }
279
280
     if( mSizeChangeCube )
281
       {
282
       mSizeChangeCube = false;
283
       mCanDrag        = false;
284
       mCanRotate      = false;
285
       mCanUI          = false;
286
       createCubeNow(mNextCubeSize);
287
       doEffectNow( BaseEffect.Type.SIZECHANGE );
288
       }
289
290
     if( mSolveCube )
291
       {
292
       mSolveCube      = false;
293
       mCanDrag        = false;
294
       mCanRotate      = false;
295
       mCanUI          = false;
296
       doEffectNow( BaseEffect.Type.SOLVE );
297
       }
298
299
     if( mScrambleCube )
300
       {
301
       mScrambleCube = false;
302
       mCanDrag      = false;
303
       mCanRotate    = false;
304
       mCanUI        = false;
305
       doEffectNow( BaseEffect.Type.SCRAMBLE );
306
       }
307
     }
308 0c52af30 Leszek Koltunski
309
///////////////////////////////////////////////////////////////////////////////////////////////////
310 aa8b36aa Leszek Koltunski
311
   @Override
312
   public void onSurfaceChanged(GL10 glUnused, int width, int height)
313
      {
314
      if( mNewCube!=null ) mNewCube.createTexture();
315
316
      float cameraDistance = CAMERA_DISTANCE*(width>height ? width:height);
317
      float fovInDegrees   = computeFOV(cameraDistance,height);
318
319
      mScreen.setProjection( fovInDegrees, 0.1f);
320
      mView.setScreenSize(width,height);
321
      mView.setCameraDist(cameraDistance);
322
      mScreen.resize(width, height);
323
324
      recomputeScaleFactor(width,height);
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 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
///////////////////////////////////////////////////////////////////////////////////////////////////
349 0c52af30 Leszek Koltunski
350 f647630d Leszek Koltunski
   public void effectFinished(final long effectID)
351 0c52af30 Leszek Koltunski
     {
352 45686da2 Leszek Koltunski
     if( effectID == mRotationFinishedID )
353 434f2f5a Leszek Koltunski
       {
354
       mRemoveRotation = true;
355
       }
356 45686da2 Leszek Koltunski
     else
357 3b12e641 Leszek Koltunski
       {
358 45686da2 Leszek Koltunski
       for(int i=0; i<BaseEffect.Type.LENGTH; i++)
359
         {
360
         if( effectID == mEffectID[i] )
361
           {
362
           mCanRotate   = true;
363
           mCanDrag     = true;
364
           mCanUI       = true;
365
           break;
366
           }
367
         }
368 3b12e641 Leszek Koltunski
       }
369 34747dd1 Leszek Koltunski
     }
370 f291130e Leszek Koltunski
371 0c52af30 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
372
373 64975793 Leszek Koltunski
   public RubikCube getCube()
374 8197c92d Leszek Koltunski
     {
375 64975793 Leszek Koltunski
     return mNewCube;
376 8197c92d Leszek Koltunski
     }
377
378
///////////////////////////////////////////////////////////////////////////////////////////////////
379
380 64975793 Leszek Koltunski
   public RubikCube getOldCube()
381 8197c92d Leszek Koltunski
     {
382 64975793 Leszek Koltunski
     return mOldCube;
383 8197c92d Leszek Koltunski
     }
384
385 434f2f5a Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
386
387 64975793 Leszek Koltunski
   public DistortedScreen getScreen()
388 434f2f5a Leszek Koltunski
     {
389 64975793 Leszek Koltunski
     return mScreen;
390 434f2f5a Leszek Koltunski
     }
391
392 8197c92d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
393
394 64975793 Leszek Koltunski
   public int getNumScrambles()
395 8197c92d Leszek Koltunski
     {
396 64975793 Leszek Koltunski
     return mScrambleCubeNum;
397 8197c92d Leszek Koltunski
     }
398 0c52af30 Leszek Koltunski
}