Project

General

Profile

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

examples / src / main / java / org / distorted / examples / meshfile / FactoryCubit.java @ 3083fab8

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.MatrixEffectMove;
23
import org.distorted.library.effect.MatrixEffectQuaternion;
24
import org.distorted.library.effect.MatrixEffectScale;
25 7edab735 Leszek Koltunski
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 33647db9 Leszek Koltunski
import java.util.ArrayList;
35
36 7edab735 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
37
38 55f20739 Leszek Koltunski
class FactoryCubit
39 7edab735 Leszek Koltunski
  {
40 4d883a92 Leszek Koltunski
  private static final double[] mBuffer = new double[3];
41
  private static final double[] mQuat1  = new double[4];
42
  private static final double[] mQuat2  = new double[4];
43
  private static final double[] mQuat3  = new double[4];
44 3083fab8 Leszek Koltunski
  private static final double[] mQuat4  = 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 3083fab8 Leszek Koltunski
    minX = minX<0 ? -minX:minX;
312
    maxX = maxX<0 ? -maxX:maxX;
313
    minY = minY<0 ? -minY:minY;
314
    maxY = maxY<0 ? -maxY:maxY;
315
316
    double max1 = Math.max(minX,minY);
317
    double max2 = Math.max(maxX,maxY);
318
    double max3 = Math.max(max1,max2);
319
320
    info.scale = max3/0.5;
321 ef231eba Leszek Koltunski
322 33647db9 Leszek Koltunski
    int len = vert3D.length;
323 1b85f172 Leszek Koltunski
    StickerInfo sInfo = new StickerInfo();
324 4d883a92 Leszek Koltunski
    sInfo.vertices = new double[2*len];
325 55f20739 Leszek Koltunski
326 33647db9 Leszek Koltunski
    for( int vertex=0; vertex<len; vertex++ )
327 55f20739 Leszek Koltunski
      {
328 1b85f172 Leszek Koltunski
      sInfo.vertices[2*vertex  ] = vert3D[vertex][0] / info.scale;
329
      sInfo.vertices[2*vertex+1] = vert3D[vertex][1] / info.scale;
330 55f20739 Leszek Koltunski
      }
331
332 28f4aba0 Leszek Koltunski
    mStickerInfo.add(sInfo);
333
334
    info.sticker = mStickerInfo.size() -1;
335 33647db9 Leszek Koltunski
    info.flip = false;
336 55f20739 Leszek Koltunski
    }
337
338
///////////////////////////////////////////////////////////////////////////////////////////////////
339
340 4d883a92 Leszek Koltunski
  private void constructNew(FaceInfo info, final double[][] vert3D)
