Project

General

Profile

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

magiccube / src / main / java / org / distorted / magic / RubikRenderer.java @ 05fa94d9

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
        mCanRotate = false;
113
        mFinishRotation=false;
114
        mRotationFinishedID = mNewCube.finishRotationNow(this);
115
        }
116

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

    
122
        if( mNewCube.isSolved() )
123
          {
124
          android.util.Log.e("renderer", "CUBE IS SOLVED NOW");
125
          }
126

    
127
        mCanRotate = true;
128
        }
129

    
130
      if( mSizeChangeCube )
131
        {
132
        mSizeChangeCube = false;
133
        mCanDrag        = false;
134
        mCanRotate      = false;
135
        createCubeNow(mNextCubeSize);
136
        doEffectNow( BaseEffect.Type.SIZECHANGE );
137
        }
138

    
139
      if( mSolveCube )
140
        {
141
        mSolveCube   = false;
142
        mCanDrag     = false;
143
        mCanRotate   = false;
144
        mCanUI       = false;
145
        doEffectNow( BaseEffect.Type.SOLVE );
146
        }
147

    
148
      if( mScrambleCube )
149
        {
150
        mScrambleCube = false;
151
        mCanDrag      = false;
152
        mCanRotate    = false;
153
        mCanUI        = false;
154
        doEffectNow( BaseEffect.Type.SCRAMBLE );
155
        }
156
      }
157

    
158
///////////////////////////////////////////////////////////////////////////////////////////////////
159

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

    
165
      float cameraDistance = CAMERA_DISTANCE*(width>height ? width:height);
166
      float fovInDegrees   = computeFOV(cameraDistance,height);
167

    
168
      mScreen.setProjection( fovInDegrees, 0.1f);
169
      mView.setScreenSize(width,height);
170
      mView.setCameraDist(cameraDistance);
171
      mScreen.resize(width, height);
172

    
173
      recomputeScaleFactor(width,height);
174

    
175
      mScreenHeight = height;
176
      mScreenWidth  = width;
177
      }
178

    
179
///////////////////////////////////////////////////////////////////////////////////////////////////
180

    
181
   @Override
182
   public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
183
      {
184
      VertexEffectSink.enable();
185
      BaseEffect.Type.enableEffects();
186

    
187
      try
188
        {
189
        DistortedLibrary.onCreate(mView.getContext());
190
        }
191
      catch(Exception ex)
192
        {
193
        android.util.Log.e("Rubik", ex.getMessage() );
194
        }
195
      }
196

    
197
///////////////////////////////////////////////////////////////////////////////////////////////////
198

    
199
   public void effectFinished(final long effectID)
200
     {
201
     if( effectID == mRotationFinishedID )
202
       {
203
       mRemoveRotation = true;
204
       }
205
     else
206
       {
207
       for(int i=0; i<BaseEffect.Type.LENGTH; i++)
208
         {
209
         if( effectID == mEffectID[i] )
210
           {
211
           mCanRotate   = true;
212
           mCanDrag     = true;
213
           mCanUI       = true;
214
           break;
215
           }
216
         }
217
       }
218
     }
219

    
220
///////////////////////////////////////////////////////////////////////////////////////////////////
221

    
222
   private float computeFOV(float cameraDistance, int screenHeight)
223
     {
224
     double halfFOVInRadians = Math.atan( screenHeight/(2*cameraDistance) );
225
     return (float)(2*halfFOVInRadians*(180/Math.PI));
226
     }
227

    
228
///////////////////////////////////////////////////////////////////////////////////////////////////
229
// no this will not race with onDrawFrame
230

    
231
   void finishRotation()
232
     {
233
     mFinishRotation = true;
234
     }
235

    
236
///////////////////////////////////////////////////////////////////////////////////////////////////
237

    
238
   boolean createCube(int newSize)
239
     {
240
     if( mCanDrag && mCanRotate && (mNewCube==null || newSize != mNewCube.getSize()) )
241
       {
242
       mSizeChangeCube = true;
243
       mNextCubeSize = newSize;
244
       return true;
245
       }
246

    
247
     return false;
248
     }
