Project

General

Profile

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

examples / src / main / java / org / distorted / examples / meshfile / FactoryCubit.java @ f4b59207

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 f4b59207 Leszek Koltunski
    return (oldX*newX+oldY*newY) / (len1*len2);
435 fe032f52 Leszek Koltunski
    }
436
437 b3d28a81 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
438 4d883a92 Leszek Koltunski
// sin of (signed!) angle between vectors 'old' and 'new', counterclockwise!
439 b3d28a81 Leszek Koltunski
440 4d883a92 Leszek Koltunski
  private double computeSin(double oldX, double oldY, double newX, double newY, double len1, double len2)
441 b3d28a81 Leszek Koltunski
    {
442 f4b59207 Leszek Koltunski
    return (newX*oldY-oldX*newY) / (len1*len2);
443 b3d28a81 Leszek Koltunski
    }
444
445 54e47d9b Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
446
447 4d883a92 Leszek Koltunski
  private void rotateAllVertices(double[] result, int len, double[] vertices, double sin, double cos)
448 54e47d9b Leszek Koltunski
    {
449 33647db9 Leszek Koltunski
    for(int i=0; i<len; i++)
450 54e47d9b Leszek Koltunski
      {
451 33647db9 Leszek Koltunski
      result[2*i  ] = vertices[2*i  ]*cos - vertices[2*i+1]*sin;
452
      result[2*i+1] = vertices[2*i  ]*sin + vertices[2*i+1]*cos;
453 54e47d9b Leszek Koltunski
      }
454
    }
455
456 6d020cb6 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
457
458 4d883a92 Leszek Koltunski
  private double computeScale(double[] v1, double[] v2)
459 6d020cb6 Leszek Koltunski
    {
460 4d883a92 Leszek Koltunski
    double lenSq1 = v1[0]*v1[0] + v1[1]*v1[1];
461
    double lenSq2 = v2[0]*v2[0] + v2[1]*v2[1];
462
463
    return Math.sqrt(lenSq2/lenSq1);
464
    }
465
466
///////////////////////////////////////////////////////////////////////////////////////////////////
467
468
  private double computeSinHalf(double cos)
469
    {
470
    return Math.sqrt((1-cos)/2);
471
    }
472
473
///////////////////////////////////////////////////////////////////////////////////////////////////
474
475
  private double computeCosHalf(double sin, double cos)
476
    {
477
    double cosHalf = Math.sqrt((1+cos)/2);
478
    return sin<0 ? -cosHalf : cosHalf;
479
    }
480
481
///////////////////////////////////////////////////////////////////////////////////////////////////
482
483
  private boolean isScaledVersionOf(double[] newVert, double[] oldVert, int len)
484
    {
485
    double EPSILON = 0.001;
486
    double scale = computeScale(newVert,oldVert);
487 55f20739 Leszek Koltunski
488 33647db9 Leszek Koltunski
    for(int i=1; i<len; i++)
489
      {
490 4d883a92 Leszek Koltunski
      double horz = oldVert[2*i  ] - scale*newVert[2*i  ];
491
      double vert = oldVert[2*i+1] - scale*newVert[2*i+1];
492 7edab735 Leszek Koltunski
493 33647db9 Leszek Koltunski
      if( horz>EPSILON || horz<-EPSILON || vert>EPSILON || vert<-EPSILON ) return false;
494
      }
495 55f20739 Leszek Koltunski
496 33647db9 Leszek Koltunski
    return true;
497 7edab735 Leszek Koltunski
    }
498
499
///////////////////////////////////////////////////////////////////////////////////////////////////
500
501 4d883a92 Leszek Koltunski
  private void mirrorAllVertices(double[] output, int len, double[] input)
502 7edab735 Leszek Koltunski
    {
503 33647db9 Leszek Koltunski
    for(int vertex=0; vertex<len; vertex++)
504
      {
505
      output[2*vertex  ] = input[2*vertex  ];
506
      output[2*vertex+1] =-input[2*vertex+1];
507
      }
508 7edab735 Leszek Koltunski
    }
509
510
///////////////////////////////////////////////////////////////////////////////////////////////////
511
512 4d883a92 Leszek Koltunski
  private void correctInfo(FaceInfo info, double scale, double sin, double cos, int oldSticker, boolean flip)
