Project

General

Profile

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

examples / src / main / java / org / distorted / examples / meshfile / FactoryCubit.java @ 6a96e571

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 6d020cb6 Leszek Koltunski
45 7edab735 Leszek Koltunski
  private static final Static1D RADIUS = new Static1D(1);
46
47 55f20739 Leszek Koltunski
  private static FactoryCubit mThis;
48 7edab735 Leszek Koltunski
49 1b85f172 Leszek Koltunski
  private static class StickerInfo
50 33647db9 Leszek Koltunski
    {
51 4d883a92 Leszek Koltunski
    double[] vertices;
52 6a96e571 Leszek Koltunski
    double dx,dy;
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 6a96e571 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
611
612
  private void centerTextures()
613
    {
614
    int numStickers = mStickerInfo.size();
615
    StickerInfo info;
616
617
    for(int sticker=0; sticker<numStickers; sticker++)
618
      {
619
      double minX = Double.MAX_VALUE;
620
      double minY = Double.MAX_VALUE;
621
      double maxX =-Double.MAX_VALUE;
622
      double maxY =-Double.MAX_VALUE;
623
624
      info = mStickerInfo.get(sticker);
625
      double[] vert = info.vertices;
626
      int numVert = vert.length/2;
627
628
      for ( int v=0; v<numVert; v++)
629
        {
630
        double x = vert[2*v  ];
631
        double y = vert[2*v+1];
632
633
        if (x < minX) minX = x;
634
        if (y < minY) minY = y;
635
        if (x > maxX) maxX = x;
636
        if (y > maxY) maxY = y;
637
        }
638
639
      info.dx = info.dy = 0.0;
640
641
      if( minX<-0.5 ) info.dx = minX + 0.5;
642
      if( minY<-0.5 ) info.dy = minY + 0.5;
643
      if( maxX> 0.5 ) info.dx = maxX - 0.5;
644
      if( maxY> 0.5 ) info.dy = maxY - 0.5;
645
646
      for ( int v=0; v<numVert; v++)
647
        {
648
        vert[2*v  ] -= info.dx;
649
        vert[2*v+1] -= info.dy;
650
        }
651
      }
652
    }
653
654 7edab735 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
655
656 4d883a92 Leszek Koltunski
  private void prepareFaceInfo( final double[][] vertices, final int[][] indexes)
657 7edab735 Leszek Koltunski
    {
658 33647db9 Leszek Koltunski
    mFaceInfo.clear();
659 1b85f172 Leszek Koltunski
    mStickerInfo.clear();
660 7edab735 Leszek Koltunski
661 33647db9 Leszek Koltunski
    int numFaces = indexes.length;
662 4d883a92 Leszek Koltunski
    FaceInfo oldInfo;
663 7edab735 Leszek Koltunski
664 33647db9 Leszek Koltunski
    for(int face=0; face<numFaces; face++)
665
      {
666
      FaceInfo newInfo = new FaceInfo();
667
      int[] index = indexes[face];
668 4d883a92 Leszek Koltunski
      double[][] vert = constructVert(vertices,index);
669 33647db9 Leszek Koltunski
      constructNew(newInfo,vert);
670 55f20739 Leszek Koltunski
671 33647db9 Leszek Koltunski
      for(int previous=0; previous<face; previous++)
672
        {
673 4d883a92 Leszek Koltunski
        oldInfo = mFaceInfo.get(previous);
674
        if( successfullyCollapsedStickers(newInfo,oldInfo) ) break;
675 33647db9 Leszek Koltunski
        }
676 7edab735 Leszek Koltunski
677 33647db9 Leszek Koltunski
      mFaceInfo.add(newInfo);
678
      }
679 6a96e571 Leszek Koltunski
680
    centerTextures();
681 7edab735 Leszek Koltunski
    }
682
683 ef231eba Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
684
685 4d883a92 Leszek Koltunski
  private void prepareAndRoundCorners(MeshBase mesh, double[][] vertices, int[][] vertIndexes,
686 1b85f172 Leszek Koltunski
                                      float[][] corners, int[] cornerIndexes )
687 ef231eba Leszek Koltunski
    {
688 1b85f172 Leszek Koltunski
    int numNeig, lenFV;
689
    int lenV = vertices.length;
690
    int[] verts = new int[2*(lenV-1)];
691
    Static3D[] staticVert = new Static3D[1];
692
    Static3D center = new Static3D(0,0,0);
693 4d883a92 Leszek Koltunski
    double cx, cy, cz;
694
    double[] singleV;
695 ef231eba Leszek Koltunski
696 1b85f172 Leszek Koltunski
    for(int v=0; v<lenV; v++)
697
      {
698
      // prepare verts[]
699
      numNeig = 0;
700 ef231eba Leszek Koltunski
701 1b85f172 Leszek Koltunski
      for (int[] vertIndex : vertIndexes)
702
        {
703
        lenFV = vertIndex.length;
704 ef231eba Leszek Koltunski
705 1b85f172 Leszek Koltunski
        for (int fv = 0; fv < lenFV; fv++)
706
          if (vertIndex[fv] == v)
707
            {
708
            int prev = fv > 0 ? fv - 1 : lenFV - 1;
709
            int next = fv < lenFV - 1 ? fv + 1 : 0;
710
711
            verts[numNeig++] = vertIndex[prev];
712
            verts[numNeig++] = vertIndex[next];
713
            }
714
        }
715
716
      cx=cy=cz=0.0f;
717
718
      // from verts[] prepare center
719
      for(int n=0; n<numNeig; n++)
720
        {
721
        singleV = vertices[verts[n]];
722
723
        cx += singleV[0];
724
        cy += singleV[1];
725
        cz += singleV[2];
726
        }
727 4d883a92 Leszek Koltunski
      center.set( (float)(cx/numNeig - vertices[v][0]),
728
                  (float)(cy/numNeig - vertices[v][1]),
729
                  (float)(cz/numNeig - vertices[v][2]));
730 1b85f172 Leszek Koltunski
731
      // round Corners
732 4d883a92 Leszek Koltunski
      staticVert[0] = new Static3D( (float)vertices[v][0], (float)vertices[v][1], (float)vertices[v][2]);
733 1b85f172 Leszek Koltunski
734
      int corn = cornerIndexes[v];
735
      float strength = corners[corn][0];
736
      float radius   = corners[corn][1];
737
738
      roundCorners(mesh, center, staticVert, strength, radius);
739
      }
740
    }
741
742
///////////////////////////////////////////////////////////////////////////////////////////////////
743
744 28f4aba0 Leszek Koltunski
  private void printInfo()
745 1b85f172 Leszek Koltunski
    {
746
    int stickers = mStickerInfo.size();
747
748 28f4aba0 Leszek Koltunski
    android.util.Log.d("D", "-------------------------");
749
750 1b85f172 Leszek Koltunski
    for(int s=0; s<stickers; s++)
751 ef231eba Leszek Koltunski
      {
752 28f4aba0 Leszek Koltunski
      String ver = "";
753 1b85f172 Leszek Koltunski
      StickerInfo info = mStickerInfo.get(s);
754
      int len = info.vertices.length/2;
755
756
      for(int i =0; i<len; i++)
757
        {
758
        ver += ("("+info.vertices[2*i]+","+info.vertices[2*i+1]+") ");
759
        }
760 28f4aba0 Leszek Koltunski
761
      android.util.Log.e("D", "sticker "+s+" "+ver);
762 ef231eba Leszek Koltunski
      }
763
764 28f4aba0 Leszek Koltunski
    android.util.Log.d("D", "-------------------------");
765 ef231eba Leszek Koltunski
766 28f4aba0 Leszek Koltunski
    int faces = mFaceInfo.size();
767 7edab735 Leszek Koltunski
768 28f4aba0 Leszek Koltunski
    for(int f=0; f<faces; f++)
769
      {
770
      FaceInfo info = mFaceInfo.get(f);
771
772
      android.util.Log.e("D", "q=("+info.qx+", "+info.qy+", "+info.qz+", "+info.qw+") v=("
773 1b85f172 Leszek Koltunski
                       +info.vx+", "+info.vy+", "+info.vz+") scale="+info.scale+" sticker="+info.sticker);
774 28f4aba0 Leszek Koltunski
      }
775
776
    android.util.Log.d("D", "-------------------------");
777 1b85f172 Leszek Koltunski
    }
778
779
///////////////////////////////////////////////////////////////////////////////////////////////////
780
781 4d883a92 Leszek Koltunski
  MeshBase createRoundedSolid(final double[][] vertices, final int[][] vertIndexes,
782
                              final float[][] bands    , final int[]   bandIndexes,
783
                              final float[][] corners  , final int[]   cornerIndexes)
784 7edab735 Leszek Koltunski
    {
785 33647db9 Leszek Koltunski
    prepareFaceInfo(vertices,vertIndexes);
786 7edab735 Leszek Koltunski
787 33647db9 Leszek Koltunski
    int numFaces = vertIndexes.length;
788
    float[] band, bandsComputed;
789
    MeshBase[] meshes = new MeshBase[numFaces];
790 1b85f172 Leszek Koltunski
    FaceInfo fInfo;
791
    StickerInfo sInfo;
792
793 28f4aba0 Leszek Koltunski
    printInfo();
794 55f20739 Leszek Koltunski
795 33647db9 Leszek Koltunski
    for(int face=0; face<numFaces; face++)
796
      {
797 1b85f172 Leszek Koltunski
      fInfo = mFaceInfo.get(face);
798
      sInfo = mStickerInfo.get(fInfo.sticker);
799 140f2c4e Leszek Koltunski
800 4d883a92 Leszek Koltunski
      double[] verts = sInfo.vertices;
801
      int lenVerts = verts.length;
802
      float[] vertsFloat = new float[lenVerts];
803
      for(int i=0; i<lenVerts; i++) vertsFloat[i] = (float)verts[i];
804
805 33647db9 Leszek Koltunski
      band = bands[bandIndexes[face]];
806
      bandsComputed = computeBands( band[0], (int)band[1], band[2], band[3], (int)band[4]);
807 4d883a92 Leszek Koltunski
      meshes[face] = new MeshPolygon(vertsFloat,bandsComputed,(int)band[5],(int)band[6]);
808 33647db9 Leszek Koltunski
      meshes[face].setEffectAssociation(0,(1<<face),0);
809
      }
810 7edab735 Leszek Koltunski
811 33647db9 Leszek Koltunski
    MeshBase mesh = new MeshJoined(meshes);
812 7edab735 Leszek Koltunski
    Static3D center = new Static3D(0,0,0);
813 fe032f52 Leszek Koltunski
814 33647db9 Leszek Koltunski
    for(int face=0; face<numFaces; face++)
815
      {
816
      int assoc = (1<<face);
817 1b85f172 Leszek Koltunski
      fInfo = mFaceInfo.get(face);
818 6a96e571 Leszek Koltunski
      sInfo = mStickerInfo.get(fInfo.sticker);
819 6d020cb6 Leszek Koltunski
820 6a96e571 Leszek Koltunski
      float dx = (float)sInfo.dx;
821
      float dy = (float)sInfo.dy;
822 4d883a92 Leszek Koltunski
      float vx = (float)fInfo.vx;
823
      float vy = (float)fInfo.vy;
824
      float vz = (float)fInfo.vz;
825
      float sc = (float)fInfo.scale;
826
      float qx = (float)fInfo.qx;
827
      float qy = (float)fInfo.qy;
828
      float qz = (float)fInfo.qz;
829
      float qw = (float)fInfo.qw;
830
831 6a96e571 Leszek Koltunski
      Static3D move2D= new Static3D(dx,dy,0.0f);
832 4d883a92 Leszek Koltunski
      Static3D move3D= new Static3D(vx,vy,vz);
833
      Static3D scale = new Static3D(sc,sc, fInfo.flip ? -sc : sc);
834
      Static4D quat  = new Static4D(qx,qy,qz,qw);
835 6d020cb6 Leszek Koltunski
836 6a96e571 Leszek Koltunski
      mesh.apply(new MatrixEffectMove(move2D)           ,assoc,-1);
837
      mesh.apply(new MatrixEffectScale(scale)           ,assoc,-1);
838
      mesh.apply(new MatrixEffectQuaternion(quat,center),assoc,-1);
839
      mesh.apply(new MatrixEffectMove(move3D)           ,assoc,-1);
840 33647db9 Leszek Koltunski
      }
841 a65604a7 Leszek Koltunski
842 1b85f172 Leszek Koltunski
    prepareAndRoundCorners(mesh, vertices, vertIndexes, corners, cornerIndexes);
843 a65604a7 Leszek Koltunski
844 7edab735 Leszek Koltunski
    return mesh;
845
    }
846
  }