Project

General

Profile

Download (24.6 KB) Statistics
| Branch: | Revision:

examples / src / main / java / org / distorted / examples / meshfile / FactoryCubit.java @ 4d883a92

1 7edab735 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
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.examples.meshfile;
21
22 1b85f172 Leszek Koltunski
import org.distorted.library.effect.MatrixEffect;
23
import org.distorted.library.effect.MatrixEffectMove;
24
import org.distorted.library.effect.MatrixEffectQuaternion;
25
import org.distorted.library.effect.MatrixEffectScale;
26 7edab735 Leszek Koltunski
import org.distorted.library.effect.VertexEffect;
27
import org.distorted.library.effect.VertexEffectDeform;
28
import org.distorted.library.mesh.MeshBase;
29
import org.distorted.library.mesh.MeshJoined;
30
import org.distorted.library.mesh.MeshPolygon;
31
import org.distorted.library.type.Static1D;
32
import org.distorted.library.type.Static3D;
33
import org.distorted.library.type.Static4D;
34
35 33647db9 Leszek Koltunski
import java.util.ArrayList;
36
37 7edab735 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
38
39 55f20739 Leszek Koltunski
class FactoryCubit
40 7edab735 Leszek Koltunski
  {
41 4d883a92 Leszek Koltunski
  private static final double[] mBuffer = new double[3];
42
  private static final double[] mQuat1  = new double[4];
43
  private static final double[] mQuat2  = new double[4];
44
  private static final double[] mQuat3  = new double[4];
45 6d020cb6 Leszek Koltunski
46 7edab735 Leszek Koltunski
  private static final Static1D RADIUS = new Static1D(1);
47
48 55f20739 Leszek Koltunski
  private static FactoryCubit mThis;
49 7edab735 Leszek Koltunski
50 1b85f172 Leszek Koltunski
  private static class StickerInfo
51 33647db9 Leszek Koltunski
    {
52 4d883a92 Leszek Koltunski
    double[] vertices;
53 1b85f172 Leszek Koltunski
    }
54
55
  private static class FaceInfo
56
    {
57
    int sticker;
58 4d883a92 Leszek Koltunski
    double vx,vy,vz;
59
    double scale;
60
    double qx,qy,qz,qw;
61 33647db9 Leszek Koltunski
    boolean flip;
62
    }
63
64 1b85f172 Leszek Koltunski
  private static final ArrayList<FaceInfo>       mFaceInfo = new ArrayList<>();
65
  private static final ArrayList<StickerInfo> mStickerInfo = new ArrayList<>();
66 33647db9 Leszek Koltunski
67 7edab735 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
68
69 55f20739 Leszek Koltunski
  private FactoryCubit()
70 7edab735 Leszek Koltunski
    {
71
72
    }
73
74
///////////////////////////////////////////////////////////////////////////////////////////////////
75
76 55f20739 Leszek Koltunski
  public static FactoryCubit getInstance()
77 7edab735 Leszek Koltunski
    {
78 55f20739 Leszek Koltunski
    if( mThis==null ) mThis = new FactoryCubit();
79 7edab735 Leszek Koltunski
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 55f20739 Leszek Koltunski
  float[] computeBands(float H, int alpha, float dist, float K, int N)
143 7edab735 Leszek Koltunski
    {
144
    float[] bands = new float[2*N];
145
146
    bands[0] = 1.0f;
147
    bands[1] = 0.0f;
148
149
    float beta = (float)Math.atan(dist*Math.tan(Math.PI*alpha/180));
150
    float sinBeta = (float)Math.sin(beta);
151
    float cosBeta = (float)Math.cos(beta);
152
    float R = cosBeta<1.0f ? H/(1.0f-cosBeta) : 0.0f;
153
    float D = R*sinBeta;
154
    float B = h(R,sinBeta,K*beta);
155
156
    if( D>1.0f )
157
      {
158
      for(int i=1; i<N; i++)
159
        {
160
        bands[2*i  ] = (float)(N-1-i)/(N-1);
161
        bands[2*i+1] = H*(1-bands[2*i]);
162
        }
163
      }
164
    else
165
      {
166 55f20739 Leszek Koltunski
      int K2 = (int)((N-3)*K);
167 7edab735 Leszek Koltunski
      int K1 = (N-3)-K2;
168
169
      for(int i=0; i<=K1; i++)
170
        {
171
        float angle = K*beta + (1-K)*beta*(K1-i)/(K1+1);
172
        float x = h(R,sinBeta,angle);
173
        bands[2*i+2] = 1.0f - x;
174
        bands[2*i+3] = g(R,D,x,cosBeta);
175
        }
176
177
      for(int i=0; i<=K2; i++)
178
        {
179
        float x = (1-B)*(i+1)/(K2+1) + B;
180
        bands[2*K1+2 + 2*i+2] = 1.0f - x;
181
        bands[2*K1+2 + 2*i+3] = g(R,D,f(D,B,x),cosBeta);
182
        }
183
      }
184
185 55f20739 Leszek Koltunski
    bands[2*N-2] = 0.0f;
186
    bands[2*N-1] =    H;
187
188 7edab735 Leszek Koltunski
    return bands;
189
    }
190
191
///////////////////////////////////////////////////////////////////////////////////////////////////
192
193
  private void roundCorners(MeshBase mesh, Static3D center, Static3D[] vertices, float strength, float regionRadius)
194
    {
195 1b85f172 Leszek Koltunski
    Static4D region= new Static4D(0,0,0,regionRadius);
196 7edab735 Leszek Koltunski
197
    float centX = center.get0();
198
    float centY = center.get1();
199
    float centZ = center.get2();
200
201
    for (Static3D vertex : vertices)
202
      {
203
      float x = strength*(centX - vertex.get0());
204
      float y = strength*(centY - vertex.get1());
205
      float z = strength*(centZ - vertex.get2());
206
207 1b85f172 Leszek Koltunski
      VertexEffect effect = new VertexEffectDeform(new Static3D(x,y,z), RADIUS, vertex, region);
208 7edab735 Leszek Koltunski
      mesh.apply(effect);
209
      }
210
    }
211
212
///////////////////////////////////////////////////////////////////////////////////////////////////
213
214 4d883a92 Leszek Koltunski
  private boolean areColinear(double[][] vertices, int index1, int index2, int index3)
215 7edab735 Leszek Koltunski
    {
216 4d883a92 Leszek Koltunski
    double x1 = vertices[index1][0];
217
    double y1 = vertices[index1][1];
218
    double z1 = vertices[index1][2];
219
    double x2 = vertices[index2][0];
220
    double y2 = vertices[index2][1];
221
    double z2 = vertices[index2][2];
222
    double x3 = vertices[index3][0];
223
    double y3 = vertices[index3][1];
224
    double z3 = vertices[index3][2];
225
226
    double v1x = x2-x1;
227
    double v1y = y2-y1;
228
    double v1z = z2-z1;
229
    double v2x = x3-x1;
230
    double v2y = y3-y1;
231
    double v2z = z3-z1;
232
233
    double A = Math.sqrt( (v1x*v1x+v1y*v1y+v1z*v1z) / (v2x*v2x+v2y*v2y+v2z*v2z) );
234 7edab735 Leszek Koltunski
235 33647db9 Leszek Koltunski
    return (v1x==A*v2x && v1y==A*v2y && v1z==A*v2z);
236 7edab735 Leszek Koltunski
    }
237
238
///////////////////////////////////////////////////////////////////////////////////////////////////
239
240 4d883a92 Leszek Koltunski
  private void computeNormalVector(double[][] vertices, int index1, int index2, int index3)
241 7edab735 Leszek Koltunski
    {
242 4d883a92 Leszek Koltunski
    double x1 = vertices[index1][0];
243
    double y1 = vertices[index1][1];
244
    double z1 = vertices[index1][2];
245
    double x2 = vertices[index2][0];
246
    double y2 = vertices[index2][1];
247
    double z2 = vertices[index2][2];
248
    double x3 = vertices[index3][0];
249
    double y3 = vertices[index3][1];
250
    double z3 = vertices[index3][2];
251
252
    double v1x = x2-x1;
253
    double v1y = y2-y1;
254
    double v1z = z2-z1;
255
    double v2x = x3-x1;
256
    double v2y = y3-y1;
257
    double v2z = z3-z1;
258 7edab735 Leszek Koltunski
259 33647db9 Leszek Koltunski
    mBuffer[0] = v1y*v2z - v2y*v1z;
260
    mBuffer[1] = v1z*v2x - v2z*v1x;
261
    mBuffer[2] = v1x*v2y - v2x*v1y;
262 ef231eba Leszek Koltunski
263 4d883a92 Leszek Koltunski
    double len = mBuffer[0]*mBuffer[0] + mBuffer[1]*mBuffer[1] + mBuffer[2]*mBuffer[2];
264
    len = Math.sqrt(len);
265 140f2c4e Leszek Koltunski
    mBuffer[0] /= len;
266
    mBuffer[1] /= len;
267
    mBuffer[2] /= len;
268 7edab735 Leszek Koltunski
    }
269
270
///////////////////////////////////////////////////////////////////////////////////////////////////
271 33647db9 Leszek Koltunski
// return quat1*quat2
272 7edab735 Leszek Koltunski
273 4d883a92 Leszek Koltunski
  private static void quatMultiply( double[] quat1, double[] quat2, double[] result )
274 7edab735 Leszek Koltunski
    {
275 4d883a92 Leszek Koltunski
    double qx = quat1[0];
276
    double qy = quat1[1];
277
    double qz = quat1[2];
278
    double qw = quat1[3];
279 7edab735 Leszek Koltunski
280 4d883a92 Leszek Koltunski
    double rx = quat2[0];
281
    double ry = quat2[1];
282
    double rz = quat2[2];
283
    double rw = quat2[3];
284 7edab735 Leszek Koltunski
285 33647db9 Leszek Koltunski
    result[0] = rw*qx - rz*qy + ry*qz + rx*qw;
286
    result[1] = rw*qy + rz*qx + ry*qw - rx*qz;
287
    result[2] = rw*qz + rz*qw - ry*qx + rx*qy;
288
    result[3] = rw*qw - rz*qz - ry*qy - rx*qx;
289 7edab735 Leszek Koltunski
    }
290
291
///////////////////////////////////////////////////////////////////////////////////////////////////
292
293 4d883a92 Leszek Koltunski
  private void fitInSquare(FaceInfo info, double[][] vert3D)
294 7edab735 Leszek Koltunski
    {
295 4d883a92 Leszek Koltunski
    double minX = Double.MAX_VALUE;
296
    double maxX =-Double.MAX_VALUE;
297
    double minY = Double.MAX_VALUE;
298
    double maxY =-Double.MAX_VALUE;
299 55f20739 Leszek Koltunski
300 4d883a92 Leszek Koltunski
    for (double[] vert : vert3D)
301 33647db9 Leszek Koltunski
      {
302 4d883a92 Leszek Koltunski
      double x = vert[0];
303
      double y = vert[1];
304 55f20739 Leszek Koltunski
305 33647db9 Leszek Koltunski
      if (x > maxX) maxX = x;
306
      if (x < minX) minX = x;
307
      if (y > maxY) maxY = y;
308
      if (y < minY) minY = y;
309
      }
310 55f20739 Leszek Koltunski
311 33647db9 Leszek Koltunski
    info.scale = Math.max(maxX-minX,maxY-minY);
312 ef231eba Leszek Koltunski
313 33647db9 Leszek Koltunski
    int len = vert3D.length;
314 1b85f172 Leszek Koltunski
    StickerInfo sInfo = new StickerInfo();
315 4d883a92 Leszek Koltunski
    sInfo.vertices = new double[2*len];
316 55f20739 Leszek Koltunski
317 33647db9 Leszek Koltunski
    for( int vertex=0; vertex<len; vertex++ )
318 55f20739 Leszek Koltunski
      {
319 1b85f172 Leszek Koltunski
      sInfo.vertices[2*vertex  ] = vert3D[vertex][0] / info.scale;
320
      sInfo.vertices[2*vertex+1] = vert3D[vertex][1] / info.scale;
321 55f20739 Leszek Koltunski
      }
322
323 28f4aba0 Leszek Koltunski
    mStickerInfo.add(sInfo);
324
325
    info.sticker = mStickerInfo.size() -1;
326 33647db9 Leszek Koltunski
    info.flip = false;
327 55f20739 Leszek Koltunski
    }
328
329
///////////////////////////////////////////////////////////////////////////////////////////////////
330
331 4d883a92 Leszek Koltunski
  private void constructNew(FaceInfo info, final double[][] vert3D)
332 55f20739 Leszek Koltunski
    {
333 33647db9 Leszek Koltunski
    // compute center of gravity
334
    info.vx = 0.0f;
335
    info.vy = 0.0f;
336
    info.vz = 0.0f;
337
    int len = vert3D.length;
338 55f20739 Leszek Koltunski
339 4d883a92 Leszek Koltunski
    for (double[] vert : vert3D)
340 55f20739 Leszek Koltunski
      {
341 33647db9 Leszek Koltunski
      info.vx += vert[0];
342
      info.vy += vert[1];
343
      info.vz += vert[2];
344 55f20739 Leszek Koltunski
      }
345
346 33647db9 Leszek Koltunski
    info.vx /= len;
347
    info.vy /= len;
348
    info.vz /= len;
349 55f20739 Leszek Koltunski
350 33647db9 Leszek Koltunski
    // move all vertices so that their center of gravity is at (0,0,0)
351
    for (int i=0; i<len; i++)
352 7cd30f7c Leszek Koltunski
      {
353 33647db9 Leszek Koltunski
      vert3D[i][0] -= info.vx;
354
      vert3D[i][1] -= info.vy;
355
      vert3D[i][2] -= info.vz;
356 7cd30f7c Leszek Koltunski
      }
357
358 33647db9 Leszek Koltunski
    // find 3 non-colinear vertices
359
    int foundIndex = -1;
360 7cd30f7c Leszek Koltunski
361 33647db9 Leszek Koltunski
    for(int vertex=2; vertex<len; vertex++)
362 7cd30f7c Leszek Koltunski
      {
363 33647db9 Leszek Koltunski
      if( !areColinear(vert3D,0,1,vertex) )
364
        {
365
        foundIndex = vertex;
366
        break;
367
        }
368 7cd30f7c Leszek Koltunski
      }
369
370 33647db9 Leszek Koltunski
    // compute the normal vector
371
    if( foundIndex==-1 )
372
      {
373
      throw new RuntimeException("all vertices colinear");
374
      }
375 7cd30f7c Leszek Koltunski
376 33647db9 Leszek Koltunski
    computeNormalVector(vert3D,0,1,foundIndex);
377
378 140f2c4e Leszek Koltunski
    // rotate so that the normal vector becomes (0,0,1)
379 4d883a92 Leszek Koltunski
    double axisX, axisY, axisZ;
380 140f2c4e Leszek Koltunski
381 ef231eba Leszek Koltunski
    if( mBuffer[0]!=0.0f || mBuffer[1]!=0.0f )
382 33647db9 Leszek Koltunski
      {
383 140f2c4e Leszek Koltunski
      axisX = -mBuffer[1];
384
      axisY =  mBuffer[0];
385
      axisZ = 0.0f;
386 ef231eba Leszek Koltunski
387 4d883a92 Leszek Koltunski
      double axiLen = axisX*axisX + axisY*axisY;
388
      axiLen = Math.sqrt(axiLen);
389 ef231eba Leszek Koltunski
      axisX /= axiLen;
390
      axisY /= axiLen;
391
      axisZ /= axiLen;
392 140f2c4e Leszek Koltunski
      }
393
    else
394
      {
395
      axisX = 0.0f;
396
      axisY = 1.0f;
397
      axisZ = 0.0f;
398
      }
399 ef231eba Leszek Koltunski
400 4d883a92 Leszek Koltunski
    double cosTheta = mBuffer[2];
401
    double sinTheta = Math.sqrt(1-cosTheta*cosTheta);
402
    double sinHalfTheta = computeSinHalf(cosTheta);
403
    double cosHalfTheta = computeCosHalf(sinTheta,cosTheta);
404 ef231eba Leszek Koltunski
405 140f2c4e Leszek Koltunski
    mQuat1[0] = axisX*sinHalfTheta;
406
    mQuat1[1] = axisY*sinHalfTheta;
407
    mQuat1[2] = axisZ*sinHalfTheta;
408
    mQuat1[3] = cosHalfTheta;
409 28f4aba0 Leszek Koltunski
    mQuat2[0] =-axisX*sinHalfTheta;
410
    mQuat2[1] =-axisY*sinHalfTheta;
411
    mQuat2[2] =-axisZ*sinHalfTheta;
412
    mQuat2[3] = cosHalfTheta;
413 ef231eba Leszek Koltunski
414 4d883a92 Leszek Koltunski
    for (double[] vert : vert3D)
415 140f2c4e Leszek Koltunski
      {
416 28f4aba0 Leszek Koltunski
      quatMultiply(mQuat1, vert  , mQuat3);
417
      quatMultiply(mQuat3, mQuat2, vert  );
418 33647db9 Leszek Koltunski
      }
419 7cd30f7c Leszek Koltunski
420 33647db9 Leszek Koltunski
    // fit the whole thing in a square and remember the scale & 2D vertices
421
    fitInSquare(info, vert3D);
422 7cd30f7c Leszek Koltunski
423 33647db9 Leszek Koltunski
    // remember the rotation
424 28f4aba0 Leszek Koltunski
    info.qx =-mQuat1[0];
425
    info.qy =-mQuat1[1];
426
    info.qz =-mQuat1[2];
427
    info.qw = mQuat1[3];
428 7cd30f7c Leszek Koltunski
    }
429
430 fe032f52 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
431
432 4d883a92 Leszek Koltunski
  private double computeCos(double oldX, double oldY, double newX, double newY, double len1, double len2)
433 fe032f52 Leszek Koltunski
    {
434 4d883a92 Leszek Koltunski
    double ret =  (oldX*newX+oldY*newY) / (len1*len2);
435 28f4aba0 Leszek Koltunski
436 4d883a92 Leszek Koltunski
    if( ret> 1.0f ) return  1.0;
437
    if( ret<-1.0f ) return -1.0;
438 28f4aba0 Leszek Koltunski
439
    return ret;
440 fe032f52 Leszek Koltunski
    }
441
442 b3d28a81 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
443 4d883a92 Leszek Koltunski
// sin of (signed!) angle between vectors 'old' and 'new', counterclockwise!
444 b3d28a81 Leszek Koltunski
445 4d883a92 Leszek Koltunski
  private double computeSin(double oldX, double oldY, double newX, double newY, double len1, double len2)
446 b3d28a81 Leszek Koltunski
    {
447 4d883a92 Leszek Koltunski
    double ret = (newX*oldY-oldX*newY) / (len1*len2);
448 28f4aba0 Leszek Koltunski
449 4d883a92 Leszek Koltunski
    if( ret> 1.0f ) return  1.0;
450
    if( ret<-1.0f ) return -1.0;
451 28f4aba0 Leszek Koltunski
452
    return ret;
453 b3d28a81 Leszek Koltunski
    }
454
455 54e47d9b Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
456
457 4d883a92 Leszek Koltunski
  private void rotateAllVertices(double[] result, int len, double[] vertices, double sin, double cos)
458 54e47d9b Leszek Koltunski
    {
459 33647db9 Leszek Koltunski
    for(int i=0; i<len; i++)
460 54e47d9b Leszek Koltunski
      {
461 33647db9 Leszek Koltunski
      result[2*i  ] = vertices[2*i  ]*cos - vertices[2*i+1]*sin;
462
      result[2*i+1] = vertices[2*i  ]*sin + vertices[2*i+1]*cos;
463 54e47d9b Leszek Koltunski
      }
464
    }
465
466 6d020cb6 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
467
468 4d883a92 Leszek Koltunski
  private double computeScale(double[] v1, double[] v2)
469 6d020cb6 Leszek Koltunski
    {
470 4d883a92 Leszek Koltunski
    double lenSq1 = v1[0]*v1[0] + v1[1]*v1[1];
471
    double lenSq2 = v2[0]*v2[0] + v2[1]*v2[1];
472
473
    return Math.sqrt(lenSq2/lenSq1);
474
    }
475
476
///////////////////////////////////////////////////////////////////////////////////////////////////
477
478
  private double computeSinHalf(double cos)
479
    {
480
    return Math.sqrt((1-cos)/2);
481
    }
482
483
///////////////////////////////////////////////////////////////////////////////////////////////////
484
485
  private double computeCosHalf(double sin, double cos)
486
    {
487
    double cosHalf = Math.sqrt((1+cos)/2);
488
    return sin<0 ? -cosHalf : cosHalf;
489
    }
490
491
///////////////////////////////////////////////////////////////////////////////////////////////////
492
493
  private boolean isScaledVersionOf(double[] newVert, double[] oldVert, int len)
494
    {
495
    double EPSILON = 0.001;
496
    double scale = computeScale(newVert,oldVert);
497 55f20739 Leszek Koltunski
498 33647db9 Leszek Koltunski
    for(int i=1; i<len; i++)
499
      {
500 4d883a92 Leszek Koltunski
      double horz = oldVert[2*i  ] - scale*newVert[2*i  ];
501
      double vert = oldVert[2*i+1] - scale*newVert[2*i+1];
502 7edab735 Leszek Koltunski
503 33647db9 Leszek Koltunski
      if( horz>EPSILON || horz<-EPSILON || vert>EPSILON || vert<-EPSILON ) return false;
504
      }
505 55f20739 Leszek Koltunski
506 33647db9 Leszek Koltunski
    return true;
507 7edab735 Leszek Koltunski
    }
508
509
///////////////////////////////////////////////////////////////////////////////////////////////////
510
511 4d883a92 Leszek Koltunski
  private void mirrorAllVertices(double[] output, int len, double[] input)
512 7edab735 Leszek Koltunski
    {
513 33647db9 Leszek Koltunski
    for(int vertex=0; vertex<len; vertex++)
514
      {
515
      output[2*vertex  ] = input[2*vertex  ];
516
      output[2*vertex+1] =-input[2*vertex+1];
517
      }
518 7edab735 Leszek Koltunski
    }
519
520
///////////////////////////////////////////////////////////////////////////////////////////////////
521
522 4d883a92 Leszek Koltunski
  private void correctInfo(FaceInfo info, double scale, double sin, double cos, int oldSticker, boolean flip)
523 7edab735 Leszek Koltunski
    {
524 1b85f172 Leszek Koltunski
    mStickerInfo.remove(info.sticker);
525 7edab735 Leszek Koltunski
526 28f4aba0 Leszek Koltunski
    info.flip    = flip;
527 1b85f172 Leszek Koltunski
    info.sticker = oldSticker;
528 28f4aba0 Leszek Koltunski
    info.scale  *= scale;
529
530
    mQuat1[0] = info.qx;
531
    mQuat1[1] = info.qy;
532
    mQuat1[2] = info.qz;
533
    mQuat1[3] = info.qw;
534 7edab735 Leszek Koltunski
535 4d883a92 Leszek Koltunski
    double sinHalf = computeSinHalf(cos);
536
    double cosHalf = computeCosHalf(sin,cos);
537 55f20739 Leszek Koltunski
538 28f4aba0 Leszek Koltunski
    mQuat2[0] = 0.0f;
539
    mQuat2[1] = 0.0f;
540
    mQuat2[2] = sinHalf;
541
    mQuat2[3] = cosHalf;
542 7edab735 Leszek Koltunski
543 33647db9 Leszek Koltunski
    quatMultiply( mQuat1, mQuat2, mQuat3 );
544 55f20739 Leszek Koltunski
545 33647db9 Leszek Koltunski
    info.qx = mQuat3[0];
546
    info.qy = mQuat3[1];
547
    info.qz = mQuat3[2];
548
    info.qw = mQuat3[3];
549 7edab735 Leszek Koltunski
    }
550
551
///////////////////////////////////////////////////////////////////////////////////////////////////
552
553 4d883a92 Leszek Koltunski
  private boolean foundVertex(FaceInfo info, double[] buffer, int len, double[] newVert,
554
                              double[] oldVert, double lenFirstOld, int oldSticker, boolean inverted)
555 7edab735 Leszek Koltunski
    {
556 33647db9 Leszek Koltunski
    for(int vertex=0; vertex<len; vertex++)
557
      {
558 4d883a92 Leszek Koltunski
      double newX = newVert[2*vertex  ];
559
      double newY = newVert[2*vertex+1];
560
      double lenIthNew = Math.sqrt(newX*newX + newY*newY);
561
      double cos = computeCos( oldVert[0], oldVert[1], newX, newY, lenIthNew, lenFirstOld);
562
      double sin = computeSin( oldVert[0], oldVert[1], newX, newY, lenIthNew, lenFirstOld);
563 7edab735 Leszek Koltunski
564 1b85f172 Leszek Koltunski
      rotateAllVertices(buffer,len,newVert,sin,cos);
565 7edab735 Leszek Koltunski
566 4d883a92 Leszek Koltunski
      if( isScaledVersionOf(buffer,oldVert,len) )
567 33647db9 Leszek Koltunski
        {
568 4d883a92 Leszek Koltunski
        double scale = computeScale(oldVert,newVert);
569
        correctInfo(info,scale,sin,cos,oldSticker,inverted);
570 33647db9 Leszek Koltunski
        return true;
571
        }
572
      }
573 55f20739 Leszek Koltunski
574 33647db9 Leszek Koltunski
    return false;
575 7edab735 Leszek Koltunski
    }
576
577
///////////////////////////////////////////////////////////////////////////////////////////////////
578
579 4d883a92 Leszek Koltunski
  private boolean successfullyCollapsedStickers(final FaceInfo newInfo, final FaceInfo oldInfo)
580 7edab735 Leszek Koltunski
    {
581 1b85f172 Leszek Koltunski
    StickerInfo sNewInfo = mStickerInfo.get(newInfo.sticker);
582 4d883a92 Leszek Koltunski
    StickerInfo sOldInfo = mStickerInfo.get(oldInfo.sticker);
583
    double[] newVert = sNewInfo.vertices;
584
    double[] oldVert = sOldInfo.vertices;
585
    int oldLen = oldVert.length;
586
    int newLen = newVert.length;
587 7edab735 Leszek Koltunski
588 4d883a92 Leszek Koltunski
    if( oldLen == newLen )
589 33647db9 Leszek Koltunski
      {
590 4d883a92 Leszek Koltunski
      int oldSticker = oldInfo.sticker;
591
      double[] buffer1 = new double[oldLen];
592
      double lenFirstOld = Math.sqrt(newVert[0]*newVert[0] + newVert[1]*newVert[1]);
593
      if( foundVertex(newInfo, buffer1, oldLen/2, newVert, oldVert, lenFirstOld, oldSticker, false) ) return true;
594
      double[] buffer2 = new double[oldLen];
595
      mirrorAllVertices(buffer2, newLen/2, newVert);
596
      if( foundVertex(newInfo, buffer1, oldLen/2, buffer2, oldVert, lenFirstOld, oldSticker, true ) ) return true;
597 33647db9 Leszek Koltunski
      }
598 55f20739 Leszek Koltunski
599 33647db9 Leszek Koltunski
    return false;
600 7edab735 Leszek Koltunski
    }
601
602
///////////////////////////////////////////////////////////////////////////////////////////////////
603
604 4d883a92 Leszek Koltunski
  private double[][] constructVert(double[][] vertices, int[] index)
605 7edab735 Leszek Koltunski
    {
606 33647db9 Leszek Koltunski
    int len = index.length;
607 4d883a92 Leszek Koltunski
    double[][] ret = new double[len][4];
608 7edab735 Leszek Koltunski
609 33647db9 Leszek Koltunski
    for(int i=0; i<len; i++)
610
      {
611
      ret[i][0] = vertices[index[i]][0];
612
      ret[i][1] = vertices[index[i]][1];
613
      ret[i][2] = vertices[index[i]][2];
614
      ret[i][3] = 1.0f;
615
      }
616 7edab735 Leszek Koltunski
617 33647db9 Leszek Koltunski
    return ret;
618 7edab735 Leszek Koltunski
    }
619
620
///////////////////////////////////////////////////////////////////////////////////////////////////
621
622 4d883a92 Leszek Koltunski
  private void prepareFaceInfo( final double[][] vertices, final int[][] indexes)
623 7edab735 Leszek Koltunski
    {
624 33647db9 Leszek Koltunski
    mFaceInfo.clear();
625 1b85f172 Leszek Koltunski
    mStickerInfo.clear();
626 7edab735 Leszek Koltunski
627 33647db9 Leszek Koltunski
    int numFaces = indexes.length;
628 4d883a92 Leszek Koltunski
    FaceInfo oldInfo;
629 7edab735 Leszek Koltunski
630 33647db9 Leszek Koltunski
    for(int face=0; face<numFaces; face++)
631
      {
632
      FaceInfo newInfo = new FaceInfo();
633
      int[] index = indexes[face];
634 4d883a92 Leszek Koltunski
      double[][] vert = constructVert(vertices,index);
635 33647db9 Leszek Koltunski
      constructNew(newInfo,vert);
636 55f20739 Leszek Koltunski
637 33647db9 Leszek Koltunski
      for(int previous=0; previous<face; previous++)
638
        {
639 4d883a92 Leszek Koltunski
        oldInfo = mFaceInfo.get(previous);
640
        if( successfullyCollapsedStickers(newInfo,oldInfo) ) break;
641 33647db9 Leszek Koltunski
        }
642 7edab735 Leszek Koltunski
643 33647db9 Leszek Koltunski
      mFaceInfo.add(newInfo);
644
      }
645 7edab735 Leszek Koltunski
    }
646
647 ef231eba Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
648
649 4d883a92 Leszek Koltunski
  private void prepareAndRoundCorners(MeshBase mesh, double[][] vertices, int[][] vertIndexes,
650 1b85f172 Leszek Koltunski
                                      float[][] corners, int[] cornerIndexes )
651 ef231eba Leszek Koltunski
    {
652 1b85f172 Leszek Koltunski
    int numNeig, lenFV;
653
    int lenV = vertices.length;
654
    int[] verts = new int[2*(lenV-1)];
655
    Static3D[] staticVert = new Static3D[1];
656
    Static3D center = new Static3D(0,0,0);
657 4d883a92 Leszek Koltunski
    double cx, cy, cz;
658
    double[] singleV;
659 ef231eba Leszek Koltunski
660 1b85f172 Leszek Koltunski
    for(int v=0; v<lenV; v++)
661
      {
662
      // prepare verts[]
663
      numNeig = 0;
664 ef231eba Leszek Koltunski
665 1b85f172 Leszek Koltunski
      for (int[] vertIndex : vertIndexes)
666
        {
667
        lenFV = vertIndex.length;
668 ef231eba Leszek Koltunski
669 1b85f172 Leszek Koltunski
        for (int fv = 0; fv < lenFV; fv++)
670
          if (vertIndex[fv] == v)
671
            {
672
            int prev = fv > 0 ? fv - 1 : lenFV - 1;
673
            int next = fv < lenFV - 1 ? fv + 1 : 0;
674
675
            verts[numNeig++] = vertIndex[prev];
676
            verts[numNeig++] = vertIndex[next];
677
            }
678
        }
679
680
      cx=cy=cz=0.0f;
681
682
      // from verts[] prepare center
683
      for(int n=0; n<numNeig; n++)
684
        {
685
        singleV = vertices[verts[n]];
686
687
        cx += singleV[0];
688
        cy += singleV[1];
689
        cz += singleV[2];
690
        }
691 4d883a92 Leszek Koltunski
      center.set( (float)(cx/numNeig - vertices[v][0]),
692
                  (float)(cy/numNeig - vertices[v][1]),
693
                  (float)(cz/numNeig - vertices[v][2]));
694 1b85f172 Leszek Koltunski
695
      // round Corners
696 4d883a92 Leszek Koltunski
      staticVert[0] = new Static3D( (float)vertices[v][0], (float)vertices[v][1], (float)vertices[v][2]);
697 1b85f172 Leszek Koltunski
698
      int corn = cornerIndexes[v];
699
      float strength = corners[corn][0];
700
      float radius   = corners[corn][1];
701
702
      roundCorners(mesh, center, staticVert, strength, radius);
703
      }
704
    }
705
706
///////////////////////////////////////////////////////////////////////////////////////////////////
707
708 28f4aba0 Leszek Koltunski
  private void printInfo()
709 1b85f172 Leszek Koltunski
    {
710
    int stickers = mStickerInfo.size();
711
712 28f4aba0 Leszek Koltunski
    android.util.Log.d("D", "-------------------------");
713
714 1b85f172 Leszek Koltunski
    for(int s=0; s<stickers; s++)
715 ef231eba Leszek Koltunski
      {
716 28f4aba0 Leszek Koltunski
      String ver = "";
717 1b85f172 Leszek Koltunski
      StickerInfo info = mStickerInfo.get(s);
718
      int len = info.vertices.length/2;
719
720
      for(int i =0; i<len; i++)
721
        {
722
        ver += ("("+info.vertices[2*i]+","+info.vertices[2*i+1]+") ");
723
        }
724 28f4aba0 Leszek Koltunski
725
      android.util.Log.e("D", "sticker "+s+" "+ver);
726 ef231eba Leszek Koltunski
      }
727
728 28f4aba0 Leszek Koltunski
    android.util.Log.d("D", "-------------------------");
729 ef231eba Leszek Koltunski
730 28f4aba0 Leszek Koltunski
    int faces = mFaceInfo.size();
731 7edab735 Leszek Koltunski
732 28f4aba0 Leszek Koltunski
    for(int f=0; f<faces; f++)
733
      {
734
      FaceInfo info = mFaceInfo.get(f);
735
736
      android.util.Log.e("D", "q=("+info.qx+", "+info.qy+", "+info.qz+", "+info.qw+") v=("
737 1b85f172 Leszek Koltunski
                       +info.vx+", "+info.vy+", "+info.vz+") scale="+info.scale+" sticker="+info.sticker);
738 28f4aba0 Leszek Koltunski
      }
739
740
    android.util.Log.d("D", "-------------------------");
741 1b85f172 Leszek Koltunski
    }
742
743
///////////////////////////////////////////////////////////////////////////////////////////////////
744
745 4d883a92 Leszek Koltunski
  MeshBase createRoundedSolid(final double[][] vertices, final int[][] vertIndexes,
746
                              final float[][] bands    , final int[]   bandIndexes,
747
                              final float[][] corners  , final int[]   cornerIndexes)
748 7edab735 Leszek Koltunski
    {
749 33647db9 Leszek Koltunski
    int EFFECTS_PER_FACE = 3;
750 7edab735 Leszek Koltunski
751 33647db9 Leszek Koltunski
    prepareFaceInfo(vertices,vertIndexes);
752 7edab735 Leszek Koltunski
753 33647db9 Leszek Koltunski
    int numFaces = vertIndexes.length;
754
    float[] band, bandsComputed;
755
    MeshBase[] meshes = new MeshBase[numFaces];
756 1b85f172 Leszek Koltunski
    FaceInfo fInfo;
757
    StickerInfo sInfo;
758
759 28f4aba0 Leszek Koltunski
    printInfo();
760 55f20739 Leszek Koltunski
761 33647db9 Leszek Koltunski
    for(int face=0; face<numFaces; face++)
762
      {
763 1b85f172 Leszek Koltunski
      fInfo = mFaceInfo.get(face);
764
      sInfo = mStickerInfo.get(fInfo.sticker);
765 140f2c4e Leszek Koltunski
766 4d883a92 Leszek Koltunski
      double[] verts = sInfo.vertices;
767
      int lenVerts = verts.length;
768
      float[] vertsFloat = new float[lenVerts];
769
      for(int i=0; i<lenVerts; i++) vertsFloat[i] = (float)verts[i];
770
771 33647db9 Leszek Koltunski
      band = bands[bandIndexes[face]];
772
      bandsComputed = computeBands( band[0], (int)band[1], band[2], band[3], (int)band[4]);
773 4d883a92 Leszek Koltunski
      meshes[face] = new MeshPolygon(vertsFloat,bandsComputed,(int)band[5],(int)band[6]);
774 33647db9 Leszek Koltunski
      meshes[face].setEffectAssociation(0,(1<<face),0);
775
      }
776 7edab735 Leszek Koltunski
777 33647db9 Leszek Koltunski
    MeshBase mesh = new MeshJoined(meshes);
778 1b85f172 Leszek Koltunski
    MatrixEffect[] effects = new MatrixEffect[EFFECTS_PER_FACE*numFaces];
779 7edab735 Leszek Koltunski
    Static3D center = new Static3D(0,0,0);
780 fe032f52 Leszek Koltunski
781 33647db9 Leszek Koltunski
    for(int face=0; face<numFaces; face++)
782
      {
783
      int assoc = (1<<face);
784 1b85f172 Leszek Koltunski
      fInfo = mFaceInfo.get(face);
785 6d020cb6 Leszek Koltunski
786 4d883a92 Leszek Koltunski
      float vx = (float)fInfo.vx;
787
      float vy = (float)fInfo.vy;
788
      float vz = (float)fInfo.vz;
789
      float sc = (float)fInfo.scale;
790
      float qx = (float)fInfo.qx;
791
      float qy = (float)fInfo.qy;
792
      float qz = (float)fInfo.qz;
793
      float qw = (float)fInfo.qw;
794
795
      Static3D move3D= new Static3D(vx,vy,vz);
796
      Static3D scale = new Static3D(sc,sc, fInfo.flip ? -sc : sc);
797
      Static4D quat  = new Static4D(qx,qy,qz,qw);
798 6d020cb6 Leszek Koltunski
799 1b85f172 Leszek Koltunski
      effects[EFFECTS_PER_FACE*face  ] = new MatrixEffectScale(scale);
800
      effects[EFFECTS_PER_FACE*face+1] = new MatrixEffectQuaternion(quat,center);
801
      effects[EFFECTS_PER_FACE*face+2] = new MatrixEffectMove(move3D);
802 a65604a7 Leszek Koltunski
803 1b85f172 Leszek Koltunski
      mesh.apply(effects[EFFECTS_PER_FACE*face  ],assoc,-1);
804
      mesh.apply(effects[EFFECTS_PER_FACE*face+1],assoc,-1);
805
      mesh.apply(effects[EFFECTS_PER_FACE*face+2],assoc,-1);
806 33647db9 Leszek Koltunski
      }
807 a65604a7 Leszek Koltunski
808 1b85f172 Leszek Koltunski
    prepareAndRoundCorners(mesh, vertices, vertIndexes, corners, cornerIndexes);
809 a65604a7 Leszek Koltunski
810 7edab735 Leszek Koltunski
    return mesh;
811
    }
812
  }