Project

General

Profile

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

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

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.SizeChangeEffect;
25
import org.distorted.effect.UnscrambleEffect;
26
import org.distorted.effect.ScrambleEffect;
27
import org.distorted.library.effect.VertexEffectSink;
28
import org.distorted.library.main.DistortedEffects;
29
import org.distorted.library.main.DistortedLibrary;
30
import org.distorted.library.main.DistortedScreen;
31
import org.distorted.library.main.DistortedTexture;
32
import org.distorted.library.mesh.MeshFlat;
33
import org.distorted.library.message.EffectListener;
34
import org.distorted.library.type.Static4D;
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
    private static final float CUBE_SCREEN_RATIO = 0.5f;
44
    private static final float CAMERA_DISTANCE   = 0.6f;  // 0.6 of the length of max(scrHeight,scrWidth)
45
    public  static final int TEXTURE_SIZE = 600;
46

    
47
    private RubikSurfaceView mView;
48
    private DistortedScreen mScreen;
49
    private Static4D mQuatCurrent, mQuatAccumulated;
50
    private Static4D mTempCurrent, mTempAccumulated;
51
    private float mCubeSizeInScreenSpace;
52
    private int mNextCubeSize, mScrambleCubeNum;
53
    private long mRotationFinishedID, mSizeChangeEffectID, mUnscrambleEffectID, mScrambleEffectID;
54
    private boolean mFinishRotation, mRemoveRotation, mFinishDragCurrent, mFinishDragAccumulated, mSolveCube, mScrambleCube;
55
    private boolean mCanRotate, mCanDrag;
56
    private RubikCube mOldCube, mNewCube;
57
    private int mScreenWidth, mScreenHeight;
58
    private MeshFlat mMesh;
59
    private SizeChangeEffect.Type mSizeChangeType;
60
    private UnscrambleEffect.Type mUnscrambleType;
61
    private ScrambleEffect.Type mScrambleType;
62
    private int mSizeChangeDuration, mUnscrambleDuration, mScrambleDuration;
63

    
64
///////////////////////////////////////////////////////////////////////////////////////////////////
65

    
66
    RubikRenderer(RubikSurfaceView v)
67
      {
68
      mView = v;
69

    
70
      mScreen = new DistortedScreen();
71

    
72
      mOldCube = null;
73
      mNewCube = null;
74

    
75
      mTempCurrent     = new Static4D(0,0,0,1);
76
      mTempAccumulated = new Static4D(0,0,0,1);
77
      mQuatCurrent     = new Static4D(0,0,0,1);
78
      mQuatAccumulated = new Static4D(0,0,0,1);
79

    
80
      mScreenWidth = mScreenHeight = 0;
81
      mScrambleCubeNum = 0;
82

    
83
      mFinishRotation        = false;
84
      mRemoveRotation        = false;
85
      mFinishDragCurrent     = false;
86
      mFinishDragAccumulated = false;
87
      mSolveCube             = false;
88
      mScrambleCube          = false;
89

    
90
      mCanRotate = true;
91
      mCanDrag   = true;
92

    
93
      mSizeChangeType    = SizeChangeEffect.Type.TRANSPARENCY;
94
      mUnscrambleType    = UnscrambleEffect.Type.SPIN;
95
      mScrambleType      = ScrambleEffect.Type.NONE;
96

    
97
      mSizeChangeDuration= 1000;
98
      mUnscrambleDuration= 1000;
99
      mScrambleDuration  = 1000;
100

    
101
      mMesh= new MeshFlat(20,20);
102
      mNextCubeSize =RubikActivity.getSize();
103
      }
104

    
105
///////////////////////////////////////////////////////////////////////////////////////////////////
106
// various things are done here delayed, 'after the next render' as not to be done mid-render and
107
// cause artifacts.
108

    
109
    @Override
110
    public void onDrawFrame(GL10 glUnused) 
111
      {
112
      mScreen.render( System.currentTimeMillis() );
113

    
114
      if( mFinishDragCurrent )
115
        {
116
        mFinishDragCurrent = false;
117
        mQuatCurrent.set(mTempCurrent);
118
        }
119

    
120
      if( mFinishDragAccumulated )
121
        {
122
        mFinishDragAccumulated = false;
123
        mQuatAccumulated.set(mTempAccumulated);
124
        }
125

    
126
      if( mFinishRotation )
127
        {
128
        mCanRotate = false;
129
        mFinishRotation=false;
130
        mRotationFinishedID = mNewCube.finishRotationNow(this);
131
        }
132

    
133
      if( mRemoveRotation )
134
        {
135
        mRemoveRotation=false;
136
        mNewCube.removeRotationNow();
137
        mCanRotate = true;
138
        }
139

    
140
      if( mNextCubeSize!=0 )
141
        {
142
        createCubeNow(mNextCubeSize);
143

    
144
        mCanDrag   = false;
145
        mCanRotate = false;
146
        mNextCubeSize = 0;
147

    
148
        sizeChangeEffect();
149
        }
150

    
151
      if( mSolveCube )
152
        {
153
        mSolveCube = false;
154
        mCanDrag   = false;
155
        mCanRotate = false;
156
        unscrambleCubeNow();
157
        }
158

    
159
      if( mScrambleCube )
160
        {
161
        mScrambleCube = false;
162
        mCanDrag      = false;
163
        mCanRotate    = false;
164
        scrambleCubeNow();
165
        }
166
      }
