Revision bdfb04b3
Added by Leszek Koltunski 11 months ago
src/main/java/org/distorted/objectlib/main/TwistyObject.java | ||
---|---|---|
1752 | 1752 |
return mObjectQuats; |
1753 | 1753 |
} |
1754 | 1754 |
|
1755 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
1756 |
// Return the 'surface' the given face of the given cubit is on. (px,py,pz) is the pre-computed |
|
1757 |
// center of the cubit (so we don't have to keep re-computing this per each face) |
|
1758 |
// If the face is not external, return null. |
|
1759 |
// |
|
1760 |
// This is needed by the TwistyObjectSolved's method2 detecting if the object is in a solved state. |
|
1761 |
// |
|
1762 |
// What is a 'surface' ? For objects with flat monochromatic external walls, it is simply a 4-tuple |
|
1763 |
// [(nx,ny,nz),d] (normal vector + distance from origin) describing a 3D plane this face is part of. |
|
1764 |
// Exceptions are objects with curved external walls (ATM Masterball & Penrose Cubes): it is a union |
|
1765 |
// of several surfaces which together define the bent, monochromatic wall. I.e. Penrose Cube has 3 |
|
1766 |
// surfaces (blue, yellow and red), each defined by 3 planes (think before the bending effect!) |
|
1767 |
// |
|
1768 |
// This is the default which simply returns the single plane. If some puzzle has more complicated |
|
1769 |
// surfaces, it needs to override this method. |
|
1770 |
// |
|
1771 |
// We never need to test if a given point is part of a given surface (see TwistyObjectSurface!) - we |
|
1772 |
// only need to be able to rotate the surface by quats and test if two surfaces are the same. Thus: |
|
1773 |
// it is possible to provide some artificial surfaces - for example, in case of the Penrose, the |
|
1774 |
// three surfaces can be only the single 'middle' plane [the one on the bend]. |
|
1775 |
|
|
1776 |
public float[] getMonochromaticSurface(int variant, int cubitIndex, int faceIndex, float px, float py, float pz) |
|
1777 |
{ |
|
1778 |
if( !faceIsOuter(cubitIndex,faceIndex) ) return null; |
|
1779 |
|
|
1780 |
Static4D cubitQuat = getCubitQuats(cubitIndex,mNumLayers); |
|
1781 |
|
|
1782 |
float[] normal = new float[4]; |
|
1783 |
float[] intPoint = new float[3]; |
|
1784 |
float[] rotPoint = new float[4]; |
|
1785 |
float[] surface = new float[4]; |
|
1786 |
|
|
1787 |
ObjectShape objShape = mShapes[variant]; |
|
1788 |
objShape.getFacePoint(faceIndex,intPoint); |
|
1789 |
objShape.getFaceNormal(faceIndex,normal); |
|
1790 |
|
|
1791 |
QuatHelper.rotateVectorByQuat(rotPoint,intPoint[0],intPoint[1],intPoint[2],1,cubitQuat); |
|
1792 |
QuatHelper.rotateVectorByQuat(surface,normal[0],normal[1],normal[2],0,cubitQuat); |
|
1793 |
|
|
1794 |
float x = rotPoint[0] + px; |
|
1795 |
float y = rotPoint[1] + py; |
|
1796 |
float z = rotPoint[2] + pz; |
|
1797 |
surface[3] = x*surface[0] + y*surface[1] + z*surface[2]; |
|
1798 |
|
|
1799 |
return surface; |
|
1800 |
} |
|
1801 |
|
|
1755 | 1802 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
1756 | 1803 |
|
1757 | 1804 |
public int[][] getVariantFaceIsOuter() |
src/main/java/org/distorted/objectlib/main/TwistyObjectSolved.java | ||
---|---|---|
388 | 388 |
for(int c=0; c<numCubits; c++) |
389 | 389 |
{ |
390 | 390 |
int variant = mParent.getCubitVariant(c,numLayers); |
391 |
ObjectShape s = shapes[variant];
|
|
392 |
int numFaces = s.getNumFaces();
|
|
391 |
ObjectShape objShape = shapes[variant];
|
|
392 |
int numFaces = objShape.getNumFaces();
|
|
393 | 393 |
mCubitFaceToPuzzleFaceMap[c] = new int[numFaces]; |
394 | 394 |
mCubitFaceToSurfaceMap[c] = new int[numFaces]; |
395 | 395 |
for(int f=0; f<numFaces; f++) mCubitFaceToSurfaceMap[c][f] = -1; |
396 | 396 |
|
397 |
Static4D cubitQuat = mParent.getCubitQuats(c,numLayers); |
|
398 |
|
|
399 | 397 |
float[] po = pos[c]; |
400 | 398 |
int poslen = po.length/3; |
401 | 399 |
float px=0, py=0, pz=0; |
... | ... | |
417 | 415 |
|
418 | 416 |
//android.util.Log.e("D", "cubit "+c+" face "+f+" puzzle face: "+ mCubitFaceToPuzzleFaceMap[c][f]); |
419 | 417 |
|
420 |
if( !mParent.faceIsOuter(c,f) ) continue; |
|
421 |
|
|
422 |
float[] surface = new float[4]; |
|
423 |
float[] rotPoint = new float[4]; |
|
424 |
float[] normal = new float[4]; |
|
425 |
float[] intPoint = new float[3]; |
|
426 |
|
|
427 |
s.getFacePoint(f,intPoint); |
|
428 |
s.getFaceNormal(f,normal); |
|
429 |
|
|
430 |
QuatHelper.rotateVectorByQuat(rotPoint,intPoint[0],intPoint[1],intPoint[2],1,cubitQuat); |
|
431 |
QuatHelper.rotateVectorByQuat(surface,normal[0],normal[1],normal[2],0,cubitQuat); |
|
432 |
|
|
433 |
float x = rotPoint[0] + px; |
|
434 |
float y = rotPoint[1] + py; |
|
435 |
float z = rotPoint[2] + pz; |
|
436 |
surface[3] = x*surface[0] + y*surface[1] + z*surface[2]; |
|
418 |
float[] surface = mParent.getMonochromaticSurface(variant,c,f,px,py,pz); |
|
437 | 419 |
|
420 |
if( surface==null ) continue; |
|
438 | 421 |
TwistyObjectSurface si = new TwistyObjectSurface(surface); |
439 | 422 |
int index = surfaceExists(tmpSurfaces,si); |
440 | 423 |
|
src/main/java/org/distorted/objectlib/main/TwistyObjectSurface.java | ||
---|---|---|
21 | 21 |
// monochromatic surfaces (Masterball, Penroses) cannot use this method.. |
22 | 22 |
// |
23 | 23 |
// 'indices' is a map which shows which surface our surface changes to when rotated by all the |
24 |
// 'numQuats' quats. |
|
24 |
// 'numQuats' quats. Only kept here for a moment, then offloaded to TwistyObjectSolved.mSurfaceTable
|
|
25 | 25 |
// |
26 | 26 |
// Used only in TwistyObjectSolved's method2. |
27 | 27 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
56 | 56 |
|
57 | 57 |
String print() |
58 | 58 |
{ |
59 |
return surface[0]+" "+surface[1]+" "+surface[2]+" "+surface[3]; |
|
59 |
int numPlanes = surface.length / 4; |
|
60 |
StringBuilder sb = new StringBuilder(); |
|
61 |
|
|
62 |
for(int p=0; p<numPlanes; p++) |
|
63 |
{ |
|
64 |
sb.append('['); |
|
65 |
sb.append(surface[4*p]); |
|
66 |
sb.append(' '); |
|
67 |
sb.append(surface[4*p+1]); |
|
68 |
sb.append(' '); |
|
69 |
sb.append(surface[4*p+2]); |
|
70 |
sb.append(' '); |
|
71 |
sb.append(surface[4*p+3]); |
|
72 |
sb.append(']'); |
|
73 |
sb.append(' '); |
|
74 |
} |
|
75 |
|
|
76 |
return sb.toString(); |
|
60 | 77 |
} |
61 | 78 |
|
62 | 79 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
63 | 80 |
|
64 |
boolean isSame(TwistyObjectSurface s)
|
|
81 |
private boolean surfaceSame(float[] s1, int i1, float[] s2, int i2)
|
|
65 | 82 |
{ |
66 | 83 |
final float MAX_ERROR = 0.01f; |
67 | 84 |
float dnx,dny,dnz,dnw; |
68 |
float[] sur = s.surface; |
|
69 |
|
|
70 |
dnx = sur[0] + surface[0]; |
|
71 |
dny = sur[1] + surface[1]; |
|
72 |
dnz = sur[2] + surface[2]; |
|
73 |
dnw = sur[3] + surface[3]; |
|
85 |
float x1 = s1[4*i1 ]; |
|
86 |
float y1 = s1[4*i1+1]; |
|
87 |
float z1 = s1[4*i1+2]; |
|
88 |
float w1 = s1[4*i1+3]; |
|
89 |
float x2 = s2[4*i2 ]; |
|
90 |
float y2 = s2[4*i2+1]; |
|
91 |
float z2 = s2[4*i2+2]; |
|
92 |
float w2 = s2[4*i2+3]; |
|
93 |
|
|
94 |
dnx = x1 + x2; |
|
95 |
dny = y1 + y2; |
|
96 |
dnz = z1 + z2; |
|
97 |
dnw = w1 + w2; |
|
74 | 98 |
|
75 | 99 |
if( dnx*dnx + dny*dny + dnz*dnz + dnw*dnw < MAX_ERROR ) return true; |
76 | 100 |
|
77 |
dnx = sur[0] - surface[0];
|
|
78 |
dny = sur[1] - surface[1];
|
|
79 |
dnz = sur[2] - surface[2];
|
|
80 |
dnw = sur[3] - surface[3];
|
|
101 |
dnx = x1 - x2;
|
|
102 |
dny = y1 - y2;
|
|
103 |
dnz = z1 - z2;
|
|
104 |
dnw = w1 - w2;
|
|
81 | 105 |
|
82 | 106 |
if( dnx*dnx + dny*dny + dnz*dnz + dnw*dnw < MAX_ERROR ) return true; |
83 | 107 |
|
84 | 108 |
return false; |
85 | 109 |
} |
86 | 110 |
|
111 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
112 |
|
|
113 |
boolean isSame(TwistyObjectSurface s) |
|
114 |
{ |
|
115 |
int n1 = surface.length/4; |
|
116 |
int n2 = s.surface.length/4; |
|
117 |
|
|
118 |
for(int n=0; n<n1; n++) |
|
119 |
{ |
|
120 |
boolean exists = false; |
|
121 |
|
|
122 |
for(int p=0; p<n2; p++) |
|
123 |
if( surfaceSame(surface,n,s.surface,p) ) |
|
124 |
{ |
|
125 |
exists = true; |
|
126 |
break; |
|
127 |
} |
|
128 |
|
|
129 |
if( !exists ) return false; |
|
130 |
} |
|
131 |
|
|
132 |
return true; |
|
133 |
} |
|
134 |
|
|
87 | 135 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
88 | 136 |
|
89 | 137 |
TwistyObjectSurface rotateSurface(Static4D quat) |
90 | 138 |
{ |
91 |
float[] ret = new float[4]; |
|
92 |
QuatHelper.rotateVectorByQuat(ret,surface[0],surface[1],surface[2],0,quat); |
|
93 |
ret[3] = surface[3]; |
|
139 |
int numPlanes = surface.length / 4; |
|
140 |
float[] ret = new float[numPlanes*4]; |
|
141 |
float[] tmp = new float[4]; |
|
142 |
|
|
143 |
for(int p=0; p<numPlanes; p++) |
|
144 |
{ |
|
145 |
QuatHelper.rotateVectorByQuat(tmp,surface[4*p],surface[4*p+1],surface[4*p+2],0,quat); |
|
146 |
ret[4*p ] = tmp[0]; |
|
147 |
ret[4*p+1] = tmp[1]; |
|
148 |
ret[4*p+2] = tmp[2]; |
|
149 |
ret[4*p+3] = surface[4*p+3]; |
|
150 |
} |
|
151 |
|
|
94 | 152 |
return new TwistyObjectSurface(ret); |
95 | 153 |
} |
96 | 154 |
} |
src/main/java/org/distorted/objectlib/objects/TwistyDino4.java | ||
---|---|---|
29 | 29 |
super(iconMode, quat, move, scale, meta, asset); |
30 | 30 |
} |
31 | 31 |
|
32 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
33 |
// here we define 8 artificial monochromatic 'surfaces' - 8 vectors coming out from the center of the |
|
34 |
// cube to each vertex and some distance (doesn't matter) |
|
35 |
|
|
36 |
private static final float[][] mMonoSurfaces = |
|
37 |
{ |
|
38 |
{ 1, 1, 1, 1 }, |
|
39 |
{ 1, 1,-1, 1 }, |
|
40 |
{ 1,-1, 1, 1 }, |
|
41 |
{ 1,-1,-1, 1 }, |
|
42 |
{-1, 1, 1, 1 }, |
|
43 |
{-1, 1,-1, 1 }, |
|
44 |
{-1,-1, 1, 1 }, |
|
45 |
{-1,-1,-1, 1 }, |
|
46 |
}; |
|
47 |
private static final int[] mSurfaceIndices = { 4,2,2,4,1,2,7,4,1,1,7,7 }; |
|
48 |
|
|
49 |
@Override |
|
50 |
public float[] getMonochromaticSurface(int variant, int cubitIndex, int faceIndex, float px, float py, float pz) |
|
51 |
{ |
|
52 |
int index = mSurfaceIndices[cubitIndex]; |
|
53 |
return faceIndex<2 ? mMonoSurfaces[index] : null; |
|
54 |
} |
|
55 |
/* |
|
32 | 56 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
33 | 57 |
|
34 | 58 |
@Override |
... | ... | |
36 | 60 |
{ |
37 | 61 |
return 1; |
38 | 62 |
} |
39 |
|
|
63 |
*/ |
|
40 | 64 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
41 | 65 |
|
42 | 66 |
@Override |
Also available in: Unified diff
Further abstractions in the 'detect solved state' engine.
It should now be able to work in all cases - but it is still buggy (Dino4 does not work now!)