Project

General

Profile

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

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

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.SolveEffect;
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, mSolveEffectID, mScrambleEffectID;
54
    private boolean mFinishRotation, mRemoveRotation, mFinishDragCurrent, mFinishDragAccumulated, mSolveCube, mScrambleCube;
55
    private boolean mCanRotate, mCanDrag, mCanScramble, mCanSolve;
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

    
66
      mScreen = new DistortedScreen();
67

    
68
      mOldCube = null;
69
      mNewCube = null;
70

    
71
      mTempCurrent     = new Static4D(0,0,0,1);
72
      mTempAccumulated = new Static4D(0,0,0,1);
73
      mQuatCurrent     = new Static4D(0,0,0,1);
74
      mQuatAccumulated = new Static4D(0,0,0,1);
75

    
76
      mScreenWidth = mScreenHeight = 0;
77
      mScrambleCubeNum = 0;
78

    
79
      mFinishRotation        = false;
80
      mRemoveRotation        = false;
81
      mFinishDragCurrent     = false;
82
      mFinishDragAccumulated = false;
83
      mSolveCube             = false;
84
      mScrambleCube          = false;
85

    
86
      mCanRotate   = true;
87
      mCanDrag     = true;
88
      mCanScramble = true;
89
      mCanSolve    = true;
90

    
91
      mMesh= new MeshFlat(20,20);
92
      mNextCubeSize =RubikActivity.getSize();
93
      }
94

    
95
///////////////////////////////////////////////////////////////////////////////////////////////////
96
// various things are done here delayed, 'after the next render' as not to be done mid-render and
97
// cause artifacts.
98

    
99
    @Override
100
    public void onDrawFrame(GL10 glUnused) 
101
      {
102
      mScreen.render( System.currentTimeMillis() );
103

    
104
      if( mFinishDragCurrent )
105
        {
106
        mFinishDragCurrent = false;
107
        mQuatCurrent.set(mTempCurrent);
108
        }
109

    
110
      if( mFinishDragAccumulated )
111
        {
112
        mFinishDragAccumulated = false;
113
        mQuatAccumulated.set(mTempAccumulated);
114
        }
115

    
116
      if( mFinishRotation )
117
        {
118
        mCanRotate = false;
119
        mFinishRotation=false;
120
        mRotationFinishedID = mNewCube.finishRotationNow(this);
121
        }
122

    
123
      if( mRemoveRotation )
124
        {
125
        mRemoveRotation=false;
126
        mNewCube.removeRotationNow();
127
        mCanRotate = true;
128
        }
129

    
130
      if( mNextCubeSize!=0 )
131
        {
132
        createCubeNow(mNextCubeSize);
133

    
134
        mCanDrag   = false;
135
        mCanRotate = false;
136
        mNextCubeSize = 0;
137
        changeSizeNow();
138
        }
139

    
140
      if( mSolveCube )
141
        {
142
        mSolveCube   = false;
143
        mCanDrag     = false;
144
        mCanRotate   = false;
145
        mCanScramble = false;
146
        mCanSolve    = false;
147
        solveCubeNow();
148
        }
149

    
150
      if( mScrambleCube )
151
        {
152
        mScrambleCube = false;
153
        mCanDrag      = false;
154
        mCanRotate    = false;
155
        mCanScramble  = false;
156
        mCanSolve     = false;
157
        scrambleCubeNow();
158
        }
159
      }
160

    
161
///////////////////////////////////////////////////////////////////////////////////////////////////
162

    
163
   @Override
164
   public void onSurfaceChanged(GL10 glUnused, int width, int height)
165
      {
166
      if( mNewCube!=null ) mNewCube.createTexture();
167

    
168
      float cameraDistance = CAMERA_DISTANCE*(width>height ? width:height);
169
      float fovInDegrees   = computeFOV(cameraDistance,height);
170

    
171
      mScreen.setProjection( fovInDegrees, 0.1f);
172
      mView.setScreenSize(width,height);
173
      mView.setCameraDist(cameraDistance);
174
      mScreen.resize(width, height);
175

    
176
      recomputeScaleFactor(width,height);
177

    
178
      mScreenHeight = height;
179
      mScreenWidth  = width;
180
      }
181

    
182
///////////////////////////////////////////////////////////////////////////////////////////////////
183

    
184
   @Override
185
   public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
186
      {
187
      VertexEffectSink.enable();
188
      SizeChangeEffect.enableEffects();
189
      ScrambleEffect.enableEffects();
190
      SolveEffect.enableEffects();
191

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

    
202
///////////////////////////////////////////////////////////////////////////////////////////////////
203

    
204
   public void effectFinished(final long effectID)
205
     {
206
     if(      effectID == mRotationFinishedID )
207
       {
208
       mRemoveRotation = true;
209
       }
210
     else if( effectID == mSizeChangeEffectID )
211
       {
212
       mCanRotate   = true;
213
       mCanDrag     = true;
214
       }
215
     else if( effectID == mSolveEffectID )
216
       {
217
       mCanRotate   = true;
218
       mCanDrag     = true;
219
       mCanSolve    = true;
220
       mCanScramble = true;
221
       }
222
     else if( effectID == mScrambleEffectID   )
223
       {
224
       mCanRotate   = true;
225
       mCanDrag     = true;
226
       mCanSolve    = true;
227
       mCanScramble = true;
228
       }
229
     }
230

    
231
///////////////////////////////////////////////////////////////////////////////////////////////////
232

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

    
239
///////////////////////////////////////////////////////////////////////////////////////////////////
240
// no this will not race with onDrawFrame
241

    
242
   void finishRotation()
243
     {
244
     mFinishRotation = true;
245
     }
246

    
247
///////////////////////////////////////////////////////////////////////////////////////////////////
248

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

    
257
     return false;
258
     }
