Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyHelicopter.java @ 9c2f0c91

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 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.objects;
21

    
22
import android.content.res.Resources;
23
import android.graphics.Canvas;
24
import android.graphics.Paint;
25

    
26
import org.distorted.library.effect.MatrixEffectQuaternion;
27
import org.distorted.library.effect.VertexEffectDeform;
28
import org.distorted.library.effect.VertexEffectMove;
29
import org.distorted.library.effect.VertexEffectRotate;
30
import org.distorted.library.effect.VertexEffectScale;
31
import org.distorted.library.main.DistortedEffects;
32
import org.distorted.library.main.DistortedTexture;
33
import org.distorted.library.mesh.MeshBase;
34
import org.distorted.library.mesh.MeshJoined;
35
import org.distorted.library.mesh.MeshPolygon;
36
import org.distorted.library.mesh.MeshSquare;
37
import org.distorted.library.mesh.MeshTriangle;
38
import org.distorted.library.type.Static1D;
39
import org.distorted.library.type.Static3D;
40
import org.distorted.library.type.Static4D;
41
import org.distorted.main.RubikSurfaceView;
42

    
43
import java.util.Random;
44

    
45
import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
46

    
47
///////////////////////////////////////////////////////////////////////////////////////////////////
48

    
49
public class TwistyHelicopter extends TwistyObject
50
{
51
  private static final float SQ2 = (float)Math.sqrt(2);
52
  private static final float SQ3 = (float)Math.sqrt(3);
53

    
54
  private static final int FACES_PER_CUBIT =6;
55

    
56
  // the six rotation axis of a Helicopter. Must be normalized.
57
  static final Static3D[] ROT_AXIS = new Static3D[]
58
         {
59
           new Static3D(     0, +SQ2/2, -SQ2/2),
60
           new Static3D(     0, -SQ2/2, -SQ2/2),
61
           new Static3D(+SQ2/2,      0, -SQ2/2),
62
           new Static3D(-SQ2/2,      0, -SQ2/2),
63
           new Static3D(+SQ2/2, -SQ2/2,      0),
64
           new Static3D(-SQ2/2, -SQ2/2,      0)
65
         };
66

    
67
  // the six axis that determine the faces
68
  static final Static3D[] FACE_AXIS = new Static3D[]
69
         {
70
           new Static3D(1,0,0), new Static3D(-1,0,0),
71
           new Static3D(0,1,0), new Static3D(0,-1,0),
72
           new Static3D(0,0,1), new Static3D(0,0,-1)
73
         };
74

    
75
  private static final int[] FACE_COLORS = new int[]
76
         {
77
           COLOR_YELLOW, COLOR_WHITE,
78
           COLOR_BLUE  , COLOR_GREEN,
79
           COLOR_RED   , COLOR_BROWN
80
         };
81

    
82
  // All legal rotation quats of a HELICOPTER (same as the Cube!)
83
  private static final Static4D[] QUATS = new Static4D[]
84
         {
85
           new Static4D( 0.00f,  0.00f,  0.00f,  1.00f ),
86
           new Static4D( 1.00f,  0.00f,  0.00f,  0.00f ),
87
           new Static4D( 0.00f,  1.00f,  0.00f,  0.00f ),
88
           new Static4D( 0.00f,  0.00f,  1.00f,  0.00f ),
89

    
90
           new Static4D( SQ2/2,  SQ2/2,  0.00f,  0.00f ),
91
           new Static4D( SQ2/2, -SQ2/2,  0.00f,  0.00f ),
92
           new Static4D( SQ2/2,  0.00f,  SQ2/2,  0.00f ),
93
           new Static4D( SQ2/2,  0.00f, -SQ2/2,  0.00f ),
94
           new Static4D( SQ2/2,  0.00f,  0.00f,  SQ2/2 ),
95
           new Static4D( SQ2/2,  0.00f,  0.00f, -SQ2/2 ),
96
           new Static4D( 0.00f,  SQ2/2,  SQ2/2,  0.00f ),
97
           new Static4D( 0.00f,  SQ2/2, -SQ2/2,  0.00f ),
98
           new Static4D( 0.00f,  SQ2/2,  0.00f,  SQ2/2 ),
99
           new Static4D( 0.00f,  SQ2/2,  0.00f, -SQ2/2 ),
100
           new Static4D( 0.00f,  0.00f,  SQ2/2,  SQ2/2 ),
101
           new Static4D( 0.00f,  0.00f,  SQ2/2, -SQ2/2 ),
102

    
103
           new Static4D( 0.50f,  0.50f,  0.50f,  0.50f ),
104
           new Static4D( 0.50f,  0.50f,  0.50f, -0.50f ),
105
           new Static4D( 0.50f,  0.50f, -0.50f,  0.50f ),
106
           new Static4D( 0.50f,  0.50f, -0.50f, -0.50f ),
107
           new Static4D( 0.50f, -0.50f,  0.50f,  0.50f ),
108
           new Static4D( 0.50f, -0.50f,  0.50f, -0.50f ),
109
           new Static4D( 0.50f, -0.50f, -0.50f,  0.50f ),
110
           new Static4D( 0.50f, -0.50f, -0.50f, -0.50f )
111
         };
112

    
113
  private static final float DIST_CORNER = 0.50f;
114
  private static final float DIST_CENTER = 0.50f;
115
  private static final float XY_CENTER   = DIST_CORNER/3;
116

    
117
  // centers of the 8 corners + 6*4 face triangles ( i.e. of the all 32 cubits)
118
  private static final Static3D[] CENTERS = new Static3D[]
119
         {
120
           new Static3D(   DIST_CORNER,   DIST_CORNER,   DIST_CORNER ),
121
           new Static3D(   DIST_CORNER,   DIST_CORNER,  -DIST_CORNER ),
122
           new Static3D(   DIST_CORNER,  -DIST_CORNER,   DIST_CORNER ),
123
           new Static3D(   DIST_CORNER,  -DIST_CORNER,  -DIST_CORNER ),
124
           new Static3D(  -DIST_CORNER,   DIST_CORNER,   DIST_CORNER ),
125
           new Static3D(  -DIST_CORNER,   DIST_CORNER,  -DIST_CORNER ),
126
           new Static3D(  -DIST_CORNER,  -DIST_CORNER,   DIST_CORNER ),
127
           new Static3D(  -DIST_CORNER,  -DIST_CORNER,  -DIST_CORNER ),
128

    
129
           new Static3D(   DIST_CENTER,     XY_CENTER,     XY_CENTER ),
130
           new Static3D(   DIST_CENTER,     XY_CENTER,    -XY_CENTER ),
131
           new Static3D(   DIST_CENTER,    -XY_CENTER,     XY_CENTER ),
132
           new Static3D(   DIST_CENTER,    -XY_CENTER,    -XY_CENTER ),
133

    
134
           new Static3D(  -DIST_CENTER,     XY_CENTER,     XY_CENTER ),
135
           new Static3D(  -DIST_CENTER,     XY_CENTER,    -XY_CENTER ),
136
           new Static3D(  -DIST_CENTER,    -XY_CENTER,     XY_CENTER ),
137
           new Static3D(  -DIST_CENTER,    -XY_CENTER,    -XY_CENTER ),
138

    
139
           new Static3D(   XY_CENTER  ,   DIST_CENTER,     XY_CENTER ),
140
           new Static3D(   XY_CENTER  ,   DIST_CENTER,    -XY_CENTER ),
141
           new Static3D(  -XY_CENTER  ,   DIST_CENTER,     XY_CENTER ),
142
           new Static3D(  -XY_CENTER  ,   DIST_CENTER,    -XY_CENTER ),
143

    
144
           new Static3D(   XY_CENTER  ,  -DIST_CENTER,     XY_CENTER ),
145
           new Static3D(   XY_CENTER  ,  -DIST_CENTER,    -XY_CENTER ),
146
           new Static3D(  -XY_CENTER  ,  -DIST_CENTER,     XY_CENTER ),
147
           new Static3D(  -XY_CENTER  ,  -DIST_CENTER,    -XY_CENTER ),
148

    
149
           new Static3D(   XY_CENTER  ,     XY_CENTER,   DIST_CENTER ),
150
           new Static3D(   XY_CENTER  ,    -XY_CENTER,   DIST_CENTER ),
151
           new Static3D(  -XY_CENTER  ,     XY_CENTER,   DIST_CENTER ),
152
           new Static3D(  -XY_CENTER  ,    -XY_CENTER,   DIST_CENTER ),
153

    
154
           new Static3D(   XY_CENTER  ,     XY_CENTER,  -DIST_CENTER ),
155
           new Static3D(   XY_CENTER  ,    -XY_CENTER,  -DIST_CENTER ),
156
           new Static3D(  -XY_CENTER  ,     XY_CENTER,  -DIST_CENTER ),
157
           new Static3D(  -XY_CENTER  ,    -XY_CENTER,  -DIST_CENTER ),
158
         };
159

    
160
  // Colors of the faces of cubits. Each cubit has 6 faces
161
  private static final int[][] mFaceMap = new int[][]
162
         {
163
           { 4,2,0, 6,6,6 },
164
           { 0,2,5, 6,6,6 },
165
           { 4,0,3, 6,6,6 },
166
           { 5,3,0, 6,6,6 },
167
           { 1,2,4, 6,6,6 },
168
           { 5,2,1, 6,6,6 },
169
           { 4,3,1, 6,6,6 },
170
           { 1,3,5, 6,6,6 },
171

    
172
           { 0 , 6,6,6,6,6 },
173
           { 0 , 6,6,6,6,6 },
174
           { 0 , 6,6,6,6,6 },
175
           { 0 , 6,6,6,6,6 },
176

    
177
           { 1 , 6,6,6,6,6 },
178
           { 1 , 6,6,6,6,6 },
179
           { 1 , 6,6,6,6,6 },
180
           { 1 , 6,6,6,6,6 },
181

    
182
           { 2 , 6,6,6,6,6 },
183
           { 2 , 6,6,6,6,6 },
184
           { 2 , 6,6,6,6,6 },
185
           { 2 , 6,6,6,6,6 },
186

    
187
           { 3 , 6,6,6,6,6 },
188
           { 3 , 6,6,6,6,6 },
189
           { 3 , 6,6,6,6,6 },
190
           { 3 , 6,6,6,6,6 },
191

    
192
           { 4 , 6,6,6,6,6 },
193
           { 4 , 6,6,6,6,6 },
194
           { 4 , 6,6,6,6,6 },
195
           { 4 , 6,6,6,6,6 },
196

    
197
           { 5 , 6,6,6,6,6 },
198
           { 5 , 6,6,6,6,6 },
199
           { 5 , 6,6,6,6,6 },
200
           { 5 , 6,6,6,6,6 },
201
         };
202

    
203
  private static int[] QUAT_INDICES =
204
      { 0,13,14,1,12,2,3,7,20,6,13,17,7,23,18,12,22,10,8,16,11,21,19,9,3,15,14,0,5,2,1,4 };
205

    
206
  private static MeshBase mCornerMesh, mFaceMesh;
207

    
208
///////////////////////////////////////////////////////////////////////////////////////////////////
209

    
210
  TwistyHelicopter(int size, Static4D quat, DistortedTexture texture,
211
                   MeshSquare mesh, DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
212
    {
213
    super(size, 60, quat, texture, mesh, effects, moves, ObjectList.HELI, res, scrWidth);
214
    }
215

    
216
///////////////////////////////////////////////////////////////////////////////////////////////////
217

    
218
  private void createCornerMesh()
219
    {
220
    float D = 0.02f;
221
    float E = 0.5f;
222
    float F = SQ2/4;
223

    
224
    float[] vertices0 = { -E+E/4,E/4, E/4,-E+E/4, E/4,E/4};
225

    
226
    float[] bands0 = { 1.0f    , 0,
227
                       1.0f-2*D, D*0.25f,
228
                       1.0f-4*D, D*0.35f,
229
                       1.0f-8*D, D*0.6f,
230
                       0.60f   , D*1.0f,
231
                       0.30f   , D*1.375f,
232
                       0.0f    , D*1.4f };
233

    
234
    MeshBase[] meshes = new MeshBase[6];
235

    
236
    meshes[0] = new MeshPolygon(vertices0, bands0, 3, 3);
237
    meshes[0].setEffectAssociation(0,1,0);
238
    meshes[1] = meshes[0].copy(true);
239
    meshes[1].setEffectAssociation(0,2,0);
240
    meshes[2] = meshes[0].copy(true);
241
    meshes[2].setEffectAssociation(0,4,0);
242

    
243
    float[] vertices1 = { -F,-1.0f/12, +F,-1.0f/12, 0,1.0f/6 };
244
    float[] bands1 = { 1.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f };
245

    
246
    meshes[3] = new MeshPolygon(vertices1,bands1,1,5);
247
    meshes[3].setEffectAssociation(0,8,0);
248
    meshes[4] = meshes[3].copy(true);
249
    meshes[4].setEffectAssociation(0,16,0);
250
    meshes[5] = meshes[3].copy(true);
251
    meshes[5].setEffectAssociation(0,32,0);
252

    
253
    mCornerMesh = new MeshJoined(meshes);
254

    
255
    Static3D axisX  = new Static3D(1,0,0);
256
    Static3D axisY  = new Static3D(0,1,0);
257
    Static3D axis0  = new Static3D(-SQ2/2,0,SQ2/2);
258
    Static3D axis1  = new Static3D(+SQ3/3,+SQ3/3,+SQ3/3);
259
    Static1D angle1 = new Static1D(+90);
260
    Static1D angle2 = new Static1D(-90);
261
    Static1D angle3 = new Static1D(-135);
262
    Static1D angle4 = new Static1D(90);
263
    Static1D angle5 = new Static1D(120);
264
    Static1D angle6 = new Static1D(240);
265
    Static3D center1= new Static3D(0,0,0);
266
    Static3D center2= new Static3D(-0.25f,-0.25f,-0.25f);
267
    Static3D move1  = new Static3D(-E/4,-E/4,0);
268
    Static3D move2  = new Static3D(-0.25f,(-1.0f/6)-0.25f,-0.25f);
269

    
270
    float d0 =-0.04f;
271
    float d1 = 0.04f;
272
    float r0 = 0.15f;
273
    float r1 = 0.10f;
274

    
275
    Static3D vec0   = new Static3D(d0*(+SQ3/3),d0*(+SQ3/3),d0*(+SQ3/3));
276
    Static3D vec1   = new Static3D(d1*(+SQ3/3),d1*(-SQ3/3),d1*(-SQ3/3));
277
    Static3D vec2   = new Static3D(d1*(-SQ3/3),d1*(+SQ3/3),d1*(-SQ3/3));
278
    Static3D vec3   = new Static3D(d1*(-SQ3/3),d1*(-SQ3/3),d1*(+SQ3/3));
279

    
280
    Static1D radius = new Static1D(0.5f);
281

    
282
    Static3D cent0  = new Static3D( 0.0f, 0.0f, 0.0f);
283
    Static3D cent1  = new Static3D(-0.5f, 0.0f, 0.0f);
284
    Static3D cent2  = new Static3D( 0.0f,-0.5f, 0.0f);
285
    Static3D cent3  = new Static3D( 0.0f, 0.0f,-0.5f);
286

    
287
    Static4D reg0   = new Static4D(0,0,0,r0);
288
    Static4D reg1   = new Static4D(0,0,0,r1);
289

    
290
    VertexEffectMove   effect0 = new VertexEffectMove(move1);
291
    VertexEffectScale  effect1 = new VertexEffectScale(new Static3D(1,1,-1));
292
    VertexEffectRotate effect2 = new VertexEffectRotate(angle1,axisX,center1);
293
    VertexEffectRotate effect3 = new VertexEffectRotate(angle2,axisY,center1);
294
    VertexEffectMove   effect4 = new VertexEffectMove(move2);
295
    VertexEffectRotate effect5 = new VertexEffectRotate(angle1,axisX,center2);
296
    VertexEffectRotate effect6 = new VertexEffectRotate(angle3,axisY,center2);
297
    VertexEffectRotate effect7 = new VertexEffectRotate(angle4,axis0,center2);
298
    VertexEffectRotate effect8 = new VertexEffectRotate(angle5,axis1,center2);
299
    VertexEffectRotate effect9 = new VertexEffectRotate(angle6,axis1,center2);
300

    
301
    VertexEffectDeform effect10= new VertexEffectDeform(vec0,radius,cent0,reg0);
302
    VertexEffectDeform effect11= new VertexEffectDeform(vec1,radius,cent1,reg1);
303
    VertexEffectDeform effect12= new VertexEffectDeform(vec2,radius,cent2,reg1);
304
    VertexEffectDeform effect13= new VertexEffectDeform(vec3,radius,cent3,reg1);
305

    
306
    effect0.setMeshAssociation( 7,-1);  // meshes 0,1,2
307
    effect1.setMeshAssociation( 6,-1);  // meshes 1,2
308
    effect2.setMeshAssociation( 2,-1);  // mesh 1
309
    effect3.setMeshAssociation( 4,-1);  // mesh 2
310
    effect4.setMeshAssociation(56,-1);  // meshes 3,4,5
311
    effect5.setMeshAssociation(56,-1);  // meshes 3,4,5
312
    effect6.setMeshAssociation(56,-1);  // meshes 3,4,5
313
    effect7.setMeshAssociation(56,-1);  // meshes 3,4,5
314
    effect8.setMeshAssociation(16,-1);  // mesh 4
315
    effect9.setMeshAssociation(32,-1);  // mesh 5
316

    
317
    effect10.setMeshAssociation(63,-1); // all meshes
318
    effect11.setMeshAssociation(63,-1); // all meshes
319
    effect12.setMeshAssociation(63,-1); // all meshes
320
    effect13.setMeshAssociation(63,-1); // all meshes
321

    
322
    mCornerMesh.apply(effect0);
323
    mCornerMesh.apply(effect1);
324
    mCornerMesh.apply(effect2);
325
    mCornerMesh.apply(effect3);
326
    mCornerMesh.apply(effect4);
327
    mCornerMesh.apply(effect5);
328
    mCornerMesh.apply(effect6);
329
    mCornerMesh.apply(effect7);
330
    mCornerMesh.apply(effect8);
331
    mCornerMesh.apply(effect9);
332

    
333
    mCornerMesh.apply(effect10);
334
    mCornerMesh.apply(effect11);
335
    mCornerMesh.apply(effect12);
336
    mCornerMesh.apply(effect13);
337

    
338
    mCornerMesh.mergeEffComponents();
339
    }
340

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

    
343
  private void createFaceMesh()
344
    {
345
    MeshBase[] meshes = new MeshBase[6];
346

    
347
    float D = 0.02f;
348
    float E = 0.5f;
349
    float F = SQ2/4;
350
    float G = 1.0f/12;
351

    
352
    float[] vertices0 = { -E+E/4,E/4, E/4,-E+E/4, E/4,E/4};
353

    
354
    float[] bands0 = { 1.0f    , 0,
355
                       1.0f-2*D, D*0.25f,
356
                       1.0f-4*D, D*0.35f,
357
                       1.0f-8*D, D*0.6f,
358
                       0.60f   , D*1.0f,
359
                       0.30f   , D*1.375f,
360
                       0.0f    , D*1.4f };
361

    
362
    meshes[0] = new MeshPolygon(vertices0, bands0, 3, 3);
363
    meshes[0].setEffectAssociation(0,1,0);
364

    
365
    float[] vertices1 = { -F,-G, +F,-G, 0,2*G};
366

    
367
    float[] bands1 = { 1.0f   , 0.0f,
368
                       0.5f   , 0.01f,
369
                       0.0f   , 0.01f };
370

    
371
    meshes[1] = new MeshPolygon(vertices1, bands1, 1, 3);
372
    meshes[1].setEffectAssociation(0,2,0);
373

    
374
    float[] vertices2 = { -E/2,-F/3, +E/2,-F/3, 0,2*F/3};
375

    
376
    float[] bands2 = { 1.0f   , 0.0f,
377
                       0.5f   , 0.01f,
378
                       0.0f   , 0.01f };
379

    
380
    meshes[2] = new MeshPolygon(vertices2, bands2, 1, 3);
381
    meshes[2].setEffectAssociation(0,4,0);
382
    meshes[3] = meshes[2].copy(true);
383
    meshes[3].setEffectAssociation(0,8,0);
384
    meshes[4] = new MeshTriangle(1);
385
    meshes[4].setEffectAssociation(0,16,0);
386
    meshes[5] = new MeshTriangle(1);
387
    meshes[5].setEffectAssociation(0,32,0);
388

    
389
    mFaceMesh = new MeshJoined(meshes);
390

    
391
    Static3D move0  = new Static3D(-1.0f/8, -1.0f/8, 0);
392
    Static3D move1  = new Static3D(-(SQ2/24)-1.0f/4, -(SQ2/24)-1.0f/4, 0);
393
    Static3D move2  = new Static3D(-E/2, F/3, 0);
394
    Static3D move3  = new Static3D(+E/2, F/3, 0);
395
    Static3D move4  = new Static3D(+E/3,+E/3, 0);
396
    Static1D angle1 = new Static1D(135);
397
    Static1D angle2 = new Static1D(90);
398
    Static1D angle3 = new Static1D(-90);
399
    Static1D angle4 = new Static1D(-135);
400
    Static3D axisX  = new Static3D(1,0,0);
401
    Static3D axisY  = new Static3D(0,1,0);
402
    Static3D axisZ  = new Static3D(0,0,1);
403
    Static3D axis1  = new Static3D(1,-1,0);
404
    Static3D center = new Static3D(0,0,0);
405
    Static3D center1= new Static3D(-0.25f,-0.25f,0);
406

    
407
    float d0 =-0.03f;
408
    float d1 =-0.04f;
409
    float r0 = 0.15f;
410
    float r1 = 0.10f;
411

    
412
    Static3D vec0   = new Static3D(d0*(+SQ3/3),d0*(+SQ3/3),d0*(+SQ3/3));
413
    Static3D vec1   = new Static3D(d1*(-SQ3/3),d1*(+SQ3/3),d1*(+SQ3/3));
414
    Static3D vec2   = new Static3D(d1*(+SQ3/3),d1*(-SQ3/3),d1*(+SQ3/3));
415

    
416
    Static1D radius = new Static1D(0.5f);
417

    
418
    Static3D cent0  = new Static3D( 0.0f, 0.0f, 0.0f);
419
    Static3D cent1  = new Static3D(-0.5f, 0.0f, 0.0f);
420
    Static3D cent2  = new Static3D( 0.0f,-0.5f, 0.0f);
421

    
422
    Static4D reg0   = new Static4D(0,0,0,r0);
423
    Static4D reg1   = new Static4D(0,0,0,r1);
424

    
425
    VertexEffectMove   effect0 = new VertexEffectMove(move0);
426
    VertexEffectRotate effect1 = new VertexEffectRotate(angle1, axisZ, center);
427
    VertexEffectMove   effect2 = new VertexEffectMove(move1);
428
    VertexEffectRotate effect3 = new VertexEffectRotate(angle2, axis1, center1);
429
    VertexEffectMove   effect4 = new VertexEffectMove(move2);
430
    VertexEffectMove   effect5 = new VertexEffectMove(move3);
431
    VertexEffectRotate effect6 = new VertexEffectRotate(angle3, axisZ, center);
432
    VertexEffectRotate effect7 = new VertexEffectRotate(angle4, axisX, center);
433
    VertexEffectRotate effect8 = new VertexEffectRotate(angle1, axisY, center);
434
    VertexEffectScale  effect9 = new VertexEffectScale(0);
435
    VertexEffectDeform effect10= new VertexEffectDeform(vec0,radius,cent0,reg0);
436
    VertexEffectDeform effect11= new VertexEffectDeform(vec1,radius,cent1,reg1);
437
    VertexEffectDeform effect12= new VertexEffectDeform(vec2,radius,cent2,reg1);
438
    VertexEffectMove   effect13= new VertexEffectMove(move4);
439

    
440
    effect0.setMeshAssociation( 1,-1);  // mesh 0
441
    effect1.setMeshAssociation( 2,-1);  // mesh 1
442
    effect2.setMeshAssociation( 2,-1);  // mesh 1
443
    effect3.setMeshAssociation( 2,-1);  // mesh 1
444
    effect4.setMeshAssociation( 4,-1);  // mesh 2
445
    effect5.setMeshAssociation( 8,-1);  // mesh 3
446
    effect6.setMeshAssociation( 8,-1);  // mesh 3
447
    effect7.setMeshAssociation( 4,-1);  // mesh 2
448
    effect8.setMeshAssociation( 8,-1);  // mesh 3
449
    effect9.setMeshAssociation(48,-1);  // meshes 4,5
450
    effect10.setMeshAssociation(15,-1); // meshes 0,1,2,3
451
    effect11.setMeshAssociation(15,-1); // meshes 0,1,2,3
452
    effect12.setMeshAssociation(15,-1); // meshes 0,1,2,3
453
    effect13.setMeshAssociation(15,-1); // meshes 0,1,2,3
454

    
455
    mFaceMesh.apply(effect0);
456
    mFaceMesh.apply(effect1);
457
    mFaceMesh.apply(effect2);
458
    mFaceMesh.apply(effect3);
459
    mFaceMesh.apply(effect4);
460
    mFaceMesh.apply(effect5);
461
    mFaceMesh.apply(effect6);
462
    mFaceMesh.apply(effect7);
463
    mFaceMesh.apply(effect8);
464
    mFaceMesh.apply(effect9);
465
    mFaceMesh.apply(effect10);
466
    mFaceMesh.apply(effect11);
467
    mFaceMesh.apply(effect12);
468
    mFaceMesh.apply(effect13);
469

    
470
    mFaceMesh.mergeEffComponents();
471
    }
472

    
473
///////////////////////////////////////////////////////////////////////////////////////////////////
474

    
475
  float getScreenRatio()
476
    {
477
    return 1.5f;
478
    }
479

    
480
///////////////////////////////////////////////////////////////////////////////////////////////////
481

    
482
  Static4D[] getQuats()
483
    {
484
    return QUATS;
485
    }
486

    
487
///////////////////////////////////////////////////////////////////////////////////////////////////
488

    
489
  boolean shouldResetTextureMaps()
490
    {
491
    return false;
492
    }
493

    
494
///////////////////////////////////////////////////////////////////////////////////////////////////
495

    
496
  int getNumFaces()
497
    {
498
    return FACE_COLORS.length;
499
    }
500

    
501
///////////////////////////////////////////////////////////////////////////////////////////////////
502

    
503
  int getNumStickerTypes()
504
    {
505
    return 1;
506
    }
507

    
508
///////////////////////////////////////////////////////////////////////////////////////////////////
509

    
510
  float getBasicStep()
511
    {
512
    return SQ2/2;
513
    }
514

    
515
///////////////////////////////////////////////////////////////////////////////////////////////////
516

    
517
  int getNumCubitFaces()
518
    {
519
    return FACES_PER_CUBIT;
520
    }
521

    
522
///////////////////////////////////////////////////////////////////////////////////////////////////
523

    
524
  Static3D[] getCubitPositions(int size)
525
    {
526
    return CENTERS;
527
    }
528

    
529
///////////////////////////////////////////////////////////////////////////////////////////////////
530

    
531
  MeshBase createCubitMesh(int cubit)
532
    {
533
    MeshBase mesh;
534

    
535
    if( cubit<8 )
536
      {
537
      if( mCornerMesh==null ) createCornerMesh();
538
      mesh = mCornerMesh.copy(true);
539
      }
540
    else
541
      {
542
      if( mFaceMesh==null ) createFaceMesh();
543
      mesh = mFaceMesh.copy(true);
544
      }
545

    
546
    int index = QUAT_INDICES[cubit];
547
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( QUATS[index], new Static3D(0,0,0) );
548
    mesh.apply(quat,0xffffffff,0);
549

    
550
    return mesh;
551
    }
552

    
553
///////////////////////////////////////////////////////////////////////////////////////////////////
554

    
555
  int getFaceColor(int cubit, int cubitface, int size)
556
    {
557
    return mFaceMap[cubit][cubitface];
558
    }
559

    
560
///////////////////////////////////////////////////////////////////////////////////////////////////
561

    
562
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top, int side)
563
    {
564
    float STROKE = 0.035f*side;
565
    float L= left+0.125f*side;
566
    float H= 0.375f*side;
567
    float LEN = 0.5f*side;
568

    
569
    paint.setAntiAlias(true);
570
    paint.setStrokeWidth(STROKE);
571
    paint.setColor(FACE_COLORS[face]);
572
    paint.setStyle(Paint.Style.FILL);
573

    
574
    canvas.drawRect(left,top,left+side,top+side,paint);
575

    
576
    paint.setColor(INTERIOR_COLOR);
577
    paint.setStyle(Paint.Style.STROKE);
578

    
579
    canvas.drawLine( L    , H,  L+LEN, H    , paint);
580
    canvas.drawLine( L    , H,  L+LEN, H+LEN, paint);
581
    canvas.drawLine( L+LEN, H,  L+LEN, H+LEN, paint);
582

    
583
    float S1 = 0.125f*side;
584
    float S2 = 0.070f*side;
585
    float X  = 0.7f*S2;
586

    
587
    float LA = left+0.625f*side;
588
    float RA = left+0.125f*side;
589
    float TA = 0.375f*side;
590
    float BA = 0.875f*side;
591

    
592
    canvas.drawArc( LA-S1, TA     , LA     , TA+S1, 270, 90, false, paint);
593
    canvas.drawArc( RA+X , TA     , RA+X+S2, TA+S2, 135,135, false, paint);
594
    canvas.drawArc( LA-S2, BA-X-S2, LA     , BA-X ,   0,135, false, paint);
595
    }
596

    
597
///////////////////////////////////////////////////////////////////////////////////////////////////
598

    
599
  float returnMultiplier()
600
    {
601
    return 2.0f;
602
    }
603

    
604
///////////////////////////////////////////////////////////////////////////////////////////////////
605

    
606
  float[] getRowChances()
607
    {
608
    float[] chances = new float[3];
609

    
610
    chances[0] = 0.5f;
611
    chances[1] = 0.5f;
612
    chances[2] = 1.0f;
613

    
614
    return chances;
615
    }
616

    
617
///////////////////////////////////////////////////////////////////////////////////////////////////
618
// PUBLIC API
619

    
620
  public Static3D[] getRotationAxis()
621
    {
622
    return ROT_AXIS;
623
    }
624

    
625
///////////////////////////////////////////////////////////////////////////////////////////////////
626

    
627
  public int getBasicAngle()
628
    {
629
    return 2;
630
    }
631

    
632
///////////////////////////////////////////////////////////////////////////////////////////////////
633

    
634
  public int computeRowFromOffset(float offset)
635
    {
636
    return offset<0.166f ? 0:2;
637
    }
638

    
639
///////////////////////////////////////////////////////////////////////////////////////////////////
640

    
641
  public float returnRotationFactor(float offset)
642
    {
643
    return 1.0f;
644
    }
645

    
646
///////////////////////////////////////////////////////////////////////////////////////////////////
647

    
648
  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
649
    {
650
    int numAxis = ROTATION_AXIS.length;
651

    
652
    if( oldRotAxis == START_AXIS )
653
      {
654
      return rnd.nextInt(numAxis);
655
      }
656
    else
657
      {
658
      int newVector = rnd.nextInt(numAxis-2);
659

    
660
      switch(oldRotAxis)
661
        {
662
        case  0:
663
        case  1: return newVector+2;
664
        case  2:
665
        case  3: return (newVector==0 || newVector==1) ? newVector:newVector+2;
666
        default: return newVector;
667
        }
668
      }
669
    }
670

    
671
///////////////////////////////////////////////////////////////////////////////////////////////////
672

    
673
  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
674
    {
675
    float rowFloat = rnd.nextFloat();
676

    
677
    for(int row=0; row<mRowChances.length; row++)
678
      {
679
      if( rowFloat<=mRowChances[row] ) return row;
680
      }
681

    
682
    return 0;
683
    }
684

    
685
///////////////////////////////////////////////////////////////////////////////////////////////////
686
// remember about the double cover or unit quaternions!
687

    
688
  private int mulQuat(int q1, int q2)
689
    {
690
    Static4D result = RubikSurfaceView.quatMultiply(QUATS[q1],QUATS[q2]);
691

    
692
    float rX = result.get0();
693
    float rY = result.get1();
694
    float rZ = result.get2();
695
    float rW = result.get3();
696

    
697
    final float MAX_ERROR = 0.1f;
698
    float dX,dY,dZ,dW;
699

    
700
    for(int i=0; i<QUATS.length; i++)
701
      {
702
      dX = QUATS[i].get0() - rX;
703
      dY = QUATS[i].get1() - rY;
704
      dZ = QUATS[i].get2() - rZ;
705
      dW = QUATS[i].get3() - rW;
706

    
707
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
708
          dY<MAX_ERROR && dY>-MAX_ERROR &&
709
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
710
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
711

    
712
      dX = QUATS[i].get0() + rX;
713
      dY = QUATS[i].get1() + rY;
714
      dZ = QUATS[i].get2() + rZ;
715
      dW = QUATS[i].get3() + rW;
716

    
717
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
718
          dY<MAX_ERROR && dY>-MAX_ERROR &&
719
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
720
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
721
      }
722

    
723
    return -1;
724
    }
725

    
726
///////////////////////////////////////////////////////////////////////////////////////////////////
727
// The Helicopter is solved if and only if:
728
//
729
// 1) all of its corner cubits are rotated with the same quat
730
// 2) all its face cubits are rotated with the same quat like the corner ones,
731
//    and optionally they also might be turned by a multiple of 90 degrees along
732
//    a vector perpendicular to the face they lie on.
733
//
734
// i.e.
735
// cubits  8, 9,10,11,12,13,14,15 - might be extra QUAT 1,8,9
736
// cubits 16,17,18,19,20,21,22,23 - might be extra QUAT 2,12,13
737
// cubits 24,25,26,27,28,29,30,31 - might be extra QUAT 3,14,15
738

    
739
  public boolean isSolved()
740
    {
741
    int q = CUBITS[0].mQuatIndex;
742

    
743
    if ( CUBITS[1].mQuatIndex == q &&
744
         CUBITS[2].mQuatIndex == q &&
745
         CUBITS[3].mQuatIndex == q &&
746
         CUBITS[4].mQuatIndex == q &&
747
         CUBITS[5].mQuatIndex == q &&
748
         CUBITS[6].mQuatIndex == q &&
749
         CUBITS[7].mQuatIndex == q  )
750
      {
751
      int q1 = mulQuat(q,1);
752
      int q2 = mulQuat(q,8);
753
      int q3 = mulQuat(q,9);
754

    
755
      for(int index=8; index<16; index++)
756
        {
757
        int qIndex = CUBITS[index].mQuatIndex;
758
        if( qIndex!=q && qIndex!=q1 && qIndex!=q2 && qIndex!=q3 ) return false;
759
        }
760

    
761
      q1 = mulQuat(q, 2);
762
      q2 = mulQuat(q,12);
763
      q3 = mulQuat(q,13);
764

    
765
      for(int index=16; index<24; index++)
766
        {
767
        int qIndex = CUBITS[index].mQuatIndex;
768
        if( qIndex!=q && qIndex!=q1 && qIndex!=q2 && qIndex!=q3 ) return false;
769
        }
770

    
771
      q1 = mulQuat(q, 3);
772
      q2 = mulQuat(q,14);
773
      q3 = mulQuat(q,15);
774

    
775
      for(int index=24; index<32; index++)
776
        {
777
        int qIndex = CUBITS[index].mQuatIndex;
778
        if( qIndex!=q && qIndex!=q1 && qIndex!=q2 && qIndex!=q3 ) return false;
779
        }
780

    
781
      return true;
782
      }
783

    
784
    return false;
785
    }
786

    
787
///////////////////////////////////////////////////////////////////////////////////////////////////
788
// only needed for solvers - there are no Helicopter solvers ATM)
789

    
790
  public String retObjectString()
791
    {
792
    return "";
793
    }
794

    
795
}
(15-15/18)