Project

General

Profile

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

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

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.TransitionEffect;
25
import org.distorted.library.effect.EffectType;
26
import org.distorted.library.effect.VertexEffectSink;
27
import org.distorted.library.main.DistortedEffects;
28
import org.distorted.library.main.DistortedLibrary;
29
import org.distorted.library.main.DistortedScreen;
30
import org.distorted.library.main.DistortedTexture;
31
import org.distorted.library.mesh.MeshQuad;
32
import org.distorted.library.message.EffectListener;
33
import org.distorted.library.message.EffectMessage;
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;
53
    private long mRotationFinishedID, mTransitionEffectID;
54
    private boolean mFinishRotation, mRemoveRotation, mFinishDragCurrent, mFinishDragAccumulated;
55
    private boolean mCanRotate, mCanDrag;
56
    private RubikCube mOldCube, mNewCube;
57

    
58
    private int mScreenWidth, mScreenHeight;
59

    
60
    private MeshQuad mMesh;
61

    
62
///////////////////////////////////////////////////////////////////////////////////////////////////
63

    
64
    RubikRenderer(RubikSurfaceView v)
65
      {
66
      mView = v;
67

    
68
      mScreen = new DistortedScreen();
69

    
70
      mOldCube = null;
71
      mNewCube = null;
72

    
73
      mTempCurrent     = new Static4D(0,0,0,1);
74
      mTempAccumulated = initializeQuat();
75
      mQuatCurrent     = new Static4D(0,0,0,1);
76
      mQuatAccumulated = initializeQuat();
77

    
78
      mScreenWidth = mScreenHeight = 0;
79

    
80
      mFinishRotation        = false;
81
      mRemoveRotation        = false;
82
      mFinishDragCurrent     = false;
83
      mFinishDragAccumulated = false;
84

    
85
      mNextCubeSize= 0;
86

    
87
      mCanRotate = true;
88
      mCanDrag   = true;
89

    
90
      mMesh= new MeshQuad();
91
      }
92

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

    
97
    public void onDrawFrame(GL10 glUnused) 
98
      {
99
      mScreen.render( System.currentTimeMillis() );
100

    
101
      if( mFinishDragCurrent )
102
        {
103
        mFinishDragCurrent = false;
104
        mQuatCurrent.set(mTempCurrent);
105
        }
106

    
107
      if( mFinishDragAccumulated )
108
        {
109
        mFinishDragAccumulated = false;
110
        mQuatAccumulated.set(mTempAccumulated);
111
        }
112

    
113
      if( mFinishRotation )
114
        {
115
        mCanRotate = false;
116
        mFinishRotation=false;
117
        mRotationFinishedID = mNewCube.finishRotationNow(this);
118
        }
119

    
120
      if( mRemoveRotation )
121
        {
122
        mRemoveRotation=false;
123
        mNewCube.removeRotationNow(this);
124
        mCanRotate = true;
125
        }
126

    
127
      if( mNextCubeSize!=0 )
128
        {
129
        mCanDrag   = false;
130
        mCanRotate = false;
131
        createCubeNow(mNextCubeSize);
132

    
133
        try
134
          {
135
          TransitionEffect effect = TransitionEffect.create(TransitionEffect.Type.ROUND);
136
          mTransitionEffectID = effect.start(mScreen,mOldCube,mNewCube,this);
137
          }
138
        catch(Exception ex)
139
          {
140
          android.util.Log.e("Renderer", "failed to create TransitionEffect, exception: "+ex.getMessage());
141
          }
142

    
143
        mNextCubeSize = 0;
144
        }
145
      }
146

    
147
///////////////////////////////////////////////////////////////////////////////////////////////////
148
// EffectListener. The library sends a message to us when it's time to call 'removeRotation'
149

    
150
   public void effectMessage(final EffectMessage em, final long effectID, final long objectID)
151
     {
152
     if(      effectID == mRotationFinishedID )
153
       {
154
       //android.util.Log.e("renderer", "rotation finished");
155

    
156
       mRemoveRotation = true;
157
       }
158
     else if( effectID == mTransitionEffectID )
159
       {
160
       /*
161
       int nM = mNewCube.getNumEffects(EffectType.MATRIX);
162
       int nV = mNewCube.getNumEffects(EffectType.VERTEX);
163
       int nF = mNewCube.getNumEffects(EffectType.FRAGMENT);
164
       int nP = mNewCube.getNumEffects(EffectType.POSTPROCESS);
165

    
166
       android.util.Log.d("renderer", "transition finished, new cube effects= "+nM+","+nV+","+nF+","+nP);
167

    
168
       int oM = mOldCube.getNumEffects(EffectType.MATRIX);
169
       int oV = mOldCube.getNumEffects(EffectType.VERTEX);
170
       int oF = mOldCube.getNumEffects(EffectType.FRAGMENT);
171
       int oP = mOldCube.getNumEffects(EffectType.POSTPROCESS);
172

    
173
       android.util.Log.d("renderer", "transition finished, old cube effects= "+oM+","+oV+","+oF+","+oP);
174
       */
175
       mCanRotate = true;
176
       mCanDrag   = true;
177
       }
178
     }