341 55f20739 Leszek Koltunski
    {
342 33647db9 Leszek Koltunski
    // compute center of gravity
343
    info.vx = 0.0f;
344
    info.vy = 0.0f;
345
    info.vz = 0.0f;
346
    int len = vert3D.length;
347 55f20739 Leszek Koltunski
348 4d883a92 Leszek Koltunski
    for (double[] vert : vert3D)
349 55f20739 Leszek Koltunski
      {
350 33647db9 Leszek Koltunski
      info.vx += vert[0];
351
      info.vy += vert[1];
352
      info.vz += vert[2];
353 55f20739 Leszek Koltunski
      }
354
355 33647db9 Leszek Koltunski
    info.vx /= len;
356
    info.vy /= len;
357
    info.vz /= len;
358 55f20739 Leszek Koltunski
359 33647db9 Leszek Koltunski
    // move all vertices so that their center of gravity is at (0,0,0)
360
    for (int i=0; i<len; i++)
361 7cd30f7c Leszek Koltunski
      {
362 33647db9 Leszek Koltunski
      vert3D[i][0] -= info.vx;
363
      vert3D[i][1] -= info.vy;
364
      vert3D[i][2] -= info.vz;
365 7cd30f7c Leszek Koltunski
      }
366
367 33647db9 Leszek Koltunski
    // find 3 non-colinear vertices
368
    int foundIndex = -1;
369 7cd30f7c Leszek Koltunski
370 33647db9 Leszek Koltunski
    for(int vertex=2; vertex<len; vertex++)
371 7cd30f7c Leszek Koltunski
      {
372 33647db9 Leszek Koltunski
      if( !areColinear(vert3D,0,1,vertex) )
373
        {
374
        foundIndex = vertex;
375
        break;
376
        }
377 7cd30f7c Leszek Koltunski
      }
378
379 33647db9 Leszek Koltunski
    // compute the normal vector
380
    if( foundIndex==-1 )
381
      {
382
      throw new RuntimeException("all vertices colinear");
383
      }
384 7cd30f7c Leszek Koltunski
385 33647db9 Leszek Koltunski
    computeNormalVector(vert3D,0,1,foundIndex);
386
387 140f2c4e Leszek Koltunski
    // rotate so that the normal vector becomes (0,0,1)
388 4d883a92 Leszek Koltunski
    double axisX, axisY, axisZ;
389 140f2c4e Leszek Koltunski
390 ef231eba Leszek Koltunski
    if( mBuffer[0]!=0.0f || mBuffer[1]!=0.0f )
391 33647db9 Leszek Koltunski
      {
392 140f2c4e Leszek Koltunski
      axisX = -mBuffer[1];
393
      axisY =  mBuffer[0];
394
      axisZ = 0.0f;
395 ef231eba Leszek Koltunski
396 4d883a92 Leszek Koltunski
      double axiLen = axisX*axisX + axisY*axisY;
397
      axiLen = Math.sqrt(axiLen);
398 ef231eba Leszek Koltunski
      axisX /= axiLen;
399
      axisY /= axiLen;
400
      axisZ /= axiLen;
401 140f2c4e Leszek Koltunski
      }
402
    else
403
      {
404
      axisX = 0.0f;
405
      axisY = 1.0f;
406
      axisZ = 0.0f;
407
      }
408 ef231eba Leszek Koltunski
409 4d883a92 Leszek Koltunski
    double cosTheta = mBuffer[2];
410
    double sinTheta = Math.sqrt(1-cosTheta*cosTheta);
411
    double sinHalfTheta = computeSinHalf(cosTheta);
412
    double cosHalfTheta = computeCosHalf(sinTheta,cosTheta);
413 ef231eba Leszek Koltunski
414 140f2c4e Leszek Koltunski
    mQuat1[0] = axisX*sinHalfTheta;
415
    mQuat1[1] = axisY*sinHalfTheta;
416
    mQuat1[2] = axisZ*sinHalfTheta;
417
    mQuat1[3] = cosHalfTheta;
418 28f4aba0 Leszek Koltunski
    mQuat2[0] =-axisX*sinHalfTheta;
419
    mQuat2[1] =-axisY*sinHalfTheta;
420
    mQuat2[2] =-axisZ*sinHalfTheta;
421
    mQuat2[3] = cosHalfTheta;
422 ef231eba Leszek Koltunski
423 4d883a92 Leszek Koltunski
    for (double[] vert : vert3D)
424 140f2c4e Leszek Koltunski
      {
425 28f4aba0 Leszek Koltunski
      quatMultiply(mQuat1, vert  , mQuat3);
426
      quatMultiply(mQuat3, mQuat2, vert  );
427 33647db9 Leszek Koltunski
      }
428 7cd30f7c Leszek Koltunski
429 33647db9 Leszek Koltunski
    // fit the whole thing in a square and remember the scale & 2D vertices
430
    fitInSquare(info, vert3D);
431 7cd30f7c Leszek Koltunski
432 33647db9 Leszek Koltunski
    // remember the rotation
433 28f4aba0 Leszek Koltunski
    info.qx =-mQuat1[0];
434
    info.qy =-mQuat1[1];
435
    info.qz =-mQuat1[2];
436
    info.qw = mQuat1[3];
437 7cd30f7c Leszek Koltunski
    }
438
439 fe032f52 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
440
441 4d883a92 Leszek Koltunski
  private double computeCos(double oldX, double oldY, double newX, double newY, double len1, double len2)
442 fe032f52 Leszek Koltunski
    {
443 3083fab8 Leszek Koltunski
    double ret= (oldX*newX+oldY*newY) / (len1*len2);
444
    if( ret<-1.0 ) return -1.0;
445
    if( ret> 1.0 ) return  1.0;
446
447
    return ret;
448 fe032f52 Leszek Koltunski
    }
449
450 b3d28a81 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
451 4d883a92 Leszek Koltunski
// sin of (signed!) angle between vectors 'old' and 'new', counterclockwise!
452 b3d28a81 Leszek Koltunski
453 4d883a92 Leszek Koltunski
  private double computeSin(double oldX, double oldY, double newX, double newY, double len1, double len2)
