Project

General

Profile

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

examples / src / main / java / org / distorted / examples / meshfile / FactoryCubit.java @ 1b85f172

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
    mStickerInfo.add(sInfo);
317 55f20739 Leszek Koltunski
318 33647db9 Leszek Koltunski
    for( int vertex=0; vertex<len; vertex++ )
319 55f20739 Leszek Koltunski
      {
320 1b85f172 Leszek Koltunski
      sInfo.vertices[2*vertex  ] = vert3D[vertex][0] / info.scale;
321
      sInfo.vertices[2*vertex+1] = vert3D[vertex][1] / info.scale;
322 55f20739 Leszek Koltunski
      }
323
324 33647db9 Leszek Koltunski
    info.flip = false;
325 55f20739 Leszek Koltunski
    }
326
327
///////////////////////////////////////////////////////////////////////////////////////////////////
328
329 33647db9 Leszek Koltunski
  private void constructNew(FaceInfo info, final float[][] vert3D)
330 55f20739 Leszek Koltunski
    {
331 33647db9 Leszek Koltunski
    // compute center of gravity
332
    info.vx = 0.0f;
333
    info.vy = 0.0f;
334
    info.vz = 0.0f;
335
    int len = vert3D.length;
336 55f20739 Leszek Koltunski
337 33647db9 Leszek Koltunski
    for (float[] vert : vert3D)
338 55f20739 Leszek Koltunski
      {
339 33647db9 Leszek Koltunski
      info.vx += vert[0];
340
      info.vy += vert[1];
341
      info.vz += vert[2];
342 55f20739 Leszek Koltunski
      }
343
344 33647db9 Leszek Koltunski
    info.vx /= len;
345
    info.vy /= len;
346
    info.vz /= len;
347 55f20739 Leszek Koltunski
348 33647db9 Leszek Koltunski
    // move all vertices so that their center of gravity is at (0,0,0)
349
    for (int i=0; i<len; i++)
350 7cd30f7c Leszek Koltunski
      {
351 33647db9 Leszek Koltunski
      vert3D[i][0] -= info.vx;
352
      vert3D[i][1] -= info.vy;
353
      vert3D[i][2] -= info.vz;
354 7cd30f7c Leszek Koltunski
      }
355
356 33647db9 Leszek Koltunski
    // find 3 non-colinear vertices
357
    int foundIndex = -1;
358 7cd30f7c Leszek Koltunski
359 33647db9 Leszek Koltunski
    for(int vertex=2; vertex<len; vertex++)
360 7cd30f7c Leszek Koltunski
      {
361 33647db9 Leszek Koltunski
      if( !areColinear(vert3D,0,1,vertex) )
362
        {
363
        foundIndex = vertex;
364
        break;
365
        }
366 7cd30f7c Leszek Koltunski
      }
367
368 33647db9 Leszek Koltunski
    // compute the normal vector
369
    if( foundIndex==-1 )
370
      {
371
      throw new RuntimeException("all vertices colinear");
372
      }
373 7cd30f7c Leszek Koltunski
374 33647db9 Leszek Koltunski
    computeNormalVector(vert3D,0,1,foundIndex);
375
376 140f2c4e Leszek Koltunski
    // rotate so that the normal vector becomes (0,0,1)
377
    float axisX, axisY, axisZ;
378
379 ef231eba Leszek Koltunski
    if( mBuffer[0]!=0.0f || mBuffer[1]!=0.0f )
380 33647db9 Leszek Koltunski
      {
381 140f2c4e Leszek Koltunski
      axisX = -mBuffer[1];
382
      axisY =  mBuffer[0];
383
      axisZ = 0.0f;
384 ef231eba Leszek Koltunski
385
      float axiLen = axisX*axisX + axisY*axisY + axisZ*axisZ;
386
      axiLen = (float)Math.sqrt(axiLen);
387
      axisX /= axiLen;
388
      axisY /= axiLen;
389
      axisZ /= axiLen;
390 140f2c4e Leszek Koltunski
      }
391
    else
392
      {
393
      axisX = 0.0f;
394
      axisY = 1.0f;
395
      axisZ = 0.0f;
396
      }
397 ef231eba Leszek Koltunski
398 140f2c4e Leszek Koltunski
    float cosTheta = mBuffer[2];
399
    float sinHalfTheta = (float)Math.sqrt(0.5f*(1-cosTheta));
400
    float cosHalfTheta = (float)Math.sqrt(0.5f*(1+cosTheta));
401 ef231eba Leszek Koltunski
402 140f2c4e Leszek Koltunski
    mQuat1[0] = axisX*sinHalfTheta;
403
    mQuat1[1] = axisY*sinHalfTheta;
404
    mQuat1[2] = axisZ*sinHalfTheta;
405
    mQuat1[3] = cosHalfTheta;
406
    mQuat2[0] = axisX*sinHalfTheta;
407
    mQuat2[1] = axisY*sinHalfTheta;
408
    mQuat2[2] = axisZ*sinHalfTheta;
409
    mQuat2[3] = -cosHalfTheta;
410 ef231eba Leszek Koltunski
411 140f2c4e Leszek Koltunski
    for (float[] vert : vert3D)
412
      {
413
      quatMultiply(mQuat1, vert, mQuat3);
414
      quatMultiply(mQuat3, mQuat2, vert);
415 33647db9 Leszek Koltunski
      }
416 7cd30f7c Leszek Koltunski
417 33647db9 Leszek Koltunski
    // fit the whole thing in a square and remember the scale & 2D vertices
418
    fitInSquare(info, vert3D);
419 7cd30f7c Leszek Koltunski
420 33647db9 Leszek Koltunski
    // remember the rotation
421
    info.qx = mQuat1[0];
422
    info.qy = mQuat1[1];
423
    info.qz = mQuat1[2];
424
    info.qw =-mQuat1[3];
425 7cd30f7c Leszek Koltunski
    }
