Revision 588ace55
Added by Leszek Koltunski about 3 years ago
src/main/java/org/distorted/control/RubikControl.java | ||
---|---|---|
26 | 26 |
import org.distorted.library.type.Static4D; |
27 | 27 |
import org.distorted.main.RubikActivity; |
28 | 28 |
import org.distorted.main.RubikSurfaceView; |
29 |
import org.distorted.objectlb.TwistyObject; |
|
29 |
import org.distorted.objectlib.TwistyObject;
|
|
30 | 30 |
|
31 | 31 |
import java.lang.ref.WeakReference; |
32 | 32 |
|
src/main/java/org/distorted/control/RubikControlRotate.java | ||
---|---|---|
22 | 22 |
import android.graphics.Bitmap; |
23 | 23 |
import android.graphics.BitmapFactory; |
24 | 24 |
|
25 |
import org.distorted.objectlb.QuatHelper; |
|
25 |
import org.distorted.objectlib.QuatHelper;
|
|
26 | 26 |
import org.distorted.library.effect.MatrixEffectQuaternion; |
27 | 27 |
import org.distorted.library.effect.MatrixEffectScale; |
28 | 28 |
import org.distorted.library.main.DistortedEffects; |
... | ... | |
38 | 38 |
import org.distorted.library.type.Static4D; |
39 | 39 |
import org.distorted.main.R; |
40 | 40 |
import org.distorted.main.RubikActivity; |
41 |
import org.distorted.objectlb.TwistyObject; |
|
41 |
import org.distorted.objectlib.TwistyObject;
|
|
42 | 42 |
|
43 | 43 |
import java.io.IOException; |
44 | 44 |
import java.io.InputStream; |
src/main/java/org/distorted/dialogs/RubikDialogNewRecord.java | ||
---|---|---|
37 | 37 |
|
38 | 38 |
import org.distorted.main.R; |
39 | 39 |
import org.distorted.main.RubikActivity; |
40 |
import org.distorted.objectlb.ObjectList; |
|
40 |
import org.distorted.objectlib.ObjectList;
|
|
41 | 41 |
import org.distorted.network.RubikScores; |
42 | 42 |
import org.distorted.screens.ScreenList; |
43 | 43 |
import org.distorted.screens.RubikScreenPlay; |
src/main/java/org/distorted/dialogs/RubikDialogPattern.java | ||
---|---|---|
41 | 41 |
|
42 | 42 |
import org.distorted.main.R; |
43 | 43 |
import org.distorted.main.RubikActivity; |
44 |
import org.distorted.objectlb.ObjectList; |
|
44 |
import org.distorted.objectlib.ObjectList;
|
|
45 | 45 |
import org.distorted.patterns.RubikPatternList; |
46 | 46 |
|
47 | 47 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
106 | 106 |
ObjectList list = RubikPatternList.getObject(i); |
107 | 107 |
int size = RubikPatternList.getSize(i); |
108 | 108 |
int sizeIndex = ObjectList.getSizeIndex(list.ordinal(),size); |
109 |
int iconID = list.getIconIDs()[sizeIndex]; |
|
109 |
int iconSize = RubikActivity.getDrawableSize(); |
|
110 |
int iconID = list.getIconIDs(iconSize)[sizeIndex]; |
|
110 | 111 |
|
111 | 112 |
ImageView imageView = new ImageView(act); |
112 | 113 |
imageView.setImageResource(iconID); |
src/main/java/org/distorted/dialogs/RubikDialogPatternView.java | ||
---|---|---|
28 | 28 |
|
29 | 29 |
import org.distorted.main.R; |
30 | 30 |
import org.distorted.main.RubikActivity; |
31 |
import org.distorted.objectlb.ObjectList; |
|
31 |
import org.distorted.objectlib.ObjectList;
|
|
32 | 32 |
import org.distorted.patterns.RubikPattern; |
33 | 33 |
import org.distorted.patterns.RubikPatternList; |
34 | 34 |
import org.distorted.screens.ScreenList; |
src/main/java/org/distorted/dialogs/RubikDialogScores.java | ||
---|---|---|
40 | 40 |
|
41 | 41 |
import org.distorted.main.R; |
42 | 42 |
import org.distorted.main.RubikActivity; |
43 |
import org.distorted.objectlb.ObjectList; |
|
43 |
import org.distorted.objectlib.ObjectList;
|
|
44 | 44 |
|
45 | 45 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
46 | 46 |
|
... | ... | |
108 | 108 |
for (int object = 0; object< ObjectList.NUM_OBJECTS; object++) |
109 | 109 |
{ |
110 | 110 |
list = ObjectList.getObject(object); |
111 |
int[] iconID = list.getIconIDs(); |
|
111 |
int iconSize = RubikActivity.getDrawableSize(); |
|
112 |
int[] iconID = list.getIconIDs(iconSize); |
|
112 | 113 |
int len = list.getSizes().length; |
113 | 114 |
|
114 | 115 |
for(int size=0; size<len; size++) |
src/main/java/org/distorted/dialogs/RubikDialogScoresPagerAdapter.java | ||
---|---|---|
33 | 33 |
import org.distorted.main.R; |
34 | 34 |
import org.distorted.network.RubikScores; |
35 | 35 |
import org.distorted.network.RubikNetwork; |
36 |
import org.distorted.objectlb.ObjectList; |
|
36 |
import org.distorted.objectlib.ObjectList;
|
|
37 | 37 |
import org.distorted.screens.RubikScreenPlay; |
38 | 38 |
|
39 | 39 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
src/main/java/org/distorted/dialogs/RubikDialogScoresView.java | ||
---|---|---|
33 | 33 |
|
34 | 34 |
import org.distorted.main.R; |
35 | 35 |
import org.distorted.main.RubikActivity; |
36 |
import org.distorted.objectlb.ObjectList; |
|
36 |
import org.distorted.objectlib.ObjectList;
|
|
37 | 37 |
import org.distorted.network.RubikScores; |
38 | 38 |
|
39 | 39 |
import static org.distorted.network.RubikNetwork.MAX_PLACES; |
src/main/java/org/distorted/dialogs/RubikDialogSetName.java | ||
---|---|---|
40 | 40 |
|
41 | 41 |
import org.distorted.main.R; |
42 | 42 |
import org.distorted.main.RubikActivity; |
43 |
import org.distorted.objectlb.ObjectList; |
|
43 |
import org.distorted.objectlib.ObjectList;
|
|
44 | 44 |
import org.distorted.network.RubikScores; |
45 | 45 |
import org.distorted.screens.ScreenList; |
46 | 46 |
import org.distorted.screens.RubikScreenPlay; |
src/main/java/org/distorted/dialogs/RubikDialogTutorialView.java | ||
---|---|---|
38 | 38 |
import org.distorted.main.BuildConfig; |
39 | 39 |
import org.distorted.main.R; |
40 | 40 |
import org.distorted.main.RubikActivity; |
41 |
import org.distorted.objectlb.ObjectList; |
|
41 |
import org.distorted.objectlib.ObjectList;
|
|
42 | 42 |
import org.distorted.tutorials.TutorialList; |
43 | 43 |
|
44 | 44 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
src/main/java/org/distorted/effects/EffectController.java | ||
---|---|---|
21 | 21 |
|
22 | 22 |
import org.distorted.helpers.MovesFinished; |
23 | 23 |
import org.distorted.library.message.EffectListener; |
24 |
import org.distorted.objectlb.TwistyObject; |
|
24 |
import org.distorted.objectlib.TwistyObject;
|
|
25 | 25 |
|
26 | 26 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
27 | 27 |
|
src/main/java/org/distorted/effects/objectchange/ObjectChangeEffect.java | ||
---|---|---|
25 | 25 |
import org.distorted.library.main.DistortedScreen; |
26 | 26 |
import org.distorted.library.message.EffectListener; |
27 | 27 |
import org.distorted.effects.EffectController; |
28 |
import org.distorted.objectlb.TwistyObject; |
|
28 |
import org.distorted.objectlib.TwistyObject;
|
|
29 | 29 |
|
30 | 30 |
import java.lang.reflect.Method; |
31 | 31 |
|
src/main/java/org/distorted/effects/scramble/ScrambleEffect.java | ||
---|---|---|
26 | 26 |
import org.distorted.library.main.DistortedScreen; |
27 | 27 |
import org.distorted.library.message.EffectListener; |
28 | 28 |
import org.distorted.effects.EffectController; |
29 |
import org.distorted.objectlb.ObjectList; |
|
30 |
import org.distorted.objectlb.TwistyObject; |
|
29 |
import org.distorted.objectlib.ObjectList;
|
|
30 |
import org.distorted.objectlib.TwistyObject;
|
|
31 | 31 |
|
32 | 32 |
import java.lang.reflect.Method; |
33 | 33 |
import java.util.Random; |
src/main/java/org/distorted/effects/solve/SolveEffect.java | ||
---|---|---|
25 | 25 |
import org.distorted.library.main.DistortedScreen; |
26 | 26 |
import org.distorted.library.message.EffectListener; |
27 | 27 |
import org.distorted.effects.EffectController; |
28 |
import org.distorted.objectlb.TwistyObject; |
|
28 |
import org.distorted.objectlib.TwistyObject;
|
|
29 | 29 |
|
30 | 30 |
import java.lang.reflect.Method; |
31 | 31 |
|
src/main/java/org/distorted/effects/win/WinEffect.java | ||
---|---|---|
25 | 25 |
import org.distorted.library.main.DistortedScreen; |
26 | 26 |
import org.distorted.library.message.EffectListener; |
27 | 27 |
import org.distorted.effects.EffectController; |
28 |
import org.distorted.objectlb.TwistyObject; |
|
28 |
import org.distorted.objectlib.TwistyObject;
|
|
29 | 29 |
|
30 | 30 |
import java.lang.reflect.Method; |
31 | 31 |
|
src/main/java/org/distorted/main/RubikActivity.java | ||
---|---|---|
21 | 21 |
|
22 | 22 |
import android.content.Intent; |
23 | 23 |
import android.content.SharedPreferences; |
24 |
import android.content.res.Resources; |
|
24 | 25 |
import android.os.Build; |
25 | 26 |
import android.os.Bundle; |
26 | 27 |
import android.os.LocaleList; |
... | ... | |
41 | 42 |
import org.distorted.helpers.BlockController; |
42 | 43 |
import org.distorted.helpers.TwistyActivity; |
43 | 44 |
import org.distorted.helpers.TwistyPreRender; |
45 |
import org.distorted.library.main.DistortedEffects; |
|
44 | 46 |
import org.distorted.library.main.DistortedLibrary; |
45 | 47 |
|
46 | 48 |
import org.distorted.library.main.DistortedScreen; |
49 |
import org.distorted.library.main.DistortedTexture; |
|
50 |
import org.distorted.library.mesh.MeshSquare; |
|
47 | 51 |
import org.distorted.library.type.Static4D; |
48 |
import org.distorted.objectlb.TwistyObject; |
|
52 |
import org.distorted.objectlib.TwistyObject;
|
|
49 | 53 |
import org.distorted.network.RubikScores; |
50 | 54 |
import org.distorted.network.RubikNetwork; |
51 |
import org.distorted.objectlb.ObjectList; |
|
55 |
import org.distorted.objectlib.ObjectList; |
|
56 |
import org.distorted.objects.TwistyBandaged2Bar; |
|
57 |
import org.distorted.objects.TwistyBandaged3Plate; |
|
58 |
import org.distorted.objects.TwistyBandagedEvil; |
|
59 |
import org.distorted.objects.TwistyBandagedFused; |
|
60 |
import org.distorted.objects.TwistyCube; |
|
61 |
import org.distorted.objects.TwistyDiamond; |
|
62 |
import org.distorted.objects.TwistyDino4; |
|
63 |
import org.distorted.objects.TwistyDino6; |
|
64 |
import org.distorted.objects.TwistyHelicopter; |
|
65 |
import org.distorted.objects.TwistyIvy; |
|
66 |
import org.distorted.objects.TwistyJing; |
|
67 |
import org.distorted.objects.TwistyKilominx; |
|
68 |
import org.distorted.objects.TwistyMegaminx; |
|
69 |
import org.distorted.objects.TwistyMirror; |
|
70 |
import org.distorted.objects.TwistyPyraminx; |
|
71 |
import org.distorted.objects.TwistyRedi; |
|
72 |
import org.distorted.objects.TwistyRex; |
|
73 |
import org.distorted.objects.TwistySkewb; |
|
74 |
import org.distorted.objects.TwistySquare1; |
|
75 |
import org.distorted.objects.TwistySquare2; |
|
76 |
import org.distorted.objects.TwistyUltimate; |
|
52 | 77 |
import org.distorted.screens.ScreenList; |
53 | 78 |
import org.distorted.screens.RubikScreenPlay; |
54 | 79 |
import org.distorted.tutorials.TutorialActivity; |
... | ... | |
649 | 674 |
myIntent.putExtra("siz", size); |
650 | 675 |
startActivity(myIntent); |
651 | 676 |
} |
677 |
|
|
678 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
679 |
|
|
680 |
public static TwistyObject create(ObjectList object, int size, Static4D quat, int[][] moves, Resources res, int scrWidth) |
|
681 |
{ |
|
682 |
DistortedTexture texture = new DistortedTexture(); |
|
683 |
DistortedEffects effects = new DistortedEffects(); |
|
684 |
MeshSquare mesh = new MeshSquare(20,20); // mesh of the node, not of the cubits |
|
685 |
|
|
686 |
switch(object.ordinal()) |
|
687 |
{ |
|
688 |
case 0: return new TwistyCube (size, quat, texture, mesh, effects, moves, res, scrWidth); |
|
689 |
case 1: return new TwistyJing (size, quat, texture, mesh, effects, moves, res, scrWidth); |
|
690 |
case 2: return new TwistyPyraminx (size, quat, texture, mesh, effects, moves, res, scrWidth); |
|
691 |
case 3: return new TwistyKilominx (size, quat, texture, mesh, effects, moves, res, scrWidth); |
|
692 |
case 4: return new TwistyMegaminx (size, quat, texture, mesh, effects, moves, res, scrWidth); |
|
693 |
case 5: return new TwistyUltimate (size, quat, texture, mesh, effects, moves, res, scrWidth); |
|
694 |
case 6: return new TwistyDiamond (size, quat, texture, mesh, effects, moves, res, scrWidth); |
|
695 |
case 7: return new TwistyDino6 (size, quat, texture, mesh, effects, moves, res, scrWidth); |
|
696 |
case 8: return new TwistyDino4 (size, quat, texture, mesh, effects, moves, res, scrWidth); |
|
697 |
case 9: return new TwistyRedi (size, quat, texture, mesh, effects, moves, res, scrWidth); |
|
698 |
case 10: return new TwistyHelicopter (size, quat, texture, mesh, effects, moves, res, scrWidth); |
|
699 |
case 11: return new TwistySkewb (size, quat, texture, mesh, effects, moves, res, scrWidth); |
|
700 |
case 12: return new TwistyIvy (size, quat, texture, mesh, effects, moves, res, scrWidth); |
|
701 |
case 13: return new TwistyRex (size, quat, texture, mesh, effects, moves, res, scrWidth); |
|
702 |
case 14: return new TwistyBandagedFused (size, quat, texture, mesh, effects, moves, res, scrWidth); |
|
703 |
case 15: return new TwistyBandaged2Bar (size, quat, texture, mesh, effects, moves, res, scrWidth); |
|
704 |
case 16: return new TwistyBandaged3Plate (size, quat, texture, mesh, effects, moves, res, scrWidth); |
|
705 |
case 17: return new TwistyBandagedEvil (size, quat, texture, mesh, effects, moves, res, scrWidth); |
|
706 |
case 18: return new TwistySquare1 (size, quat, texture, mesh, effects, moves, res, scrWidth); |
|
707 |
case 19: return new TwistySquare2 (size, quat, texture, mesh, effects, moves, res, scrWidth); |
|
708 |
case 20: return new TwistyMirror (size, quat, texture, mesh, effects, moves, res, scrWidth); |
|
709 |
} |
|
710 |
|
|
711 |
return null; |
|
712 |
} |
|
652 | 713 |
} |
src/main/java/org/distorted/main/RubikPreRender.java | ||
---|---|---|
42 | 42 |
import org.distorted.helpers.BlockController; |
43 | 43 |
import org.distorted.helpers.MovesFinished; |
44 | 44 |
import org.distorted.helpers.TwistyPreRender; |
45 |
import org.distorted.objectlb.TwistyObject; |
|
46 |
import org.distorted.objectlb.ObjectList; |
|
45 |
import org.distorted.objectlib.TwistyObject;
|
|
46 |
import org.distorted.objectlib.ObjectList;
|
|
47 | 47 |
import org.distorted.network.RubikScores; |
48 | 48 |
import org.distorted.screens.RubikScreenPlay; |
49 | 49 |
import org.distorted.screens.ScreenList; |
... | ... | |
124 | 124 |
Context con = mView.getContext(); |
125 | 125 |
Resources res = con.getResources(); |
126 | 126 |
|
127 |
mNewObject = object.create(size, mView.getQuat(), moves, res, mScreenWidth);
|
|
127 |
mNewObject = RubikActivity.create(object,size, mView.getQuat(), moves, res, mScreenWidth);
|
|
128 | 128 |
|
129 | 129 |
if( mNewObject!=null ) |
130 | 130 |
{ |
src/main/java/org/distorted/main/RubikSurfaceView.java | ||
---|---|---|
30 | 30 |
|
31 | 31 |
import com.google.firebase.crashlytics.FirebaseCrashlytics; |
32 | 32 |
|
33 |
import org.distorted.objectlb.QuatHelper; |
|
33 |
import org.distorted.objectlib.QuatHelper;
|
|
34 | 34 |
import org.distorted.library.type.Static2D; |
35 | 35 |
import org.distorted.library.type.Static4D; |
36 |
import org.distorted.objectlb.TwistyObject; |
|
37 |
import org.distorted.objectlb.Movement; |
|
36 |
import org.distorted.objectlib.TwistyObject;
|
|
37 |
import org.distorted.objectlib.Movement;
|
|
38 | 38 |
import org.distorted.screens.RubikScreenReady; |
39 | 39 |
import org.distorted.solvers.SolverMain; |
40 | 40 |
import org.distorted.screens.ScreenList; |
src/main/java/org/distorted/network/RubikNetwork.java | ||
---|---|---|
27 | 27 |
import androidx.fragment.app.FragmentActivity; |
28 | 28 |
|
29 | 29 |
import org.distorted.library.main.DistortedLibrary; |
30 |
import org.distorted.objectlb.ObjectList; |
|
30 |
import org.distorted.objectlib.ObjectList;
|
|
31 | 31 |
|
32 | 32 |
import java.io.InputStream; |
33 | 33 |
import java.net.HttpURLConnection; |
... | ... | |
36 | 36 |
import java.security.MessageDigest; |
37 | 37 |
import java.security.NoSuchAlgorithmException; |
38 | 38 |
|
39 |
import static org.distorted.objectlb.ObjectList.MAX_LEVEL; |
|
39 |
import static org.distorted.objectlib.ObjectList.MAX_LEVEL;
|
|
40 | 40 |
|
41 | 41 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
42 | 42 |
|
src/main/java/org/distorted/network/RubikScores.java | ||
---|---|---|
26 | 26 |
import com.google.firebase.crashlytics.FirebaseCrashlytics; |
27 | 27 |
|
28 | 28 |
import org.distorted.main.BuildConfig; |
29 |
import org.distorted.objectlb.ObjectList; |
|
29 |
import org.distorted.objectlib.ObjectList;
|
|
30 | 30 |
|
31 | 31 |
import java.util.UUID; |
32 | 32 |
|
33 |
import static org.distorted.objectlb.ObjectList.MAX_NUM_OBJECTS; |
|
34 |
import static org.distorted.objectlb.ObjectList.NUM_OBJECTS; |
|
35 |
import static org.distorted.objectlb.ObjectList.MAX_LEVEL; |
|
33 |
import static org.distorted.objectlib.ObjectList.MAX_NUM_OBJECTS;
|
|
34 |
import static org.distorted.objectlib.ObjectList.NUM_OBJECTS;
|
|
35 |
import static org.distorted.objectlib.ObjectList.MAX_LEVEL;
|
|
36 | 36 |
|
37 | 37 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
38 | 38 |
// hold my own scores, and some other statistics. |
src/main/java/org/distorted/objectlb/Cubit.java | ||
---|---|---|
1 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
2 |
// Copyright 2019 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.objectlb; |
|
21 |
|
|
22 |
import android.content.SharedPreferences; |
|
23 |
|
|
24 |
import org.distorted.library.type.Static4D; |
|
25 |
|
|
26 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
27 |
|
|
28 |
public class Cubit |
|
29 |
{ |
|
30 |
private final float[] mOrigPosition; |
|
31 |
private final float[] mCurrentPosition; |
|
32 |
private final int mNumAxis; |
|
33 |
private final int mLen; |
|
34 |
private final int[] mRotationRow; |
|
35 |
private TwistyObject mParent; |
|
36 |
|
|
37 |
int mQuatIndex; |
|
38 |
|
|
39 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
40 |
|
|
41 |
Cubit(TwistyObject parent, float[] position, int numAxis) |
|
42 |
{ |
|
43 |
mQuatIndex= 0; |
|
44 |
mParent = parent; |
|
45 |
mLen = position.length; |
|
46 |
|
|
47 |
mOrigPosition = new float[mLen]; |
|
48 |
mCurrentPosition = new float[mLen]; |
|
49 |
|
|
50 |
for(int i=0; i<mLen; i++) |
|
51 |
{ |
|
52 |
mOrigPosition[i] = position[i]; |
|
53 |
mCurrentPosition[i] = position[i]; |
|
54 |
} |
|
55 |
|
|
56 |
mNumAxis = numAxis; |
|
57 |
mRotationRow = new int[mNumAxis]; |
|
58 |
computeRotationRow(); |
|
59 |
} |
|
60 |
|
|
61 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
62 |
// Because of quatMultiplication, errors can accumulate - so to avoid this, we |
|
63 |
// correct the value of the 'scramble' quat to what it should be - one of the legal quats from the |
|
64 |
// list QUATS. |
|
65 |
// |
|
66 |
// We also have to remember that the group of unit quaternions is a double-cover of rotations |
|
67 |
// in 3D ( q represents the same rotation as -q ) - so invert if needed. |
|
68 |
|
|
69 |
private int normalizeScrambleQuat(Static4D quat) |
|
70 |
{ |
|
71 |
float x = quat.get0(); |
|
72 |
float y = quat.get1(); |
|
73 |
float z = quat.get2(); |
|
74 |
float w = quat.get3(); |
|
75 |
float xd,yd,zd,wd; |
|
76 |
float diff, mindiff = Float.MAX_VALUE; |
|
77 |
int ret=0; |
|
78 |
int num_quats = mParent.OBJECT_QUATS.length; |
|
79 |
Static4D qt; |
|
80 |
|
|
81 |
for(int q=0; q<num_quats; q++) |
|
82 |
{ |
|
83 |
qt = mParent.OBJECT_QUATS[q]; |
|
84 |
|
|
85 |
xd = x - qt.get0(); |
|
86 |
yd = y - qt.get1(); |
|
87 |
zd = z - qt.get2(); |
|
88 |
wd = w - qt.get3(); |
|
89 |
|
|
90 |
diff = xd*xd + yd*yd + zd*zd + wd*wd; |
|
91 |
|
|
92 |
if( diff < mindiff ) |
|
93 |
{ |
|
94 |
ret = q; |
|
95 |
mindiff = diff; |
|
96 |
} |
|
97 |
|
|
98 |
xd = x + qt.get0(); |
|
99 |
yd = y + qt.get1(); |
|
100 |
zd = z + qt.get2(); |
|
101 |
wd = w + qt.get3(); |
|
102 |
|
|
103 |
diff = xd*xd + yd*yd + zd*zd + wd*wd; |
|
104 |
|
|
105 |
if( diff < mindiff ) |
|
106 |
{ |
|
107 |
ret = q; |
|
108 |
mindiff = diff; |
|
109 |
} |
|
110 |
} |
|
111 |
|
|
112 |
return ret; |
|
113 |
} |
|
114 |
|
|
115 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
116 |
|
|
117 |
private void computeRotationRow() |
|
118 |
{ |
|
119 |
for(int i=0; i<mNumAxis; i++) |
|
120 |
{ |
|
121 |
mRotationRow[i] = mParent.computeRow(mCurrentPosition,i); |
|
122 |
} |
|
123 |
} |
|
124 |
|
|
125 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
126 |
|
|
127 |
void modifyCurrentPosition(Static4D quat) |
|
128 |
{ |
|
129 |
Static4D cubitCenter; |
|
130 |
Static4D rotatedCenter; |
|
131 |
int len = mLen/3; |
|
132 |
|
|
133 |
for(int i=0; i<len; i++) |
|
134 |
{ |
|
135 |
cubitCenter = new Static4D(mCurrentPosition[3*i], mCurrentPosition[3*i+1], mCurrentPosition[3*i+2], 0); |
|
136 |
rotatedCenter = QuatHelper.rotateVectorByQuat( cubitCenter, quat); |
|
137 |
|
|
138 |
mCurrentPosition[3*i ] = rotatedCenter.get0(); |
|
139 |
mCurrentPosition[3*i+1] = rotatedCenter.get1(); |
|
140 |
mCurrentPosition[3*i+2] = rotatedCenter.get2(); |
|
141 |
|
|
142 |
mParent.clampPos(mCurrentPosition, 3*i); |
|
143 |
} |
|
144 |
|
|
145 |
computeRotationRow(); |
|
146 |
} |
|
147 |
|
|
148 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
149 |
|
|
150 |
int computeAssociation() |
|
151 |
{ |
|
152 |
int result = 0, accumulativeShift = 0; |
|
153 |
|
|
154 |
for(int axis=0; axis<mNumAxis; axis++) |
|
155 |
{ |
|
156 |
result += (mRotationRow[axis]<<accumulativeShift); |
|
157 |
accumulativeShift += ObjectList.MAX_OBJECT_SIZE; |
|
158 |
} |
|
159 |
|
|
160 |
return result; |
|
161 |
} |
|
162 |
|
|
163 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
164 |
|
|
165 |
void savePreferences(SharedPreferences.Editor editor) |
|
166 |
{ |
|
167 |
String number = mOrigPosition[0]+"_"+mOrigPosition[1]+"_"+mOrigPosition[2]; |
|
168 |
editor.putInt("q_"+number, mQuatIndex); |
|
169 |
} |
|
170 |
|
|
171 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
172 |
|
|
173 |
int restorePreferences(SharedPreferences preferences) |
|
174 |
{ |
|
175 |
String number = mOrigPosition[0]+"_"+mOrigPosition[1]+"_"+mOrigPosition[2]; |
|
176 |
mQuatIndex = preferences.getInt("q_"+number, 0); |
|
177 |
return mQuatIndex; |
|
178 |
} |
|
179 |
|
|
180 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
181 |
|
|
182 |
int removeRotationNow(Static4D quat) |
|
183 |
{ |
|
184 |
Static4D q = QuatHelper.quatMultiply(quat,mParent.OBJECT_QUATS[mQuatIndex]); |
|
185 |
mQuatIndex = normalizeScrambleQuat(q); |
|
186 |
|
|
187 |
modifyCurrentPosition(quat); |
|
188 |
|
|
189 |
return mQuatIndex; |
|
190 |
} |
|
191 |
|
|
192 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
193 |
|
|
194 |
void solve() |
|
195 |
{ |
|
196 |
mQuatIndex = 0; |
|
197 |
System.arraycopy(mOrigPosition, 0, mCurrentPosition, 0, mCurrentPosition.length); |
|
198 |
computeRotationRow(); |
|
199 |
} |
|
200 |
|
|
201 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
202 |
|
|
203 |
void releaseResources() |
|
204 |
{ |
|
205 |
mParent = null; |
|
206 |
} |
|
207 |
|
|
208 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
209 |
// this is only needed for MODE_REPLACE objects (i.e. - currently - CUBE_3), so it is enough to only |
|
210 |
// take into consideration the first position. |
|
211 |
|
|
212 |
float getDistSquared(float[] point) |
|
213 |
{ |
|
214 |
float dx = mCurrentPosition[0] - point[0]; |
|
215 |
float dy = mCurrentPosition[1] - point[1]; |
|
216 |
float dz = mCurrentPosition[2] - point[2]; |
|
217 |
|
|
218 |
return dx*dx + dy*dy + dz*dz; |
|
219 |
} |
|
220 |
|
|
221 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
222 |
|
|
223 |
public int getRotRow(int index) |
|
224 |
{ |
|
225 |
return mRotationRow[index]; |
|
226 |
} |
|
227 |
} |
src/main/java/org/distorted/objectlb/FactoryCubit.java | ||
---|---|---|
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.objectlb; |
|
21 |
|
|
22 |
import org.distorted.library.effect.MatrixEffectMove; |
|
23 |
import org.distorted.library.effect.MatrixEffectQuaternion; |
|
24 |
import org.distorted.library.effect.MatrixEffectScale; |
|
25 |
import org.distorted.library.effect.VertexEffect; |
|
26 |
import org.distorted.library.effect.VertexEffectDeform; |
|
27 |
import org.distorted.library.mesh.MeshBase; |
|
28 |
import org.distorted.library.mesh.MeshJoined; |
|
29 |
import org.distorted.library.mesh.MeshPolygon; |
|
30 |
import org.distorted.library.type.Static1D; |
|
31 |
import org.distorted.library.type.Static3D; |
|
32 |
import org.distorted.library.type.Static4D; |
|
33 |
|
|
34 |
import java.util.ArrayList; |
|
35 |
|
|
36 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
37 |
|
|
38 |
public class FactoryCubit |
|
39 |
{ |
|
40 |
private static final Static1D RADIUS = new Static1D(1); |
|
41 |
private static FactoryCubit mThis; |
|
42 |
|
|
43 |
private static final double[] mBuffer = new double[3]; |
|
44 |
private static final double[] mQuat1 = new double[4]; |
|
45 |
private static final double[] mQuat2 = new double[4]; |
|
46 |
private static final double[] mQuat3 = new double[4]; |
|
47 |
private static final double[] mQuat4 = new double[4]; |
|
48 |
|
|
49 |
private static class StickerCoords |
|
50 |
{ |
|
51 |
double[] vertices; |
|
52 |
} |
|
53 |
|
|
54 |
private static class FaceTransform |
|
55 |
{ |
|
56 |
int sticker; |
|
57 |
double vx,vy,vz; |
|
58 |
double scale; |
|
59 |
double qx,qy,qz,qw; |
|
60 |
boolean flip; |
|
61 |
} |
|
62 |
|
|
63 |
private static final ArrayList<FaceTransform> mNewFaceTransf = new ArrayList<>(); |
|
64 |
private static final ArrayList<FaceTransform> mOldFaceTransf = new ArrayList<>(); |
|
65 |
private static final ArrayList<StickerCoords> mStickerCoords = new ArrayList<>(); |
|
66 |
|
|
67 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
68 |
|
|
69 |
private FactoryCubit() |
|
70 |
{ |
|
71 |
|
|
72 |
} |
|
73 |
|
|
74 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
75 |
|
|
76 |
public static FactoryCubit getInstance() |
|
77 |
{ |
|
78 |
if( mThis==null ) mThis = new FactoryCubit(); |
|
79 |
|
|
80 |
return mThis; |
|
81 |
} |
|
82 |
|
|
83 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
84 |
// H - height of the band in the middle |
|
85 |
// alpha - angle of the edge [0,90] |
|
86 |
// dist - often in a polygon the distance from edge to center is not 1, but something else. |
|
87 |
// This is the distance. |
|
88 |
// K - where to begin the second, much more flat part of the band. [0,1] |
|
89 |
// N - number of bands. N>=3 |
|
90 |
// |
|
91 |
// theory: two distinct parts to the band: |
|
92 |
// 1) (0,B) - steep |
|
93 |
// 2) (B,1) - flat |
|
94 |
// |
|
95 |
// In first part, we have y = g(x) ; in second - y = g(f(x)) where |
|
96 |
// |
|
97 |
// g(x) = sqrt( R^2 - (x-D)^2 ) - R*cos(alpha) |
|
98 |
// f(x) = ((D-B)/(1-B)*x + B*(1-D)/(1-B) |
|
99 |
// h(x) = R*(sin(alpha) - sin(x)) |
|
100 |
// R = H/(1-cos(alpha)) |
|
101 |
// D = H*sin(alpha) |
|
102 |
// B = h(K*alpha) |
|
103 |
// |
|
104 |
// The N points are taken at: |
|
105 |
// |
|
106 |
// 1) in the second part, there are K2 = (N-3)/3 such points |
|
107 |
// 2) in the first - K1 = (N-3) - K2 |
|
108 |
// 3) also, the 3 points 0,B,1 |
|
109 |
// |
|
110 |
// so we have the sequence A[i] of N points |
|
111 |
// |
|
112 |
// 0 |
|
113 |
// h((i+1)*(1-K)*alpha/(K1+1)) (i=0,1,...,K1-1) |
|
114 |
// B |
|
115 |
// (1-B)*(i+1)/(K2+1) + B (i=0,i,...,K2-1) |
|
116 |
// 1 |
|
117 |
|
|
118 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
119 |
|
|
120 |
private float f(float D, float B, float x) |
|
121 |
{ |
|
122 |
return ((D-B)*x + B*(1-D))/(1-B); |
|
123 |
} |
|
124 |
|
|
125 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
126 |
|
|
127 |
private float g(float R, float D, float x, float cosAlpha) |
|
128 |
{ |
|
129 |
float d = x-D; |
|
130 |
return (float)(Math.sqrt(R*R-d*d)-R*cosAlpha); |
|
131 |
} |
|
132 |
|
|
133 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
134 |
|
|
135 |
private float h(float R, float sinAlpha, float x) |
|
136 |
{ |
|
137 |
return R*(sinAlpha-(float)Math.sin(x)); |
|
138 |
} |
|
139 |
|
|
140 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
141 |
|
|
142 |
private boolean areColinear(double[][] vertices, int index1, int index2, int index3) |
|
143 |
{ |
|
144 |
double x1 = vertices[index1][0]; |
|
145 |
double y1 = vertices[index1][1]; |
|
146 |
double z1 = vertices[index1][2]; |
|
147 |
double x2 = vertices[index2][0]; |
|
148 |
double y2 = vertices[index2][1]; |
|
149 |
double z2 = vertices[index2][2]; |
|
150 |
double x3 = vertices[index3][0]; |
|
151 |
double y3 = vertices[index3][1]; |
|
152 |
double z3 = vertices[index3][2]; |
|
153 |
|
|
154 |
double v1x = x2-x1; |
|
155 |
double v1y = y2-y1; |
|
156 |
double v1z = z2-z1; |
|
157 |
double v2x = x3-x1; |
|
158 |
double v2y = y3-y1; |
|
159 |
double v2z = z3-z1; |
|
160 |
|
|
161 |
double A = Math.sqrt( (v1x*v1x+v1y*v1y+v1z*v1z) / (v2x*v2x+v2y*v2y+v2z*v2z) ); |
|
162 |
|
|
163 |
return (v1x==A*v2x && v1y==A*v2y && v1z==A*v2z); |
|
164 |
} |
|
165 |
|
|
166 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
167 |
|
|
168 |
private void computeNormalVector(double[][] vertices, int index1, int index2, int index3) |
|
169 |
{ |
|
170 |
double x1 = vertices[index1][0]; |
|
171 |
double y1 = vertices[index1][1]; |
|
172 |
double z1 = vertices[index1][2]; |
|
173 |
double x2 = vertices[index2][0]; |
|
174 |
double y2 = vertices[index2][1]; |
|
175 |
double z2 = vertices[index2][2]; |
|
176 |
double x3 = vertices[index3][0]; |
|
177 |
double y3 = vertices[index3][1]; |
|
178 |
double z3 = vertices[index3][2]; |
|
179 |
|
|
180 |
double v1x = x2-x1; |
|
181 |
double v1y = y2-y1; |
|
182 |
double v1z = z2-z1; |
|
183 |
double v2x = x3-x1; |
|
184 |
double v2y = y3-y1; |
|
185 |
double v2z = z3-z1; |
|
186 |
|
|
187 |
mBuffer[0] = v1y*v2z - v2y*v1z; |
|
188 |
mBuffer[1] = v1z*v2x - v2z*v1x; |
|
189 |
mBuffer[2] = v1x*v2y - v2x*v1y; |
|
190 |
|
|
191 |
double len = mBuffer[0]*mBuffer[0] + mBuffer[1]*mBuffer[1] + mBuffer[2]*mBuffer[2]; |
|
192 |
len = Math.sqrt(len); |
|
193 |
mBuffer[0] /= len; |
|
194 |
mBuffer[1] /= len; |
|
195 |
mBuffer[2] /= len; |
|
196 |
} |
|
197 |
|
|
198 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
199 |
// return quat1*quat2 |
|
200 |
|
|
201 |
private static void quatMultiply( double[] quat1, double[] quat2, double[] result ) |
|
202 |
{ |
|
203 |
double qx = quat1[0]; |
|
204 |
double qy = quat1[1]; |
|
205 |
double qz = quat1[2]; |
|
206 |
double qw = quat1[3]; |
|
207 |
|
|
208 |
double rx = quat2[0]; |
|
209 |
double ry = quat2[1]; |
|
210 |
double rz = quat2[2]; |
|
211 |
double rw = quat2[3]; |
|
212 |
|
|
213 |
result[0] = rw*qx - rz*qy + ry*qz + rx*qw; |
|
214 |
result[1] = rw*qy + rz*qx + ry*qw - rx*qz; |
|
215 |
result[2] = rw*qz + rz*qw - ry*qx + rx*qy; |
|
216 |
result[3] = rw*qw - rz*qz - ry*qy - rx*qx; |
|
217 |
} |
|
218 |
|
|
219 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
220 |
|
|
221 |
private void fitInSquare(FaceTransform info, double[][] vert3D) |
|
222 |
{ |
|
223 |
double minX = Double.MAX_VALUE; |
|
224 |
double maxX =-Double.MAX_VALUE; |
|
225 |
double minY = Double.MAX_VALUE; |
|
226 |
double maxY =-Double.MAX_VALUE; |
|
227 |
|
|
228 |
for (double[] vert : vert3D) |
|
229 |
{ |
|
230 |
double x = vert[0]; |
|
231 |
double y = vert[1]; |
|
232 |
|
|
233 |
if (x > maxX) maxX = x; |
|
234 |
if (x < minX) minX = x; |
|
235 |
if (y > maxY) maxY = y; |
|
236 |
if (y < minY) minY = y; |
|
237 |
} |
|
238 |
|
|
239 |
minX = minX<0 ? -minX:minX; |
|
240 |
maxX = maxX<0 ? -maxX:maxX; |
|
241 |
minY = minY<0 ? -minY:minY; |
|
242 |
maxY = maxY<0 ? -maxY:maxY; |
|
243 |
|
|
244 |
double max1 = Math.max(minX,minY); |
|
245 |
double max2 = Math.max(maxX,maxY); |
|
246 |
double max3 = Math.max(max1,max2); |
|
247 |
|
|
248 |
info.scale = max3/0.5; |
|
249 |
|
|
250 |
int len = vert3D.length; |
|
251 |
StickerCoords sInfo = new StickerCoords(); |
|
252 |
sInfo.vertices = new double[2*len]; |
|
253 |
|
|
254 |
for( int vertex=0; vertex<len; vertex++ ) |
|
255 |
{ |
|
256 |
sInfo.vertices[2*vertex ] = vert3D[vertex][0] / info.scale; |
|
257 |
sInfo.vertices[2*vertex+1] = vert3D[vertex][1] / info.scale; |
|
258 |
} |
|
259 |
|
|
260 |
mStickerCoords.add(sInfo); |
|
261 |
|
|
262 |
info.sticker = mStickerCoords.size() -1; |
|
263 |
info.flip = false; |
|
264 |
} |
|
265 |
|
|
266 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
267 |
|
|
268 |
private FaceTransform constructNewTransform(final double[][] vert3D) |
|
269 |
{ |
|
270 |
FaceTransform ft = new FaceTransform(); |
|
271 |
|
|
272 |
// compute center of gravity |
|
273 |
ft.vx = 0.0f; |
|
274 |
ft.vy = 0.0f; |
|
275 |
ft.vz = 0.0f; |
|
276 |
int len = vert3D.length; |
|
277 |
|
|
278 |
for (double[] vert : vert3D) |
|
279 |
{ |
|
280 |
ft.vx += vert[0]; |
|
281 |
ft.vy += vert[1]; |
|
282 |
ft.vz += vert[2]; |
|
283 |
} |
|
284 |
|
|
285 |
ft.vx /= len; |
|
286 |
ft.vy /= len; |
|
287 |
ft.vz /= len; |
|
288 |
|
|
289 |
// move all vertices so that their center of gravity is at (0,0,0) |
|
290 |
for (int i=0; i<len; i++) |
|
291 |
{ |
|
292 |
vert3D[i][0] -= ft.vx; |
|
293 |
vert3D[i][1] -= ft.vy; |
|
294 |
vert3D[i][2] -= ft.vz; |
|
295 |
} |
|
296 |
|
|
297 |
// find 3 non-colinear vertices |
|
298 |
int foundIndex = -1; |
|
299 |
|
|
300 |
for(int vertex=2; vertex<len; vertex++) |
|
301 |
{ |
|
302 |
if( !areColinear(vert3D,0,1,vertex) ) |
|
303 |
{ |
|
304 |
foundIndex = vertex; |
|
305 |
break; |
|
306 |
} |
|
307 |
} |
|
308 |
|
|
309 |
// compute the normal vector |
|
310 |
if( foundIndex==-1 ) |
|
311 |
{ |
|
312 |
throw new RuntimeException("all vertices colinear"); |
|
313 |
} |
|
314 |
|
|
315 |
computeNormalVector(vert3D,0,1,foundIndex); |
|
316 |
|
|
317 |
// rotate so that the normal vector becomes (0,0,1) |
|
318 |
double axisX, axisY, axisZ; |
|
319 |
|
|
320 |
if( mBuffer[0]!=0.0f || mBuffer[1]!=0.0f ) |
|
321 |
{ |
|
322 |
axisX = -mBuffer[1]; |
|
323 |
axisY = mBuffer[0]; |
|
324 |
axisZ = 0.0f; |
|
325 |
|
|
326 |
double axiLen = axisX*axisX + axisY*axisY; |
|
327 |
axiLen = Math.sqrt(axiLen); |
|
328 |
axisX /= axiLen; |
|
329 |
axisY /= axiLen; |
|
330 |
axisZ /= axiLen; |
|
331 |
} |
|
332 |
else |
|
333 |
{ |
|
334 |
axisX = 0.0f; |
|
335 |
axisY = 1.0f; |
|
336 |
axisZ = 0.0f; |
|
337 |
} |
|
338 |
|
|
339 |
double cosTheta = mBuffer[2]; |
|
340 |
double sinTheta = Math.sqrt(1-cosTheta*cosTheta); |
|
341 |
double sinHalfTheta = computeSinHalf(cosTheta); |
|
342 |
double cosHalfTheta = computeCosHalf(sinTheta,cosTheta); |
|
343 |
|
|
344 |
mQuat1[0] = axisX*sinHalfTheta; |
|
345 |
mQuat1[1] = axisY*sinHalfTheta; |
|
346 |
mQuat1[2] = axisZ*sinHalfTheta; |
|
347 |
mQuat1[3] = cosHalfTheta; |
|
348 |
mQuat2[0] =-axisX*sinHalfTheta; |
|
349 |
mQuat2[1] =-axisY*sinHalfTheta; |
|
350 |
mQuat2[2] =-axisZ*sinHalfTheta; |
|
351 |
mQuat2[3] = cosHalfTheta; |
|
352 |
|
|
353 |
for (double[] vert : vert3D) |
|
354 |
{ |
|
355 |
quatMultiply(mQuat1, vert , mQuat3); |
|
356 |
quatMultiply(mQuat3, mQuat2, vert ); |
|
357 |
} |
|
358 |
|
|
359 |
// fit the whole thing in a square and remember the scale & 2D vertices |
|
360 |
fitInSquare(ft, vert3D); |
|
361 |
|
|
362 |
// remember the rotation |
|
363 |
ft.qx =-mQuat1[0]; |
|
364 |
ft.qy =-mQuat1[1]; |
|
365 |
ft.qz =-mQuat1[2]; |
|
366 |
ft.qw = mQuat1[3]; |
|
367 |
|
|
368 |
return ft; |
|
369 |
} |
|
370 |
|
|
371 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
372 |
|
|
373 |
private void rotateAllVertices(double[] result, int len, double[] vertices, double sin, double cos) |
|
374 |
{ |
|
375 |
for(int i=0; i<len; i++) |
|
376 |
{ |
|
377 |
result[2*i ] = vertices[2*i ]*cos - vertices[2*i+1]*sin; |
|
378 |
result[2*i+1] = vertices[2*i ]*sin + vertices[2*i+1]*cos; |
|
379 |
} |
|
380 |
} |
|
381 |
|
|
382 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
383 |
|
|
384 |
private double computeScale(double[] v1, double[] v2, int v1i, int v2i) |
|
385 |
{ |
|
386 |
double v1x = v1[2*v1i]; |
|
387 |
double v1y = v1[2*v1i+1]; |
|
388 |
double v2x = v2[2*v2i]; |
|
389 |
double v2y = v2[2*v2i+1]; |
|
390 |
|
|
391 |
double lenSq1 = v1x*v1x + v1y*v1y; |
|
392 |
double lenSq2 = v2x*v2x + v2y*v2y; |
|
393 |
|
|
394 |
return Math.sqrt(lenSq2/lenSq1); |
|
395 |
} |
|
396 |
|
|
397 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
398 |
// valid for 0<angle<2*PI |
|
399 |
|
|
400 |
private double computeSinHalf(double cos) |
|
401 |
{ |
|
402 |
return Math.sqrt((1-cos)/2); |
|
403 |
} |
|
404 |
|
|
405 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
406 |
// valid for 0<angle<2*PI |
|
407 |
|
|
408 |
private double computeCosHalf(double sin, double cos) |
|
409 |
{ |
|
410 |
double cosHalf = Math.sqrt((1+cos)/2); |
|
411 |
return sin<0 ? -cosHalf : cosHalf; |
|
412 |
} |
|
413 |
|
|
414 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
415 |
|
|
416 |
private int computeRotatedIndex(int oldVertex, int len, int rotatedVertex, boolean inverted) |
|
417 |
{ |
|
418 |
int v = (rotatedVertex + (inverted? -oldVertex : oldVertex)); |
|
419 |
if( v>=len ) v-=len; |
|
420 |
if( v< 0 ) v+=len; |
|
421 |
|
|
422 |
return v; |
|
423 |
} |
|
424 |
|
|
425 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
426 |
|
|
427 |
private boolean isScaledVersionOf(double[] newVert, double[] oldVert, int len, int vertex, boolean inverted) |
|
428 |
{ |
|
429 |
int newZeroIndex = computeRotatedIndex(0,len,vertex,inverted); |
|
430 |
double EPSILON = 0.001; |
|
431 |
double scale = computeScale(newVert,oldVert,newZeroIndex,0); |
|
432 |
|
|
433 |
for(int i=1; i<len; i++) |
|
434 |
{ |
|
435 |
int index = computeRotatedIndex(i,len,vertex,inverted); |
|
436 |
|
|
437 |
double horz = oldVert[2*i ] - scale*newVert[2*index ]; |
|
438 |
double vert = oldVert[2*i+1] - scale*newVert[2*index+1]; |
|
439 |
|
|
440 |
if( horz>EPSILON || horz<-EPSILON || vert>EPSILON || vert<-EPSILON ) return false; |
|
441 |
} |
|
442 |
|
|
443 |
return true; |
|
444 |
} |
|
445 |
|
|
446 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
447 |
|
|
448 |
private void mirrorAllVertices(double[] output, int len, double[] input) |
|
449 |
{ |
|
450 |
for(int vertex=0; vertex<len; vertex++) |
|
451 |
{ |
|
452 |
output[2*vertex ] = input[2*vertex ]; |
|
453 |
output[2*vertex+1] =-input[2*vertex+1]; |
|
454 |
} |
|
455 |
} |
|
456 |
|
|
457 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
458 |
|
|
459 |
private void correctInfo(FaceTransform info, double scale, double sin, double cos, int oldSticker, boolean flip) |
|
460 |
{ |
|
461 |
mStickerCoords.remove(info.sticker); |
|
462 |
|
|
463 |
info.flip = flip; |
|
464 |
info.sticker = oldSticker; |
|
465 |
info.scale *= scale; |
|
466 |
|
|
467 |
mQuat1[0] = info.qx; |
|
468 |
mQuat1[1] = info.qy; |
|
469 |
mQuat1[2] = info.qz; |
|
470 |
mQuat1[3] = info.qw; |
|
471 |
|
|
472 |
double sinHalf = computeSinHalf(cos); |
|
473 |
double cosHalf = computeCosHalf(sin,cos); |
|
474 |
|
|
475 |
if( flip ) |
|
476 |
{ |
|
477 |
mQuat3[0] = 0.0f; |
|
478 |
mQuat3[1] = 0.0f; |
|
479 |
mQuat3[2] = sinHalf; |
|
480 |
mQuat3[3] = cosHalf; |
|
481 |
|
|
482 |
mQuat4[0] = 1.0; |
|
483 |
mQuat4[1] = 0.0; |
|
484 |
mQuat4[2] = 0.0; |
|
485 |
mQuat4[3] = 0.0; |
|
486 |
|
|
487 |
quatMultiply( mQuat3, mQuat4, mQuat2 ); |
|
488 |
} |
|
489 |
else |
|
490 |
{ |
|
491 |
mQuat2[0] = 0.0f; |
|
492 |
mQuat2[1] = 0.0f; |
|
493 |
mQuat2[2] = sinHalf; |
|
494 |
mQuat2[3] = cosHalf; |
|
495 |
} |
|
496 |
|
|
497 |
quatMultiply( mQuat1, mQuat2, mQuat3 ); |
|
498 |
|
|
499 |
info.qx = mQuat3[0]; |
|
500 |
info.qy = mQuat3[1]; |
|
501 |
info.qz = mQuat3[2]; |
|
502 |
info.qw = mQuat3[3]; |
|
503 |
} |
|
504 |
|
|
505 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
506 |
|
|
507 |
private void printVert(double[] buffer) |
|
508 |
{ |
|
509 |
int len = buffer.length/2; |
|
510 |
String str = ""; |
|
511 |
|
|
512 |
for(int i=0; i<len; i++) |
|
513 |
{ |
|
514 |
str += (" ("+buffer[2*i]+" , "+buffer[2*i+1]+" ) "); |
|
515 |
} |
|
516 |
|
|
517 |
android.util.Log.d("D", str); |
|
518 |
} |
|
519 |
|
|
520 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
521 |
|
|
522 |
private boolean foundVertex(FaceTransform info, double[] buffer, int len, double[] newVert, |
|
523 |
double[] oldVert, double lenFirstOld, int oldSticker, boolean inverted) |
|
524 |
{ |
|
525 |
for(int vertex=0; vertex<len; vertex++) |
|
526 |
{ |
|
527 |
double newX = newVert[2*vertex ]; |
|
528 |
double newY = newVert[2*vertex+1]; |
|
529 |
double lenIthNew = Math.sqrt(newX*newX + newY*newY); |
|
530 |
double cos = QuatHelper.computeCos( oldVert[0], oldVert[1], newX, newY, lenIthNew, lenFirstOld); |
|
531 |
double sin = QuatHelper.computeSin( oldVert[0], oldVert[1], newX, newY, lenIthNew, lenFirstOld); |
|
532 |
|
|
533 |
rotateAllVertices(buffer,len,newVert,sin,cos); |
|
534 |
|
|
535 |
if( isScaledVersionOf(buffer,oldVert,len,vertex,inverted) ) |
|
536 |
{ |
|
537 |
int newZeroIndex = computeRotatedIndex(0,len,vertex,inverted); |
|
538 |
double scale = computeScale(oldVert,newVert,0,newZeroIndex); |
|
539 |
correctInfo(info,scale,sin,cos,oldSticker,inverted); |
|
540 |
return true; |
|
541 |
} |
|
542 |
} |
|
543 |
|
|
544 |
return false; |
|
545 |
} |
|
546 |
|
|
547 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
548 |
|
|
549 |
private boolean successfullyCollapsedStickers(final FaceTransform newInfo, final FaceTransform oldInfo) |
|
550 |
{ |
|
551 |
StickerCoords sNewInfo = mStickerCoords.get(newInfo.sticker); |
|
552 |
StickerCoords sOldInfo = mStickerCoords.get(oldInfo.sticker); |
|
553 |
double[] newVert = sNewInfo.vertices; |
|
554 |
double[] oldVert = sOldInfo.vertices; |
|
555 |
int oldLen = oldVert.length; |
|
556 |
int newLen = newVert.length; |
|
557 |
|
|
558 |
if( oldLen == newLen ) |
|
559 |
{ |
|
560 |
int oldSticker = oldInfo.sticker; |
|
561 |
double[] buffer1 = new double[oldLen]; |
|
562 |
double lenFirstOld = Math.sqrt(oldVert[0]*oldVert[0] + oldVert[1]*oldVert[1]); |
|
563 |
if( foundVertex(newInfo, buffer1, oldLen/2, newVert, oldVert, lenFirstOld, oldSticker, false) ) return true; |
|
564 |
double[] buffer2 = new double[oldLen]; |
|
565 |
mirrorAllVertices(buffer2, newLen/2, newVert); |
|
566 |
if( foundVertex(newInfo, buffer1, oldLen/2, buffer2, oldVert, lenFirstOld, oldSticker, true ) ) return true; |
|
567 |
} |
|
568 |
|
|
569 |
return false; |
|
570 |
} |
|
571 |
|
|
572 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
573 |
|
|
574 |
private double[][] constructVert(double[][] vertices, int[] index) |
|
575 |
{ |
|
576 |
int len = index.length; |
|
577 |
double[][] ret = new double[len][4]; |
|
578 |
|
|
579 |
for(int i=0; i<len; i++) |
|
580 |
{ |
|
581 |
ret[i][0] = vertices[index[i]][0]; |
|
582 |
ret[i][1] = vertices[index[i]][1]; |
|
583 |
ret[i][2] = vertices[index[i]][2]; |
|
584 |
ret[i][3] = 1.0f; |
|
585 |
} |
|
586 |
|
|
587 |
return ret; |
|
588 |
} |
|
589 |
|
|
590 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
591 |
|
|
592 |
private void prepareAndRoundCorners(MeshBase mesh, double[][] vertices, |
|
593 |
float[][] corners, int[] cornerIndexes, |
|
594 |
float[][] centers, int[] centerIndexes ) |
|
595 |
{ |
|
596 |
int lenV = vertices.length; |
|
597 |
Static3D[] staticVert = new Static3D[1]; |
|
598 |
Static3D center = new Static3D(0,0,0); |
|
599 |
|
|
600 |
for(int v=0; v<lenV; v++) |
|
601 |
{ |
|
602 |
staticVert[0] = new Static3D( (float)vertices[v][0], (float)vertices[v][1], (float)vertices[v][2]); |
|
603 |
|
|
604 |
int cent = centerIndexes[v]; |
|
605 |
|
|
606 |
if( cent>=0 ) |
|
607 |
{ |
|
608 |
center.set( centers[cent][0], centers[cent][1], centers[cent][2]); |
|
609 |
|
|
610 |
int corn = cornerIndexes[v]; |
|
611 |
|
|
612 |
if( corn>=0 ) |
|
613 |
{ |
|
614 |
float strength = corners[corn][0]; |
|
615 |
float radius = corners[corn][1]; |
|
616 |
roundCorners(mesh, center, staticVert, strength, radius); |
|
617 |
} |
|
618 |
} |
|
619 |
} |
|
620 |
} |
|
621 |
|
|
622 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
623 |
|
|
624 |
private void correctComponents(MeshBase mesh, int numComponents) |
|
625 |
{ |
|
626 |
int numTexToBeAdded = numComponents-mesh.getNumTexComponents(); |
|
627 |
|
|
628 |
mesh.mergeEffComponents(); |
|
629 |
|
|
630 |
for(int i=0; i<numTexToBeAdded; i++ ) mesh.addEmptyTexComponent(); |
|
631 |
} |
|
632 |
|
|
633 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
634 |
|
|
635 |
private void printTransform(FaceTransform f) |
|
636 |
{ |
|
637 |
android.util.Log.e("D", "q=("+f.qx+", "+f.qy+", "+f.qz+", "+f.qw+") v=(" |
|
638 |
+f.vx+", "+f.vy+", "+f.vz+") scale="+f.scale+" sticker="+f.sticker); |
|
639 |
} |
|
640 |
|
|
641 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
642 |
// PUBLIC |
|
643 |
|
|
644 |
public float[] computeBands(float H, int alpha, float dist, float K, int N) |
|
645 |
{ |
|
646 |
float[] bands = new float[2*N]; |
|
647 |
|
|
648 |
bands[0] = 1.0f; |
|
649 |
bands[1] = 0.0f; |
|
650 |
|
|
651 |
float beta = (float)Math.atan(dist*Math.tan(Math.PI*alpha/180)); |
|
652 |
float sinBeta = (float)Math.sin(beta); |
|
653 |
float cosBeta = (float)Math.cos(beta); |
|
654 |
float R = cosBeta<1.0f ? H/(1.0f-cosBeta) : 0.0f; |
|
655 |
float D = R*sinBeta; |
|
656 |
float B = h(R,sinBeta,K*beta); |
|
657 |
|
|
658 |
if( D>1.0f ) |
|
659 |
{ |
|
660 |
for(int i=1; i<N; i++) |
|
661 |
{ |
|
662 |
bands[2*i ] = (float)(N-1-i)/(N-1); |
|
663 |
bands[2*i+1] = H*(1-bands[2*i]); |
|
664 |
} |
|
665 |
} |
|
666 |
else |
|
667 |
{ |
|
668 |
int K2 = (int)((N-3)*K); |
|
669 |
int K1 = (N-3)-K2; |
|
670 |
|
|
671 |
for(int i=0; i<=K1; i++) |
|
672 |
{ |
|
673 |
float angle = K*beta + (1-K)*beta*(K1-i)/(K1+1); |
|
674 |
float x = h(R,sinBeta,angle); |
|
675 |
bands[2*i+2] = 1.0f - x; |
|
676 |
bands[2*i+3] = g(R,D,x,cosBeta); |
|
677 |
} |
|
678 |
|
|
679 |
for(int i=0; i<=K2; i++) |
|
680 |
{ |
|
681 |
float x = (1-B)*(i+1)/(K2+1) + B; |
|
682 |
bands[2*K1+2 + 2*i+2] = 1.0f - x; |
|
683 |
bands[2*K1+2 + 2*i+3] = g(R,D,f(D,B,x),cosBeta); |
|
684 |
} |
|
685 |
} |
|
686 |
|
|
687 |
bands[2*N-2] = 0.0f; |
|
688 |
bands[2*N-1] = H; |
|
689 |
|
|
690 |
return bands; |
|
691 |
} |
|
692 |
|
|
693 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
694 |
|
|
695 |
public void roundCorners(MeshBase mesh, Static3D center, Static3D[] vertices, float strength, float regionRadius) |
|
696 |
{ |
|
697 |
Static4D reg= new Static4D(0,0,0,regionRadius); |
|
698 |
|
|
699 |
float centX = center.get0(); |
|
700 |
float centY = center.get1(); |
|
701 |
float centZ = center.get2(); |
|
702 |
|
|
703 |
for (Static3D vertex : vertices) |
|
704 |
{ |
|
705 |
float x = strength*(centX - vertex.get0()); |
|
706 |
float y = strength*(centY - vertex.get1()); |
|
707 |
float z = strength*(centZ - vertex.get2()); |
|
708 |
|
|
709 |
VertexEffect effect = new VertexEffectDeform(new Static3D(x,y,z), RADIUS, vertex, reg); |
|
710 |
mesh.apply(effect); |
|
711 |
} |
|
712 |
} |
|
713 |
|
|
714 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
715 |
|
|
716 |
public void printStickerCoords() |
|
717 |
{ |
|
718 |
int stickers = mStickerCoords.size(); |
|
719 |
|
|
720 |
android.util.Log.d("D", "---- STICKER COORDS ----"); |
|
721 |
|
|
722 |
for(int s=0; s<stickers; s++) |
|
723 |
{ |
|
724 |
String ver = "{ "; |
|
725 |
StickerCoords info = mStickerCoords.get(s); |
|
726 |
int len = info.vertices.length/2; |
|
727 |
|
|
728 |
for(int i =0; i<len; i++) |
|
729 |
{ |
|
730 |
if( i!=0 ) ver += ", "; |
|
731 |
ver += ( (float)info.vertices[2*i]+"f, "+(float)info.vertices[2*i+1]+"f"); |
|
732 |
} |
|
733 |
|
|
734 |
ver += " }"; |
|
735 |
android.util.Log.d("D", ver); |
|
736 |
} |
|
737 |
|
|
738 |
android.util.Log.d("D", "---- END STICKER COORDS ----"); |
|
739 |
} |
|
740 |
|
|
741 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
742 |
|
|
743 |
public void printFaceTransform() |
|
744 |
{ |
|
745 |
android.util.Log.d("D", "---- OLD FACE TRANSFORM ---"); |
|
746 |
|
|
747 |
int oldfaces = mOldFaceTransf.size(); |
|
748 |
|
|
749 |
for(int f=0; f<oldfaces; f++) |
|
750 |
{ |
|
751 |
printTransform(mOldFaceTransf.get(f)); |
|
752 |
} |
|
753 |
|
|
754 |
android.util.Log.d("D", "---- NEW FACE TRANSFORM ---"); |
|
755 |
|
|
756 |
int newfaces = mNewFaceTransf.size(); |
|
757 |
|
|
758 |
for(int f=0; f<newfaces; f++) |
|
759 |
{ |
|
760 |
printTransform(mNewFaceTransf.get(f)); |
|
761 |
} |
|
762 |
} |
|
763 |
|
|
764 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
765 |
|
|
766 |
public void clear() |
|
767 |
{ |
|
768 |
mStickerCoords.clear(); |
|
769 |
mNewFaceTransf.clear(); |
|
770 |
mOldFaceTransf.clear(); |
|
771 |
} |
|
772 |
|
|
773 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
774 |
|
|
775 |
public void createNewFaceTransform( final double[][] vertices, final int[][] indexes) |
|
776 |
{ |
|
777 |
FaceTransform ft; |
|
778 |
int numNew = mNewFaceTransf.size(); |
|
779 |
|
|
780 |
for(int i=0; i<numNew; i++) |
|
781 |
{ |
|
782 |
ft = mNewFaceTransf.remove(0); |
|
783 |
mOldFaceTransf.add(ft); |
|
784 |
} |
|
785 |
|
|
786 |
int numFaces = indexes.length; |
|
787 |
int numOld = mOldFaceTransf.size(); |
|
788 |
|
|
789 |
for (int face=0; face<numFaces; face++) |
|
790 |
{ |
|
791 |
boolean collapsed = false; |
|
792 |
|
|
793 |
double[][] vert = constructVert(vertices, indexes[face]); |
|
794 |
FaceTransform newT = constructNewTransform(vert); |
|
795 |
|
|
796 |
for (int old=0; !collapsed && old<numOld; old++) |
|
797 |
{ |
|
798 |
ft = mOldFaceTransf.get(old); |
|
799 |
if (successfullyCollapsedStickers(newT, ft)) collapsed = true; |
|
800 |
} |
|
801 |
|
|
802 |
for (int pre=0; !collapsed && pre<face; pre++) |
|
803 |
{ |
|
804 |
ft = mNewFaceTransf.get(pre); |
|
805 |
if (successfullyCollapsedStickers(newT, ft)) collapsed = true; |
|
806 |
} |
|
807 |
|
|
808 |
mNewFaceTransf.add(newT); |
|
809 |
} |
|
810 |
} |
|
811 |
|
|
812 |
|
|
813 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
814 |
|
|
815 |
public void createNewFaceTransform(final ObjectShape shape) |
|
816 |
{ |
|
817 |
double[][] vertices = shape.getVertices(); |
|
818 |
int[][] indices = shape.getVertIndices(); |
|
819 |
createNewFaceTransform(vertices,indices); |
|
820 |
} |
|
821 |
|
|
822 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
823 |
|
|
824 |
private void computeConvexityCenter(double[] out, float[] in, FaceTransform ft) |
|
825 |
{ |
|
826 |
if( in==null ) |
|
827 |
{ |
|
828 |
out[0] = out[1] = 0.0f; |
|
829 |
} |
|
830 |
else |
|
831 |
{ |
|
832 |
out[0] = in[0] - ft.vx; |
|
833 |
out[1] = in[1] - ft.vy; |
|
834 |
out[2] = in[2] - ft.vz; |
|
835 |
out[3] = 1.0f; |
|
836 |
|
|
837 |
mQuat1[0] =-ft.qx; |
|
838 |
mQuat1[1] =-ft.qy; |
|
839 |
mQuat1[2] =-ft.qz; |
|
840 |
mQuat1[3] = ft.qw; |
|
841 |
|
|
842 |
mQuat2[0] = -mQuat1[0]; |
|
843 |
mQuat2[1] = -mQuat1[1]; |
|
844 |
mQuat2[2] = -mQuat1[2]; |
|
845 |
mQuat2[3] = +mQuat1[3]; |
|
846 |
|
|
847 |
quatMultiply(mQuat1, out , mQuat3); |
|
848 |
quatMultiply(mQuat3, mQuat2, out ); |
Also available in: Unified diff
Prepare the 'objectlib' package to be separated into a library module