454 b3d28a81 Leszek Koltunski
    {
455 3083fab8 Leszek Koltunski
    double ret= (newX*oldY-oldX*newY) / (len1*len2);
456
    if( ret<-1.0 ) return -1.0;
457
    if( ret> 1.0 ) return  1.0;
458
459
    return ret;
460 b3d28a81 Leszek Koltunski
    }
461
462 54e47d9b Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
463
464 4d883a92 Leszek Koltunski
  private void rotateAllVertices(double[] result, int len, double[] vertices, double sin, double cos)
465 54e47d9b Leszek Koltunski
    {
466 33647db9 Leszek Koltunski
    for(int i=0; i<len; i++)
467 54e47d9b Leszek Koltunski
      {
468 33647db9 Leszek Koltunski
      result[2*i  ] = vertices[2*i  ]*cos - vertices[2*i+1]*sin;
469
      result[2*i+1] = vertices[2*i  ]*sin + vertices[2*i+1]*cos;
470 54e47d9b Leszek Koltunski
      }
471
    }
472
473 6d020cb6 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
474
475 4d883a92 Leszek Koltunski
  private double computeScale(double[] v1, double[] v2)
476 6d020cb6 Leszek Koltunski
    {
477 4d883a92 Leszek Koltunski
    double lenSq1 = v1[0]*v1[0] + v1[1]*v1[1];
478
    double lenSq2 = v2[0]*v2[0] + v2[1]*v2[1];
479
480
    return Math.sqrt(lenSq2/lenSq1);
481
    }
482
483
///////////////////////////////////////////////////////////////////////////////////////////////////
484
485
  private double computeSinHalf(double cos)
486
    {
487
    return Math.sqrt((1-cos)/2);
488
    }
489
490
///////////////////////////////////////////////////////////////////////////////////////////////////
491
492
  private double computeCosHalf(double sin, double cos)
493
    {
494
    double cosHalf = Math.sqrt((1+cos)/2);
495
    return sin<0 ? -cosHalf : cosHalf;
496
    }
497
498
///////////////////////////////////////////////////////////////////////////////////////////////////
499
500 3083fab8 Leszek Koltunski
  private int computeRotatedIndex(int oldVertex, int len, int rotatedVertex, boolean inverted)
501
    {
502
    int v = (rotatedVertex + (inverted? -oldVertex : oldVertex));
503
    if( v>=len ) v-=len;
504
    if( v< 0   ) v+=len;
505
506
    return v;
507
    }
508
509
///////////////////////////////////////////////////////////////////////////////////////////////////
510
511
  private boolean isScaledVersionOf(double[] newVert, double[] oldVert, int len, int vertex, boolean inverted)
512 4d883a92 Leszek Koltunski
    {
513
    double EPSILON = 0.001;
514
    double scale = computeScale(newVert,oldVert);
515 55f20739 Leszek Koltunski
516 33647db9 Leszek Koltunski
    for(int i=1; i<len; i++)
517
      {
518 3083fab8 Leszek Koltunski
      int index = computeRotatedIndex(i,len,vertex,inverted);
519
520
      double horz = oldVert[2*i  ] - scale*newVert[2*index  ];
521
      double vert = oldVert[2*i+1] - scale*newVert[2*index+1];
522 7edab735 Leszek Koltunski
523 33647db9 Leszek Koltunski
      if( horz>EPSILON || horz<-EPSILON || vert>EPSILON || vert<-EPSILON ) return false;
524
      }
525 55f20739 Leszek Koltunski
526 33647db9 Leszek Koltunski
    return true;
527 7edab735 Leszek Koltunski
    }
528
529
///////////////////////////////////////////////////////////////////////////////////////////////////
530
531 4d883a92 Leszek Koltunski
  private void mirrorAllVertices(double[] output, int len, double[] input)
532 7edab735 Leszek Koltunski
    {
533 33647db9 Leszek Koltunski
    for(int vertex=0; vertex<len; vertex++)
534
      {
535
      output[2*vertex  ] = input[2*vertex  ];
536
      output[2*vertex+1] =-input[2*vertex+1];
537
      }
538 7edab735 Leszek Koltunski
    }
539
540
///////////////////////////////////////////////////////////////////////////////////////////////////
541
542 4d883a92 Leszek Koltunski
  private void correctInfo(FaceInfo info, double scale, double sin, double cos, int oldSticker, boolean flip)
