Project

General

Profile

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

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

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.AppearEffect;
25
import org.distorted.effect.DisappearEffect;
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.type.Static4D;
34

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

    
38
///////////////////////////////////////////////////////////////////////////////////////////////////
39

    
40
public class RubikRenderer implements GLSurfaceView.Renderer, EffectListener
41
{
42
    private static final float CUBE_SCREEN_RATIO = 0.5f;
43
    private static final float CAMERA_DISTANCE   = 0.6f;  // 0.6 of the length of max(scrHeight,scrWidth)
44
    public  static final int TEXTURE_SIZE = 600;
45

    
46
    private RubikSurfaceView mView;
47
    private DistortedScreen mScreen;
48
    private Static4D mQuatCurrent, mQuatAccumulated;
49
    private Static4D mTempCurrent, mTempAccumulated;
50
    private float mCubeSizeInScreenSpace;
51
    private int mNextCubeSize;
52
    private long mRotationFinishedID, mDisappearEffectID, mAppearEffectID;
53
    private boolean mFinishRotation, mRemoveRotation, mFinishDragCurrent, mFinishDragAccumulated;
54
    private boolean mCanRotate, mCanDrag;
55
    private RubikCube mOldCube, mNewCube;
56
    private int mScreenWidth, mScreenHeight;
57
    private MeshQuad mMesh;
58
    private AppearEffect.Type mAppearType;
59
    private DisappearEffect.Type mDisappearType;
60
    private int mAppearDuration, mDisappearDuration;
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 = new Static4D(0,0,0,1);
75
      mQuatCurrent     = new Static4D(0,0,0,1);
76
      mQuatAccumulated = new Static4D(0,0,0,1);
77

    
78
      mScreenWidth = mScreenHeight = 0;
79

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

    
85
      mCanRotate = true;
86
      mCanDrag   = true;
87

    
88
      mAppearType        = AppearEffect.Type.SCALE;
89
      mDisappearType     = DisappearEffect.Type.SCALE;
90
      mAppearDuration    = 1000;
91
      mDisappearDuration = 1000;
92

    
93
      mMesh= new MeshQuad();
94
      mNextCubeSize =RubikActivity.getSize();
95
      }
96

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

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

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

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

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

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

    
132
      if( mNextCubeSize!=0 )
133
        {
134
        createCubeNow(mNextCubeSize);
135

    
136
        mCanDrag   = false;
137
        mCanRotate = false;
138
        mNextCubeSize = 0;
139

    
140
        if( mOldCube!=null ) disappearCube();
141
        else                    appearCube();
142
        }
143
      }
144

    
145
///////////////////////////////////////////////////////////////////////////////////////////////////
146

    
147
   @Override
148
   public void onSurfaceChanged(GL10 glUnused, int width, int height)
149
      {
150
      if( mNewCube!=null ) mNewCube.createTexture();
151

    
152
      float cameraDistance = CAMERA_DISTANCE*(width>height ? width:height);
153
      float fovInDegrees   = computeFOV(cameraDistance,height);
154

    
155
      mScreen.setProjection( fovInDegrees, 0.1f);
156
      mView.setScreenSize(width,height);
157
      mView.setCameraDist(cameraDistance);
158
      mScreen.resize(width, height);
159

    
160
      recomputeScaleFactor(width,height);
161

    
162
      mScreenHeight = height;
163
      mScreenWidth  = width;
164
      }
165

    
166
///////////////////////////////////////////////////////////////////////////////////////////////////
167

    
168
   @Override
169
   public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
170
      {
171
      VertexEffectSink.enable();
172
      AppearEffect.enableEffects();
173
      DisappearEffect.enableEffects();
174

    
175
      try
176
        {
177
        DistortedLibrary.onCreate(mView.getContext());
178
        }
179
      catch(Exception ex)
180
        {
181
        android.util.Log.e("Rubik", ex.getMessage() );
182
        }
183
      }
184

    
185
///////////////////////////////////////////////////////////////////////////////////////////////////
186

    
187
   public void effectFinished(final long effectID)
188
     {
189
     if(      effectID == mRotationFinishedID)
190
       {
191
       mRemoveRotation = true;
192
       }
193
     else if( effectID == mDisappearEffectID )
194
       {
195
       appearCube();
196
       }
197
     else if( effectID == mAppearEffectID    )
198
       {
199
       mCanRotate = true;
200
       mCanDrag   = true;
201
       }
202
     }
203

    
204
///////////////////////////////////////////////////////////////////////////////////////////////////
205

    
206
   private void disappearCube()
