Project

General

Profile

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

magiccube / src / main / java / org / distorted / magic / RubikRenderer.java @ 775e675d

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