426
427 fe032f52 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
428
429 33647db9 Leszek Koltunski
  private float computeCos(float x1, float y1, float x2, float y2, float len1, float len2)
430 fe032f52 Leszek Koltunski
    {
431 33647db9 Leszek Koltunski
    return (x1*x2+y1*y2) / (len1*len2);
432 fe032f52 Leszek Koltunski
    }
433
434 b3d28a81 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
435 33647db9 Leszek Koltunski
// sin of (signed!) angle between vectors (x1,y1) and (x2,y2), counterclockwise!
436 b3d28a81 Leszek Koltunski
437 33647db9 Leszek Koltunski
  private float computeSin(float x1, float y1, float x2, float y2, float len1, float len2)
438 b3d28a81 Leszek Koltunski
    {
439 33647db9 Leszek Koltunski
    return (x2*y1-x1*y2) / (len1*len2);
440 b3d28a81 Leszek Koltunski
    }
441
442 54e47d9b Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
443
444 33647db9 Leszek Koltunski
  private void rotateAllVertices(float[] result, int len, float[] vertices, float sin, float cos)
445 54e47d9b Leszek Koltunski
    {
446 33647db9 Leszek Koltunski
    for(int i=0; i<len; i++)
447 54e47d9b Leszek Koltunski
      {
448 33647db9 Leszek Koltunski
      result[2*i  ] = vertices[2*i  ]*cos - vertices[2*i+1]*sin;
449
      result[2*i+1] = vertices[2*i  ]*sin + vertices[2*i+1]*cos;
450 54e47d9b Leszek Koltunski
      }
451
    }
452
453 6d020cb6 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
454
455 33647db9 Leszek Koltunski
  private boolean isScaledVersionOf(float[] v1, float[] v2, int len)