179

    
180
///////////////////////////////////////////////////////////////////////////////////////////////////
181
    
182
    public void onSurfaceChanged(GL10 glUnused, int width, int height) 
183
      {
184
      float cameraDistance = CAMERA_DISTANCE*(width>height ? width:height);
185
      float fovInDegrees   = computeFOV(cameraDistance,height);
186

    
187
      mScreen.setProjection( fovInDegrees, 0.1f);
188
      mView.setScreenSize(width,height);
189
      mView.setCameraDist(cameraDistance);
190
      mScreen.resize(width, height);
191

    
192
      recomputeScaleFactor(width,height);
193

    
194
      mScreenHeight = height;
195
      mScreenWidth  = width;
196
      }
197

    
198
///////////////////////////////////////////////////////////////////////////////////////////////////
199
    
200
    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
201
      {
202
      mNewCube.createTexture();
203
      mScreen.detachAll();
204
      mScreen.attach(mNewCube);
205

    
206
      VertexEffectSink.enable();
207
      TransitionEffect.enableEffects();
208

    
209
      try
210
        {
211
        DistortedLibrary.onCreate(mView.getContext());
212
        }
213
      catch(Exception ex)
214
        {
215
        android.util.Log.e("Rubik", ex.getMessage() );
216
        }
217
      }
218

    
219
///////////////////////////////////////////////////////////////////////////////////////////////////
220

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

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

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

    
235
///////////////////////////////////////////////////////////////////////////////////////////////////
236

    
237
   boolean createCube(int newSize)
238
     {
239
     if( mCanDrag && mCanRotate )
240
       {
241
       mNextCubeSize = newSize;
242
       return true;
243
       }
244

    
245
     android.util.Log.e("renderer", "cannot change, drag="+mCanDrag+" rotate="+mCanRotate);
246

    
247
     return false;
248
     }
249

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

    
252
   void createCubeNow(int newSize)
253
     {
254
     int oldSize = mNewCube==null ? 0 : mNewCube.getSize();
255

    
256
     if( oldSize!=newSize )
257
       {
258
       if( mOldCube!=null ) mOldCube.releaseResources();
259
       mOldCube = mNewCube;
260

    
261
       DistortedTexture texture = new DistortedTexture(TEXTURE_SIZE,TEXTURE_SIZE);
262
       DistortedEffects effects = new DistortedEffects();
263

    
264
       mNewCube = new RubikCube(newSize, mQuatCurrent, mQuatAccumulated, texture, mMesh, effects);
265
       mNewCube.createTexture();
266

    
267
       if( mScreenWidth!=0 )
268
         {
269
         recomputeScaleFactor(mScreenWidth,mScreenHeight);
270
         }
271
       }
272
     }
273

    
274
///////////////////////////////////////////////////////////////////////////////////////////////////
275

    
276
   private void recomputeScaleFactor(int screenWidth, int screenHeight)
277
     {
278
     mCubeSizeInScreenSpace = CUBE_SCREEN_RATIO*(screenWidth>screenHeight ? screenHeight:screenWidth);
279
     mNewCube.recomputeScaleFactor(screenWidth, screenHeight, mCubeSizeInScreenSpace);
280
     }
281

    
282
///////////////////////////////////////////////////////////////////////////////////////////////////
283

    
284
   void scrambleCube()
285
     {
286

    
287
     }
288

    
289
///////////////////////////////////////////////////////////////////////////////////////////////////
290

    
291
   float returnCubeSizeInScreenSpace()
292
     {
293
     return mCubeSizeInScreenSpace;
294
     }
295

    
296
///////////////////////////////////////////////////////////////////////////////////////////////////
297

    
298
   boolean canRotate()
299
     {
300
     return mCanRotate;
301
     }
302

    
303
///////////////////////////////////////////////////////////////////////////////////////////////////
304

    
305
   boolean canDrag()
306
     {
307
     return mCanDrag;
308
     }
309

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

    
312
   RubikCube getCube()
313
     {
314
     return mNewCube;
315
     }
316

    
317
///////////////////////////////////////////////////////////////////////////////////////////////////
318
// Initial rotation of the cube. Something semi-random that looks good.
319

    
320
   Static4D initializeQuat()
321
     {
322
     return new Static4D(-0.25189602f,0.3546389f,0.009657208f,0.90038127f);
323
     }
324

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

    
327
   void setQuatCurrent(Static4D current)
328
     {
329
     mTempCurrent.set(current);
330
     mFinishDragCurrent = true;
331
     }
332

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

    
335
   void setQuatAccumulated(Static4D accumulated)
336
     {
337
     mTempAccumulated.set(accumulated);
338
     mFinishDragAccumulated = true;
339
     }
340
}
(3-3/4)