543 7edab735 Leszek Koltunski
    {
544 1b85f172 Leszek Koltunski
    mStickerInfo.remove(info.sticker);
545 7edab735 Leszek Koltunski
546 28f4aba0 Leszek Koltunski
    info.flip    = flip;
547 1b85f172 Leszek Koltunski
    info.sticker = oldSticker;
548 28f4aba0 Leszek Koltunski
    info.scale  *= scale;
549
550
    mQuat1[0] = info.qx;
551
    mQuat1[1] = info.qy;
552
    mQuat1[2] = info.qz;
553
    mQuat1[3] = info.qw;
554 7edab735 Leszek Koltunski
555 4d883a92 Leszek Koltunski
    double sinHalf = computeSinHalf(cos);
556
    double cosHalf = computeCosHalf(sin,cos);
557 55f20739 Leszek Koltunski
558 3083fab8 Leszek Koltunski
    if( flip )
559
      {
560
      mQuat3[0] = 0.0f;
561
      mQuat3[1] = 0.0f;
562
      mQuat3[2] = sinHalf;
563
      mQuat3[3] = cosHalf;
564
565
      mQuat4[0] = 1.0;
566
      mQuat4[1] = 0.0;
567
      mQuat4[2] = 0.0;
568
      mQuat4[3] = 0.0;
569
570
      quatMultiply( mQuat3, mQuat4, mQuat2 );
571
      }
572
    else
573
      {
574
      mQuat2[0] = 0.0f;
575
      mQuat2[1] = 0.0f;
576
      mQuat2[2] = sinHalf;
577
      mQuat2[3] = cosHalf;
578
      }
579 7edab735 Leszek Koltunski
580 33647db9 Leszek Koltunski
    quatMultiply( mQuat1, mQuat2, mQuat3 );
581 55f20739 Leszek Koltunski
582 33647db9 Leszek Koltunski
    info.qx = mQuat3[0];
583
    info.qy = mQuat3[1];
584
    info.qz = mQuat3[2];
585
    info.qw = mQuat3[3];
586 7edab735 Leszek Koltunski
    }
587
588 3083fab8 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
589
590
  private void printVert(double[] buffer)
591
    {
592
    int len = buffer.length/2;
593
    String str = "";
594
595
    for(int i=0; i<len; i++)
596
      {
597
      str += (" ("+buffer[2*i]+" , "+buffer[2*i+1]+" ) ");
598
      }
599
600
    android.util.Log.d("D", str);
601
    }
602
603 7edab735 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
604
605 4d883a92 Leszek Koltunski
  private boolean foundVertex(FaceInfo info, double[] buffer, int len, double[] newVert,
606
                              double[] oldVert, double lenFirstOld, int oldSticker, boolean inverted)
607 7edab735 Leszek Koltunski
    {
608 33647db9 Leszek Koltunski
    for(int vertex=0; vertex<len; vertex++)
609
      {
610 4d883a92 Leszek Koltunski
      double newX = newVert[2*vertex  ];
611
      double newY = newVert[2*vertex+1];
612
      double lenIthNew = Math.sqrt(newX*newX + newY*newY);
613
      double cos = computeCos( oldVert[0], oldVert[1], newX, newY, lenIthNew, lenFirstOld);
614
      double sin = computeSin( oldVert[0], oldVert[1], newX, newY, lenIthNew, lenFirstOld);
615 7edab735 Leszek Koltunski
616 1b85f172 Leszek Koltunski
      rotateAllVertices(buffer,len,newVert,sin,cos);
617 7edab735 Leszek Koltunski
618 3083fab8 Leszek Koltunski
      if( isScaledVersionOf(buffer,oldVert,len,vertex,inverted) )
619 33647db9 Leszek Koltunski
        {
620 4d883a92 Leszek Koltunski
        double scale = computeScale(oldVert,newVert);
621
        correctInfo(info,scale,sin,cos,oldSticker,inverted);
622 33647db9 Leszek Koltunski
        return true;
623
        }
624
      }
625 55f20739 Leszek Koltunski
626 33647db9 Leszek Koltunski
    return false;
627 7edab735 Leszek Koltunski
    }