456 6d020cb6 Leszek Koltunski
    {
457 33647db9 Leszek Koltunski
    float EPSILON = 0.001f;
458
    float scale = v1[0]!=0.0f ? v2[0]/v1[0] : v2[1]/v1[1];
459 55f20739 Leszek Koltunski
460 33647db9 Leszek Koltunski
    for(int i=1; i<len; i++)
461
      {
462
      float horz = v2[2*i  ] - scale*v1[2*i  ];
463
      float vert = v2[2*i+1] - scale*v1[2*i+1];
464 7edab735 Leszek Koltunski
465 33647db9 Leszek Koltunski
      if( horz>EPSILON || horz<-EPSILON || vert>EPSILON || vert<-EPSILON ) return false;
466
      }
467 55f20739 Leszek Koltunski
468 33647db9 Leszek Koltunski
    return true;
469 7edab735 Leszek Koltunski
    }
470
471
///////////////////////////////////////////////////////////////////////////////////////////////////
472
473 33647db9 Leszek Koltunski
  private void mirrorAllVertices(float[] output, int len, float[] input)
474 7edab735 Leszek Koltunski
    {
475 33647db9 Leszek Koltunski
    for(int vertex=0; vertex<len; vertex++)
476
      {
477
      output[2*vertex  ] = input[2*vertex  ];
478
      output[2*vertex+1] =-input[2*vertex+1];
479
      }
480 7edab735 Leszek Koltunski
    }
481
482
///////////////////////////////////////////////////////////////////////////////////////////////////
483
484 1b85f172 Leszek Koltunski
  private void correctInfo(FaceInfo info, float scale, float sin, float cos, int oldSticker, boolean flip)
485 7edab735 Leszek Koltunski
    {
486 1b85f172 Leszek Koltunski
    mStickerInfo.remove(info.sticker);
487 7edab735 Leszek Koltunski
488 1b85f172 Leszek Koltunski
    info.flip = flip;
489
    info.sticker = oldSticker;
490 33647db9 Leszek Koltunski
    info.scale *= scale;
491 7edab735 Leszek Koltunski
492 33647db9 Leszek Koltunski
    mQuat1[0] = 0.0f;
493
    mQuat1[1] = 0.0f;
494
    mQuat1[2] = sin;
495
    mQuat1[3] = cos;
496 55f20739 Leszek Koltunski
497 33647db9 Leszek Koltunski
    mQuat2[0] = info.qx;
498
    mQuat2[1] = info.qy;
499
    mQuat2[2] = info.qz;
500
    mQuat2[3] = info.qw;
501 7edab735 Leszek Koltunski
502 33647db9 Leszek Koltunski
    quatMultiply( mQuat1, mQuat2, mQuat3 );
503 55f20739 Leszek Koltunski
504 33647db9 Leszek Koltunski
    info.qx = mQuat3[0];
505
    info.qy = mQuat3[1];
506
    info.qz = mQuat3[2];
507
    info.qw = mQuat3[3];
508 7edab735 Leszek Koltunski
    }
509
510
///////////////////////////////////////////////////////////////////////////////////////////////////
511
512 1b85f172 Leszek Koltunski
  private boolean foundVertex(FaceInfo info, float[] buffer, int len, float[] preVert,
513
                              float[] newVert, float lenVert, int oldSticker, boolean inverted)
514 7edab735 Leszek Koltunski
    {
515 33647db9 Leszek Koltunski
    for(int vertex=0; vertex<len; vertex++)
516
      {
517 1b85f172 Leszek Koltunski
      float xR = newVert[2*vertex  ];
518
      float yR = newVert[2*vertex+1];
519 33647db9 Leszek Koltunski
      float lenRotV = (float)Math.sqrt(xR*xR+yR*yR);
520 1b85f172 Leszek Koltunski
      float cos = computeCos(xR,yR,preVert[0],preVert[1], lenRotV, lenVert);
521
      float sin = computeSin(xR,yR,preVert[0],preVert[1], lenRotV, lenVert);
522 7edab735 Leszek Koltunski
523 1b85f172 Leszek Koltunski
      rotateAllVertices(buffer,len,newVert,sin,cos);
524 7edab735 Leszek Koltunski
525 1b85f172 Leszek Koltunski
      if( isScaledVersionOf(buffer,preVert,len) )
526 33647db9 Leszek Koltunski
        {
527 1b85f172 Leszek Koltunski
        float scale = preVert[0]!=0.0f ? buffer[0]/preVert[0] : buffer[1]/preVert[1];
528
        correctInfo(info,scale,sin,cos,oldSticker,inverted);
529 33647db9 Leszek Koltunski
        return true;
530
        }
531
      }
532 55f20739 Leszek Koltunski
533 33647db9 Leszek Koltunski
    return false;
534 7edab735 Leszek Koltunski
    }
