Project

General

Profile

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

examples / src / main / java / org / distorted / examples / meshfile / FactoryCubit.java @ 99571baa

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 1b85f172 Leszek Koltunski
709 db9903e8 Leszek Koltunski
        if( corn>=0 )
710
          {
711
          float strength = corners[corn][0];
712
          float radius   = corners[corn][1];
713
          roundCorners(mesh, center, staticVert, strength, radius);
714
          }
715 1b85f172 Leszek Koltunski
        }
716 6983badf Leszek Koltunski
      }
717
    }
718 1b85f172 Leszek Koltunski
719 6983badf Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
720 1b85f172 Leszek Koltunski
721 6983badf Leszek Koltunski
  private void correctComponents(MeshBase mesh, int numComponents)
722
    {
723
    int numTexToBeAdded = numComponents-mesh.getNumTexComponents();
724 1b85f172 Leszek Koltunski
725 6983badf Leszek Koltunski
    //mesh.mergeEffComponents();
726 1b85f172 Leszek Koltunski
727 6983badf Leszek Koltunski
    for(int i=0; i<numTexToBeAdded; i++ ) mesh.addEmptyTexComponent();
728
    }
729 1b85f172 Leszek Koltunski
730 6983badf Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
731 1b85f172 Leszek Koltunski
732 6983badf Leszek Koltunski
  private void printTransform(FaceTransform f)
733
    {
734
    android.util.Log.e("D", "q=("+f.qx+", "+f.qy+", "+f.qz+", "+f.qw+") v=("
735
                       +f.vx+", "+f.vy+", "+f.vz+") scale="+f.scale+" sticker="+f.sticker);
736 1b85f172 Leszek Koltunski
    }
737
738
///////////////////////////////////////////////////////////////////////////////////////////////////
739 6983badf Leszek Koltunski
// PUBLIC
740 1b85f172 Leszek Koltunski
741 6983badf Leszek Koltunski
  public void printStickerCoords()
742 1b85f172 Leszek Koltunski
    {
743 6983badf Leszek Koltunski
    int stickers = mStickerCoords.size();
744 1b85f172 Leszek Koltunski
745 6983badf Leszek Koltunski
    android.util.Log.d("D", "---- STICKER COORDS ----");
746 28f4aba0 Leszek Koltunski
747 1b85f172 Leszek Koltunski
    for(int s=0; s<stickers; s++)
748 ef231eba Leszek Koltunski
      {
749 6983badf Leszek Koltunski
      String ver = "{ ";
750
      StickerCoords info = mStickerCoords.get(s);
751 1b85f172 Leszek Koltunski
      int len = info.vertices.length/2;
752
753
      for(int i =0; i<len; i++)
754
        {
755 6983badf Leszek Koltunski
        if( i!=0 ) ver += ", ";
756
        ver += ( (float)info.vertices[2*i]+"f, "+(float)info.vertices[2*i+1]+"f");
757 1b85f172 Leszek Koltunski
        }
758 28f4aba0 Leszek Koltunski
759 6983badf Leszek Koltunski
      ver += " }";
760
      android.util.Log.d("D", ver);
761 ef231eba Leszek Koltunski
      }
762
763 6983badf Leszek Koltunski
    android.util.Log.d("D", "---- END STICKER COORDS ----");
764
    }
765
766
///////////////////////////////////////////////////////////////////////////////////////////////////
767
768
  public void printFaceTransform()
769
    {
770
    android.util.Log.d("D", "---- OLD FACE TRANSFORM ---");
771 ef231eba Leszek Koltunski
772 6983badf Leszek Koltunski
    int oldfaces = mOldFaceTransf.size();
773 7edab735 Leszek Koltunski
774 6983badf Leszek Koltunski
    for(int f=0; f<oldfaces; f++)
775 28f4aba0 Leszek Koltunski
      {
776 6983badf Leszek Koltunski
      printTransform(mOldFaceTransf.get(f));
777
      }
778
779
    android.util.Log.d("D", "---- NEW FACE TRANSFORM ---");
780 28f4aba0 Leszek Koltunski
781 6983badf Leszek Koltunski
    int newfaces = mNewFaceTransf.size();
782
783
    for(int f=0; f<newfaces; f++)
784
      {
785
      printTransform(mNewFaceTransf.get(f));
786 28f4aba0 Leszek Koltunski
      }
787 6983badf Leszek Koltunski
    }
788 28f4aba0 Leszek Koltunski
789 6983badf Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
790
791
  public void clear()
792
    {
793
    mStickerCoords.clear();
794
    mNewFaceTransf.clear();
795
    mOldFaceTransf.clear();
796 1b85f172 Leszek Koltunski
    }
797
798
///////////////////////////////////////////////////////////////////////////////////////////////////
799
800 6983badf Leszek Koltunski
  public void createNewFaceTransform( final double[][] vertices, final int[][] indexes)