628
629
///////////////////////////////////////////////////////////////////////////////////////////////////
630
631 4d883a92 Leszek Koltunski
  private boolean successfullyCollapsedStickers(final FaceInfo newInfo, final FaceInfo oldInfo)
632 7edab735 Leszek Koltunski
    {
633 1b85f172 Leszek Koltunski
    StickerInfo sNewInfo = mStickerInfo.get(newInfo.sticker);
634 4d883a92 Leszek Koltunski
    StickerInfo sOldInfo = mStickerInfo.get(oldInfo.sticker);
635
    double[] newVert = sNewInfo.vertices;
636
    double[] oldVert = sOldInfo.vertices;
637
    int oldLen = oldVert.length;
638
    int newLen = newVert.length;
639 7edab735 Leszek Koltunski
640 4d883a92 Leszek Koltunski
    if( oldLen == newLen )
641 33647db9 Leszek Koltunski
      {
642 4d883a92 Leszek Koltunski
      int oldSticker = oldInfo.sticker;
643
      double[] buffer1 = new double[oldLen];
644 f4b59207 Leszek Koltunski
      double lenFirstOld = Math.sqrt(oldVert[0]*oldVert[0] + oldVert[1]*oldVert[1]);
645 4d883a92 Leszek Koltunski
      if( foundVertex(newInfo, buffer1, oldLen/2, newVert, oldVert, lenFirstOld, oldSticker, false) ) return true;
646
      double[] buffer2 = new double[oldLen];
647
      mirrorAllVertices(buffer2, newLen/2, newVert);
648
      if( foundVertex(newInfo, buffer1, oldLen/2, buffer2, oldVert, lenFirstOld, oldSticker, true ) ) return true;
649 33647db9 Leszek Koltunski
      }
650 55f20739 Leszek Koltunski
651 33647db9 Leszek Koltunski
    return false;
652 7edab735 Leszek Koltunski
    }
653
654
///////////////////////////////////////////////////////////////////////////////////////////////////
655
656 4d883a92 Leszek Koltunski
  private double[][] constructVert(double[][] vertices, int[] index)
657 7edab735 Leszek Koltunski
    {
658 33647db9 Leszek Koltunski
    int len = index.length;
659 4d883a92 Leszek Koltunski
    double[][] ret = new double[len][4];
660 7edab735 Leszek Koltunski
661 33647db9 Leszek Koltunski
    for(int i=0; i<len; i++)
662
      {
663
      ret[i][0] = vertices[index[i]][0];
664
      ret[i][1] = vertices[index[i]][1];
665
      ret[i][2] = vertices[index[i]][2];
666
      ret[i][3] = 1.0f;
667
      }
668 7edab735 Leszek Koltunski
669 33647db9 Leszek Koltunski
    return ret;
670 7edab735 Leszek Koltunski
    }
671
672
///////////////////////////////////////////////////////////////////////////////////////////////////
673
674 4d883a92 Leszek Koltunski
  private void prepareFaceInfo( final double[][] vertices, final int[][] indexes)
675 7edab735 Leszek Koltunski
    {
676 33647db9 Leszek Koltunski
    mFaceInfo.clear();
677 1b85f172 Leszek Koltunski
    mStickerInfo.clear();
678 7edab735 Leszek Koltunski
679 33647db9 Leszek Koltunski
    int numFaces = indexes.length;
680 4d883a92 Leszek Koltunski
    FaceInfo oldInfo;
681 7edab735 Leszek Koltunski
682 33647db9 Leszek Koltunski
    for(int face=0; face<numFaces; face++)
683
      {
684
      FaceInfo newInfo = new FaceInfo();
685
      int[] index = indexes[face];
686 4d883a92 Leszek Koltunski
      double[][] vert = constructVert(vertices,index);
687 33647db9 Leszek Koltunski
      constructNew(newInfo,vert);
688 55f20739 Leszek Koltunski
689 33647db9 Leszek Koltunski
      for(int previous=0; previous<face; previous++)
690
        {
691 4d883a92 Leszek Koltunski
        oldInfo = mFaceInfo.get(previous);
692
        if( successfullyCollapsedStickers(newInfo,oldInfo) ) break;
693 33647db9 Leszek Koltunski
        }
694 7edab735 Leszek Koltunski
695 33647db9 Leszek Koltunski
      mFaceInfo.add(newInfo);
696
      }
697 7edab735 Leszek Koltunski
    }
