Project

General

Profile

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

magiccube / src / main / java / org / distorted / magic / RubikRenderer.java @ 4f9f99a2

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
// PUBLIC API
209
///////////////////////////////////////////////////////////////////////////////////////////////////
210
// various things are done here delayed, 'after the next render' as not to be done mid-render and
211
// cause artifacts.
212

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

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

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

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

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

    
243
       boolean solved = mNewCube.isSolved();
244

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

    
258
       mIsSolved = solved;
259
       }
260

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

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

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

    
290
///////////////////////////////////////////////////////////////////////////////////////////////////
291

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

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

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

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

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

    
313
///////////////////////////////////////////////////////////////////////////////////////////////////
314

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

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

    
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
           break;
349
           }
350
         }
351
       }
352
     }
353

    
354
///////////////////////////////////////////////////////////////////////////////////////////////////
355

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

    
361
///////////////////////////////////////////////////////////////////////////////////////////////////
362

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

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

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

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

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