Project

General

Profile

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

magiccube / src / main / java / org / distorted / magic / RubikRenderer.java @ 5560eea9

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.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, mDisappearEffectID, mAppearEffectID;
54
    private boolean mFinishRotation, mRemoveRotation, mFinishDragCurrent, mFinishDragAccumulated;
55
    private boolean mCanRotate, mCanDrag;
56
    private RubikCube mOldCube, mNewCube;
57
    private int mScreenWidth, mScreenHeight;
58
    private MeshQuad mMesh;
59
    private AppearEffect.Type mAppearType;
60
    private DisappearEffect.Type mDisappearType;
61
    private int mAppearDuration, mDisappearDuration;
62

    
63
///////////////////////////////////////////////////////////////////////////////////////////////////
64

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

    
69
      mScreen = new DistortedScreen();
70

    
71
      mOldCube = null;
72
      mNewCube = null;
73

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

    
79
      mScreenWidth = mScreenHeight = 0;
80

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

    
86
      mCanRotate = true;
87
      mCanDrag   = true;
88

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

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

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

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

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

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

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

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

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

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

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

    
146
///////////////////////////////////////////////////////////////////////////////////////////////////
147

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

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

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

    
161
      recomputeScaleFactor(width,height);
162

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

    
167
///////////////////////////////////////////////////////////////////////////////////////////////////
168

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

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

    
186
///////////////////////////////////////////////////////////////////////////////////////////////////
187

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

    
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206

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

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

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

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

    
239
///////////////////////////////////////////////////////////////////////////////////////////////////
240

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

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

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

    
255
///////////////////////////////////////////////////////////////////////////////////////////////////
256

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

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

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

    
269
///////////////////////////////////////////////////////////////////////////////////////////////////
270

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

    
276
///////////////////////////////////////////////////////////////////////////////////////////////////
277

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

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

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

    
293
     return false;
294
     }
295

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

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

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

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

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

    
315
///////////////////////////////////////////////////////////////////////////////////////////////////
316

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

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

    
327
///////////////////////////////////////////////////////////////////////////////////////////////////
328

    
329
   void scrambleCube()
330
     {
331

    
332
     }
333

    
334
///////////////////////////////////////////////////////////////////////////////////////////////////
335

    
336
   float returnCubeSizeInScreenSpace()
337
     {
338
     return mCubeSizeInScreenSpace;
339
     }
340

    
341
///////////////////////////////////////////////////////////////////////////////////////////////////
342

    
343
   boolean canRotate()
344
     {
345
     return mCanRotate;
346
     }
347

    
348
///////////////////////////////////////////////////////////////////////////////////////////////////
349

    
350
   boolean canDrag()
351
     {
352
     return mCanDrag;
353
     }
354

    
355
///////////////////////////////////////////////////////////////////////////////////////////////////
356

    
357
   RubikCube getCube()
358
     {
359
     return mNewCube;
360
     }
361

    
362
///////////////////////////////////////////////////////////////////////////////////////////////////
363

    
364
   void setQuatCurrent(Static4D current)
365
     {
366
     mTempCurrent.set(current);
367
     mFinishDragCurrent = true;
368
     }
369

    
370
///////////////////////////////////////////////////////////////////////////////////////////////////
371

    
372
   void setQuatAccumulated(Static4D accumulated)
373
     {
374
     mTempAccumulated.set(accumulated);
375
     mFinishDragAccumulated = true;
376
     }
377
}
(4-4/6)