Project

General

Profile

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

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

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

    
34
import javax.microedition.khronos.egl.EGLConfig;
35
import javax.microedition.khronos.opengles.GL10;
36

    
37
///////////////////////////////////////////////////////////////////////////////////////////////////
38

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

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

    
57
///////////////////////////////////////////////////////////////////////////////////////////////////
58

    
59
    RubikRenderer(RubikSurfaceView v)
60
      {
61
      mView = v;
62
      mScreen = new DistortedScreen();
63

    
64
      mOldCube = null;
65
      mNewCube = null;
66

    
67
      mScreenWidth = mScreenHeight = 0;
68
      mScrambleCubeNum = 0;
69

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

    
78
      mCanRotate   = true;
79
      mCanDrag     = true;
80
      mCanUI       = true;
81

    
82
      mEffectID = new long[BaseEffect.Type.LENGTH];
83

    
84
      mMesh= new MeshFlat(20,20);
85
      mNextCubeSize = RubikSize.getSize(mView.getRedButton()).getCubeSize();
86
      }
87

    
88
///////////////////////////////////////////////////////////////////////////////////////////////////
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
       mNewCube.recomputeScaleFactor(mScreenWidth, mScreenHeight);
112
       }
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
     try
125
       {
126
       mEffectID[index] = type.startEffect(this);
127
       }
128
     catch( Exception ex )
129
       {
130
       android.util.Log.e("renderer", "exception starting effect: "+ex.getMessage());
131

    
132
       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
///////////////////////////////////////////////////////////////////////////////////////////////////
212
// various things are done here delayed, 'after the next render' as not to be done mid-render and
213
// cause artifacts.
214

    
215
   @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
         mView.leaveScrambleModeNonUI();
254
         }
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

    
293
///////////////////////////////////////////////////////////////////////////////////////////////////
294

    
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

    
306
      mScreen.setProjection( fovInDegrees, 0.1f);
307
      mScreen.resize(width, height);
308

    
309
      if( mNewCube!=null )
310
        {
311
        mNewCube.recomputeScaleFactor(width, height);
312
        }
313

    
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
      BaseEffect.Type.enableEffects();
325

    
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

    
338
   public void effectFinished(final long effectID)
339
     {
340
     if( effectID == mRotationFinishedID )
341
       {
342
       mRemoveRotation = true;
343
       }
344
     else
345
       {
346
       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
       }
357
     }
358

    
359
///////////////////////////////////////////////////////////////////////////////////////////////////
360

    
361
   public RubikCube getCube()
362
     {
363
     return mNewCube;
364
     }
365

    
366
///////////////////////////////////////////////////////////////////////////////////////////////////
367

    
368
   public RubikCube getOldCube()
369
     {
370
     return mOldCube;
371
     }
372

    
373
///////////////////////////////////////////////////////////////////////////////////////////////////
374

    
375
   public DistortedScreen getScreen()
376
     {
377
     return mScreen;
378
     }
379

    
380
///////////////////////////////////////////////////////////////////////////////////////////////////
381

    
382
   public int getNumScrambles()
383
     {
384
     return mScrambleCubeNum;
385
     }
386
}
(3-3/10)