167

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

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

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

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

    
183
      recomputeScaleFactor(width,height);
184

    
185
      mScreenHeight = height;
186
      mScreenWidth  = width;
187
      }
188

    
189
///////////////////////////////////////////////////////////////////////////////////////////////////
190

    
191
   @Override
192
   public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
193
      {
194
      VertexEffectSink.enable();
195
      SizeChangeEffect.enableEffects();
196
      ScrambleEffect.enableEffects();
197
      UnscrambleEffect.enableEffects();
198

    
199
      try
200
        {
201
        DistortedLibrary.onCreate(mView.getContext());
202
        }
203
      catch(Exception ex)
204
        {
205
        android.util.Log.e("Rubik", ex.getMessage() );
206
        }
207
      }
208

    
209
///////////////////////////////////////////////////////////////////////////////////////////////////
210

    
211
   public void effectFinished(final long effectID)
212
     {
213
     if(      effectID == mRotationFinishedID        )
214
       {
215
       mRemoveRotation = true;
216
       }
217
     else if( effectID == mSizeChangeEffectID        )
218
       {
219
       mCanRotate = true;
220
       mCanDrag   = true;
221
       }
222
     else if( effectID == mUnscrambleEffectID        )
223
       {
224
       mCanRotate = true;
225
       mCanDrag   = true;
226
       }
227
     else if( effectID == mScrambleEffectID          )
228
       {
229
       mCanRotate = true;
230
       mCanDrag   = true;
231
       }
232
     }
233

    
234
///////////////////////////////////////////////////////////////////////////////////////////////////
235

    
236
   private void sizeChangeEffect()
237
     {
238
     try
239
       {
240
       SizeChangeEffect effect = SizeChangeEffect.create(mSizeChangeType);
241
       mSizeChangeEffectID = effect.start(mSizeChangeDuration,mScreen,mOldCube,mNewCube,this);
242
       }
243
     catch(Exception ex)
244
       {
245
       android.util.Log.e("Renderer", "failed to create SizeChangeEffect, exception: "+ex.getMessage());
246

    
247
       if( mOldCube!=null ) mScreen.detach(mOldCube);
248
       mScreen.attach(mNewCube);
249
       mCanRotate = true;
250
       mCanDrag   = true;
251
       }
252
     }
253

    
254
///////////////////////////////////////////////////////////////////////////////////////////////////
255

    
256
   private float computeFOV(float cameraDistance, int screenHeight)
257
     {
258
     double halfFOVInRadians = Math.atan( screenHeight/(2*cameraDistance) );
259
     return (float)(2*halfFOVInRadians*(180/Math.PI));
260
     }
261

    
262
///////////////////////////////////////////////////////////////////////////////////////////////////
263
// no this will not race with onDrawFrame
264

    
265
   void finishRotation()
266
     {
267
     mFinishRotation = true;
268
     }
269

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

    
272
   void setSizeChangeDuration(int duration)
273
     {
274
     mSizeChangeDuration = duration;
275
     }
276

    
277
///////////////////////////////////////////////////////////////////////////////////////////////////
278

    
279
   void setUnscrambleDuration(int duration)
280
     {
281
     mUnscrambleDuration = duration;
282
     }
283

    
284
///////////////////////////////////////////////////////////////////////////////////////////////////
285

    
286
   void setScrambleDuration(int duration)
287
     {
288
     mScrambleDuration = duration;
289
     }
290

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

    
293
   void setSizeChangeType(SizeChangeEffect.Type type)
294
     {
295
     mSizeChangeType = type;
296
     }
297

    
298
///////////////////////////////////////////////////////////////////////////////////////////////////
299

    
300
   void setUnscrambleType(UnscrambleEffect.Type type)
301
     {
302
     mUnscrambleType = type;
303
     }
304

    
305
///////////////////////////////////////////////////////////////////////////////////////////////////
306

    
307
   void setScrambleType(ScrambleEffect.Type type)
308
     {
309
     mScrambleType = type;
310
     }