259

    
260
///////////////////////////////////////////////////////////////////////////////////////////////////
261

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

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

    
272
///////////////////////////////////////////////////////////////////////////////////////////////////
273

    
274
   void scrambleCube(int num)
275
     {
276
     if( mCanScramble )
277
       {
278
       mScrambleCube = true;
279
       mScrambleCubeNum = num;
280
       }
281
     }
282

    
283
///////////////////////////////////////////////////////////////////////////////////////////////////
284

    
285
   void solveCube()
286
     {
287
     if( mCanSolve )
288
       {
289
       mSolveCube = true;
290
       }
291
     }
292

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

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

    
300
     DistortedTexture texture = new DistortedTexture(TEXTURE_SIZE,TEXTURE_SIZE);
301
     DistortedEffects effects = new DistortedEffects();
302

    
303
     mNewCube = new RubikCube(newSize, mQuatCurrent, mQuatAccumulated, texture, mMesh, effects);
304
     mNewCube.createTexture();
305

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

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

    
314
   private void changeSizeNow()
315
     {
316
     try
317
       {
318
       int pos0 = RubikSettingsEnum.getEnum(0).getCurrentPos();
319
       int typ0 = RubikSettingsEnum.getEnum(0).getCurrentType();
320
       int pos = RubikSettingsEnum.translatePos(pos0)+1;
321
       SizeChangeEffect effect = SizeChangeEffect.create(typ0);
322
       mSizeChangeEffectID = effect.start(pos,mScreen,mOldCube,mNewCube,this);
323
       }
324
     catch(Exception ex)
325
       {
326
       android.util.Log.e("Renderer", "failed to create SizeChangeEffect, exception: "+ex.getMessage());
327

    
328
       if( mOldCube!=null ) mScreen.detach(mOldCube);
329
       mScreen.attach(mNewCube);
330
       mCanRotate = true;
331
       mCanDrag   = true;
332
       }
333
     }
334

    
335
///////////////////////////////////////////////////////////////////////////////////////////////////
336

    
337
   private void solveCubeNow()
338
     {
339
     try
340
       {
341
       int pos1 = RubikSettingsEnum.getEnum(1).getCurrentPos();
342
       int typ1 = RubikSettingsEnum.getEnum(1).getCurrentType();
343
       int pos = RubikSettingsEnum.translatePos(pos1)+1;
344
       SolveEffect effect = SolveEffect.create(typ1);
345
       mSolveEffectID = effect.start(pos,mScreen,mNewCube,this);
346
       }
347
     catch(Exception ex)
348
       {
349
       android.util.Log.e("Renderer", "failed to create SolveEffect, exception: "+ex.getMessage());
350

    
351
       mNewCube.solve();    //
352
       mCanRotate = true;   // just solve the cube
353
       mCanDrag   = true;   //
354
       }
355
     }
356

    
357
///////////////////////////////////////////////////////////////////////////////////////////////////
358

    
359
   private void scrambleCubeNow()
360
     {
361
     try
362
       {
363
       int pos2 = RubikSettingsEnum.getEnum(2).getCurrentPos();
364
       int typ2 = RubikSettingsEnum.getEnum(2).getCurrentType();
365
       int pos = RubikSettingsEnum.translatePos(pos2)+1;
366
       ScrambleEffect effect = ScrambleEffect.create(typ2);
367
       mScrambleEffectID = effect.start(pos,mNewCube,mScrambleCubeNum,this);
368
       }
369
     catch(Exception ex)
370
       {
371
       android.util.Log.e("Renderer", "failed to create ScrambleEffect, exception: "+ex.getMessage());
372

    
373
       mCanRotate = true;
374
       mCanDrag   = true;
375
       }
376
     }
377

    
378
///////////////////////////////////////////////////////////////////////////////////////////////////
379

    
380
   float returnCubeSizeInScreenSpace()
381
     {
382
     return mCubeSizeInScreenSpace;
383
     }
384

    
385
///////////////////////////////////////////////////////////////////////////////////////////////////
386

    
387
   boolean canRotate()
388
     {
389
     return mCanRotate;
390
     }
391

    
392
///////////////////////////////////////////////////////////////////////////////////////////////////
393

    
394
   boolean canDrag()
395
     {
396
     return mCanDrag;
397
     }
398

    
399
///////////////////////////////////////////////////////////////////////////////////////////////////
400

    
401
   RubikCube getCube()
402
     {
403
     return mNewCube;
404
     }
405

    
406
///////////////////////////////////////////////////////////////////////////////////////////////////
407

    
408
   void setQuatCurrent(Static4D current)
409
     {
410
     mTempCurrent.set(current);
411
     mFinishDragCurrent = true;
412
     }
413

    
414
///////////////////////////////////////////////////////////////////////////////////////////////////
415

    
416
   void setQuatAccumulated(Static4D accumulated)
417
     {
418
     mTempAccumulated.set(accumulated);
419
     mFinishDragAccumulated = true;
420
     }
421
}
(4-4/7)