535
536
///////////////////////////////////////////////////////////////////////////////////////////////////
537
538 1b85f172 Leszek Koltunski
  private boolean successfullyCollapsedStickers(final FaceInfo newInfo, final FaceInfo preInfo)
539 7edab735 Leszek Koltunski
    {
540 1b85f172 Leszek Koltunski
    StickerInfo sNewInfo = mStickerInfo.get(newInfo.sticker);
541
    StickerInfo sPreInfo = mStickerInfo.get(preInfo.sticker);
542
    int len = sPreInfo.vertices.length;
543
    float[] newVert = sNewInfo.vertices;
544 7edab735 Leszek Koltunski
545 1b85f172 Leszek Koltunski
    if( len == newVert.length )
546 33647db9 Leszek Koltunski
      {
547 1b85f172 Leszek Koltunski
      int oldSticker = preInfo.sticker;
548
      float[] tmp1 = new float[len];
549
      float lenVert = (float)Math.sqrt(newVert[0]*newVert[0] + newVert[1]*newVert[1]);
550
      if( foundVertex(newInfo, tmp1, len/2, sPreInfo.vertices, newVert, lenVert, oldSticker, false) ) return true;
551
      float[] tmp2 = new float[len];
552
      mirrorAllVertices(tmp2,len/2,sPreInfo.vertices);
553
      if( foundVertex(newInfo, tmp1, len/2, tmp2             , newVert, lenVert, oldSticker, true ) ) return true;
554 33647db9 Leszek Koltunski
      }
555 55f20739 Leszek Koltunski
556 33647db9 Leszek Koltunski
    return false;
557 7edab735 Leszek Koltunski
    }
558
559
///////////////////////////////////////////////////////////////////////////////////////////////////
560
561 33647db9 Leszek Koltunski
  private float[][] constructVert(float[][] vertices, int[] index)
562 7edab735 Leszek Koltunski
    {
563 33647db9 Leszek Koltunski
    int len = index.length;
564
    float[][] ret = new float[len][4];
565 7edab735 Leszek Koltunski
566 33647db9 Leszek Koltunski
    for(int i=0; i<len; i++)
567
      {
568
      ret[i][0] = vertices[index[i]][0];
569
      ret[i][1] = vertices[index[i]][1];
570
      ret[i][2] = vertices[index[i]][2];
571
      ret[i][3] = 1.0f;
572
      }
573 7edab735 Leszek Koltunski
574 33647db9 Leszek Koltunski
    return ret;
575 7edab735 Leszek Koltunski
    }
576
577
///////////////////////////////////////////////////////////////////////////////////////////////////
578
579 33647db9 Leszek Koltunski
  private void prepareFaceInfo( final float[][] vertices, final int[][] indexes)
580 7edab735 Leszek Koltunski
    {
581 33647db9 Leszek Koltunski
    mFaceInfo.clear();
582 1b85f172 Leszek Koltunski
    mStickerInfo.clear();
583 7edab735 Leszek Koltunski
584 33647db9 Leszek Koltunski
    int numFaces = indexes.length;
585 1b85f172 Leszek Koltunski
    FaceInfo preInfo;
586 7edab735 Leszek Koltunski
587 33647db9 Leszek Koltunski
    for(int face=0; face<numFaces; face++)
588
      {
589
      FaceInfo newInfo = new FaceInfo();
590
      int[] index = indexes[face];
591
      float[][] vert = constructVert(vertices,index);
592
      constructNew(newInfo,vert);
593 55f20739 Leszek Koltunski
594 33647db9 Leszek Koltunski
      for(int previous=0; previous<face; previous++)
595
        {
596 1b85f172 Leszek Koltunski
        preInfo = mFaceInfo.get(previous);
597
        if( successfullyCollapsedStickers(newInfo,preInfo) ) break;
598 33647db9 Leszek Koltunski
        }
599 7edab735 Leszek Koltunski
600 33647db9 Leszek Koltunski
      mFaceInfo.add(newInfo);
601
      }
602 7edab735 Leszek Koltunski
    }