207
     {
208
     try
209
       {
210
       DisappearEffect effect = DisappearEffect.create(mDisappearType);
211
       mDisappearEffectID = effect.start(mDisappearDuration,mScreen,mOldCube,this);
212
       }
213
     catch(Exception ex)
214
       {
215
       android.util.Log.e("Renderer", "failed to create DisappearEffect, exception: "+ex.getMessage());
216
       }
217
     }
218

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

    
221
   private void appearCube()
222
     {
223
     try
224
       {
225
       AppearEffect effect = AppearEffect.create(mAppearType);
226
       mAppearEffectID = effect.start(mAppearDuration,mScreen,mNewCube,this);
227
       }
228
     catch(Exception ex)
229
       {
230
       android.util.Log.e("Renderer", "failed to create AppearEffect, exception: "+ex.getMessage());
231

    
232
       mScreen.attach(mNewCube); //
233
       mCanRotate = true;        // just appear the cube
234
       mCanDrag   = true;        //
235
       }
236
     }
237

    
238
///////////////////////////////////////////////////////////////////////////////////////////////////
239

    
240
   private float computeFOV(float cameraDistance, int screenHeight)
241
     {
242
     double halfFOVInRadians = Math.atan( screenHeight/(2*cameraDistance) );
243
     return (float)(2*halfFOVInRadians*(180/Math.PI));
244
     }
245

    
246
///////////////////////////////////////////////////////////////////////////////////////////////////
247
// no this will not race with onDrawFrame
248

    
249
   void finishRotation()
250
     {
251
     mFinishRotation = true;
252
     }
253

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

    
256
   void setAppearDuration(int duration)
257
     {
258
     mAppearDuration = duration;
259
     }
260

    
261
///////////////////////////////////////////////////////////////////////////////////////////////////
262

    
263
   void setDisappearDuration(int duration)
264
     {
265
     mDisappearDuration = duration;
266
     }
267

    
268
///////////////////////////////////////////////////////////////////////////////////////////////////
269

    
270
   void setAppearType(AppearEffect.Type type)
271
     {
272
     mAppearType = type;
273
     }
274

    
275
///////////////////////////////////////////////////////////////////////////////////////////////////
276

    
277
   void setDisappearType(DisappearEffect.Type type)
278
     {
279
     mDisappearType = type;
280
     }
281

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

    
284
   boolean createCube(int newSize)
285
     {
286
     if( mCanDrag && mCanRotate && (mNewCube==null || newSize != mNewCube.getSize()) )
287
       {
288
       mNextCubeSize = newSize;
289
       return true;
290
       }
291

    
292
     return false;
293
     }
294

    
295
///////////////////////////////////////////////////////////////////////////////////////////////////
296

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

    
302
     DistortedTexture texture = new DistortedTexture(TEXTURE_SIZE,TEXTURE_SIZE);
303
     DistortedEffects effects = new DistortedEffects();
304

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

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

    
314
///////////////////////////////////////////////////////////////////////////////////////////////////
315

    
316
   private void recomputeScaleFactor(int screenWidth, int screenHeight)
317
     {
318
     mCubeSizeInScreenSpace = CUBE_SCREEN_RATIO*(screenWidth>screenHeight ? screenHeight:screenWidth);
319

    
320
     if( mNewCube!=null )
321
       {
322
       mNewCube.recomputeScaleFactor(screenWidth, screenHeight, mCubeSizeInScreenSpace);
323
       }
324
     }
325

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

    
328
   void scrambleCube(int num)
329
     {
330
     android.util.Log.e("renderer","scrambling "+num+" times");
331
     }
332

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

    
335
   void solveCube()
336
     {
337
     android.util.Log.e("renderer","solving cube");
338
     }
339

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

    
342
   float returnCubeSizeInScreenSpace()
343
     {
344
     return mCubeSizeInScreenSpace;
345
     }
346

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

    
349
   boolean canRotate()
350
     {
351
     return mCanRotate;
352
     }
353

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

    
356
   boolean canDrag()
357
     {
358
     return mCanDrag;
359
     }
360

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

    
363
   RubikCube getCube()
364
     {
365
     return mNewCube;
366
     }
367

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

    
370
   void setQuatCurrent(Static4D current)
371
     {
372
     mTempCurrent.set(current);
373
     mFinishDragCurrent = true;
374
     }
375

    
376
///////////////////////////////////////////////////////////////////////////////////////////////////
377

    
378
   void setQuatAccumulated(Static4D accumulated)
379
     {
380
     mTempAccumulated.set(accumulated);
381
     mFinishDragAccumulated = true;
382
     }
383
}
(4-4/6)