311

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

    
314
   boolean createCube(int newSize)
315
     {
316
     if( mCanDrag && mCanRotate && (mNewCube==null || newSize != mNewCube.getSize()) )
317
       {
318
       mNextCubeSize = newSize;
319
       return true;
320
       }
321

    
322
     return false;
323
     }
324

    
325
///////////////////////////////////////////////////////////////////////////////////////////////////
326

    
327
   private void createCubeNow(int newSize)
328
     {
329
     if( mOldCube!=null ) mOldCube.releaseResources();
330
     mOldCube = mNewCube;
331

    
332
     DistortedTexture texture = new DistortedTexture(TEXTURE_SIZE,TEXTURE_SIZE);
333
     DistortedEffects effects = new DistortedEffects();
334

    
335
     mNewCube = new RubikCube(newSize, mQuatCurrent, mQuatAccumulated, texture, mMesh, effects);
336
     mNewCube.createTexture();
337

    
338
     if( mScreenWidth!=0 )
339
       {
340
       recomputeScaleFactor(mScreenWidth,mScreenHeight);
341
       }
342
     }
343

    
344
///////////////////////////////////////////////////////////////////////////////////////////////////
345

    
346
   private void recomputeScaleFactor(int screenWidth, int screenHeight)
347
     {
348
     mCubeSizeInScreenSpace = CUBE_SCREEN_RATIO*(screenWidth>screenHeight ? screenHeight:screenWidth);
349

    
350
     if( mNewCube!=null )
351
       {
352
       mNewCube.recomputeScaleFactor(screenWidth, screenHeight, mCubeSizeInScreenSpace);
353
       }
354
     }
355

    
356
///////////////////////////////////////////////////////////////////////////////////////////////////
357

    
358
   void scrambleCube(int num)
359
     {
360
     mScrambleCube = true;
361
     mScrambleCubeNum = num;
362
     }
363

    
364
///////////////////////////////////////////////////////////////////////////////////////////////////
365

    
366
   private void scrambleCubeNow()
367
     {
368
     try
369
       {
370
       ScrambleEffect effect = ScrambleEffect.create(mScrambleType);
371
       mScrambleEffectID = effect.start(mScrambleDuration,mNewCube,mScrambleCubeNum,this);
372
       }
373
     catch(Exception ex)
374
       {
375
       android.util.Log.e("Renderer", "failed to create ScrambleEffect, exception: "+ex.getMessage());
376

    
377
       mCanRotate = true;
378
       mCanDrag   = true;
379
       }
380
     }
381

    
382
///////////////////////////////////////////////////////////////////////////////////////////////////
383

    
384
   void unscrambleCube()
385
     {
386
     mSolveCube = true;
387
     }
388

    
389
///////////////////////////////////////////////////////////////////////////////////////////////////
390

    
391
   private void unscrambleCubeNow()
392
     {
393
     try
394
       {
395
       UnscrambleEffect effect = UnscrambleEffect.create(mUnscrambleType);
396
       mUnscrambleEffectID = effect.start(mUnscrambleDuration,mScreen,mNewCube,this);
397
       }
398
     catch(Exception ex)
399
       {
400
       android.util.Log.e("Renderer", "failed to create UnscrambleEffect, exception: "+ex.getMessage());
401

    
402
       mNewCube.unscramble();    //
403
       mCanRotate = true;        // just unscramble the cube
404
       mCanDrag   = true;        //
405
       }
406
     }
407

    
408
///////////////////////////////////////////////////////////////////////////////////////////////////
409

    
410
   float returnCubeSizeInScreenSpace()
411
     {
412
     return mCubeSizeInScreenSpace;
413
     }
414

    
415
///////////////////////////////////////////////////////////////////////////////////////////////////
416

    
417
   boolean canRotate()
418
     {
419
     return mCanRotate;
420
     }
421

    
422
///////////////////////////////////////////////////////////////////////////////////////////////////
423

    
424
   boolean canDrag()
425
     {
426
     return mCanDrag;
427
     }
428

    
429
///////////////////////////////////////////////////////////////////////////////////////////////////
430

    
431
   RubikCube getCube()
432
     {
433
     return mNewCube;
434
     }
435

    
436
///////////////////////////////////////////////////////////////////////////////////////////////////
437

    
438
   void setQuatCurrent(Static4D current)
439
     {
440
     mTempCurrent.set(current);
441
     mFinishDragCurrent = true;
442
     }
443

    
444
///////////////////////////////////////////////////////////////////////////////////////////////////
445

    
446
   void setQuatAccumulated(Static4D accumulated)
447
     {
448
     mTempAccumulated.set(accumulated);
449
     mFinishDragAccumulated = true;
450
     }
451
}
(4-4/6)