513 7edab735 Leszek Koltunski
    {
514 1b85f172 Leszek Koltunski
    mStickerInfo.remove(info.sticker);
515 7edab735 Leszek Koltunski
516 28f4aba0 Leszek Koltunski
    info.flip    = flip;
517 1b85f172 Leszek Koltunski
    info.sticker = oldSticker;
518 28f4aba0 Leszek Koltunski
    info.scale  *= scale;
519
520
    mQuat1[0] = info.qx;
521
    mQuat1[1] = info.qy;
522
    mQuat1[2] = info.qz;
523
    mQuat1[3] = info.qw;
524 7edab735 Leszek Koltunski
525 4d883a92 Leszek Koltunski
    double sinHalf = computeSinHalf(cos);
526
    double cosHalf = computeCosHalf(sin,cos);
527 55f20739 Leszek Koltunski
528 28f4aba0 Leszek Koltunski
    mQuat2[0] = 0.0f;
529
    mQuat2[1] = 0.0f;
530
    mQuat2[2] = sinHalf;
531
    mQuat2[3] = cosHalf;
532 7edab735 Leszek Koltunski
533 33647db9 Leszek Koltunski
    quatMultiply( mQuat1, mQuat2, mQuat3 );
534 55f20739 Leszek Koltunski
535 33647db9 Leszek Koltunski
    info.qx = mQuat3[0];
536
    info.qy = mQuat3[1];
537
    info.qz = mQuat3[2];
538
    info.qw = mQuat3[3];
539 7edab735 Leszek Koltunski
    }
540
541
///////////////////////////////////////////////////////////////////////////////////////////////////
542
543 4d883a92 Leszek Koltunski
  private boolean foundVertex(FaceInfo info, double[] buffer, int len, double[] newVert,
544
                              double[] oldVert, double lenFirstOld, int oldSticker, boolean inverted)
545 7edab735 Leszek Koltunski
    {
546 33647db9 Leszek Koltunski
    for(int vertex=0; vertex<len; vertex++)
547
      {
548 4d883a92 Leszek Koltunski
      double newX = newVert[2*vertex  ];
549
      double newY = newVert[2*vertex+1];
550
      double lenIthNew = Math.sqrt(newX*newX + newY*newY);
551
      double cos = computeCos( oldVert[0], oldVert[1], newX, newY, lenIthNew, lenFirstOld);
552
      double sin = computeSin( oldVert[0], oldVert[1], newX, newY, lenIthNew, lenFirstOld);
553 7edab735 Leszek Koltunski
554 1b85f172 Leszek Koltunski
      rotateAllVertices(buffer,len,newVert,sin,cos);
555 7edab735 Leszek Koltunski
556 4d883a92 Leszek Koltunski
      if( isScaledVersionOf(buffer,oldVert,len) )
557 33647db9 Leszek Koltunski
        {
558 4d883a92 Leszek Koltunski
        double scale = computeScale(oldVert,newVert);
559
        correctInfo(info,scale,sin,cos,oldSticker,inverted);
560 33647db9 Leszek Koltunski
        return true;
561
        }
562
      }
563 55f20739 Leszek Koltunski
564 33647db9 Leszek Koltunski
    return false;
565 7edab735 Leszek Koltunski
    }
566
567
///////////////////////////////////////////////////////////////////////////////////////////////////
568
569 4d883a92 Leszek Koltunski
  private boolean successfullyCollapsedStickers(final FaceInfo newInfo, final FaceInfo oldInfo)
