Project

General

Profile

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

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

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
import org.distorted.library.type.Static4D;
33

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

    
37
///////////////////////////////////////////////////////////////////////////////////////////////////
38

    
39
public class RubikRenderer implements GLSurfaceView.Renderer, EffectListener
40
{
41
    private static final float CUBE_SCREEN_RATIO = 0.5f;
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 Static4D mQuatCurrent, mQuatAccumulated;
48
    private Static4D mTempCurrent, mTempAccumulated;
49
    private float mCubeSizeInScreenSpace;
50
    private int mNextCubeSize, mScrambleCubeNum;
51
    private long mRotationFinishedID;
52
    private long[] mEffectID;
53
    private boolean mFinishRotation, mRemoveRotation, mFinishDragCurrent, mFinishDragAccumulated, mSolveCube, mScrambleCube;
54
    private boolean mCanRotate, mCanDrag, mCanScramble, mCanSolve;
55
    private RubikCube mOldCube, mNewCube;
56
    private int mScreenWidth, mScreenHeight;
57
    private MeshFlat mMesh;
58

    
59
///////////////////////////////////////////////////////////////////////////////////////////////////
60

    
61
    RubikRenderer(RubikSurfaceView v)
62
      {
63
      mView = v;
64

    
65
      mScreen = new DistortedScreen();
66

    
67
      mOldCube = null;
68
      mNewCube = null;
69

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

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

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

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

    
90
      mEffectID = new long[BaseEffect.Type.LENGTH];
91

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

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

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

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

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

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

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

    
131
      if( mNextCubeSize!=0 )
132
        {
133
        createCubeNow(mNextCubeSize);
134
        mCanDrag   = false;
135
        mCanRotate = false;
136
        mNextCubeSize = 0;
137
        doEffectNow(0);
138
        }
139

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

    
150
      if( mScrambleCube )
151
        {
152
        mScrambleCube = false;
153
        mCanDrag      = false;
154
        mCanRotate    = false;
155
        mCanScramble  = false;
156
        mCanSolve     = false;
157
        doEffectNow(2);
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
      BaseEffect.Type.enableEffects();
189

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

    
200
///////////////////////////////////////////////////////////////////////////////////////////////////
201

    
202
   public void effectFinished(final long effectID)
203
     {
204
     if(      effectID == mRotationFinishedID )
205
       {
206
       mRemoveRotation = true;
207
       }
208
     else if( effectID == mEffectID[0] )
209
       {
210
       mCanRotate   = true;
211
       mCanDrag     = true;
212
       }
213
     else if( effectID == mEffectID[1] )
214
       {
215
       mCanRotate   = true;
216
       mCanDrag     = true;
217
       mCanSolve    = true;
218
       mCanScramble = true;
219
       }
220
     else if( effectID == mEffectID[2] )
221
       {
222
       mCanRotate   = true;
223
       mCanDrag     = true;
224
       mCanSolve    = true;
225
       mCanScramble = true;
226
       }
227
     }
228

    
229
///////////////////////////////////////////////////////////////////////////////////////////////////
230

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

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

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

    
245
///////////////////////////////////////////////////////////////////////////////////////////////////
246

    
247
   boolean createCube(int newSize)
248
     {
249
     if( mCanDrag && mCanRotate && (mNewCube==null || newSize != mNewCube.getSize()) )
250
       {
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( mCanScramble )
275
       {
276
       mScrambleCube = true;
277
       mScrambleCubeNum = num;
278
       }
279
     }
280

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

    
283
   void solveCube()
284
     {
285
     if( mCanSolve )
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, mQuatCurrent, mQuatAccumulated, texture, mMesh, effects);
302
     mNewCube.createTexture();
303

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

    
310
///////////////////////////////////////////////////////////////////////////////////////////////////
311

    
312
   private void doEffectNow(int index)
313
     {
314
     mEffectID[index] = BaseEffect.Type.getType(index).startEffect(this);
315

    
316
     if( mEffectID[index] == -1 )
317
       {
318
       mCanRotate = true;
319
       mCanDrag   = true;
320
       }
321
     }
322

    
323
///////////////////////////////////////////////////////////////////////////////////////////////////
324

    
325
   float returnCubeSizeInScreenSpace()
326
     {
327
     return mCubeSizeInScreenSpace;
328
     }
329

    
330
///////////////////////////////////////////////////////////////////////////////////////////////////
331

    
332
   boolean canRotate()
333
     {
334
     return mCanRotate;
335
     }
336

    
337
///////////////////////////////////////////////////////////////////////////////////////////////////
338

    
339
   boolean canDrag()
340
     {
341
     return mCanDrag;
342
     }
343

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

    
346
   public RubikCube getCube()
347
     {
348
     return mNewCube;
349
     }
350

    
351
///////////////////////////////////////////////////////////////////////////////////////////////////
352

    
353
   public RubikCube getOldCube()
354
     {
355
     return mOldCube;
356
     }
357

    
358
///////////////////////////////////////////////////////////////////////////////////////////////////
359

    
360
   public DistortedScreen getScreen()
361
     {
362
     return mScreen;
363
     }
364

    
365
///////////////////////////////////////////////////////////////////////////////////////////////////
366

    
367
   public int getNumScrambles()
368
     {
369
     return mScrambleCubeNum;
370
     }
371

    
372
///////////////////////////////////////////////////////////////////////////////////////////////////
373

    
374
   void setQuatCurrent(Static4D current)
375
     {
376
     mTempCurrent.set(current);
377
     mFinishDragCurrent = true;
378
     }
379

    
380
///////////////////////////////////////////////////////////////////////////////////////////////////
381

    
382
   void setQuatAccumulated(Static4D accumulated)
383
     {
384
     mTempAccumulated.set(accumulated);
385
     mFinishDragAccumulated = true;
386
     }
387
}
(4-4/6)