Project

General

Profile

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

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

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