Project

General

Profile

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

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

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.RubikCubeMovement;
34

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

    
38
///////////////////////////////////////////////////////////////////////////////////////////////////
39

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

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

    
58
///////////////////////////////////////////////////////////////////////////////////////////////////
59

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

    
65
      mOldCube = null;
66
      mNewCube = null;
67

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

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

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

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

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

    
89
///////////////////////////////////////////////////////////////////////////////////////////////////
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
       mNewCube.recomputeScaleFactor(mScreenWidth, mScreenHeight);
113
       }
114

    
115
     RubikCubeMovement movement = new RubikCubeMovement(mNewCube);
116
     mView.setMovement(movement);
117

    
118
     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
     try
129
       {
130
       mEffectID[index] = type.startEffect(this);
131
       }
132
     catch( Exception ex )
133
       {
134
       android.util.Log.e("renderer", "exception starting effect: "+ex.getMessage());
135

    
136
       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
///////////////////////////////////////////////////////////////////////////////////////////////////
216
// various things are done here delayed, 'after the next render' as not to be done mid-render and
217
// cause artifacts.
218

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

    
297
///////////////////////////////////////////////////////////////////////////////////////////////////
298

    
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

    
310
      mScreen.setProjection( fovInDegrees, 0.1f);
311
      mScreen.resize(width, height);
312

    
313
      if( mNewCube!=null )
314
        {
315
        mNewCube.recomputeScaleFactor(width, height);
316
        }
317

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

    
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

    
342
   public void effectFinished(final long effectID)
343
     {
344
     if( effectID == mRotationFinishedID )
345
       {
346
       mRemoveRotation = true;
347
       }
348
     else
349
       {
350
       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
       }
361
     }
362

    
363
///////////////////////////////////////////////////////////////////////////////////////////////////
364

    
365
   public RubikCube getCube()
366
     {
367
     return mNewCube;
368
     }
369

    
370
///////////////////////////////////////////////////////////////////////////////////////////////////
371

    
372
   public RubikCube getOldCube()
373
     {
374
     return mOldCube;
375
     }
376

    
377
///////////////////////////////////////////////////////////////////////////////////////////////////
378

    
379
   public DistortedScreen getScreen()
380
     {
381
     return mScreen;
382
     }
383

    
384
///////////////////////////////////////////////////////////////////////////////////////////////////
385

    
386
   public int getNumScrambles()
387
     {
388
     return mScrambleCubeNum;
389
     }
390
}
(3-3/10)