Project

General

Profile

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

magiccube / src / main / java / org / distorted / control / RubikControlRotate.java @ 3f7a4363

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.library.effect.MatrixEffectQuaternion;
26
import org.distorted.library.effect.MatrixEffectScale;
27
import org.distorted.library.main.DistortedEffects;
28
import org.distorted.library.main.DistortedNode;
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.Dynamic;
34
import org.distorted.library.type.Dynamic3D;
35
import org.distorted.library.type.Dynamic4D;
36
import org.distorted.library.type.Static3D;
37
import org.distorted.library.type.Static4D;
38

    
39
import org.distorted.objectlib.main.TwistyObject;
40
import org.distorted.objectlib.main.QuatHelper;
41

    
42
import org.distorted.main.R;
43
import org.distorted.main.RubikActivity;
44

    
45
import java.io.IOException;
46
import java.io.InputStream;
47

    
48
///////////////////////////////////////////////////////////////////////////////////////////////////
49

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

    
55
  private static Static4D INIT_QUAT;
56

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

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

    
69
///////////////////////////////////////////////////////////////////////////////////////////////////
70

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

    
82
     return null;
83
     }
84

    
85
///////////////////////////////////////////////////////////////////////////////////////////////////
86

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

    
92
    alphaY /= 2;
93
    alphaZ /= 2;
94

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

    
100
    Static4D qZ = new Static4D(0,0,sinZ,cosZ);
101
    Static4D qY = new Static4D(0,sinY,0,cosY);
102

    
103
    INIT_QUAT = QuatHelper.quatMultiply(qY,qZ);
104
    }
105

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

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

    
118
///////////////////////////////////////////////////////////////////////////////////////////////////
119

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

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

    
132
    float axX = rotAxisX.get0();
133
    float axY = rotAxisX.get1();
134
    float axZ = rotAxisX.get2();
135

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

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

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

    
152
    android.util.Log.e("D", "axis chosen: "+chosen);
153

    
154

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

    
158
///////////////////////////////////////////////////////////////////////////////////////////////////
159

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

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

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

    
177

    
178
Static4D d = mDynamic4.getPoint(1);
179

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

    
182
    }
183

    
184
///////////////////////////////////////////////////////////////////////////////////////////////////
185

    
186
  private void setObjectEffectsStage2()
187
    {
188

    
189
    }
190

    
191
///////////////////////////////////////////////////////////////////////////////////////////////////
192

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

    
198
    DistortedScreen screen = mControl.getScreen();
199
    int wid = screen.getWidth();
200

    
201
    Static3D scaleStart= new Static3D(1,1,1);
202
    Static3D scaleEnd  = new Static3D(wid,wid,wid);
203

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

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

    
215
///////////////////////////////////////////////////////////////////////////////////////////////////
216

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

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

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

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

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

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

    
242

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

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

    
253
    mObjectEffects[0].apply(scale);
254
    mObjectEffects[0].apply(quat);
255
    }
256

    
257
///////////////////////////////////////////////////////////////////////////////////////////////////
258

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

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

    
272
///////////////////////////////////////////////////////////////////////////////////////////////////
273

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

    
282
    RubikActivity act = mControl.getActivity();
283

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

    
289
      if( bmpArrow!=null ) textureArrow.setTexture(bmpArrow);
290

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

    
299
///////////////////////////////////////////////////////////////////////////////////////////////////
300

    
301
  long getEffectID()
302
    {
303
    return mObjectEffectID;
304
    }
305

    
306
///////////////////////////////////////////////////////////////////////////////////////////////////
307

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

    
317
    return mScreenNodes;
318
    }
319

    
320
///////////////////////////////////////////////////////////////////////////////////////////////////
321

    
322
  DistortedNode[] returnScreenNodes()
323
    {
324
    return mScreenNodes;
325
    }
326

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

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

    
340
    return mObjectNodes;
341
    }
342

    
343
///////////////////////////////////////////////////////////////////////////////////////////////////
344

    
345
   DistortedNode[] returnObjectNodes()
346
    {
347
    return mObjectNodes;
348
    }
349

    
350
///////////////////////////////////////////////////////////////////////////////////////////////////
351

    
352
  RubikControlRotate(RubikControl control)
353
    {
354
    mControl = control;
355
    }
356

    
357
///////////////////////////////////////////////////////////////////////////////////////////////////
358

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

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