Project

General

Profile

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

magiccube / src / main / java / org / distorted / control / RubikControlRotate.java @ 588ace55

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2021 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube 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
// Magic Cube 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 Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.control;
21

    
22
import android.graphics.Bitmap;
23
import android.graphics.BitmapFactory;
24

    
25
import org.distorted.objectlib.QuatHelper;
26
import org.distorted.library.effect.MatrixEffectQuaternion;
27
import org.distorted.library.effect.MatrixEffectScale;
28
import org.distorted.library.main.DistortedEffects;
29
import org.distorted.library.main.DistortedNode;
30
import org.distorted.library.main.DistortedScreen;
31
import org.distorted.library.main.DistortedTexture;
32
import org.distorted.library.mesh.MeshQuad;
33
import org.distorted.library.message.EffectListener;
34
import org.distorted.library.type.Dynamic;
35
import org.distorted.library.type.Dynamic3D;
36
import org.distorted.library.type.Dynamic4D;
37
import org.distorted.library.type.Static3D;
38
import org.distorted.library.type.Static4D;
39
import org.distorted.main.R;
40
import org.distorted.main.RubikActivity;
41
import org.distorted.objectlib.TwistyObject;
42

    
43
import java.io.IOException;
44
import java.io.InputStream;
45

    
46
///////////////////////////////////////////////////////////////////////////////////////////////////
47

    
48
class RubikControlRotate implements EffectListener
49
  {
50
  private static final int NUM_SCREEN = 0;
51
  private static final int NUM_OBJECT = 1;
52

    
53
  private static Static4D INIT_QUAT;
54

    
55
  private final RubikControl mControl;
56
  private DistortedEffects[] mScreenEffects, mObjectEffects;
57
  private DistortedNode[] mScreenNodes, mObjectNodes;
58
  private long mScreenEffectID, mObjectEffectID, mCubeEffectID;
59
  private Static4D mObjRotQuat;
60

    
61
  private Dynamic3D mDynamic3;
62
  private Dynamic4D mDynamic4;
63
  private MatrixEffectScale mScale;
64
  private MatrixEffectQuaternion mQuaternion;
65
  private MeshQuad mScreenQuad, mObjectQuad;
66

    
67
///////////////////////////////////////////////////////////////////////////////////////////////////
68

    
69
   private Bitmap openBitmap(RubikActivity act, int resource)
70
     {
71
     try( InputStream is = act.getResources().openRawResource(resource) )
72
       {
73
       return BitmapFactory.decodeStream(is);
74
       }
75
     catch( IOException e )
76
       {
77
       // ignore
78
       }
79

    
80
     return null;
81
     }
82

    
83
///////////////////////////////////////////////////////////////////////////////////////////////////
84

    
85
  private void computeInitQuat()
86
    {
87
    double alphaZ = 0;//-Math.PI* 0.1250f;
88
    double alphaY = 0;//-Math.PI* 0.0625f;
89

    
90
    alphaY /= 2;
91
    alphaZ /= 2;
92

    
93
    float sinZ = (float)Math.sin(alphaZ);
94
    float cosZ = (float)Math.cos(alphaZ);
95
    float sinY = (float)Math.sin(alphaY);
96
    float cosY = (float)Math.cos(alphaY);
97

    
98
    Static4D qZ = new Static4D(0,0,sinZ,cosZ);
99
    Static4D qY = new Static4D(0,sinY,0,cosY);
100

    
101
    INIT_QUAT = QuatHelper.quatMultiply(qY,qZ);
102
    }
103

    
104
///////////////////////////////////////////////////////////////////////////////////////////////////
105
// Take 3D vector 'ax', rotate it by quaternion 'objQuat' to get vector V1.
106
// Take 3D vector (1,0,0) and rotate it by INIT_QUAT to get vector V2.
107
// Return a quaternion Q such that if we rotate V1 by Q, we get V2.
108

    
109
  private Static4D computeQuat(Static3D ax, Static4D objQuat, float x, float y, float z)
110
    {
111
    Static4D ax4D = new Static4D( ax.get0(), ax.get1(), ax.get2(), 0);
112
    Static4D axRo = QuatHelper.rotateVectorByQuat(ax4D,objQuat);
113
    return QuatHelper.retRotationQuat(axRo.get0(),axRo.get1(),axRo.get2(),x,y,z);
114
    }
115

    
116
///////////////////////////////////////////////////////////////////////////////////////////////////
117

    
118
  private void computeRotQuat()
119
    {
120
    TwistyObject object = mControl.getObject();
121
    Static3D[] axis = object.getRotationAxis();
122
    int chosen=-1,numAxis = axis.length;
123
    float cos,maxCos = -1.0f;
124
    Static4D quat;
125

    
126
    Static4D objCurrQuat = mControl.getCurrQuat();
127
    Static4D axisX = new Static4D(1,0,0,0);
128
    Static4D rotAxisX = QuatHelper.rotateVectorByQuat(axisX,INIT_QUAT);
129

    
130
    float axX = rotAxisX.get0();
131
    float axY = rotAxisX.get1();
132
    float axZ = rotAxisX.get2();
133

    
134
    for (int a=0; a<numAxis; a++)
135
      {
136
      quat = computeQuat(axis[a],objCurrQuat,axX,axY,axZ);
137
      cos = quat.get3();
138

    
139
android.util.Log.e("D", "axis="+a+" "+quat.get0()+" "+quat.get1()+" "+quat.get2()+" "+quat.get3() );
140

    
141
      if (cos > maxCos)
142
        {
143
        maxCos = cos;
144
        chosen = a;
145
        if( mObjRotQuat==null ) mObjRotQuat = new Static4D(quat);
146
        else mObjRotQuat.set(quat);
147
        }
148
      }
149

    
150
    android.util.Log.e("D", "axis chosen: "+chosen);
151

    
152

    
153
android.util.Log.e("D", mObjRotQuat.get0()+" "+mObjRotQuat.get1()+" "+mObjRotQuat.get2()+" "+mObjRotQuat.get3() );
154
    }
155

    
156
///////////////////////////////////////////////////////////////////////////////////////////////////
157

    
158
  private void setScreenEffectsStage1()
159
    {
160
    mDynamic3.resetToBeginning();
161
    mScale.notifyWhenFinished(mControl);
162
    }
163

    
164
///////////////////////////////////////////////////////////////////////////////////////////////////
165
// the whole cube rotates so that its axis is alignled according to the Euler angles defined in
166
// computeInitQuat()
167

    
168
  private void setObjectEffectsStage1()
169
    {
170
    TwistyObject obj = mControl.getObject();
171
    obj.apply(mQuaternion,0);
172
    mDynamic4.resetToBeginning();
173
    mQuaternion.notifyWhenFinished(this);
174

    
175

    
176
Static4D d = mDynamic4.getPoint(1);
177

    
178
android.util.Log.e("D", "set: "+d.get0()+" "+d.get1()+" "+d.get2()+" "+d.get3() );
179

    
180
    }
181

    
182
///////////////////////////////////////////////////////////////////////////////////////////////////
183

    
184
  private void setObjectEffectsStage2()
185
    {
186

    
187
    }
188

    
189
///////////////////////////////////////////////////////////////////////////////////////////////////
190

    
191
  private void createScreenEffects()
192
    {
193
    mScreenEffects   = new DistortedEffects[NUM_SCREEN];
194
    mScreenEffects[0]= new DistortedEffects();
195

    
196
    DistortedScreen screen = mControl.getScreen();
197
    int wid = screen.getWidth();
198

    
199
    Static3D scaleStart= new Static3D(1,1,1);
200
    Static3D scaleEnd  = new Static3D(wid,wid,wid);
201

    
202
    mDynamic3 = new Dynamic3D(10000,0.5f);
203
    mDynamic3.add(scaleStart);
204
    mDynamic3.add(scaleEnd  );
205
    mDynamic3.add(scaleStart);
206
    mDynamic3.setMode(Dynamic.MODE_PATH);
207

    
208
    mScale = new MatrixEffectScale(mDynamic3);
209
    mScreenEffectID = mScale.getID();
210
    mScreenEffects[0].apply(mScale);
211
    }
212

    
213
///////////////////////////////////////////////////////////////////////////////////////////////////
214

    
215
  private void createObjectEffects()
216
    {
217
    mObjectEffects   = new DistortedEffects[NUM_OBJECT];
218
    mObjectEffects[0]= new DistortedEffects();
219

    
220
    mDynamic4 = new Dynamic4D(5000,0.5f);
221
    mDynamic4.add(new Static4D(0,0,0,1));
222
    mDynamic4.add(mObjRotQuat);
223
    mDynamic4.add(mObjRotQuat);
224
    mDynamic4.add(mObjRotQuat);
225
    mDynamic4.setMode(Dynamic.MODE_PATH);
226

    
227
android.util.Log.e("D", "create: "+mObjRotQuat.get0()+" "+mObjRotQuat.get1()+" "+mObjRotQuat.get2()+" "+mObjRotQuat.get3() );
228

    
229
TwistyObject obj = mControl.getObject();
230
Static3D ax = obj.getRotationAxis()[0];
231
Static4D axis = new Static4D(ax.get0(), ax.get1(), ax.get2(), 0);
232

    
233
Static4D v1 = QuatHelper.rotateVectorByQuat( new Static4D(1,0,0,0), INIT_QUAT);
234
Static4D v2 = QuatHelper.rotateVectorByQuat( axis                 , mObjRotQuat);
235

    
236
android.util.Log.e("D", "v1: "+v1.get0()+" "+v1.get1()+" "+v1.get2()+" "+v1.get3());
237
android.util.Log.e("D", "v2: "+v2.get0()+" "+v2.get1()+" "+v2.get2()+" "+v2.get3());
238
android.util.Log.e("D", "ax: "+ax.get0()+" "+ax.get1()+" "+ax.get2());
239

    
240

    
241
    Static3D center = new Static3D(0,0,0);
242
    mQuaternion = new MatrixEffectQuaternion(mDynamic4, center);
243
    mCubeEffectID = mQuaternion.getID();
244

    
245
    DistortedScreen screen = mControl.getScreen();
246
    int wid = screen.getWidth();
247
    Static3D scaleFactor = new Static3D(wid,wid*0.1f,10);
248
    MatrixEffectScale scale = new MatrixEffectScale(scaleFactor);
249
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion(INIT_QUAT,center);
250

    
251
    mObjectEffects[0].apply(scale);
252
    mObjectEffects[0].apply(quat);
253
    }
254

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

    
257
  private void createScreenNodes()
258
    {
259
    if( mScreenNodes==null )
260
      {
261
      mScreenNodes= new DistortedNode[NUM_SCREEN];
262
      mScreenQuad = new MeshQuad();
263
      }
264

    
265
    DistortedTexture texture = new DistortedTexture();
266
    texture.setColorARGB(0xff00ff00);
267
    mScreenNodes[0] = new DistortedNode(texture, mScreenEffects[0], mScreenQuad);
268
    }
269

    
270
///////////////////////////////////////////////////////////////////////////////////////////////////
271

    
272
  private void createObjectNodes()
273
    {
274
    if( mObjectNodes==null )
275
      {
276
      mObjectNodes= new DistortedNode[NUM_OBJECT];
277
      mObjectQuad = new MeshQuad();
278
      }
279

    
280
    RubikActivity act = mControl.getActivity();
281

    
282
    if( act!=null )
283
      {
284
      Bitmap bmpArrow = openBitmap(act, R.drawable.ui_axis_arrow);
285
      DistortedTexture textureArrow = new DistortedTexture();
286

    
287
      if( bmpArrow!=null ) textureArrow.setTexture(bmpArrow);
288

    
289
      mObjectNodes[0] = new DistortedNode(textureArrow, mObjectEffects[0], mObjectQuad);
290
      }
291
    else
292
      {
293
      android.util.Log.e("D", "Activity NULL!!");
294
      }
295
    }
296

    
297
///////////////////////////////////////////////////////////////////////////////////////////////////
298

    
299
  long getEffectID()
300
    {
301
    return mObjectEffectID;
302
    }
303

    
304
///////////////////////////////////////////////////////////////////////////////////////////////////
305

    
306
  DistortedNode[] getScreenNodes()
307
    {
308
    if( NUM_SCREEN>0 )
309
      {
310
      if( mScreenEffects==null ) createScreenEffects();
311
      createScreenNodes();
312
      setScreenEffectsStage1();
313
      }
314

    
315
    return mScreenNodes;
316
    }
317

    
318
///////////////////////////////////////////////////////////////////////////////////////////////////
319

    
320
  DistortedNode[] returnScreenNodes()
321
    {
322
    return mScreenNodes;
323
    }
324

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

    
327
   DistortedNode[] getObjectNodes()
328
    {
329
    if( NUM_OBJECT>0 )
330
      {
331
      if( INIT_QUAT==null ) computeInitQuat();
332
      computeRotQuat();
333
      if( mObjectEffects==null ) createObjectEffects();
334
      createObjectNodes();
335
      setObjectEffectsStage1();
336
      }
337

    
338
    return mObjectNodes;
339
    }
340

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

    
343
   DistortedNode[] returnObjectNodes()
344
    {
345
    return mObjectNodes;
346
    }
347

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

    
350
  RubikControlRotate(RubikControl control)
351
    {
352
    mControl = control;
353
    }
354

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

    
357
  @Override
358
  public void effectFinished(long effectID)
359
    {
360
    if( effectID==mCubeEffectID)
361
      {
362
      setObjectEffectsStage2();
363

    
364
      TwistyObject obj = mControl.getObject();
365
      obj.remove(mCubeEffectID);
366
      mObjectEffectID = -1;
367
      mControl.effectFinished(mObjectEffectID);
368
      }
369
    }
370
  }
(2-2/3)