698
699 ef231eba Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
700
701 4d883a92 Leszek Koltunski
  private void prepareAndRoundCorners(MeshBase mesh, double[][] vertices, int[][] vertIndexes,
702 1b85f172 Leszek Koltunski
                                      float[][] corners, int[] cornerIndexes )
703 ef231eba Leszek Koltunski
    {
704 1b85f172 Leszek Koltunski
    int numNeig, lenFV;
705
    int lenV = vertices.length;
706
    int[] verts = new int[2*(lenV-1)];
707
    Static3D[] staticVert = new Static3D[1];
708
    Static3D center = new Static3D(0,0,0);
709 4d883a92 Leszek Koltunski
    double cx, cy, cz;
710
    double[] singleV;
711 ef231eba Leszek Koltunski
712 1b85f172 Leszek Koltunski
    for(int v=0; v<lenV; v++)
713
      {
714
      // prepare verts[]
715
      numNeig = 0;
716 ef231eba Leszek Koltunski
717 1b85f172 Leszek Koltunski
      for (int[] vertIndex : vertIndexes)
718
        {
719
        lenFV = vertIndex.length;
720 ef231eba Leszek Koltunski
721 1b85f172 Leszek Koltunski
        for (int fv = 0; fv < lenFV; fv++)
722
          if (vertIndex[fv] == v)
723
            {
724
            int prev = fv > 0 ? fv - 1 : lenFV - 1;
725
            int next = fv < lenFV - 1 ? fv + 1 : 0;
726
727
            verts[numNeig++] = vertIndex[prev];
728
            verts[numNeig++] = vertIndex[next];
729
            }
730
        }
731
732
      cx=cy=cz=0.0f;
733
734
      // from verts[] prepare center
735
      for(int n=0; n<numNeig; n++)
736
        {
737
        singleV = vertices[verts[n]];
738
739
        cx += singleV[0];
740
        cy += singleV[1];
741
        cz += singleV[2];
742
        }
743 4d883a92 Leszek Koltunski
      center.set( (float)(cx/numNeig - vertices[v][0]),
744
                  (float)(cy/numNeig - vertices[v][1]),
745
                  (float)(cz/numNeig - vertices[v][2]));
746 1b85f172 Leszek Koltunski
747
      // round Corners
748 4d883a92 Leszek Koltunski
      staticVert[0] = new Static3D( (float)vertices[v][0], (float)vertices[v][1], (float)vertices[v][2]);
749 1b85f172 Leszek Koltunski
750
      int corn = cornerIndexes[v];
751
      float strength = corners[corn][0];
752
      float radius   = corners[corn][1];
753
754
      roundCorners(mesh, center, staticVert, strength, radius);
755
      }
756
    }
757
758
///////////////////////////////////////////////////////////////////////////////////////////////////
759
760 28f4aba0 Leszek Koltunski
  private void printInfo()
761 1b85f172 Leszek Koltunski
    {
762
    int stickers = mStickerInfo.size();
763
764 28f4aba0 Leszek Koltunski
    android.util.Log.d("D", "-------------------------");
765
766 1b85f172 Leszek Koltunski
    for(int s=0; s<stickers; s++)
767 ef231eba Leszek Koltunski
      {
768 28f4aba0 Leszek Koltunski
      String ver = "";
769 1b85f172 Leszek Koltunski
      StickerInfo info = mStickerInfo.get(s);
770
      int len = info.vertices.length/2;
771
772
      for(int i =0; i<len; i++)
773
        {
774
        ver += ("("+info.vertices[2*i]+","+info.vertices[2*i+1]+") ");
775
        }
776 28f4aba0 Leszek Koltunski
777
      android.util.Log.e("D", "sticker "+s+" "+ver);
778 ef231eba Leszek Koltunski
      }
779
780 28f4aba0 Leszek Koltunski
    android.util.Log.d("D", "-------------------------");
781 ef231eba Leszek Koltunski
782 28f4aba0 Leszek Koltunski
    int faces = mFaceInfo.size();
783 7edab735 Leszek Koltunski
784 28f4aba0 Leszek Koltunski
    for(int f=0; f<faces; f++)
785
      {
786
      FaceInfo info = mFaceInfo.get(f);
787
788
      android.util.Log.e("D", "q=("+info.qx+", "+info.qy+", "+info.qz+", "+info.qw+") v=("
789 1b85f172 Leszek Koltunski
                       +info.vx+", "+info.vy+", "+info.vz+") scale="+info.scale+" sticker="+info.sticker);
790 28f4aba0 Leszek Koltunski
      }
791
792
    android.util.Log.d("D", "-------------------------");
793 1b85f172 Leszek Koltunski
    }