801 7edab735 Leszek Koltunski
    {
802 6983badf Leszek Koltunski
    FaceTransform ft;
803
    int numNew = mNewFaceTransf.size();
804
805
    for(int i=0; i<numNew; i++)
806
      {
807
      ft = mNewFaceTransf.remove(0);
808
      mOldFaceTransf.add(ft);
809
      }
810
811
    int numFaces = indexes.length;
812
    int numOld = mOldFaceTransf.size();
813
814
    for (int face=0; face<numFaces; face++)
815
      {
816
      boolean collapsed = false;
817
818
      double[][] vert = constructVert(vertices, indexes[face]);
819
820
      FaceTransform newT = constructNewTransform(vert);
821
822
      for (int old=0; !collapsed && old<numOld; old++)
823
        {
824
        ft = mOldFaceTransf.get(old);
825
        if (successfullyCollapsedStickers(newT, ft)) collapsed = true;
826
        }
827
828
      for (int pre=0; !collapsed && pre<face; pre++)
829
        {
830
        ft = mNewFaceTransf.get(pre);
831
        if (successfullyCollapsedStickers(newT, ft)) collapsed = true;
832
        }
833 7edab735 Leszek Koltunski
834 6983badf Leszek Koltunski
      mNewFaceTransf.add(newT);
835
      }
836
    }
837
838
///////////////////////////////////////////////////////////////////////////////////////////////////
839
840
  public MeshBase createRoundedSolid(final double[][] vertices, final int[][] vertIndexes,
841
                                     final float[][] bands    , final int[]   bandIndexes,
842
                                     final float[][] corners  , final int[]   cornerIndexes,
843
                                     final float[][] centers  , final int[]   centerIndexes,
844
                                     final int numComponents )
845
    {
846 33647db9 Leszek Koltunski
    int numFaces = vertIndexes.length;
847
    float[] band, bandsComputed;
848
    MeshBase[] meshes = new MeshBase[numFaces];
849 6983badf Leszek Koltunski
    FaceTransform fInfo;
850
    StickerCoords sInfo;
851 55f20739 Leszek Koltunski
852 33647db9 Leszek Koltunski
    for(int face=0; face<numFaces; face++)
853
      {
854 6983badf Leszek Koltunski
      fInfo = mNewFaceTransf.get(face);
855
      sInfo = mStickerCoords.get(fInfo.sticker);
856 140f2c4e Leszek Koltunski
857 4d883a92 Leszek Koltunski
      double[] verts = sInfo.vertices;
858
      int lenVerts = verts.length;
859
      float[] vertsFloat = new float[lenVerts];
860
      for(int i=0; i<lenVerts; i++) vertsFloat[i] = (float)verts[i];
861
862 33647db9 Leszek Koltunski
      band = bands[bandIndexes[face]];
863
      bandsComputed = computeBands( band[0], (int)band[1], band[2], band[3], (int)band[4]);
864 4d883a92 Leszek Koltunski
      meshes[face] = new MeshPolygon(vertsFloat,bandsComputed,(int)band[5],(int)band[6]);
865 33647db9 Leszek Koltunski
      meshes[face].setEffectAssociation(0,(1<<face),0);
866
      }
867 7edab735 Leszek Koltunski
868 33647db9 Leszek Koltunski
    MeshBase mesh = new MeshJoined(meshes);
869 7edab735 Leszek Koltunski
    Static3D center = new Static3D(0,0,0);
870 fe032f52 Leszek Koltunski
871 33647db9 Leszek Koltunski
    for(int face=0; face<numFaces; face++)
872
      {
873
      int assoc = (1<<face);
874 6983badf Leszek Koltunski
      fInfo = mNewFaceTransf.get(face);
875 6d020cb6 Leszek Koltunski
876 4d883a92 Leszek Koltunski
      float vx = (float)fInfo.vx;
877
      float vy = (float)fInfo.vy;
878
      float vz = (float)fInfo.vz;
879
      float sc = (float)fInfo.scale;
880
      float qx = (float)fInfo.qx;
881
      float qy = (float)fInfo.qy;
882
      float qz = (float)fInfo.qz;
883
      float qw = (float)fInfo.qw;
884
885
      Static3D scale = new Static3D(sc,sc, fInfo.flip ? -sc : sc);
886 3083fab8 Leszek Koltunski
      Static3D move3D= new Static3D(vx,vy,vz);
887 4d883a92 Leszek Koltunski
      Static4D quat  = new Static4D(qx,qy,qz,qw);
888 6d020cb6 Leszek Koltunski
889 6a96e571 Leszek Koltunski
      mesh.apply(new MatrixEffectScale(scale)           ,assoc,-1);
890
      mesh.apply(new MatrixEffectQuaternion(quat,center),assoc,-1);
891
      mesh.apply(new MatrixEffectMove(move3D)           ,assoc,-1);
892 33647db9 Leszek Koltunski
      }
893 a65604a7 Leszek Koltunski
894 6983badf Leszek Koltunski
    prepareAndRoundCorners(mesh, vertices, corners, cornerIndexes, centers, centerIndexes);
895
896
    correctComponents(mesh,numComponents);
897 a65604a7 Leszek Koltunski
898 7edab735 Leszek Koltunski
    return mesh;
899
    }
900
  }