Project

General

Profile

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

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

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// Distorted 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
// Distorted 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 Distorted.  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

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

    
36
///////////////////////////////////////////////////////////////////////////////////////////////////
37

    
38
public class RubikRenderer implements GLSurfaceView.Renderer, EffectListener
39
{
40
    private static final float CUBE_SCREEN_RATIO = 0.5f;
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 float mCubeSizeInScreenSpace;
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 RubikCube mOldCube, mNewCube;
54
    private int mScreenWidth, mScreenHeight;
55
    private MeshFlat mMesh;
56

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

    
59
    RubikRenderer(RubikSurfaceView v)
60
      {
61
      mView = v;
62

    
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 = RubikActivity.getSize();
87
      }
88

    
89
///////////////////////////////////////////////////////////////////////////////////////////////////
90
// various things are done here delayed, 'after the next render' as not to be done mid-render and
91
// cause artifacts.
92

    
93
    @Override
94
    public void onDrawFrame(GL10 glUnused) 
95
      {
96
      mScreen.render( System.currentTimeMillis() );
97

    
98
      if( mSetQuatCurrent )
99
        {
100
        mSetQuatCurrent = false;
101
        mView.setQuatCurrent();
102
        }
103

    
104
      if( mSetQuatAccumulated )
105
        {
106
        mSetQuatAccumulated = false;
107
        mView.setQuatAccumulated();
108
        }
109

    
110
      if( mFinishRotation )
111
        {
112
        mFinishRotation = false;
113
        mCanRotate      = false;
114
        mCanUI          = false;
115
        mRotationFinishedID = mNewCube.finishRotationNow(this);
116
        }
117

    
118
      if( mRemoveRotation )
119
        {
120
        mRemoveRotation=false;
121
        mNewCube.removeRotationNow();
122

    
123
        if( mNewCube.isSolved() )
124
          {
125
          mCanDrag        = false;
126
          mCanRotate      = false;
127
          mCanUI          = false;
128
          doEffectNow( BaseEffect.Type.WIN );
129
          }
130
        else
131
          {
132
          mCanRotate = true;
133
          mCanUI     = true;
134
          }
135
        }
136

    
137
      if( mSizeChangeCube )
138
        {
139
        mSizeChangeCube = false;
140
        mCanDrag        = false;
141
        mCanRotate      = false;
142
        mCanUI          = false;
143
        createCubeNow(mNextCubeSize);
144
        doEffectNow( BaseEffect.Type.SIZECHANGE );
145
        }
146

    
147
      if( mSolveCube )
148
        {
149
        mSolveCube      = false;
150
        mCanDrag        = false;
151
        mCanRotate      = false;
152
        mCanUI          = false;
153
        doEffectNow( BaseEffect.Type.SOLVE );
154
        }
155

    
156
      if( mScrambleCube )
157
        {
158
        mScrambleCube = false;
159
        mCanDrag      = false;
160
        mCanRotate    = false;
161
        mCanUI        = false;
162
        doEffectNow( BaseEffect.Type.SCRAMBLE );
163
        }
164
      }
165

    
166
///////////////////////////////////////////////////////////////////////////////////////////////////
167

    
168
   @Override
169
   public void onSurfaceChanged(GL10 glUnused, int width, int height)
170
      {
171
      if( mNewCube!=null ) mNewCube.createTexture();
172

    
173
      float cameraDistance = CAMERA_DISTANCE*(width>height ? width:height);
174
      float fovInDegrees   = computeFOV(cameraDistance,height);
175

    
176
      mScreen.setProjection( fovInDegrees, 0.1f);
177
      mView.setScreenSize(width,height);
178
      mView.setCameraDist(cameraDistance);
179
      mScreen.resize(width, height);
180

    
181
      recomputeScaleFactor(width,height);
182

    
183
      mScreenHeight = height;
184
      mScreenWidth  = width;
185
      }
186

    
187
///////////////////////////////////////////////////////////////////////////////////////////////////
188

    
189
   @Override
190
   public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
191
      {
192
      VertexEffectSink.enable();
193
      BaseEffect.Type.enableEffects();
194

    
195
      try
196
        {
197
        DistortedLibrary.onCreate(mView.getContext());
198
        }
199
      catch(Exception ex)
200
        {
201
        android.util.Log.e("Rubik", ex.getMessage() );
202
        }
203
      }
204

    
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206

    
207
   public void effectFinished(final long effectID)
208
     {
209
     if( effectID == mRotationFinishedID )
210
       {
211
       mRemoveRotation = true;
212
       }
213
     else
214
       {
215
       for(int i=0; i<BaseEffect.Type.LENGTH; i++)
216
         {
217
         if( effectID == mEffectID[i] )
218
           {
219
           mCanRotate   = true;
220
           mCanDrag     = true;
221
           mCanUI       = true;
222
           break;
223
           }
224
         }
225
       }
226
     }
227

    
228
///////////////////////////////////////////////////////////////////////////////////////////////////
229

    
230
   private float computeFOV(float cameraDistance, int screenHeight)
231
     {
232
     double halfFOVInRadians = Math.atan( screenHeight/(2*cameraDistance) );
233
     return (float)(2*halfFOVInRadians*(180/Math.PI));
234
     }
235

    
236
///////////////////////////////////////////////////////////////////////////////////////////////////
237
// no this will not race with onDrawFrame
238

    
239
   void finishRotation()
240
     {
241
     mFinishRotation = true;
242
     }
243

    
244
///////////////////////////////////////////////////////////////////////////////////////////////////
245

    
246
   boolean createCube(int newSize)
247
     {
248
     if( mCanDrag && mCanRotate && (mNewCube==null || newSize != mNewCube.getSize()) )
249
       {
250
       mSizeChangeCube = true;
251
       mNextCubeSize = newSize;
252
       return true;
253
       }
254

    
255
     return false;
256
     }
257

    
258
///////////////////////////////////////////////////////////////////////////////////////////////////
259

    
260
   private void recomputeScaleFactor(int screenWidth, int screenHeight)
261
     {
262
     mCubeSizeInScreenSpace = CUBE_SCREEN_RATIO*(screenWidth>screenHeight ? screenHeight:screenWidth);
263

    
264
     if( mNewCube!=null )
265
       {
266
       mNewCube.recomputeScaleFactor(screenWidth, screenHeight, mCubeSizeInScreenSpace);
267
       }
268
     }
269

    
270
///////////////////////////////////////////////////////////////////////////////////////////////////
271

    
272
   void scrambleCube(int num)
273
     {
274
     if( mCanUI )
275
       {
276
       mScrambleCube = true;
277
       mScrambleCubeNum = num;
278
       }
279
     }
280

    
281
///////////////////////////////////////////////////////////////////////////////////////////////////
282

    
283
   void solveCube()
284
     {
285
     if( mCanUI )
286
       {
287
       mSolveCube = true;
288
       }
289
     }
290

    
291
///////////////////////////////////////////////////////////////////////////////////////////////////
292

    
293
   private void createCubeNow(int newSize)
294
     {
295
     if( mOldCube!=null ) mOldCube.releaseResources();
296
     mOldCube = mNewCube;
297

    
298
     DistortedTexture texture = new DistortedTexture(TEXTURE_SIZE,TEXTURE_SIZE);
299
     DistortedEffects effects = new DistortedEffects();
300

    
301
     mNewCube = new RubikCube(newSize, mView.getQuatCurrent(), mView.getQuatAccumulated(), texture, mMesh, effects);
302
     mNewCube.createTexture();
303

    
304
     if( mScreenWidth!=0 )
305
       {
306
       recomputeScaleFactor(mScreenWidth,mScreenHeight);
307
       }
308
     }
309

    
310
///////////////////////////////////////////////////////////////////////////////////////////////////
311
// do all 'adjustable' effects (SizeChange, Solve, Scramble)
312

    
313
   private void doEffectNow(BaseEffect.Type type)
314
     {
315
     int index = type.ordinal();
316

    
317
     mEffectID[index] = type.startEffect(this);
318

    
319
     if( mEffectID[index] < 0 )
320
       {
321
       mCanUI     = true;
322
       mCanRotate = true;
323
       mCanDrag   = true;
324
       }
325
     }
326

    
327
///////////////////////////////////////////////////////////////////////////////////////////////////
328

    
329
   float returnCubeSizeInScreenSpace()
330
     {
331
     return mCubeSizeInScreenSpace;
332
     }
333

    
334
///////////////////////////////////////////////////////////////////////////////////////////////////
335

    
336
   boolean canRotate()
337
     {
338
     return mCanRotate;
339
     }
340

    
341
///////////////////////////////////////////////////////////////////////////////////////////////////
342

    
343
   boolean canDrag()
344
     {
345
     return mCanDrag;
346
     }
347

    
348
///////////////////////////////////////////////////////////////////////////////////////////////////
349

    
350
   public RubikCube getCube()
351
     {
352
     return mNewCube;
353
     }
354

    
355
///////////////////////////////////////////////////////////////////////////////////////////////////
356

    
357
   public RubikCube getOldCube()
358
     {
359
     return mOldCube;
360
     }
361

    
362
///////////////////////////////////////////////////////////////////////////////////////////////////
363

    
364
   public DistortedScreen getScreen()
365
     {
366
     return mScreen;
367
     }
368

    
369
///////////////////////////////////////////////////////////////////////////////////////////////////
370

    
371
   public int getNumScrambles()
372
     {
373
     return mScrambleCubeNum;
374
     }
375

    
376
///////////////////////////////////////////////////////////////////////////////////////////////////
377

    
378
   void setQuatCurrentOnNextRender()
379
     {
380
     mSetQuatCurrent = true;
381
     }
382

    
383
///////////////////////////////////////////////////////////////////////////////////////////////////
384

    
385
   void setQuatAccumulatedOnNextRender()
386
     {
387
     mSetQuatAccumulated = true;
388
     }
389
}
(4-4/6)