603
604 ef231eba Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
605
606 1b85f172 Leszek Koltunski
  private void prepareAndRoundCorners(MeshBase mesh, float[][] vertices, int[][] vertIndexes,
607
                                      float[][] corners, int[] cornerIndexes )
608 ef231eba Leszek Koltunski
    {
609 1b85f172 Leszek Koltunski
    int numNeig, lenFV;
610
    int lenV = vertices.length;
611
    int[] verts = new int[2*(lenV-1)];
612
    Static3D[] staticVert = new Static3D[1];
613
    Static3D center = new Static3D(0,0,0);
614
    float cx, cy, cz;
615
    float[] singleV;
616 ef231eba Leszek Koltunski
617 1b85f172 Leszek Koltunski
    for(int v=0; v<lenV; v++)
618
      {
619
      // prepare verts[]
620
      numNeig = 0;
621 ef231eba Leszek Koltunski
622 1b85f172 Leszek Koltunski
      for (int[] vertIndex : vertIndexes)
623
        {
624
        lenFV = vertIndex.length;
625 ef231eba Leszek Koltunski
626 1b85f172 Leszek Koltunski
        for (int fv = 0; fv < lenFV; fv++)
627
          if (vertIndex[fv] == v)
628
            {
629
            int prev = fv > 0 ? fv - 1 : lenFV - 1;
630
            int next = fv < lenFV - 1 ? fv + 1 : 0;
631
632
            verts[numNeig++] = vertIndex[prev];
633
            verts[numNeig++] = vertIndex[next];
634
            }
635
        }
636
637
      cx=cy=cz=0.0f;
638
639
      // from verts[] prepare center
640
      for(int n=0; n<numNeig; n++)
641
        {
642
        singleV = vertices[verts[n]];
643
644
        cx += singleV[0];
645
        cy += singleV[1];
646
        cz += singleV[2];
647
        }
648
      center.set(cx/numNeig - vertices[v][0],cy/numNeig - vertices[v][1],cz/numNeig - vertices[v][2]);
649
650
      // round Corners
651
      staticVert[0] = new Static3D(vertices[v][0], vertices[v][1], vertices[v][2]);
652
653
      int corn = cornerIndexes[v];
654
      float strength = corners[corn][0];
655
      float radius   = corners[corn][1];
656
657
      roundCorners(mesh, center, staticVert, strength, radius);
658
      }
659
    }
660
661
///////////////////////////////////////////////////////////////////////////////////////////////////
662
663
  private void printStickerInfo()
664
    {
665
    String ver="";
666
    int stickers = mStickerInfo.size();
667
668
    for(int s=0; s<stickers; s++)
669 ef231eba Leszek Koltunski
      {
670 1b85f172 Leszek Koltunski
      ver = "";
671
      StickerInfo info = mStickerInfo.get(s);
672
      int len = info.vertices.length/2;
673
674
      for(int i =0; i<len; i++)
675
        {
676
        ver += ("("+info.vertices[2*i]+","+info.vertices[2*i+1]+") ");
677
        }
678 ef231eba Leszek Koltunski
      }
679
680
    android.util.Log.e("D", "vertices= "+ver);
681
    }
682
683 7edab735 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
684
685 1b85f172 Leszek Koltunski
  private void printFaceInfo(FaceInfo info)
686
    {
687
    android.util.Log.e("D", "q=("+info.qx+", "+info.qy+", "+info.qz+", "+info.qw+") v=("
688
                       +info.vx+", "+info.vy+", "+info.vz+") scale="+info.scale+" sticker="+info.sticker);
689
    }
690
691
///////////////////////////////////////////////////////////////////////////////////////////////////
692
693
  MeshBase createRoundedSolid(final float[][] vertices, final int[][] vertIndexes,
694
                              final float[][] bands   , final int[]   bandIndexes,
695
                              final float[][] corners , final int[]   cornerIndexes)
