Project

General

Profile

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

magiccube / src / main / java / org / distorted / magic / RubikRenderer.java @ 211b48f2

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.uistate.RubikState;
34
import org.distorted.uistate.RubikStatePlay;
35

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

    
39
///////////////////////////////////////////////////////////////////////////////////////////////////
40

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

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

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

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

    
66
      mOldCube = null;
67
      mNewCube = null;
68

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

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

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

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

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

    
88
      RubikStatePlay play = (RubikStatePlay) RubikState.PLAY.getStateClass();
89
      int size = play.getButton();
90
      mNextCubeSize = RubikSize.getSize(size).getCubeSize();
91
      }
92

    
93
///////////////////////////////////////////////////////////////////////////////////////////////////
94

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

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

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

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

    
111
     mIsSolved = true;
112
     }
113

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

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

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

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

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

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

    
143
///////////////////////////////////////////////////////////////////////////////////////////////////
144

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

    
154
     return false;
155
     }
156

    
157
///////////////////////////////////////////////////////////////////////////////////////////////////
158

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

    
168
///////////////////////////////////////////////////////////////////////////////////////////////////
169

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

    
178
///////////////////////////////////////////////////////////////////////////////////////////////////
179

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

    
185
///////////////////////////////////////////////////////////////////////////////////////////////////
186

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

    
192
///////////////////////////////////////////////////////////////////////////////////////////////////
193

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

    
199
///////////////////////////////////////////////////////////////////////////////////////////////////
200

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

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

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

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

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

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

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

    
242
       boolean solved = mNewCube.isSolved();
243

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

    
257
       mIsSolved = solved;
258
       }
259

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

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

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

    
289
///////////////////////////////////////////////////////////////////////////////////////////////////
290

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

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

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

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

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

    
312
///////////////////////////////////////////////////////////////////////////////////////////////////
313

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

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

    
330
///////////////////////////////////////////////////////////////////////////////////////////////////
331

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

    
353
///////////////////////////////////////////////////////////////////////////////////////////////////
354

    
355
   public RubikCube getCube()
356
     {
357
     return mNewCube;
358
     }
359

    
360
///////////////////////////////////////////////////////////////////////////////////////////////////
361

    
362
   public RubikCube getOldCube()
363
     {
364
     return mOldCube;
365
     }
366

    
367
///////////////////////////////////////////////////////////////////////////////////////////////////
368

    
369
   public DistortedScreen getScreen()
370
     {
371
     return mScreen;
372
     }
373

    
374
///////////////////////////////////////////////////////////////////////////////////////////////////
375

    
376
   public int getNumScrambles()
377
     {
378
     return mScrambleCubeNum;
379
     }
380
}
(2-2/5)