Project

General

Profile

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

examples / src / main / java / org / distorted / examples / meshfile / FactoryCubit.java @ 6983badf

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 6983badf Leszek Koltunski
  private static class StickerCoords
51 33647db9 Leszek Koltunski
    {
52 4d883a92 Leszek Koltunski
    double[] vertices;
53 1b85f172 Leszek Koltunski
    }
54
55 6983badf Leszek Koltunski
  private static class FaceTransform
56 1b85f172 Leszek Koltunski
    {
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 6983badf Leszek Koltunski
  private static final ArrayList<FaceTransform> mNewFaceTransf = new ArrayList<>();
65
  private static final ArrayList<FaceTransform> mOldFaceTransf = new ArrayList<>();
66
  private static final ArrayList<StickerCoords> mStickerCoords = new ArrayList<>();
67
68 33647db9 Leszek Koltunski
69 7edab735 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
70
71 55f20739 Leszek Koltunski
  private FactoryCubit()
72 7edab735 Leszek Koltunski
    {
73
74
    }
75
76
///////////////////////////////////////////////////////////////////////////////////////////////////
77
78 55f20739 Leszek Koltunski
  public static FactoryCubit getInstance()
79 7edab735 Leszek Koltunski
    {
80 55f20739 Leszek Koltunski
    if( mThis==null ) mThis = new FactoryCubit();
81 7edab735 Leszek Koltunski
82
    return mThis;
83
    }
84
85
///////////////////////////////////////////////////////////////////////////////////////////////////
86
// H - height of the band in the middle
87
// alpha - angle of the edge  [0,90]
88
// dist - often in a polygon the distance from edge to center is not 1, but something else.
89
// This is the distance.
90
// K - where to begin the second, much more flat part of the band. [0,1]
91
// N - number of bands. N>=3
92
//
93
// theory: two distinct parts to the band:
94
// 1) (0,B) - steep
95
// 2) (B,1) - flat
96
//
97
// In first part, we have y = g(x) ; in second - y = g(f(x)) where
98
//
99
// g(x) = sqrt( R^2 - (x-D)^2 ) - R*cos(alpha)
100
// f(x) = ((D-B)/(1-B)*x + B*(1-D)/(1-B)
101
// h(x) = R*(sin(alpha) - sin(x))
102
// R = H/(1-cos(alpha))
103
// D = H*sin(alpha)
104
// B = h(K*alpha)
105
//
106
// The N points are taken at:
107
//
108
// 1) in the second part, there are K2 = (N-3)/3 such points
109
// 2) in the first - K1 = (N-3) - K2
110
// 3) also, the 3 points 0,B,1
111
//
112
// so we have the sequence A[i] of N points
113
//
114
// 0
115
// h((i+1)*(1-K)*alpha/(K1+1)) (i=0,1,...,K1-1)
116
// B
117
// (1-B)*(i+1)/(K2+1) + B   (i=0,i,...,K2-1)
118
// 1
119
120
///////////////////////////////////////////////////////////////////////////////////////////////////
121
122
  private float f(float D, float B, float x)
123
    {
124
    return ((D-B)*x + B*(1-D))/(1-B);
125
    }
126
127
///////////////////////////////////////////////////////////////////////////////////////////////////
128
129
  private float g(float R, float D, float x, float cosAlpha)
130
    {
131
    float d = x-D;
132
    return (float)(Math.sqrt(R*R-d*d)-R*cosAlpha);
133
    }
134
135
///////////////////////////////////////////////////////////////////////////////////////////////////
136
137
  private float h(float R, float sinAlpha, float x)
138
    {
139
    return R*(sinAlpha-(float)Math.sin(x));
140
    }
141
142
///////////////////////////////////////////////////////////////////////////////////////////////////
143
144 55f20739 Leszek Koltunski
  float[] computeBands(float H, int alpha, float dist, float K, int N)
145 7edab735 Leszek Koltunski
    {
146
    float[] bands = new float[2*N];
147
148
    bands[0] = 1.0f;
149
    bands[1] = 0.0f;
150
151
    float beta = (float)Math.atan(dist*Math.tan(Math.PI*alpha/180));
152
    float sinBeta = (float)Math.sin(beta);
153
    float cosBeta = (float)Math.cos(beta);
154
    float R = cosBeta<1.0f ? H/(1.0f-cosBeta) : 0.0f;
155
    float D = R*sinBeta;
156
    float B = h(R,sinBeta,K*beta);
157
158
    if( D>1.0f )
159
      {
160
      for(int i=1; i<N; i++)
161
        {
162
        bands[2*i  ] = (float)(N-1-i)/(N-1);
163
        bands[2*i+1] = H*(1-bands[2*i]);
164
        }
165
      }
166
    else
167
      {
168 55f20739 Leszek Koltunski
      int K2 = (int)((N-3)*K);
169 7edab735 Leszek Koltunski
      int K1 = (N-3)-K2;
170
171
      for(int i=0; i<=K1; i++)
172
        {
173
        float angle = K*beta + (1-K)*beta*(K1-i)/(K1+1);
174
        float x = h(R,sinBeta,angle);
175
        bands[2*i+2] = 1.0f - x;
176
        bands[2*i+3] = g(R,D,x,cosBeta);
177
        }
178
179
      for(int i=0; i<=K2; i++)
180
        {
181
        float x = (1-B)*(i+1)/(K2+1) + B;
182
        bands[2*K1+2 + 2*i+2] = 1.0f - x;
183
        bands[2*K1+2 + 2*i+3] = g(R,D,f(D,B,x),cosBeta);
184
        }
185
      }
186
187 55f20739 Leszek Koltunski
    bands[2*N-2] = 0.0f;
188
    bands[2*N-1] =    H;
189
190 7edab735 Leszek Koltunski
    return bands;
191
    }
192
193
///////////////////////////////////////////////////////////////////////////////////////////////////
194
195
  private void roundCorners(MeshBase mesh, Static3D center, Static3D[] vertices, float strength, float regionRadius)
196
    {
197 1b85f172 Leszek Koltunski
    Static4D region= new Static4D(0,0,0,regionRadius);
198 7edab735 Leszek Koltunski
199
    float centX = center.get0();
200
    float centY = center.get1();
201
    float centZ = center.get2();
202
203
    for (Static3D vertex : vertices)
204
      {
205
      float x = strength*(centX - vertex.get0());
206
      float y = strength*(centY - vertex.get1());
207
      float z = strength*(centZ - vertex.get2());
208
209 1b85f172 Leszek Koltunski
      VertexEffect effect = new VertexEffectDeform(new Static3D(x,y,z), RADIUS, vertex, region);
210 7edab735 Leszek Koltunski
      mesh.apply(effect);
211
      }
212
    }
213
214
///////////////////////////////////////////////////////////////////////////////////////////////////
215
216 4d883a92 Leszek Koltunski
  private boolean areColinear(double[][] vertices, int index1, int index2, int index3)
217 7edab735 Leszek Koltunski
    {
218 4d883a92 Leszek Koltunski
    double x1 = vertices[index1][0];
219
    double y1 = vertices[index1][1];
220
    double z1 = vertices[index1][2];
221
    double x2 = vertices[index2][0];
222
    double y2 = vertices[index2][1];
223
    double z2 = vertices[index2][2];
224
    double x3 = vertices[index3][0];
225
    double y3 = vertices[index3][1];
226
    double z3 = vertices[index3][2];
227
228
    double v1x = x2-x1;
229
    double v1y = y2-y1;
230
    double v1z = z2-z1;
231
    double v2x = x3-x1;
232
    double v2y = y3-y1;
233
    double v2z = z3-z1;
234
235
    double A = Math.sqrt( (v1x*v1x+v1y*v1y+v1z*v1z) / (v2x*v2x+v2y*v2y+v2z*v2z) );
236 7edab735 Leszek Koltunski
237 33647db9 Leszek Koltunski
    return (v1x==A*v2x && v1y==A*v2y && v1z==A*v2z);
238 7edab735 Leszek Koltunski
    }
239
240
///////////////////////////////////////////////////////////////////////////////////////////////////
241
242 4d883a92 Leszek Koltunski
  private void computeNormalVector(double[][] vertices, int index1, int index2, int index3)
243 7edab735 Leszek Koltunski
    {
244 4d883a92 Leszek Koltunski
    double x1 = vertices[index1][0];
245
    double y1 = vertices[index1][1];
246
    double z1 = vertices[index1][2];
247
    double x2 = vertices[index2][0];
248
    double y2 = vertices[index2][1];
249
    double z2 = vertices[index2][2];
250
    double x3 = vertices[index3][0];
251
    double y3 = vertices[index3][1];
252
    double z3 = vertices[index3][2];
253
254
    double v1x = x2-x1;
255
    double v1y = y2-y1;
256
    double v1z = z2-z1;
257
    double v2x = x3-x1;
258
    double v2y = y3-y1;
259
    double v2z = z3-z1;
260 7edab735 Leszek Koltunski
261 33647db9 Leszek Koltunski
    mBuffer[0] = v1y*v2z - v2y*v1z;
262
    mBuffer[1] = v1z*v2x - v2z*v1x;
263
    mBuffer[2] = v1x*v2y - v2x*v1y;
264 ef231eba Leszek Koltunski
265 4d883a92 Leszek Koltunski
    double len = mBuffer[0]*mBuffer[0] + mBuffer[1]*mBuffer[1] + mBuffer[2]*mBuffer[2];
266
    len = Math.sqrt(len);
267 140f2c4e Leszek Koltunski
    mBuffer[0] /= len;
268
    mBuffer[1] /= len;
269
    mBuffer[2] /= len;
270 7edab735 Leszek Koltunski
    }
271
272
///////////////////////////////////////////////////////////////////////////////////////////////////
273 33647db9 Leszek Koltunski
// return quat1*quat2
274 7edab735 Leszek Koltunski
275 4d883a92 Leszek Koltunski
  private static void quatMultiply( double[] quat1, double[] quat2, double[] result )
276 7edab735 Leszek Koltunski
    {
277 4d883a92 Leszek Koltunski
    double qx = quat1[0];
278
    double qy = quat1[1];
279
    double qz = quat1[2];
280
    double qw = quat1[3];
281 7edab735 Leszek Koltunski
282 4d883a92 Leszek Koltunski
    double rx = quat2[0];
283
    double ry = quat2[1];
284
    double rz = quat2[2];
285
    double rw = quat2[3];
286 7edab735 Leszek Koltunski
287 33647db9 Leszek Koltunski
    result[0] = rw*qx - rz*qy + ry*qz + rx*qw;
288
    result[1] = rw*qy + rz*qx + ry*qw - rx*qz;
289
    result[2] = rw*qz + rz*qw - ry*qx + rx*qy;
290
    result[3] = rw*qw - rz*qz - ry*qy - rx*qx;
291 7edab735 Leszek Koltunski
    }
292
293
///////////////////////////////////////////////////////////////////////////////////////////////////
294
295 6983badf Leszek Koltunski
  private void fitInSquare(FaceTransform info, double[][] vert3D)
296 7edab735 Leszek Koltunski
    {
297 4d883a92 Leszek Koltunski
    double minX = Double.MAX_VALUE;
298
    double maxX =-Double.MAX_VALUE;
299
    double minY = Double.MAX_VALUE;
300
    double maxY =-Double.MAX_VALUE;
301 55f20739 Leszek Koltunski
302 4d883a92 Leszek Koltunski
    for (double[] vert : vert3D)
303 33647db9 Leszek Koltunski
      {
304 4d883a92 Leszek Koltunski
      double x = vert[0];
305
      double y = vert[1];
306 55f20739 Leszek Koltunski
307 33647db9 Leszek Koltunski
      if (x > maxX) maxX = x;
308
      if (x < minX) minX = x;
309
      if (y > maxY) maxY = y;
310
      if (y < minY) minY = y;
311
      }
312 55f20739 Leszek Koltunski
313 3083fab8 Leszek Koltunski
    minX = minX<0 ? -minX:minX;
314
    maxX = maxX<0 ? -maxX:maxX;
315
    minY = minY<0 ? -minY:minY;
316
    maxY = maxY<0 ? -maxY:maxY;
317
318
    double max1 = Math.max(minX,minY);
319
    double max2 = Math.max(maxX,maxY);
320
    double max3 = Math.max(max1,max2);
321
322
    info.scale = max3/0.5;
323 ef231eba Leszek Koltunski
324 33647db9 Leszek Koltunski
    int len = vert3D.length;
325 6983badf Leszek Koltunski
    StickerCoords sInfo = new StickerCoords();
326 4d883a92 Leszek Koltunski
    sInfo.vertices = new double[2*len];
327 55f20739 Leszek Koltunski
328 33647db9 Leszek Koltunski
    for( int vertex=0; vertex<len; vertex++ )
329 55f20739 Leszek Koltunski
      {
330 1b85f172 Leszek Koltunski
      sInfo.vertices[2*vertex  ] = vert3D[vertex][0] / info.scale;
331
      sInfo.vertices[2*vertex+1] = vert3D[vertex][1] / info.scale;
332 55f20739 Leszek Koltunski
      }
333
334 6983badf Leszek Koltunski
    mStickerCoords.add(sInfo);
335 28f4aba0 Leszek Koltunski
336 6983badf Leszek Koltunski
    info.sticker = mStickerCoords.size() -1;
337 33647db9 Leszek Koltunski
    info.flip = false;
338 55f20739 Leszek Koltunski
    }
339
340
///////////////////////////////////////////////////////////////////////////////////////////////////
341
342 6983badf Leszek Koltunski
  private FaceTransform constructNewTransform(final double[][] vert3D)
343 55f20739 Leszek Koltunski
    {
344 6983badf Leszek Koltunski
    FaceTransform ft = new FaceTransform();
345
346 33647db9 Leszek Koltunski
    // compute center of gravity
347 6983badf Leszek Koltunski
    ft.vx = 0.0f;
348
    ft.vy = 0.0f;
349
    ft.vz = 0.0f;
350 33647db9 Leszek Koltunski
    int len = vert3D.length;
351 55f20739 Leszek Koltunski
352 4d883a92 Leszek Koltunski
    for (double[] vert : vert3D)
353 55f20739 Leszek Koltunski
      {
354 6983badf Leszek Koltunski
      ft.vx += vert[0];
355
      ft.vy += vert[1];
356
      ft.vz += vert[2];
357 55f20739 Leszek Koltunski
      }
358
359 6983badf Leszek Koltunski
    ft.vx /= len;
360
    ft.vy /= len;
361
    ft.vz /= len;
362 55f20739 Leszek Koltunski
363 33647db9 Leszek Koltunski
    // move all vertices so that their center of gravity is at (0,0,0)
364
    for (int i=0; i<len; i++)
365 7cd30f7c Leszek Koltunski
      {
366 6983badf Leszek Koltunski
      vert3D[i][0] -= ft.vx;
367
      vert3D[i][1] -= ft.vy;
368
      vert3D[i][2] -= ft.vz;
369 7cd30f7c Leszek Koltunski
      }
370
371 33647db9 Leszek Koltunski
    // find 3 non-colinear vertices
372
    int foundIndex = -1;
373 7cd30f7c Leszek Koltunski
374 33647db9 Leszek Koltunski
    for(int vertex=2; vertex<len; vertex++)
375 7cd30f7c Leszek Koltunski
      {
376 33647db9 Leszek Koltunski
      if( !areColinear(vert3D,0,1,vertex) )
377
        {
378
        foundIndex = vertex;
379
        break;
380
        }
381 7cd30f7c Leszek Koltunski
      }
382
383 33647db9 Leszek Koltunski
    // compute the normal vector
384
    if( foundIndex==-1 )
385
      {
386
      throw new RuntimeException("all vertices colinear");
387
      }
388 7cd30f7c Leszek Koltunski
389 33647db9 Leszek Koltunski
    computeNormalVector(vert3D,0,1,foundIndex);
390
391 140f2c4e Leszek Koltunski
    // rotate so that the normal vector becomes (0,0,1)
392 4d883a92 Leszek Koltunski
    double axisX, axisY, axisZ;
393 140f2c4e Leszek Koltunski
394 ef231eba Leszek Koltunski
    if( mBuffer[0]!=0.0f || mBuffer[1]!=0.0f )
395 33647db9 Leszek Koltunski
      {
396 140f2c4e Leszek Koltunski
      axisX = -mBuffer[1];
397
      axisY =  mBuffer[0];
398
      axisZ = 0.0f;
399 ef231eba Leszek Koltunski
400 4d883a92 Leszek Koltunski
      double axiLen = axisX*axisX + axisY*axisY;
401
      axiLen = Math.sqrt(axiLen);
402 ef231eba Leszek Koltunski
      axisX /= axiLen;
403
      axisY /= axiLen;
404
      axisZ /= axiLen;
405 140f2c4e Leszek Koltunski
      }
406
    else
407
      {
408
      axisX = 0.0f;
409
      axisY = 1.0f;
410
      axisZ = 0.0f;
411
      }
412 ef231eba Leszek Koltunski
413 4d883a92 Leszek Koltunski
    double cosTheta = mBuffer[2];
414
    double sinTheta = Math.sqrt(1-cosTheta*cosTheta);
415
    double sinHalfTheta = computeSinHalf(cosTheta);
416
    double cosHalfTheta = computeCosHalf(sinTheta,cosTheta);
417 ef231eba Leszek Koltunski
418 140f2c4e Leszek Koltunski
    mQuat1[0] = axisX*sinHalfTheta;
419
    mQuat1[1] = axisY*sinHalfTheta;
420
    mQuat1[2] = axisZ*sinHalfTheta;
421
    mQuat1[3] = cosHalfTheta;
422 28f4aba0 Leszek Koltunski
    mQuat2[0] =-axisX*sinHalfTheta;
423
    mQuat2[1] =-axisY*sinHalfTheta;
424
    mQuat2[2] =-axisZ*sinHalfTheta;
425
    mQuat2[3] = cosHalfTheta;
426 ef231eba Leszek Koltunski
427 4d883a92 Leszek Koltunski
    for (double[] vert : vert3D)
428 140f2c4e Leszek Koltunski
      {
429 28f4aba0 Leszek Koltunski
      quatMultiply(mQuat1, vert  , mQuat3);
430
      quatMultiply(mQuat3, mQuat2, vert  );
431 33647db9 Leszek Koltunski
      }
432 7cd30f7c Leszek Koltunski
433 33647db9 Leszek Koltunski
    // fit the whole thing in a square and remember the scale & 2D vertices
434 6983badf Leszek Koltunski
    fitInSquare(ft, vert3D);
435 7cd30f7c Leszek Koltunski
436 33647db9 Leszek Koltunski
    // remember the rotation
437 6983badf Leszek Koltunski
    ft.qx =-mQuat1[0];
438
    ft.qy =-mQuat1[1];
439
    ft.qz =-mQuat1[2];
440
    ft.qw = mQuat1[3];
441
442
    return ft;
443 7cd30f7c Leszek Koltunski
    }
444
445 fe032f52 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
446
447 4d883a92 Leszek Koltunski
  private double computeCos(double oldX, double oldY, double newX, double newY, double len1, double len2)
448 fe032f52 Leszek Koltunski
    {
449 3083fab8 Leszek Koltunski
    double ret= (oldX*newX+oldY*newY) / (len1*len2);
450
    if( ret<-1.0 ) return -1.0;
451
    if( ret> 1.0 ) return  1.0;
452
453
    return ret;
454 fe032f52 Leszek Koltunski
    }
455
456 b3d28a81 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
457 4d883a92 Leszek Koltunski
// sin of (signed!) angle between vectors 'old' and 'new', counterclockwise!
458 b3d28a81 Leszek Koltunski
459 4d883a92 Leszek Koltunski
  private double computeSin(double oldX, double oldY, double newX, double newY, double len1, double len2)
460 b3d28a81 Leszek Koltunski
    {
461 3083fab8 Leszek Koltunski
    double ret= (newX*oldY-oldX*newY) / (len1*len2);
462
    if( ret<-1.0 ) return -1.0;
463
    if( ret> 1.0 ) return  1.0;
464
465
    return ret;
466 b3d28a81 Leszek Koltunski
    }
467
468 54e47d9b Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
469
470 4d883a92 Leszek Koltunski
  private void rotateAllVertices(double[] result, int len, double[] vertices, double sin, double cos)
471 54e47d9b Leszek Koltunski
    {
472 33647db9 Leszek Koltunski
    for(int i=0; i<len; i++)
473 54e47d9b Leszek Koltunski
      {
474 33647db9 Leszek Koltunski
      result[2*i  ] = vertices[2*i  ]*cos - vertices[2*i+1]*sin;
475
      result[2*i+1] = vertices[2*i  ]*sin + vertices[2*i+1]*cos;
476 54e47d9b Leszek Koltunski
      }
477
    }
478
479 6d020cb6 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
480
481 6983badf Leszek Koltunski
  private double computeScale(double[] v1, double[] v2, int v1i, int v2i)
482 6d020cb6 Leszek Koltunski
    {
483 6983badf Leszek Koltunski
    double v1x = v1[2*v1i];
484
    double v1y = v1[2*v1i+1];
485
    double v2x = v2[2*v2i];
486
    double v2y = v2[2*v2i+1];
487
488
    double lenSq1 = v1x*v1x + v1y*v1y;
489
    double lenSq2 = v2x*v2x + v2y*v2y;
490 4d883a92 Leszek Koltunski
491
    return Math.sqrt(lenSq2/lenSq1);
492
    }
493
494
///////////////////////////////////////////////////////////////////////////////////////////////////
495 6983badf Leszek Koltunski
// valid for 0<angle<2*PI
496 4d883a92 Leszek Koltunski
497
  private double computeSinHalf(double cos)
498
    {
499
    return Math.sqrt((1-cos)/2);
500
    }
501
502
///////////////////////////////////////////////////////////////////////////////////////////////////
503 6983badf Leszek Koltunski
// valid for 0<angle<2*PI
504 4d883a92 Leszek Koltunski
505
  private double computeCosHalf(double sin, double cos)
506
    {
507
    double cosHalf = Math.sqrt((1+cos)/2);
508
    return sin<0 ? -cosHalf : cosHalf;
509
    }
510
511
///////////////////////////////////////////////////////////////////////////////////////////////////
512
513 3083fab8 Leszek Koltunski
  private int computeRotatedIndex(int oldVertex, int len, int rotatedVertex, boolean inverted)
514
    {
515
    int v = (rotatedVertex + (inverted? -oldVertex : oldVertex));
516
    if( v>=len ) v-=len;
517
    if( v< 0   ) v+=len;
518
519
    return v;
520
    }
521
522
///////////////////////////////////////////////////////////////////////////////////////////////////
523
524
  private boolean isScaledVersionOf(double[] newVert, double[] oldVert, int len, int vertex, boolean inverted)
525 4d883a92 Leszek Koltunski
    {
526 6983badf Leszek Koltunski
    int newZeroIndex = computeRotatedIndex(0,len,vertex,inverted);
527 4d883a92 Leszek Koltunski
    double EPSILON = 0.001;
528 6983badf Leszek Koltunski
    double scale = computeScale(newVert,oldVert,newZeroIndex,0);
529 55f20739 Leszek Koltunski
530 33647db9 Leszek Koltunski
    for(int i=1; i<len; i++)
531
      {
532 3083fab8 Leszek Koltunski
      int index = computeRotatedIndex(i,len,vertex,inverted);
533
534
      double horz = oldVert[2*i  ] - scale*newVert[2*index  ];
535
      double vert = oldVert[2*i+1] - scale*newVert[2*index+1];
536 7edab735 Leszek Koltunski
537 33647db9 Leszek Koltunski
      if( horz>EPSILON || horz<-EPSILON || vert>EPSILON || vert<-EPSILON ) return false;
538
      }
539 55f20739 Leszek Koltunski
540 33647db9 Leszek Koltunski
    return true;
541 7edab735 Leszek Koltunski
    }
542
543
///////////////////////////////////////////////////////////////////////////////////////////////////
544
545 4d883a92 Leszek Koltunski
  private void mirrorAllVertices(double[] output, int len, double[] input)
546 7edab735 Leszek Koltunski
    {
547 33647db9 Leszek Koltunski
    for(int vertex=0; vertex<len; vertex++)
548
      {
549
      output[2*vertex  ] = input[2*vertex  ];
550
      output[2*vertex+1] =-input[2*vertex+1];
551
      }
552 7edab735 Leszek Koltunski
    }
553
554
///////////////////////////////////////////////////////////////////////////////////////////////////
555
556 6983badf Leszek Koltunski
  private void correctTransform(FaceTransform ft, double scale, double sin, double cos, int oldSticker, boolean flip)
557 7edab735 Leszek Koltunski
    {
558 6983badf Leszek Koltunski
    mStickerCoords.remove(ft.sticker);
559 7edab735 Leszek Koltunski
560 6983badf Leszek Koltunski
    ft.flip    = flip;
561
    ft.sticker = oldSticker;
562
    ft.scale  *= scale;
563 28f4aba0 Leszek Koltunski
564 6983badf Leszek Koltunski
    mQuat1[0] = ft.qx;
565
    mQuat1[1] = ft.qy;
566
    mQuat1[2] = ft.qz;
567
    mQuat1[3] = ft.qw;
568 7edab735 Leszek Koltunski
569 4d883a92 Leszek Koltunski
    double sinHalf = computeSinHalf(cos);
570
    double cosHalf = computeCosHalf(sin,cos);
571 55f20739 Leszek Koltunski
572 3083fab8 Leszek Koltunski
    if( flip )
573
      {
574
      mQuat3[0] = 0.0f;
575
      mQuat3[1] = 0.0f;
576
      mQuat3[2] = sinHalf;
577
      mQuat3[3] = cosHalf;
578
579
      mQuat4[0] = 1.0;
580
      mQuat4[1] = 0.0;
581
      mQuat4[2] = 0.0;
582
      mQuat4[3] = 0.0;
583
584
      quatMultiply( mQuat3, mQuat4, mQuat2 );
585
      }
586
    else
587
      {
588
      mQuat2[0] = 0.0f;
589
      mQuat2[1] = 0.0f;
590
      mQuat2[2] = sinHalf;
591
      mQuat2[3] = cosHalf;
592
      }
593 7edab735 Leszek Koltunski
594 33647db9 Leszek Koltunski
    quatMultiply( mQuat1, mQuat2, mQuat3 );
595 55f20739 Leszek Koltunski
596 6983badf Leszek Koltunski
    ft.qx = mQuat3[0];
597
    ft.qy = mQuat3[1];
598
    ft.qz = mQuat3[2];
599
    ft.qw = mQuat3[3];
600 7edab735 Leszek Koltunski
    }
601
602 3083fab8 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
603
604
  private void printVert(double[] buffer)
605
    {
606
    int len = buffer.length/2;
607
    String str = "";
608
609
    for(int i=0; i<len; i++)
610
      {
611
      str += (" ("+buffer[2*i]+" , "+buffer[2*i+1]+" ) ");
612
      }
613
614
    android.util.Log.d("D", str);
615
    }
616
617 7edab735 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
618
619 6983badf Leszek Koltunski
  private boolean foundVertex(FaceTransform ft, double[] buffer, int len, double[] newVert,
620 4d883a92 Leszek Koltunski
                              double[] oldVert, double lenFirstOld, int oldSticker, boolean inverted)
621 7edab735 Leszek Koltunski
    {
622 33647db9 Leszek Koltunski
    for(int vertex=0; vertex<len; vertex++)
623
      {
624 4d883a92 Leszek Koltunski
      double newX = newVert[2*vertex  ];
625
      double newY = newVert[2*vertex+1];
626
      double lenIthNew = Math.sqrt(newX*newX + newY*newY);
627
      double cos = computeCos( oldVert[0], oldVert[1], newX, newY, lenIthNew, lenFirstOld);
628
      double sin = computeSin( oldVert[0], oldVert[1], newX, newY, lenIthNew, lenFirstOld);
629 7edab735 Leszek Koltunski
630 1b85f172 Leszek Koltunski
      rotateAllVertices(buffer,len,newVert,sin,cos);
631 7edab735 Leszek Koltunski
632 3083fab8 Leszek Koltunski
      if( isScaledVersionOf(buffer,oldVert,len,vertex,inverted) )
633 33647db9 Leszek Koltunski
        {
634 6983badf Leszek Koltunski
        int newZeroIndex = computeRotatedIndex(0,len,vertex,inverted);
635
        double scale = computeScale(oldVert,newVert,0,newZeroIndex);
636
        correctTransform(ft,scale,sin,cos,oldSticker,inverted);
637 33647db9 Leszek Koltunski
        return true;
638
        }
639
      }
640 55f20739 Leszek Koltunski
641 33647db9 Leszek Koltunski
    return false;
642 7edab735 Leszek Koltunski
    }
643
644
///////////////////////////////////////////////////////////////////////////////////////////////////
645
646 6983badf Leszek Koltunski
  private boolean successfullyCollapsedStickers(final FaceTransform newInfo, final FaceTransform oldInfo)
647 7edab735 Leszek Koltunski
    {
648 6983badf Leszek Koltunski
    StickerCoords sNewInfo = mStickerCoords.get(newInfo.sticker);
649
    StickerCoords sOldInfo = mStickerCoords.get(oldInfo.sticker);
650 4d883a92 Leszek Koltunski
    double[] newVert = sNewInfo.vertices;
651
    double[] oldVert = sOldInfo.vertices;
652
    int oldLen = oldVert.length;
653
    int newLen = newVert.length;
654 7edab735 Leszek Koltunski
655 4d883a92 Leszek Koltunski
    if( oldLen == newLen )
656 33647db9 Leszek Koltunski
      {
657 4d883a92 Leszek Koltunski
      int oldSticker = oldInfo.sticker;
658
      double[] buffer1 = new double[oldLen];
659 f4b59207 Leszek Koltunski
      double lenFirstOld = Math.sqrt(oldVert[0]*oldVert[0] + oldVert[1]*oldVert[1]);
660 4d883a92 Leszek Koltunski
      if( foundVertex(newInfo, buffer1, oldLen/2, newVert, oldVert, lenFirstOld, oldSticker, false) ) return true;
661
      double[] buffer2 = new double[oldLen];
662
      mirrorAllVertices(buffer2, newLen/2, newVert);
663
      if( foundVertex(newInfo, buffer1, oldLen/2, buffer2, oldVert, lenFirstOld, oldSticker, true ) ) return true;
664 33647db9 Leszek Koltunski
      }
665 55f20739 Leszek Koltunski
666 33647db9 Leszek Koltunski
    return false;
667 7edab735 Leszek Koltunski
    }
668
669
///////////////////////////////////////////////////////////////////////////////////////////////////
670
671 4d883a92 Leszek Koltunski
  private double[][] constructVert(double[][] vertices, int[] index)
672 7edab735 Leszek Koltunski
    {
673 33647db9 Leszek Koltunski
    int len = index.length;
674 4d883a92 Leszek Koltunski
    double[][] ret = new double[len][4];
675 7edab735 Leszek Koltunski
676 33647db9 Leszek Koltunski
    for(int i=0; i<len; i++)
677
      {
678
      ret[i][0] = vertices[index[i]][0];
679
      ret[i][1] = vertices[index[i]][1];
680
      ret[i][2] = vertices[index[i]][2];
681
      ret[i][3] = 1.0f;
682
      }
683 7edab735 Leszek Koltunski
684 33647db9 Leszek Koltunski
    return ret;
685 7edab735 Leszek Koltunski
    }
686
687
///////////////////////////////////////////////////////////////////////////////////////////////////
688
689 6983badf Leszek Koltunski
  private void prepareAndRoundCorners(MeshBase mesh, double[][] vertices,
690
                                      float[][] corners, int[] cornerIndexes,
691
                                      float[][] centers, int[] centerIndexes )
692 ef231eba Leszek Koltunski
    {
693 1b85f172 Leszek Koltunski
    int lenV = vertices.length;
694
    Static3D[] staticVert = new Static3D[1];
695
    Static3D center = new Static3D(0,0,0);
696 ef231eba Leszek Koltunski
697 1b85f172 Leszek Koltunski
    for(int v=0; v<lenV; v++)
698
      {
699 6983badf Leszek Koltunski
      staticVert[0] = new Static3D( (float)vertices[v][0], (float)vertices[v][1], (float)vertices[v][2]);
700 ef231eba Leszek Koltunski
701 6983badf Leszek Koltunski
      int cent = centerIndexes[v];
702
703
      if( cent>=0 )
704 1b85f172 Leszek Koltunski
        {
705 6983badf Leszek Koltunski
        center.set( centers[cent][0], centers[cent][1], centers[cent][2]);
706 ef231eba Leszek Koltunski
707 6983badf Leszek Koltunski
        int corn = cornerIndexes[v];
708
        float strength = corners[corn][0];
709
        float radius   = corners[corn][1];
710 1b85f172 Leszek Koltunski
711 6983badf Leszek Koltunski
        roundCorners(mesh, center, staticVert, strength, radius);
712 1b85f172 Leszek Koltunski
        }
713 6983badf Leszek Koltunski
      }
714
    }
715 1b85f172 Leszek Koltunski
716 6983badf Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
717 1b85f172 Leszek Koltunski
718 6983badf Leszek Koltunski
  private void correctComponents(MeshBase mesh, int numComponents)
719
    {
720
    int numTexToBeAdded = numComponents-mesh.getNumTexComponents();
721 1b85f172 Leszek Koltunski
722 6983badf Leszek Koltunski
    //mesh.mergeEffComponents();
723 1b85f172 Leszek Koltunski
724 6983badf Leszek Koltunski
    for(int i=0; i<numTexToBeAdded; i++ ) mesh.addEmptyTexComponent();
725
    }
726 1b85f172 Leszek Koltunski
727 6983badf Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
728 1b85f172 Leszek Koltunski
729 6983badf Leszek Koltunski
  private void printTransform(FaceTransform f)
730
    {
731
    android.util.Log.e("D", "q=("+f.qx+", "+f.qy+", "+f.qz+", "+f.qw+") v=("
732
                       +f.vx+", "+f.vy+", "+f.vz+") scale="+f.scale+" sticker="+f.sticker);
733 1b85f172 Leszek Koltunski
    }
734
735
///////////////////////////////////////////////////////////////////////////////////////////////////
736 6983badf Leszek Koltunski
// PUBLIC
737 1b85f172 Leszek Koltunski
738 6983badf Leszek Koltunski
  public void printStickerCoords()
739 1b85f172 Leszek Koltunski
    {
740 6983badf Leszek Koltunski
    int stickers = mStickerCoords.size();
741 1b85f172 Leszek Koltunski
742 6983badf Leszek Koltunski
    android.util.Log.d("D", "---- STICKER COORDS ----");
743 28f4aba0 Leszek Koltunski
744 1b85f172 Leszek Koltunski
    for(int s=0; s<stickers; s++)
745 ef231eba Leszek Koltunski
      {
746 6983badf Leszek Koltunski
      String ver = "{ ";
747
      StickerCoords info = mStickerCoords.get(s);
748 1b85f172 Leszek Koltunski
      int len = info.vertices.length/2;
749
750
      for(int i =0; i<len; i++)
751
        {
752 6983badf Leszek Koltunski
        if( i!=0 ) ver += ", ";
753
        ver += ( (float)info.vertices[2*i]+"f, "+(float)info.vertices[2*i+1]+"f");
754 1b85f172 Leszek Koltunski
        }
755 28f4aba0 Leszek Koltunski
756 6983badf Leszek Koltunski
      ver += " }";
757
      android.util.Log.d("D", ver);
758 ef231eba Leszek Koltunski
      }
759
760 6983badf Leszek Koltunski
    android.util.Log.d("D", "---- END STICKER COORDS ----");
761
    }
762
763
///////////////////////////////////////////////////////////////////////////////////////////////////
764
765
  public void printFaceTransform()
766
    {
767
    android.util.Log.d("D", "---- OLD FACE TRANSFORM ---");
768 ef231eba Leszek Koltunski
769 6983badf Leszek Koltunski
    int oldfaces = mOldFaceTransf.size();
770 7edab735 Leszek Koltunski
771 6983badf Leszek Koltunski
    for(int f=0; f<oldfaces; f++)
772 28f4aba0 Leszek Koltunski
      {
773 6983badf Leszek Koltunski
      printTransform(mOldFaceTransf.get(f));
774
      }
775
776
    android.util.Log.d("D", "---- NEW FACE TRANSFORM ---");
777 28f4aba0 Leszek Koltunski
778 6983badf Leszek Koltunski
    int newfaces = mNewFaceTransf.size();
779
780
    for(int f=0; f<newfaces; f++)
781
      {
782
      printTransform(mNewFaceTransf.get(f));
783 28f4aba0 Leszek Koltunski
      }
784 6983badf Leszek Koltunski
    }
785 28f4aba0 Leszek Koltunski
786 6983badf Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
787
788
  public void clear()
789
    {
790
    mStickerCoords.clear();
791
    mNewFaceTransf.clear();
792
    mOldFaceTransf.clear();
793 1b85f172 Leszek Koltunski
    }
794
795
///////////////////////////////////////////////////////////////////////////////////////////////////
796
797 6983badf Leszek Koltunski
  public void createNewFaceTransform( final double[][] vertices, final int[][] indexes)
798 7edab735 Leszek Koltunski
    {
799 6983badf Leszek Koltunski
    FaceTransform ft;
800
    int numNew = mNewFaceTransf.size();
801
802
    for(int i=0; i<numNew; i++)
803
      {
804
      ft = mNewFaceTransf.remove(0);
805
      mOldFaceTransf.add(ft);
806
      }
807
808
    int numFaces = indexes.length;
809
    int numOld = mOldFaceTransf.size();
810
811
    for (int face=0; face<numFaces; face++)
812
      {
813
      boolean collapsed = false;
814
815
      double[][] vert = constructVert(vertices, indexes[face]);
816
817
      FaceTransform newT = constructNewTransform(vert);
818
819
      for (int old=0; !collapsed && old<numOld; old++)
820
        {
821
        ft = mOldFaceTransf.get(old);
822
        if (successfullyCollapsedStickers(newT, ft)) collapsed = true;
823
        }
824
825
      for (int pre=0; !collapsed && pre<face; pre++)
826
        {
827
        ft = mNewFaceTransf.get(pre);
828
        if (successfullyCollapsedStickers(newT, ft)) collapsed = true;
829
        }
830 7edab735 Leszek Koltunski
831 6983badf Leszek Koltunski
      mNewFaceTransf.add(newT);
832
      }
833
    }
834
835
///////////////////////////////////////////////////////////////////////////////////////////////////
836
837
  public MeshBase createRoundedSolid(final double[][] vertices, final int[][] vertIndexes,
838
                                     final float[][] bands    , final int[]   bandIndexes,
839
                                     final float[][] corners  , final int[]   cornerIndexes,
840
                                     final float[][] centers  , final int[]   centerIndexes,
841
                                     final int numComponents )
842
    {
843 33647db9 Leszek Koltunski
    int numFaces = vertIndexes.length;
844
    float[] band, bandsComputed;
845
    MeshBase[] meshes = new MeshBase[numFaces];
846 6983badf Leszek Koltunski
    FaceTransform fInfo;
847
    StickerCoords sInfo;
848 55f20739 Leszek Koltunski
849 33647db9 Leszek Koltunski
    for(int face=0; face<numFaces; face++)
850
      {
851 6983badf Leszek Koltunski
      fInfo = mNewFaceTransf.get(face);
852
      sInfo = mStickerCoords.get(fInfo.sticker);
853 140f2c4e Leszek Koltunski
854 4d883a92 Leszek Koltunski
      double[] verts = sInfo.vertices;
855
      int lenVerts = verts.length;
856
      float[] vertsFloat = new float[lenVerts];
857
      for(int i=0; i<lenVerts; i++) vertsFloat[i] = (float)verts[i];
858
859 33647db9 Leszek Koltunski
      band = bands[bandIndexes[face]];
860
      bandsComputed = computeBands( band[0], (int)band[1], band[2], band[3], (int)band[4]);
861 4d883a92 Leszek Koltunski
      meshes[face] = new MeshPolygon(vertsFloat,bandsComputed,(int)band[5],(int)band[6]);
862 33647db9 Leszek Koltunski
      meshes[face].setEffectAssociation(0,(1<<face),0);
863
      }
864 7edab735 Leszek Koltunski
865 33647db9 Leszek Koltunski
    MeshBase mesh = new MeshJoined(meshes);
866 7edab735 Leszek Koltunski
    Static3D center = new Static3D(0,0,0);
867 fe032f52 Leszek Koltunski
868 33647db9 Leszek Koltunski
    for(int face=0; face<numFaces; face++)
869
      {
870
      int assoc = (1<<face);
871 6983badf Leszek Koltunski
      fInfo = mNewFaceTransf.get(face);
872 6d020cb6 Leszek Koltunski
873 4d883a92 Leszek Koltunski
      float vx = (float)fInfo.vx;
874
      float vy = (float)fInfo.vy;
875
      float vz = (float)fInfo.vz;
876
      float sc = (float)fInfo.scale;
877
      float qx = (float)fInfo.qx;
878
      float qy = (float)fInfo.qy;
879
      float qz = (float)fInfo.qz;
880
      float qw = (float)fInfo.qw;
881
882
      Static3D scale = new Static3D(sc,sc, fInfo.flip ? -sc : sc);
883 3083fab8 Leszek Koltunski
      Static3D move3D= new Static3D(vx,vy,vz);
884 4d883a92 Leszek Koltunski
      Static4D quat  = new Static4D(qx,qy,qz,qw);
885 6d020cb6 Leszek Koltunski
886 6a96e571 Leszek Koltunski
      mesh.apply(new MatrixEffectScale(scale)           ,assoc,-1);
887
      mesh.apply(new MatrixEffectQuaternion(quat,center),assoc,-1);
888
      mesh.apply(new MatrixEffectMove(move3D)           ,assoc,-1);
889 33647db9 Leszek Koltunski
      }
890 a65604a7 Leszek Koltunski
891 6983badf Leszek Koltunski
    prepareAndRoundCorners(mesh, vertices, corners, cornerIndexes, centers, centerIndexes);
892
893
    correctComponents(mesh,numComponents);
894 a65604a7 Leszek Koltunski
895 7edab735 Leszek Koltunski
    return mesh;
896
    }
897
  }