570 7edab735 Leszek Koltunski
    {
571 1b85f172 Leszek Koltunski
    StickerInfo sNewInfo = mStickerInfo.get(newInfo.sticker);
572 4d883a92 Leszek Koltunski
    StickerInfo sOldInfo = mStickerInfo.get(oldInfo.sticker);
573
    double[] newVert = sNewInfo.vertices;
574
    double[] oldVert = sOldInfo.vertices;
575
    int oldLen = oldVert.length;
576
    int newLen = newVert.length;
577 7edab735 Leszek Koltunski
578 4d883a92 Leszek Koltunski
    if( oldLen == newLen )
579 33647db9 Leszek Koltunski
      {
580 4d883a92 Leszek Koltunski
      int oldSticker = oldInfo.sticker;
581
      double[] buffer1 = new double[oldLen];
582 f4b59207 Leszek Koltunski
      double lenFirstOld = Math.sqrt(oldVert[0]*oldVert[0] + oldVert[1]*oldVert[1]);
583 4d883a92 Leszek Koltunski
      if( foundVertex(newInfo, buffer1, oldLen/2, newVert, oldVert, lenFirstOld, oldSticker, false) ) return true;
584
      double[] buffer2 = new double[oldLen];
585
      mirrorAllVertices(buffer2, newLen/2, newVert);
586
      if( foundVertex(newInfo, buffer1, oldLen/2, buffer2, oldVert, lenFirstOld, oldSticker, true ) ) return true;
587 33647db9 Leszek Koltunski
      }
588 55f20739 Leszek Koltunski
589 33647db9 Leszek Koltunski
    return false;
590 7edab735 Leszek Koltunski
    }
591
592
///////////////////////////////////////////////////////////////////////////////////////////////////
593
594 4d883a92 Leszek Koltunski
  private double[][] constructVert(double[][] vertices, int[] index)
595 7edab735 Leszek Koltunski
    {
596 33647db9 Leszek Koltunski
    int len = index.length;
597 4d883a92 Leszek Koltunski
    double[][] ret = new double[len][4];
598 7edab735 Leszek Koltunski
599 33647db9 Leszek Koltunski
    for(int i=0; i<len; i++)
600
      {
601
      ret[i][0] = vertices[index[i]][0];
602
      ret[i][1] = vertices[index[i]][1];
603
      ret[i][2] = vertices[index[i]][2];
604
      ret[i][3] = 1.0f;
605
      }
606 7edab735 Leszek Koltunski
607 33647db9 Leszek Koltunski
    return ret;
608 7edab735 Leszek Koltunski
    }
609
610
///////////////////////////////////////////////////////////////////////////////////////////////////
611
612 4d883a92 Leszek Koltunski
  private void prepareFaceInfo( final double[][] vertices, final int[][] indexes)
613 7edab735 Leszek Koltunski
    {
614 33647db9 Leszek Koltunski
    mFaceInfo.clear();
615 1b85f172 Leszek Koltunski
    mStickerInfo.clear();
616 7edab735 Leszek Koltunski
617 33647db9 Leszek Koltunski
    int numFaces = indexes.length;
618 4d883a92 Leszek Koltunski
    FaceInfo oldInfo;
619 7edab735 Leszek Koltunski
620 33647db9 Leszek Koltunski
    for(int face=0; face<numFaces; face++)
621
      {
622
      FaceInfo newInfo = new FaceInfo();
623
      int[] index = indexes[face];
624 4d883a92 Leszek Koltunski
      double[][] vert = constructVert(vertices,index);
625 33647db9 Leszek Koltunski
      constructNew(newInfo,vert);
626 55f20739 Leszek Koltunski
627 33647db9 Leszek Koltunski
      for(int previous=0; previous<face; previous++)
628
        {
629 4d883a92 Leszek Koltunski
        oldInfo = mFaceInfo.get(previous);
630
        if( successfullyCollapsedStickers(newInfo,oldInfo) ) break;
631 33647db9 Leszek Koltunski
        }
632 7edab735 Leszek Koltunski
633 33647db9 Leszek Koltunski
      mFaceInfo.add(newInfo);
634
      }
635 7edab735 Leszek Koltunski
    }
636
637 ef231eba Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
638
639 4d883a92 Leszek Koltunski
  private void prepareAndRoundCorners(MeshBase mesh, double[][] vertices, int[][] vertIndexes,
640 1b85f172 Leszek Koltunski
                                      float[][] corners, int[] cornerIndexes )
