Project

General

Profile

Download (8.17 KB) Statistics
| Branch: | Revision:

examples / src / main / java / org / distorted / examples / rubik / RubikRenderer.java @ 5d8a1d51

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.examples.rubik;
21

    
22
import android.opengl.GLSurfaceView;
23

    
24
import org.distorted.library.effect.VertexEffectSink;
25
import org.distorted.library.main.Distorted;
26
import org.distorted.library.main.DistortedScreen;
27
import org.distorted.library.message.EffectListener;
28
import org.distorted.library.message.EffectMessage;
29
import org.distorted.library.type.Static3D;
30
import org.distorted.library.type.Static4D;
31

    
32
import javax.microedition.khronos.egl.EGLConfig;
33
import javax.microedition.khronos.opengles.GL10;
34

    
35
///////////////////////////////////////////////////////////////////////////////////////////////////
36

    
37
class RubikRenderer implements GLSurfaceView.Renderer, EffectListener
38
{
39
    private static final float CUBE_SCREEN_RATIO = 0.5f;
40
    private static final float CAMERA_DISTANCE   = 0.6f;  // 0.6 of the length of max(scrHeight,scrWidth)
41

    
42
    private RubikSurfaceView mView;
43
    private DistortedScreen mScreen;
44
    private Static3D mMove, mScale;
45
    private Static4D mQuatCurrent, mQuatAccumulated;
46
    private Static4D mTempCurrent, mTempAccumulated;
47
    private float mCubeSizeInScreenSpace;
48
    private boolean mFinishRotation, mRemoveRotation, mFinishDragCurrent, mFinishDragAccumulated;
49
    private boolean mCanRotate;
50
    private RubikCube mCube;
51

    
52
///////////////////////////////////////////////////////////////////////////////////////////////////
53

    
54
    RubikRenderer(RubikSurfaceView v)
55
      {
56
      mView = v;
57

    
58
      mScreen = new DistortedScreen();
59

    
60
      mTempCurrent     = new Static4D(0,0,0,1);
61
      mTempAccumulated = initializeQuat();
62
      mQuatCurrent     = new Static4D(0,0,0,1);
63
      mQuatAccumulated = initializeQuat();
64

    
65
      mMove  = new Static3D(0,0,0);
66
      mScale = new Static3D(1,1,1);
67

    
68
      mFinishRotation        = false;
69
      mRemoveRotation        = false;
70
      mFinishDragCurrent     = false;
71
      mFinishDragAccumulated = false;
72

    
73
      mCanRotate = true;
74

    
75
      mCube = new RubikCube( RubikActivity.DEFAULT_CUBE_SIZE, mMove, mScale, mQuatCurrent, mQuatAccumulated);
76
      }
77

    
78
///////////////////////////////////////////////////////////////////////////////////////////////////
79
// various things are done here delayed, 'after the next render' as not to be done mid-render and
80
// cause artifacts.
81

    
82
    public void onDrawFrame(GL10 glUnused) 
83
      {
84
      mScreen.render( System.currentTimeMillis() );
85

    
86
      if( mFinishDragCurrent )
87
        {
88
        mFinishDragCurrent = false;
89
        mQuatCurrent.set(mTempCurrent);
90
        }
91

    
92
      if( mFinishDragAccumulated )
93
        {
94
        mFinishDragAccumulated = false;
95
        mQuatAccumulated.set(mTempAccumulated);
96
        }
97

    
98
      if( mFinishRotation )
99
        {
100
        mCanRotate = false;
101
        mFinishRotation=false;
102
        mCube.finishRotationCalledOnNextRender(this);
103
        }
104

    
105
      if( mRemoveRotation )
106
        {
107
        mRemoveRotation=false;
108
        mCube.removeRotationCalledOnNextRender(this);
109
        mCanRotate = true;
110
        }
111
      }
112

    
113
///////////////////////////////////////////////////////////////////////////////////////////////////
114
// EffectListener. The library sends a message to us when it's time to call 'removeRotation'
115

    
116
   public void effectMessage(final EffectMessage em, final long effectID, final long objectID)
117
     {
118
     switch(em)
119
        {
120
        case EFFECT_FINISHED: mRemoveRotation = true; break;
121
        }
122
     }
123

    
124
///////////////////////////////////////////////////////////////////////////////////////////////////
125
    
126
    public void onSurfaceChanged(GL10 glUnused, int width, int height) 
127
      {
128
      float cameraDistance = CAMERA_DISTANCE*(width>height ? width:height);
129
      float fovInDegrees   = computeFOV(cameraDistance,height);
130

    
131
      mScreen.setProjection( fovInDegrees, 0.1f);
132
      mView.setScreenSize(width,height);
133
      mView.setCameraDist(cameraDistance);
134

    
135
      mCubeSizeInScreenSpace = CUBE_SCREEN_RATIO*(width>height ? height:width);
136
      float texSize = mCube.getTextureSize();
137
      float scaleFactor = mCubeSizeInScreenSpace/(texSize*mCube.getSize());
138

    
139
      mMove.set( (width-scaleFactor*texSize)/2 , (height-scaleFactor*texSize)/2 , -scaleFactor*texSize/2 );
140
      mScale.set(scaleFactor,scaleFactor,scaleFactor);
141

    
142
      mScreen.resize(width, height);
143
      }
144

    
145
///////////////////////////////////////////////////////////////////////////////////////////////////
146
    
147
    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
148
      {
149
      mCube.createTexture();
150
      mScreen.detachAll();
151
      mCube.attachToScreen(mScreen);
152

    
153
      VertexEffectSink.enable();
154

    
155
      try
156
        {
157
        Distorted.onCreate(mView.getContext());
158
        }
159
      catch(Exception ex)
160
        {
161
        android.util.Log.e("Rubik", ex.getMessage() );
162
        }
163
      }
164

    
165
///////////////////////////////////////////////////////////////////////////////////////////////////
166

    
167
    private float computeFOV(float cameraDistance, int screenHeight)
168
      {
169
      double halfFOVInRadians = Math.atan( screenHeight/(2*cameraDistance) );
170
      return (float)(2*halfFOVInRadians*(180/Math.PI));
171
      }
172

    
173
///////////////////////////////////////////////////////////////////////////////////////////////////
174
// no this will not race with onDrawFrame
175

    
176
    void finishRotation()
177
      {
178
      mFinishRotation = true;
179
      }
180

    
181
///////////////////////////////////////////////////////////////////////////////////////////////////
182

    
183
    float returnCubeSizeInScreenSpace()
184
      {
185
      return mCubeSizeInScreenSpace;
186
      }
187

    
188
///////////////////////////////////////////////////////////////////////////////////////////////////
189

    
190
    boolean canRotate()
191
      {
192
      return mCanRotate;
193
      }
194

    
195
///////////////////////////////////////////////////////////////////////////////////////////////////
196

    
197
    RubikCube getCube()
198
      {
199
      return mCube;
200
      }
201

    
202
///////////////////////////////////////////////////////////////////////////////////////////////////
203
// Initial rotation of the cube. Something semi-random that looks good.
204

    
205
    Static4D initializeQuat()
206
      {
207
      return new Static4D(-0.25189602f,0.3546389f,0.009657208f,0.90038127f);
208
      }
209

    
210
///////////////////////////////////////////////////////////////////////////////////////////////////
211

    
212
    void setQuatCurrent(Static4D current)
213
      {
214
      mTempCurrent.set(current);
215
      mFinishDragCurrent = true;
216
      }
217

    
218
///////////////////////////////////////////////////////////////////////////////////////////////////
219

    
220
    void setQuatAccumulated(Static4D accumulated)
221
      {
222
      mTempAccumulated.set(accumulated);
223
      mFinishDragAccumulated = true;
224
      }
225
}
(3-3/4)