794
795
///////////////////////////////////////////////////////////////////////////////////////////////////
796
797 4d883a92 Leszek Koltunski
  MeshBase createRoundedSolid(final double[][] vertices, final int[][] vertIndexes,
798
                              final float[][] bands    , final int[]   bandIndexes,
799
                              final float[][] corners  , final int[]   cornerIndexes)
800 7edab735 Leszek Koltunski
    {
801 33647db9 Leszek Koltunski
    prepareFaceInfo(vertices,vertIndexes);
802 7edab735 Leszek Koltunski
803 33647db9 Leszek Koltunski
    int numFaces = vertIndexes.length;
804
    float[] band, bandsComputed;
805
    MeshBase[] meshes = new MeshBase[numFaces];
806 1b85f172 Leszek Koltunski
    FaceInfo fInfo;
807
    StickerInfo sInfo;
808
809 28f4aba0 Leszek Koltunski
    printInfo();
810 55f20739 Leszek Koltunski
811 33647db9 Leszek Koltunski
    for(int face=0; face<numFaces; face++)
812
      {
813 1b85f172 Leszek Koltunski
      fInfo = mFaceInfo.get(face);
814
      sInfo = mStickerInfo.get(fInfo.sticker);
815 140f2c4e Leszek Koltunski
816 4d883a92 Leszek Koltunski
      double[] verts = sInfo.vertices;
817
      int lenVerts = verts.length;
818
      float[] vertsFloat = new float[lenVerts];
819
      for(int i=0; i<lenVerts; i++) vertsFloat[i] = (float)verts[i];
820
821 33647db9 Leszek Koltunski
      band = bands[bandIndexes[face]];
822
      bandsComputed = computeBands( band[0], (int)band[1], band[2], band[3], (int)band[4]);
823 4d883a92 Leszek Koltunski
      meshes[face] = new MeshPolygon(vertsFloat,bandsComputed,(int)band[5],(int)band[6]);
824 33647db9 Leszek Koltunski
      meshes[face].setEffectAssociation(0,(1<<face),0);
825
      }
826 7edab735 Leszek Koltunski
827 33647db9 Leszek Koltunski
    MeshBase mesh = new MeshJoined(meshes);
828 7edab735 Leszek Koltunski
    Static3D center = new Static3D(0,0,0);
829 fe032f52 Leszek Koltunski
830 33647db9 Leszek Koltunski
    for(int face=0; face<numFaces; face++)
831
      {
832
      int assoc = (1<<face);
833 1b85f172 Leszek Koltunski
      fInfo = mFaceInfo.get(face);
834 6d020cb6 Leszek Koltunski
835 4d883a92 Leszek Koltunski
      float vx = (float)fInfo.vx;
836
      float vy = (float)fInfo.vy;
837
      float vz = (float)fInfo.vz;
838
      float sc = (float)fInfo.scale;
839
      float qx = (float)fInfo.qx;
840
      float qy = (float)fInfo.qy;
841
      float qz = (float)fInfo.qz;
842
      float qw = (float)fInfo.qw;
843
844
      Static3D scale = new Static3D(sc,sc, fInfo.flip ? -sc : sc);
845 3083fab8 Leszek Koltunski
      Static3D move3D= new Static3D(vx,vy,vz);
846 4d883a92 Leszek Koltunski
      Static4D quat  = new Static4D(qx,qy,qz,qw);
847 6d020cb6 Leszek Koltunski
848 6a96e571 Leszek Koltunski
      mesh.apply(new MatrixEffectScale(scale)           ,assoc,-1);
849
      mesh.apply(new MatrixEffectQuaternion(quat,center),assoc,-1);
850
      mesh.apply(new MatrixEffectMove(move3D)           ,assoc,-1);
851 33647db9 Leszek Koltunski
      }
852 a65604a7 Leszek Koltunski
853 1b85f172 Leszek Koltunski
    prepareAndRoundCorners(mesh, vertices, vertIndexes, corners, cornerIndexes);
854 a65604a7 Leszek Koltunski
855 7edab735 Leszek Koltunski
    return mesh;
856
    }
857
  }