641 ef231eba Leszek Koltunski
    {
642 1b85f172 Leszek Koltunski
    int numNeig, lenFV;
643
    int lenV = vertices.length;
644
    int[] verts = new int[2*(lenV-1)];
645
    Static3D[] staticVert = new Static3D[1];
646
    Static3D center = new Static3D(0,0,0);
647 4d883a92 Leszek Koltunski
    double cx, cy, cz;
648
    double[] singleV;
649 ef231eba Leszek Koltunski
650 1b85f172 Leszek Koltunski
    for(int v=0; v<lenV; v++)
651
      {
652
      // prepare verts[]
653
      numNeig = 0;
654 ef231eba Leszek Koltunski
655 1b85f172 Leszek Koltunski
      for (int[] vertIndex : vertIndexes)
656
        {
657
        lenFV = vertIndex.length;
658 ef231eba Leszek Koltunski
659 1b85f172 Leszek Koltunski
        for (int fv = 0; fv < lenFV; fv++)
660
          if (vertIndex[fv] == v)
661
            {
662
            int prev = fv > 0 ? fv - 1 : lenFV - 1;
663
            int next = fv < lenFV - 1 ? fv + 1 : 0;
664
665
            verts[numNeig++] = vertIndex[prev];
666
            verts[numNeig++] = vertIndex[next];
667
            }
668
        }
669
670
      cx=cy=cz=0.0f;
671
672
      // from verts[] prepare center
673
      for(int n=0; n<numNeig; n++)
674
        {
675
        singleV = vertices[verts[n]];
676
677
        cx += singleV[0];
678
        cy += singleV[1];
679
        cz += singleV[2];
680
        }
681 4d883a92 Leszek Koltunski
      center.set( (float)(cx/numNeig - vertices[v][0]),
682
                  (float)(cy/numNeig - vertices[v][1]),
683
                  (float)(cz/numNeig - vertices[v][2]));
684 1b85f172 Leszek Koltunski
685
      // round Corners
686 4d883a92 Leszek Koltunski
      staticVert[0] = new Static3D( (float)vertices[v][0], (float)vertices[v][1], (float)vertices[v][2]);
687 1b85f172 Leszek Koltunski
688
      int corn = cornerIndexes[v];
689
      float strength = corners[corn][0];
690
      float radius   = corners[corn][1];
691
692
      roundCorners(mesh, center, staticVert, strength, radius);
693
      }
694
    }
695
696
///////////////////////////////////////////////////////////////////////////////////////////////////
697
698 28f4aba0 Leszek Koltunski
  private void printInfo()
699 1b85f172 Leszek Koltunski
    {
700
    int stickers = mStickerInfo.size();
701
702 28f4aba0 Leszek Koltunski
    android.util.Log.d("D", "-------------------------");
703
704 1b85f172 Leszek Koltunski
    for(int s=0; s<stickers; s++)
705 ef231eba Leszek Koltunski
      {
706 28f4aba0 Leszek Koltunski
      String ver = "";
707 1b85f172 Leszek Koltunski
      StickerInfo info = mStickerInfo.get(s);
708
      int len = info.vertices.length/2;
709
710
      for(int i =0; i<len; i++)
711
        {
712
        ver += ("("+info.vertices[2*i]+","+info.vertices[2*i+1]+") ");
713
        }
714 28f4aba0 Leszek Koltunski
715
      android.util.Log.e("D", "sticker "+s+" "+ver);
716 ef231eba Leszek Koltunski
      }
717
718 28f4aba0 Leszek Koltunski
    android.util.Log.d("D", "-------------------------");
719 ef231eba Leszek Koltunski
720 28f4aba0 Leszek Koltunski
    int faces = mFaceInfo.size();
721 7edab735 Leszek Koltunski
722 28f4aba0 Leszek Koltunski
    for(int f=0; f<faces; f++)
723
      {
724
      FaceInfo info = mFaceInfo.get(f);
725
726
      android.util.Log.e("D", "q=("+info.qx+", "+info.qy+", "+info.qz+", "+info.qw+") v=("
727 1b85f172 Leszek Koltunski
                       +info.vx+", "+info.vy+", "+info.vz+") scale="+info.scale+" sticker="+info.sticker);
728 28f4aba0 Leszek Koltunski
      }
729
730
    android.util.Log.d("D", "-------------------------");
731 1b85f172 Leszek Koltunski
    }
732
733
///////////////////////////////////////////////////////////////////////////////////////////////////
734
735 4d883a92 Leszek Koltunski
  MeshBase createRoundedSolid(final double[][] vertices, final int[][] vertIndexes,
736
                              final float[][] bands    , final int[]   bandIndexes,
737
                              final float[][] corners  , final int[]   cornerIndexes)
