Project

General

Profile

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

examples / src / main / java / org / distorted / examples / meshfile / FactoryCubit.java @ 28f4aba0

1 7edab735 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is free software: you can redistribute it and/or modify                            //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Magic Cube is distributed in the hope that it will be useful,                                 //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19
20
package org.distorted.examples.meshfile;
21
22 1b85f172 Leszek Koltunski
import org.distorted.library.effect.MatrixEffect;
23
import org.distorted.library.effect.MatrixEffectMove;
24
import org.distorted.library.effect.MatrixEffectQuaternion;
25
import org.distorted.library.effect.MatrixEffectScale;
26 7edab735 Leszek Koltunski
import org.distorted.library.effect.VertexEffect;
27
import org.distorted.library.effect.VertexEffectDeform;
28
import org.distorted.library.mesh.MeshBase;
29
import org.distorted.library.mesh.MeshJoined;
30
import org.distorted.library.mesh.MeshPolygon;
31
import org.distorted.library.type.Static1D;
32
import org.distorted.library.type.Static3D;
33
import org.distorted.library.type.Static4D;
34
35 33647db9 Leszek Koltunski
import java.util.ArrayList;
36
37 7edab735 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
38
39 55f20739 Leszek Koltunski
class FactoryCubit
40 7edab735 Leszek Koltunski
  {
41 33647db9 Leszek Koltunski
  private static final float[] mBuffer = new float[3];
42
  private static final float[] mQuat1  = new float[4];
43
  private static final float[] mQuat2  = new float[4];
44
  private static final float[] mQuat3  = new float[4];
45 6d020cb6 Leszek Koltunski
46 7edab735 Leszek Koltunski
  private static final Static1D RADIUS = new Static1D(1);
47
48 55f20739 Leszek Koltunski
  private static FactoryCubit mThis;
49 7edab735 Leszek Koltunski
50 1b85f172 Leszek Koltunski
  private static class StickerInfo
51 33647db9 Leszek Koltunski
    {
52
    float[] vertices;
53 1b85f172 Leszek Koltunski
    }
54
55
  private static class FaceInfo
56
    {
57
    int sticker;
58 33647db9 Leszek Koltunski
    float vx,vy,vz;
59
    float scale;
60
    float qx,qy,qz,qw;
61
    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 33647db9 Leszek Koltunski
  private boolean areColinear(float[][] vertices, int index1, int index2, int index3)
215 7edab735 Leszek Koltunski
    {
216 33647db9 Leszek Koltunski
    float x1 = vertices[index1][0];
217
    float y1 = vertices[index1][1];
218
    float z1 = vertices[index1][2];
219
    float x2 = vertices[index2][0];
220
    float y2 = vertices[index2][1];
221
    float z2 = vertices[index2][2];
222
    float x3 = vertices[index3][0];
223
    float y3 = vertices[index3][1];
224
    float z3 = vertices[index3][2];
225 7edab735 Leszek Koltunski
226 33647db9 Leszek Koltunski
    float v1x = x2-x1;
227
    float v1y = y2-y1;
228
    float v1z = z2-z1;
229
    float v2x = x3-x1;
230
    float v2y = y3-y1;
231
    float v2z = z3-z1;
232 7edab735 Leszek Koltunski
233 33647db9 Leszek Koltunski
    float A = (float)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 33647db9 Leszek Koltunski
  private void computeNormalVector(float[][] vertices, int index1, int index2, int index3)
241 7edab735 Leszek Koltunski
    {
242 33647db9 Leszek Koltunski
    float x1 = vertices[index1][0];
243
    float y1 = vertices[index1][1];
244
    float z1 = vertices[index1][2];
245
    float x2 = vertices[index2][0];
246
    float y2 = vertices[index2][1];
247
    float z2 = vertices[index2][2];
248
    float x3 = vertices[index3][0];
249
    float y3 = vertices[index3][1];
250
    float z3 = vertices[index3][2];
251 7edab735 Leszek Koltunski
252 33647db9 Leszek Koltunski
    float v1x = x2-x1;
253
    float v1y = y2-y1;
254
    float v1z = z2-z1;
255
    float v2x = x3-x1;
256
    float v2y = y3-y1;
257
    float 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 140f2c4e Leszek Koltunski
    float len = mBuffer[0]*mBuffer[0] + mBuffer[1]*mBuffer[1] + mBuffer[2]*mBuffer[2];
264
    len = (float)Math.sqrt(len);
265
    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 33647db9 Leszek Koltunski
  private static void quatMultiply( float[] quat1, float[] quat2, float[] result )
274 7edab735 Leszek Koltunski
    {
275 33647db9 Leszek Koltunski
    float qx = quat1[0];
276
    float qy = quat1[1];
277
    float qz = quat1[2];
278
    float qw = quat1[3];
279 7edab735 Leszek Koltunski
280 33647db9 Leszek Koltunski
    float rx = quat2[0];
281
    float ry = quat2[1];
282
    float rz = quat2[2];
283
    float 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 33647db9 Leszek Koltunski
  private void fitInSquare(FaceInfo info, float[][] vert3D)
294 7edab735 Leszek Koltunski
    {
295 33647db9 Leszek Koltunski
    float minX = Float.MAX_VALUE;
296
    float maxX =-Float.MAX_VALUE;
297
    float minY = Float.MAX_VALUE;
298
    float maxY =-Float.MAX_VALUE;
299 55f20739 Leszek Koltunski
300 33647db9 Leszek Koltunski
    for (float[] vert : vert3D)
301
      {
302
      float x = vert[0];
303
      float 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
    sInfo.vertices = new float[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 33647db9 Leszek Koltunski
  private void constructNew(FaceInfo info, final float[][] 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 33647db9 Leszek Koltunski
    for (float[] 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
    float axisX, axisY, axisZ;
380
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 28f4aba0 Leszek Koltunski
      float axiLen = axisX*axisX + axisY*axisY;
388 ef231eba Leszek Koltunski
      axiLen = (float)Math.sqrt(axiLen);
389
      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 140f2c4e Leszek Koltunski
    float cosTheta = mBuffer[2];
401
    float sinHalfTheta = (float)Math.sqrt(0.5f*(1-cosTheta));
402
    float cosHalfTheta = (float)Math.sqrt(0.5f*(1+cosTheta));
403 ef231eba Leszek Koltunski
404 140f2c4e Leszek Koltunski
    mQuat1[0] = axisX*sinHalfTheta;
405
    mQuat1[1] = axisY*sinHalfTheta;
406
    mQuat1[2] = axisZ*sinHalfTheta;
407
    mQuat1[3] = cosHalfTheta;
408 28f4aba0 Leszek Koltunski
    mQuat2[0] =-axisX*sinHalfTheta;
409
    mQuat2[1] =-axisY*sinHalfTheta;
410
    mQuat2[2] =-axisZ*sinHalfTheta;
411
    mQuat2[3] = cosHalfTheta;
412 ef231eba Leszek Koltunski
413 140f2c4e Leszek Koltunski
    for (float[] vert : vert3D)
414
      {
415 28f4aba0 Leszek Koltunski
      quatMultiply(mQuat1, vert  , mQuat3);
416
      quatMultiply(mQuat3, mQuat2, vert  );
417 33647db9 Leszek Koltunski
      }
418 7cd30f7c Leszek Koltunski
419 33647db9 Leszek Koltunski
    // fit the whole thing in a square and remember the scale & 2D vertices
420
    fitInSquare(info, vert3D);
421 7cd30f7c Leszek Koltunski
422 33647db9 Leszek Koltunski
    // remember the rotation
423 28f4aba0 Leszek Koltunski
    info.qx =-mQuat1[0];
424
    info.qy =-mQuat1[1];
425
    info.qz =-mQuat1[2];
426
    info.qw = mQuat1[3];
427 7cd30f7c Leszek Koltunski
    }
428
429 fe032f52 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
430
431 33647db9 Leszek Koltunski
  private float computeCos(float x1, float y1, float x2, float y2, float len1, float len2)
432 fe032f52 Leszek Koltunski
    {
433 28f4aba0 Leszek Koltunski
    float ret =  (x1*x2+y1*y2) / (len1*len2);
434
435
    if( ret> 1.0f ) return  1.0f;
436
    if( ret<-1.0f ) return -1.0f;
437
438
    return ret;
439 fe032f52 Leszek Koltunski
    }
440
441 b3d28a81 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
442 33647db9 Leszek Koltunski
// sin of (signed!) angle between vectors (x1,y1) and (x2,y2), counterclockwise!
443 b3d28a81 Leszek Koltunski
444 33647db9 Leszek Koltunski
  private float computeSin(float x1, float y1, float x2, float y2, float len1, float len2)
445 b3d28a81 Leszek Koltunski
    {
446 28f4aba0 Leszek Koltunski
    float ret = (x2*y1-x1*y2) / (len1*len2);
447
448
    if( ret> 1.0f ) return  1.0f;
449
    if( ret<-1.0f ) return -1.0f;
450
451
    return ret;
452 b3d28a81 Leszek Koltunski
    }
453
454 54e47d9b Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
455
456 33647db9 Leszek Koltunski
  private void rotateAllVertices(float[] result, int len, float[] vertices, float sin, float cos)
457 54e47d9b Leszek Koltunski
    {
458 33647db9 Leszek Koltunski
    for(int i=0; i<len; i++)
459 54e47d9b Leszek Koltunski
      {
460 33647db9 Leszek Koltunski
      result[2*i  ] = vertices[2*i  ]*cos - vertices[2*i+1]*sin;
461
      result[2*i+1] = vertices[2*i  ]*sin + vertices[2*i+1]*cos;
462 54e47d9b Leszek Koltunski
      }
463
    }
464
465 6d020cb6 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
466
467 33647db9 Leszek Koltunski
  private boolean isScaledVersionOf(float[] v1, float[] v2, int len)
468 6d020cb6 Leszek Koltunski
    {
469 33647db9 Leszek Koltunski
    float EPSILON = 0.001f;
470
    float scale = v1[0]!=0.0f ? v2[0]/v1[0] : v2[1]/v1[1];
471 55f20739 Leszek Koltunski
472 33647db9 Leszek Koltunski
    for(int i=1; i<len; i++)
473
      {
474
      float horz = v2[2*i  ] - scale*v1[2*i  ];
475
      float vert = v2[2*i+1] - scale*v1[2*i+1];
476 7edab735 Leszek Koltunski
477 33647db9 Leszek Koltunski
      if( horz>EPSILON || horz<-EPSILON || vert>EPSILON || vert<-EPSILON ) return false;
478
      }
479 55f20739 Leszek Koltunski
480 33647db9 Leszek Koltunski
    return true;
481 7edab735 Leszek Koltunski
    }
482
483
///////////////////////////////////////////////////////////////////////////////////////////////////
484
485 33647db9 Leszek Koltunski
  private void mirrorAllVertices(float[] output, int len, float[] input)
486 7edab735 Leszek Koltunski
    {
487 33647db9 Leszek Koltunski
    for(int vertex=0; vertex<len; vertex++)
488
      {
489
      output[2*vertex  ] = input[2*vertex  ];
490
      output[2*vertex+1] =-input[2*vertex+1];
491
      }
492 7edab735 Leszek Koltunski
    }
493
494
///////////////////////////////////////////////////////////////////////////////////////////////////
495
496 28f4aba0 Leszek Koltunski
  private void correctInfo(FaceInfo info, float scale, float cos, int oldSticker, boolean flip)
497 7edab735 Leszek Koltunski
    {
498 1b85f172 Leszek Koltunski
    mStickerInfo.remove(info.sticker);
499 7edab735 Leszek Koltunski
500 28f4aba0 Leszek Koltunski
    info.flip    = flip;
501 1b85f172 Leszek Koltunski
    info.sticker = oldSticker;
502 28f4aba0 Leszek Koltunski
    info.scale  *= scale;
503
504
    mQuat1[0] = info.qx;
505
    mQuat1[1] = info.qy;
506
    mQuat1[2] = info.qz;
507
    mQuat1[3] = info.qw;
508 7edab735 Leszek Koltunski
509 28f4aba0 Leszek Koltunski
    float sinHalf = (float)Math.sqrt(0.5f*(1-cos));
510
    float cosHalf = (float)Math.sqrt(0.5f*(1+cos));
511 55f20739 Leszek Koltunski
512 28f4aba0 Leszek Koltunski
    mQuat2[0] = 0.0f;
513
    mQuat2[1] = 0.0f;
514
    mQuat2[2] = sinHalf;
515
    mQuat2[3] = cosHalf;
516 7edab735 Leszek Koltunski
517 33647db9 Leszek Koltunski
    quatMultiply( mQuat1, mQuat2, mQuat3 );
518 55f20739 Leszek Koltunski
519 33647db9 Leszek Koltunski
    info.qx = mQuat3[0];
520
    info.qy = mQuat3[1];
521
    info.qz = mQuat3[2];
522
    info.qw = mQuat3[3];
523 7edab735 Leszek Koltunski
    }
524
525
///////////////////////////////////////////////////////////////////////////////////////////////////
526
527 1b85f172 Leszek Koltunski
  private boolean foundVertex(FaceInfo info, float[] buffer, int len, float[] preVert,
528
                              float[] newVert, float lenVert, int oldSticker, boolean inverted)
529 7edab735 Leszek Koltunski
    {
530 33647db9 Leszek Koltunski
    for(int vertex=0; vertex<len; vertex++)
531
      {
532 28f4aba0 Leszek Koltunski
      float xR = preVert[2*vertex  ];
533
      float yR = preVert[2*vertex+1];
534 33647db9 Leszek Koltunski
      float lenRotV = (float)Math.sqrt(xR*xR+yR*yR);
535 28f4aba0 Leszek Koltunski
      float cos = computeCos(xR,yR,newVert[0],newVert[1], lenRotV, lenVert);
536
      float sin = computeSin(xR,yR,newVert[0],newVert[1], lenRotV, lenVert);
537 7edab735 Leszek Koltunski
538 1b85f172 Leszek Koltunski
      rotateAllVertices(buffer,len,newVert,sin,cos);
539 7edab735 Leszek Koltunski
540 1b85f172 Leszek Koltunski
      if( isScaledVersionOf(buffer,preVert,len) )
541 33647db9 Leszek Koltunski
        {
542 1b85f172 Leszek Koltunski
        float scale = preVert[0]!=0.0f ? buffer[0]/preVert[0] : buffer[1]/preVert[1];
543 28f4aba0 Leszek Koltunski
        correctInfo(info,scale,cos,oldSticker,inverted);
544 33647db9 Leszek Koltunski
        return true;
545
        }
546
      }
547 55f20739 Leszek Koltunski
548 33647db9 Leszek Koltunski
    return false;
549 7edab735 Leszek Koltunski
    }
550
551
///////////////////////////////////////////////////////////////////////////////////////////////////
552
553 1b85f172 Leszek Koltunski
  private boolean successfullyCollapsedStickers(final FaceInfo newInfo, final FaceInfo preInfo)
554 7edab735 Leszek Koltunski
    {
555 1b85f172 Leszek Koltunski
    StickerInfo sNewInfo = mStickerInfo.get(newInfo.sticker);
556
    StickerInfo sPreInfo = mStickerInfo.get(preInfo.sticker);
557
    int len = sPreInfo.vertices.length;
558
    float[] newVert = sNewInfo.vertices;
559 7edab735 Leszek Koltunski
560 1b85f172 Leszek Koltunski
    if( len == newVert.length )
561 33647db9 Leszek Koltunski
      {
562 1b85f172 Leszek Koltunski
      int oldSticker = preInfo.sticker;
563
      float[] tmp1 = new float[len];
564
      float lenVert = (float)Math.sqrt(newVert[0]*newVert[0] + newVert[1]*newVert[1]);
565
      if( foundVertex(newInfo, tmp1, len/2, sPreInfo.vertices, newVert, lenVert, oldSticker, false) ) return true;
566
      float[] tmp2 = new float[len];
567
      mirrorAllVertices(tmp2,len/2,sPreInfo.vertices);
568
      if( foundVertex(newInfo, tmp1, len/2, tmp2             , newVert, lenVert, oldSticker, true ) ) return true;
569 33647db9 Leszek Koltunski
      }
570 55f20739 Leszek Koltunski
571 33647db9 Leszek Koltunski
    return false;
572 7edab735 Leszek Koltunski
    }
573
574
///////////////////////////////////////////////////////////////////////////////////////////////////
575
576 33647db9 Leszek Koltunski
  private float[][] constructVert(float[][] vertices, int[] index)
577 7edab735 Leszek Koltunski
    {
578 33647db9 Leszek Koltunski
    int len = index.length;
579
    float[][] ret = new float[len][4];
580 7edab735 Leszek Koltunski
581 33647db9 Leszek Koltunski
    for(int i=0; i<len; i++)
582
      {
583
      ret[i][0] = vertices[index[i]][0];
584
      ret[i][1] = vertices[index[i]][1];
585
      ret[i][2] = vertices[index[i]][2];
586
      ret[i][3] = 1.0f;
587
      }
588 7edab735 Leszek Koltunski
589 33647db9 Leszek Koltunski
    return ret;
590 7edab735 Leszek Koltunski
    }
591
592
///////////////////////////////////////////////////////////////////////////////////////////////////
593
594 33647db9 Leszek Koltunski
  private void prepareFaceInfo( final float[][] vertices, final int[][] indexes)
595 7edab735 Leszek Koltunski
    {
596 33647db9 Leszek Koltunski
    mFaceInfo.clear();
597 1b85f172 Leszek Koltunski
    mStickerInfo.clear();
598 7edab735 Leszek Koltunski
599 33647db9 Leszek Koltunski
    int numFaces = indexes.length;
600 1b85f172 Leszek Koltunski
    FaceInfo preInfo;
601 7edab735 Leszek Koltunski
602 33647db9 Leszek Koltunski
    for(int face=0; face<numFaces; face++)
603
      {
604
      FaceInfo newInfo = new FaceInfo();
605
      int[] index = indexes[face];
606
      float[][] vert = constructVert(vertices,index);
607
      constructNew(newInfo,vert);
608 55f20739 Leszek Koltunski
609 33647db9 Leszek Koltunski
      for(int previous=0; previous<face; previous++)
610
        {
611 1b85f172 Leszek Koltunski
        preInfo = mFaceInfo.get(previous);
612
        if( successfullyCollapsedStickers(newInfo,preInfo) ) break;
613 33647db9 Leszek Koltunski
        }
614 7edab735 Leszek Koltunski
615 33647db9 Leszek Koltunski
      mFaceInfo.add(newInfo);
616
      }
617 7edab735 Leszek Koltunski
    }
618
619 ef231eba Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
620
621 1b85f172 Leszek Koltunski
  private void prepareAndRoundCorners(MeshBase mesh, float[][] vertices, int[][] vertIndexes,
622
                                      float[][] corners, int[] cornerIndexes )
623 ef231eba Leszek Koltunski
    {
624 1b85f172 Leszek Koltunski
    int numNeig, lenFV;
625
    int lenV = vertices.length;
626
    int[] verts = new int[2*(lenV-1)];
627
    Static3D[] staticVert = new Static3D[1];
628
    Static3D center = new Static3D(0,0,0);
629
    float cx, cy, cz;
630
    float[] singleV;
631 ef231eba Leszek Koltunski
632 1b85f172 Leszek Koltunski
    for(int v=0; v<lenV; v++)
633
      {
634
      // prepare verts[]
635
      numNeig = 0;
636 ef231eba Leszek Koltunski
637 1b85f172 Leszek Koltunski
      for (int[] vertIndex : vertIndexes)
638
        {
639
        lenFV = vertIndex.length;
640 ef231eba Leszek Koltunski
641 1b85f172 Leszek Koltunski
        for (int fv = 0; fv < lenFV; fv++)
642
          if (vertIndex[fv] == v)
643
            {
644
            int prev = fv > 0 ? fv - 1 : lenFV - 1;
645
            int next = fv < lenFV - 1 ? fv + 1 : 0;
646
647
            verts[numNeig++] = vertIndex[prev];
648
            verts[numNeig++] = vertIndex[next];
649
            }
650
        }
651
652
      cx=cy=cz=0.0f;
653
654
      // from verts[] prepare center
655
      for(int n=0; n<numNeig; n++)
656
        {
657
        singleV = vertices[verts[n]];
658
659
        cx += singleV[0];
660
        cy += singleV[1];
661
        cz += singleV[2];
662
        }
663
      center.set(cx/numNeig - vertices[v][0],cy/numNeig - vertices[v][1],cz/numNeig - vertices[v][2]);
664
665
      // round Corners
666
      staticVert[0] = new Static3D(vertices[v][0], vertices[v][1], vertices[v][2]);
667
668
      int corn = cornerIndexes[v];
669
      float strength = corners[corn][0];
670
      float radius   = corners[corn][1];
671
672
      roundCorners(mesh, center, staticVert, strength, radius);
673
      }
674
    }
675
676
///////////////////////////////////////////////////////////////////////////////////////////////////
677
678 28f4aba0 Leszek Koltunski
  private void printInfo()
679 1b85f172 Leszek Koltunski
    {
680
    int stickers = mStickerInfo.size();
681
682 28f4aba0 Leszek Koltunski
    android.util.Log.d("D", "-------------------------");
683
684 1b85f172 Leszek Koltunski
    for(int s=0; s<stickers; s++)
685 ef231eba Leszek Koltunski
      {
686 28f4aba0 Leszek Koltunski
      String ver = "";
687 1b85f172 Leszek Koltunski
      StickerInfo info = mStickerInfo.get(s);
688
      int len = info.vertices.length/2;
689
690
      for(int i =0; i<len; i++)
691
        {
692
        ver += ("("+info.vertices[2*i]+","+info.vertices[2*i+1]+") ");
693
        }
694 28f4aba0 Leszek Koltunski
695
      android.util.Log.e("D", "sticker "+s+" "+ver);
696 ef231eba Leszek Koltunski
      }
697
698 28f4aba0 Leszek Koltunski
    android.util.Log.d("D", "-------------------------");
699 ef231eba Leszek Koltunski
700 28f4aba0 Leszek Koltunski
    int faces = mFaceInfo.size();
701 7edab735 Leszek Koltunski
702 28f4aba0 Leszek Koltunski
    for(int f=0; f<faces; f++)
703
      {
704
      FaceInfo info = mFaceInfo.get(f);
705
706
      android.util.Log.e("D", "q=("+info.qx+", "+info.qy+", "+info.qz+", "+info.qw+") v=("
707 1b85f172 Leszek Koltunski
                       +info.vx+", "+info.vy+", "+info.vz+") scale="+info.scale+" sticker="+info.sticker);
708 28f4aba0 Leszek Koltunski
      }
709
710
    android.util.Log.d("D", "-------------------------");
711 1b85f172 Leszek Koltunski
    }
712
713
///////////////////////////////////////////////////////////////////////////////////////////////////
714
715
  MeshBase createRoundedSolid(final float[][] vertices, final int[][] vertIndexes,
716
                              final float[][] bands   , final int[]   bandIndexes,
717
                              final float[][] corners , final int[]   cornerIndexes)
718 7edab735 Leszek Koltunski
    {
719 33647db9 Leszek Koltunski
    int EFFECTS_PER_FACE = 3;
720 7edab735 Leszek Koltunski
721 33647db9 Leszek Koltunski
    prepareFaceInfo(vertices,vertIndexes);
722 7edab735 Leszek Koltunski
723 33647db9 Leszek Koltunski
    int numFaces = vertIndexes.length;
724
    float[] band, bandsComputed;
725
    MeshBase[] meshes = new MeshBase[numFaces];
726 1b85f172 Leszek Koltunski
    FaceInfo fInfo;
727
    StickerInfo sInfo;
728
729 28f4aba0 Leszek Koltunski
    printInfo();
730 55f20739 Leszek Koltunski
731 33647db9 Leszek Koltunski
    for(int face=0; face<numFaces; face++)
732
      {
733 1b85f172 Leszek Koltunski
      fInfo = mFaceInfo.get(face);
734
      sInfo = mStickerInfo.get(fInfo.sticker);
735 140f2c4e Leszek Koltunski
736 33647db9 Leszek Koltunski
      band = bands[bandIndexes[face]];
737
      bandsComputed = computeBands( band[0], (int)band[1], band[2], band[3], (int)band[4]);
738 1b85f172 Leszek Koltunski
      meshes[face] = new MeshPolygon(sInfo.vertices,bandsComputed,(int)band[5],(int)band[6]);
739 33647db9 Leszek Koltunski
      meshes[face].setEffectAssociation(0,(1<<face),0);
740
      }
741 7edab735 Leszek Koltunski
742 33647db9 Leszek Koltunski
    MeshBase mesh = new MeshJoined(meshes);
743 1b85f172 Leszek Koltunski
    MatrixEffect[] effects = new MatrixEffect[EFFECTS_PER_FACE*numFaces];
744 7edab735 Leszek Koltunski
    Static3D center = new Static3D(0,0,0);
745 fe032f52 Leszek Koltunski
746 33647db9 Leszek Koltunski
    for(int face=0; face<numFaces; face++)
747
      {
748
      int assoc = (1<<face);
749 1b85f172 Leszek Koltunski
      fInfo = mFaceInfo.get(face);
750 6d020cb6 Leszek Koltunski
751 1b85f172 Leszek Koltunski
      Static3D move3D= new Static3D(fInfo.vx,fInfo.vy,fInfo.vz);
752
      Static3D scale = new Static3D(fInfo.scale,fInfo.scale, fInfo.flip ? -fInfo.scale : fInfo.scale);
753
      Static4D quat  = new Static4D(fInfo.qx,fInfo.qy,fInfo.qz,fInfo.qw);
754 6d020cb6 Leszek Koltunski
755 1b85f172 Leszek Koltunski
      effects[EFFECTS_PER_FACE*face  ] = new MatrixEffectScale(scale);
756
      effects[EFFECTS_PER_FACE*face+1] = new MatrixEffectQuaternion(quat,center);
757
      effects[EFFECTS_PER_FACE*face+2] = new MatrixEffectMove(move3D);
758 a65604a7 Leszek Koltunski
759 1b85f172 Leszek Koltunski
      mesh.apply(effects[EFFECTS_PER_FACE*face  ],assoc,-1);
760
      mesh.apply(effects[EFFECTS_PER_FACE*face+1],assoc,-1);
761
      mesh.apply(effects[EFFECTS_PER_FACE*face+2],assoc,-1);
762 33647db9 Leszek Koltunski
      }
763 a65604a7 Leszek Koltunski
764 1b85f172 Leszek Koltunski
    prepareAndRoundCorners(mesh, vertices, vertIndexes, corners, cornerIndexes);
765 a65604a7 Leszek Koltunski
766 7edab735 Leszek Koltunski
    return mesh;
767
    }
768
  }