696 7edab735 Leszek Koltunski
    {
697 33647db9 Leszek Koltunski
    int EFFECTS_PER_FACE = 3;
698 7edab735 Leszek Koltunski
699 33647db9 Leszek Koltunski
    prepareFaceInfo(vertices,vertIndexes);
700 7edab735 Leszek Koltunski
701 33647db9 Leszek Koltunski
    int numFaces = vertIndexes.length;
702
    float[] band, bandsComputed;
703
    MeshBase[] meshes = new MeshBase[numFaces];
704 1b85f172 Leszek Koltunski
    FaceInfo fInfo;
705
    StickerInfo sInfo;
706
707
    //printStickerInfo();
708 55f20739 Leszek Koltunski
709 33647db9 Leszek Koltunski
    for(int face=0; face<numFaces; face++)
710
      {
711 1b85f172 Leszek Koltunski
      fInfo = mFaceInfo.get(face);
712
      sInfo = mStickerInfo.get(fInfo.sticker);
713 140f2c4e Leszek Koltunski
714 1b85f172 Leszek Koltunski
      //printFaceInfo(fInfo);
715 140f2c4e Leszek Koltunski
716 33647db9 Leszek Koltunski
      band = bands[bandIndexes[face]];
717
      bandsComputed = computeBands( band[0], (int)band[1], band[2], band[3], (int)band[4]);
718 1b85f172 Leszek Koltunski
      meshes[face] = new MeshPolygon(sInfo.vertices,bandsComputed,(int)band[5],(int)band[6]);
719 33647db9 Leszek Koltunski
      meshes[face].setEffectAssociation(0,(1<<face),0);
720
      }
721 7edab735 Leszek Koltunski
722 33647db9 Leszek Koltunski
    MeshBase mesh = new MeshJoined(meshes);
723 1b85f172 Leszek Koltunski
    MatrixEffect[] effects = new MatrixEffect[EFFECTS_PER_FACE*numFaces];
724 7edab735 Leszek Koltunski
    Static3D center = new Static3D(0,0,0);
725 fe032f52 Leszek Koltunski
726 33647db9 Leszek Koltunski
    for(int face=0; face<numFaces; face++)
727
      {
728
      int assoc = (1<<face);
729 1b85f172 Leszek Koltunski
      fInfo = mFaceInfo.get(face);
730 6d020cb6 Leszek Koltunski
731 1b85f172 Leszek Koltunski
      Static3D move3D= new Static3D(fInfo.vx,fInfo.vy,fInfo.vz);
732
      Static3D scale = new Static3D(fInfo.scale,fInfo.scale, fInfo.flip ? -fInfo.scale : fInfo.scale);
733
      Static4D quat  = new Static4D(fInfo.qx,fInfo.qy,fInfo.qz,fInfo.qw);
734 6d020cb6 Leszek Koltunski
735 1b85f172 Leszek Koltunski
      effects[EFFECTS_PER_FACE*face  ] = new MatrixEffectScale(scale);
736
      effects[EFFECTS_PER_FACE*face+1] = new MatrixEffectQuaternion(quat,center);
737
      effects[EFFECTS_PER_FACE*face+2] = new MatrixEffectMove(move3D);
738 a65604a7 Leszek Koltunski
739 1b85f172 Leszek Koltunski
      mesh.apply(effects[EFFECTS_PER_FACE*face  ],assoc,-1);
740
      mesh.apply(effects[EFFECTS_PER_FACE*face+1],assoc,-1);
741
      mesh.apply(effects[EFFECTS_PER_FACE*face+2],assoc,-1);
742 33647db9 Leszek Koltunski
      }
743 a65604a7 Leszek Koltunski
744 1b85f172 Leszek Koltunski
    prepareAndRoundCorners(mesh, vertices, vertIndexes, corners, cornerIndexes);
745 a65604a7 Leszek Koltunski
746 7edab735 Leszek Koltunski
    return mesh;
747
    }
748
  }