738 7edab735 Leszek Koltunski
    {
739 33647db9 Leszek Koltunski
    int EFFECTS_PER_FACE = 3;
740 7edab735 Leszek Koltunski
741 33647db9 Leszek Koltunski
    prepareFaceInfo(vertices,vertIndexes);
742 7edab735 Leszek Koltunski
743 33647db9 Leszek Koltunski
    int numFaces = vertIndexes.length;
744
    float[] band, bandsComputed;
745
    MeshBase[] meshes = new MeshBase[numFaces];
746 1b85f172 Leszek Koltunski
    FaceInfo fInfo;
747
    StickerInfo sInfo;
748
749 28f4aba0 Leszek Koltunski
    printInfo();
750 55f20739 Leszek Koltunski
751 33647db9 Leszek Koltunski
    for(int face=0; face<numFaces; face++)
752
      {
753 1b85f172 Leszek Koltunski
      fInfo = mFaceInfo.get(face);
754
      sInfo = mStickerInfo.get(fInfo.sticker);
755 140f2c4e Leszek Koltunski
756 4d883a92 Leszek Koltunski
      double[] verts = sInfo.vertices;
757
      int lenVerts = verts.length;
758
      float[] vertsFloat = new float[lenVerts];
759
      for(int i=0; i<lenVerts; i++) vertsFloat[i] = (float)verts[i];
760
761 33647db9 Leszek Koltunski
      band = bands[bandIndexes[face]];
762
      bandsComputed = computeBands( band[0], (int)band[1], band[2], band[3], (int)band[4]);
763 4d883a92 Leszek Koltunski
      meshes[face] = new MeshPolygon(vertsFloat,bandsComputed,(int)band[5],(int)band[6]);
764 33647db9 Leszek Koltunski
      meshes[face].setEffectAssociation(0,(1<<face),0);
765
      }
766 7edab735 Leszek Koltunski
767 33647db9 Leszek Koltunski
    MeshBase mesh = new MeshJoined(meshes);
768 1b85f172 Leszek Koltunski
    MatrixEffect[] effects = new MatrixEffect[EFFECTS_PER_FACE*numFaces];
769 7edab735 Leszek Koltunski
    Static3D center = new Static3D(0,0,0);
770 fe032f52 Leszek Koltunski
771 33647db9 Leszek Koltunski
    for(int face=0; face<numFaces; face++)
772
      {
773
      int assoc = (1<<face);
774 1b85f172 Leszek Koltunski
      fInfo = mFaceInfo.get(face);
775 6d020cb6 Leszek Koltunski
776 4d883a92 Leszek Koltunski
      float vx = (float)fInfo.vx;
777
      float vy = (float)fInfo.vy;
778
      float vz = (float)fInfo.vz;
779
      float sc = (float)fInfo.scale;
780
      float qx = (float)fInfo.qx;
781
      float qy = (float)fInfo.qy;
782
      float qz = (float)fInfo.qz;
783
      float qw = (float)fInfo.qw;
784
785
      Static3D move3D= new Static3D(vx,vy,vz);
786
      Static3D scale = new Static3D(sc,sc, fInfo.flip ? -sc : sc);
787
      Static4D quat  = new Static4D(qx,qy,qz,qw);
788 6d020cb6 Leszek Koltunski
789 1b85f172 Leszek Koltunski
      effects[EFFECTS_PER_FACE*face  ] = new MatrixEffectScale(scale);
790
      effects[EFFECTS_PER_FACE*face+1] = new MatrixEffectQuaternion(quat,center);
791
      effects[EFFECTS_PER_FACE*face+2] = new MatrixEffectMove(move3D);
792 a65604a7 Leszek Koltunski
793 1b85f172 Leszek Koltunski
      mesh.apply(effects[EFFECTS_PER_FACE*face  ],assoc,-1);
794
      mesh.apply(effects[EFFECTS_PER_FACE*face+1],assoc,-1);
795
      mesh.apply(effects[EFFECTS_PER_FACE*face+2],assoc,-1);
796 33647db9 Leszek Koltunski
      }
797 a65604a7 Leszek Koltunski
798 1b85f172 Leszek Koltunski
    prepareAndRoundCorners(mesh, vertices, vertIndexes, corners, cornerIndexes);
799 a65604a7 Leszek Koltunski
800 7edab735 Leszek Koltunski
    return mesh;
801
    }
802
  }