249

    
250
///////////////////////////////////////////////////////////////////////////////////////////////////
251

    
252
   private void recomputeScaleFactor(int screenWidth, int screenHeight)
253
     {
254
     mCubeSizeInScreenSpace = CUBE_SCREEN_RATIO*(screenWidth>screenHeight ? screenHeight:screenWidth);
255

    
256
     if( mNewCube!=null )
257
       {
258
       mNewCube.recomputeScaleFactor(screenWidth, screenHeight, mCubeSizeInScreenSpace);
259
       }
260
     }
261

    
262
///////////////////////////////////////////////////////////////////////////////////////////////////
263

    
264
   void scrambleCube(int num)
265
     {
266
     if( mCanUI )
267
       {
268
       mScrambleCube = true;
269
       mScrambleCubeNum = num;
270
       }
271
     }
272

    
273
///////////////////////////////////////////////////////////////////////////////////////////////////
274

    
275
   void solveCube()
276
     {
277
     if( mCanUI )
278
       {
279
       mSolveCube = true;
280
       }
281
     }
282

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

    
285
   private void createCubeNow(int newSize)
286
     {
287
     if( mOldCube!=null ) mOldCube.releaseResources();
288
     mOldCube = mNewCube;
289

    
290
     DistortedTexture texture = new DistortedTexture(TEXTURE_SIZE,TEXTURE_SIZE);
291
     DistortedEffects effects = new DistortedEffects();
292

    
293
     mNewCube = new RubikCube(newSize, mView.getQuatCurrent(), mView.getQuatAccumulated(), texture, mMesh, effects);
294
     mNewCube.createTexture();
295

    
296
     if( mScreenWidth!=0 )
297
       {
298
       recomputeScaleFactor(mScreenWidth,mScreenHeight);
299
       }
300
     }
301

    
302
///////////////////////////////////////////////////////////////////////////////////////////////////
303
// do all 'adjustable' effects (SizeChange, Solve, Scramble)
304

    
305
   private void doEffectNow(BaseEffect.Type type)
306
     {
307
     int index = type.ordinal();
308

    
309
     mEffectID[index] = type.startEffect(this);
310

    
311
     if( mEffectID[index] == -1 )
312
       {
313
       mCanUI     = true;
314
       mCanRotate = true;
315
       mCanDrag   = true;
316
       }
317
     }
318

    
319
///////////////////////////////////////////////////////////////////////////////////////////////////
320

    
321
   float returnCubeSizeInScreenSpace()
322
     {
323
     return mCubeSizeInScreenSpace;
324
     }
325

    
326
///////////////////////////////////////////////////////////////////////////////////////////////////
327

    
328
   boolean canRotate()
329
     {
330
     return mCanRotate;
331
     }
332

    
333
///////////////////////////////////////////////////////////////////////////////////////////////////
334

    
335
   boolean canDrag()
336
     {
337
     return mCanDrag;
338
     }
339

    
340
///////////////////////////////////////////////////////////////////////////////////////////////////
341

    
342
   public RubikCube getCube()
343
     {
344
     return mNewCube;
345
     }
346

    
347
///////////////////////////////////////////////////////////////////////////////////////////////////
348

    
349
   public RubikCube getOldCube()
350
     {
351
     return mOldCube;
352
     }
353

    
354
///////////////////////////////////////////////////////////////////////////////////////////////////
355

    
356
   public DistortedScreen getScreen()
357
     {
358
     return mScreen;
359
     }
360

    
361
///////////////////////////////////////////////////////////////////////////////////////////////////
362

    
363
   public int getNumScrambles()
364
     {
365
     return mScrambleCubeNum;
366
     }
367

    
368
///////////////////////////////////////////////////////////////////////////////////////////////////
369

    
370
   void setQuatCurrentOnNextRender()
371
     {
372
     mSetQuatCurrent = true;
373
     }
374

    
375
///////////////////////////////////////////////////////////////////////////////////////////////////
376

    
377
   void setQuatAccumulatedOnNextRender()
378
     {
379
     mSetQuatAccumulated = true;
380
     }
381
}
(4-4/6)