Project

General

Profile

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

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

1
///////////////////////////////////////////////////////////////////////////////////////////////////
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
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
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
import java.util.ArrayList;
36

    
37
///////////////////////////////////////////////////////////////////////////////////////////////////
38

    
39
class FactoryCubit
40
  {
41
  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

    
46
  private static final Static1D RADIUS = new Static1D(1);
47

    
48
  private static FactoryCubit mThis;
49

    
50
  private static class StickerInfo
51
    {
52
    float[] vertices;
53
    }
54

    
55
  private static class FaceInfo
56
    {
57
    int sticker;
58
    float vx,vy,vz;
59
    float scale;
60
    float qx,qy,qz,qw;
61
    boolean flip;
62
    }
63

    
64
  private static final ArrayList<FaceInfo>       mFaceInfo = new ArrayList<>();
65
  private static final ArrayList<StickerInfo> mStickerInfo = new ArrayList<>();
66

    
67
///////////////////////////////////////////////////////////////////////////////////////////////////
68

    
69
  private FactoryCubit()
70
    {
71

    
72
    }
73

    
74
///////////////////////////////////////////////////////////////////////////////////////////////////
75

    
76
  public static FactoryCubit getInstance()
77
    {
78
    if( mThis==null ) mThis = new FactoryCubit();
79

    
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
  float[] computeBands(float H, int alpha, float dist, float K, int N)
143
    {
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
      int K2 = (int)((N-3)*K);
167
      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
    bands[2*N-2] = 0.0f;
186
    bands[2*N-1] =    H;
187

    
188
    return bands;
189
    }
190

    
191
///////////////////////////////////////////////////////////////////////////////////////////////////
192

    
193
  private void roundCorners(MeshBase mesh, Static3D center, Static3D[] vertices, float strength, float regionRadius)
194
    {
195
    Static4D region= new Static4D(0,0,0,regionRadius);
196

    
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
      VertexEffect effect = new VertexEffectDeform(new Static3D(x,y,z), RADIUS, vertex, region);
208
      mesh.apply(effect);
209
      }
210
    }
211

    
212
///////////////////////////////////////////////////////////////////////////////////////////////////
213

    
214
  private boolean areColinear(float[][] vertices, int index1, int index2, int index3)
215
    {
216
    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

    
226
    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

    
233
    float A = (float)Math.sqrt( (v1x*v1x+v1y*v1y+v1z*v1z) / (v2x*v2x+v2y*v2y+v2z*v2z) );
234

    
235
    return (v1x==A*v2x && v1y==A*v2y && v1z==A*v2z);
236
    }
237

    
238
///////////////////////////////////////////////////////////////////////////////////////////////////
239

    
240
  private void computeNormalVector(float[][] vertices, int index1, int index2, int index3)
241
    {
242
    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

    
252
    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

    
259
    mBuffer[0] = v1y*v2z - v2y*v1z;
260
    mBuffer[1] = v1z*v2x - v2z*v1x;
261
    mBuffer[2] = v1x*v2y - v2x*v1y;
262

    
263
    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
    }
269

    
270
///////////////////////////////////////////////////////////////////////////////////////////////////
271
// return quat1*quat2
272

    
273
  private static void quatMultiply( float[] quat1, float[] quat2, float[] result )
274
    {
275
    float qx = quat1[0];
276
    float qy = quat1[1];
277
    float qz = quat1[2];
278
    float qw = quat1[3];
279

    
280
    float rx = quat2[0];
281
    float ry = quat2[1];
282
    float rz = quat2[2];
283
    float rw = quat2[3];
284

    
285
    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
    }
290

    
291
///////////////////////////////////////////////////////////////////////////////////////////////////
292

    
293
  private void fitInSquare(FaceInfo info, float[][] vert3D)
294
    {
295
    float minX = Float.MAX_VALUE;
296
    float maxX =-Float.MAX_VALUE;
297
    float minY = Float.MAX_VALUE;
298
    float maxY =-Float.MAX_VALUE;
299

    
300
    for (float[] vert : vert3D)
301
      {
302
      float x = vert[0];
303
      float y = vert[1];
304

    
305
      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

    
311
    info.scale = Math.max(maxX-minX,maxY-minY);
312

    
313
    int len = vert3D.length;
314
    StickerInfo sInfo = new StickerInfo();
315
    sInfo.vertices = new float[2*len];
316
    mStickerInfo.add(sInfo);
317

    
318
    for( int vertex=0; vertex<len; vertex++ )
319
      {
320
      sInfo.vertices[2*vertex  ] = vert3D[vertex][0] / info.scale;
321
      sInfo.vertices[2*vertex+1] = vert3D[vertex][1] / info.scale;
322
      }
323

    
324
    info.flip = false;
325
    }
326

    
327
///////////////////////////////////////////////////////////////////////////////////////////////////
328

    
329
  private void constructNew(FaceInfo info, final float[][] vert3D)
330
    {
331
    // 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

    
337
    for (float[] vert : vert3D)
338
      {
339
      info.vx += vert[0];
340
      info.vy += vert[1];
341
      info.vz += vert[2];
342
      }
343

    
344
    info.vx /= len;
345
    info.vy /= len;
346
    info.vz /= len;
347

    
348
    // move all vertices so that their center of gravity is at (0,0,0)
349
    for (int i=0; i<len; i++)
350
      {
351
      vert3D[i][0] -= info.vx;
352
      vert3D[i][1] -= info.vy;
353
      vert3D[i][2] -= info.vz;
354
      }
355

    
356
    // find 3 non-colinear vertices
357
    int foundIndex = -1;
358

    
359
    for(int vertex=2; vertex<len; vertex++)
360
      {
361
      if( !areColinear(vert3D,0,1,vertex) )
362
        {
363
        foundIndex = vertex;
364
        break;
365
        }
366
      }
367

    
368
    // compute the normal vector
369
    if( foundIndex==-1 )
370
      {
371
      throw new RuntimeException("all vertices colinear");
372
      }
373

    
374
    computeNormalVector(vert3D,0,1,foundIndex);
375

    
376
    // rotate so that the normal vector becomes (0,0,1)
377
    float axisX, axisY, axisZ;
378

    
379
    if( mBuffer[0]!=0.0f || mBuffer[1]!=0.0f )
380
      {
381
      axisX = -mBuffer[1];
382
      axisY =  mBuffer[0];
383
      axisZ = 0.0f;
384

    
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
      }
391
    else
392
      {
393
      axisX = 0.0f;
394
      axisY = 1.0f;
395
      axisZ = 0.0f;
396
      }
397

    
398
    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

    
402
    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

    
411
    for (float[] vert : vert3D)
412
      {
413
      quatMultiply(mQuat1, vert, mQuat3);
414
      quatMultiply(mQuat3, mQuat2, vert);
415
      }
416

    
417
    // fit the whole thing in a square and remember the scale & 2D vertices
418
    fitInSquare(info, vert3D);
419

    
420
    // remember the rotation
421
    info.qx = mQuat1[0];
422
    info.qy = mQuat1[1];
423
    info.qz = mQuat1[2];
424
    info.qw =-mQuat1[3];
425
    }
426

    
427
///////////////////////////////////////////////////////////////////////////////////////////////////
428

    
429
  private float computeCos(float x1, float y1, float x2, float y2, float len1, float len2)
430
    {
431
    return (x1*x2+y1*y2) / (len1*len2);
432
    }
433

    
434
///////////////////////////////////////////////////////////////////////////////////////////////////
435
// sin of (signed!) angle between vectors (x1,y1) and (x2,y2), counterclockwise!
436

    
437
  private float computeSin(float x1, float y1, float x2, float y2, float len1, float len2)
438
    {
439
    return (x2*y1-x1*y2) / (len1*len2);
440
    }
441

    
442
///////////////////////////////////////////////////////////////////////////////////////////////////
443

    
444
  private void rotateAllVertices(float[] result, int len, float[] vertices, float sin, float cos)
445
    {
446
    for(int i=0; i<len; i++)
447
      {
448
      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
      }
451
    }
452

    
453
///////////////////////////////////////////////////////////////////////////////////////////////////
454

    
455
  private boolean isScaledVersionOf(float[] v1, float[] v2, int len)
456
    {
457
    float EPSILON = 0.001f;
458
    float scale = v1[0]!=0.0f ? v2[0]/v1[0] : v2[1]/v1[1];
459

    
460
    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

    
465
      if( horz>EPSILON || horz<-EPSILON || vert>EPSILON || vert<-EPSILON ) return false;
466
      }
467

    
468
    return true;
469
    }
470

    
471
///////////////////////////////////////////////////////////////////////////////////////////////////
472

    
473
  private void mirrorAllVertices(float[] output, int len, float[] input)
474
    {
475
    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
    }
481

    
482
///////////////////////////////////////////////////////////////////////////////////////////////////
483

    
484
  private void correctInfo(FaceInfo info, float scale, float sin, float cos, int oldSticker, boolean flip)
485
    {
486
    mStickerInfo.remove(info.sticker);
487

    
488
    info.flip = flip;
489
    info.sticker = oldSticker;
490
    info.scale *= scale;
491

    
492
    mQuat1[0] = 0.0f;
493
    mQuat1[1] = 0.0f;
494
    mQuat1[2] = sin;
495
    mQuat1[3] = cos;
496

    
497
    mQuat2[0] = info.qx;
498
    mQuat2[1] = info.qy;
499
    mQuat2[2] = info.qz;
500
    mQuat2[3] = info.qw;
501

    
502
    quatMultiply( mQuat1, mQuat2, mQuat3 );
503

    
504
    info.qx = mQuat3[0];
505
    info.qy = mQuat3[1];
506
    info.qz = mQuat3[2];
507
    info.qw = mQuat3[3];
508
    }
509

    
510
///////////////////////////////////////////////////////////////////////////////////////////////////
511

    
512
  private boolean foundVertex(FaceInfo info, float[] buffer, int len, float[] preVert,
513
                              float[] newVert, float lenVert, int oldSticker, boolean inverted)
514
    {
515
    for(int vertex=0; vertex<len; vertex++)
516
      {
517
      float xR = newVert[2*vertex  ];
518
      float yR = newVert[2*vertex+1];
519
      float lenRotV = (float)Math.sqrt(xR*xR+yR*yR);
520
      float cos = computeCos(xR,yR,preVert[0],preVert[1], lenRotV, lenVert);
521
      float sin = computeSin(xR,yR,preVert[0],preVert[1], lenRotV, lenVert);
522

    
523
      rotateAllVertices(buffer,len,newVert,sin,cos);
524

    
525
      if( isScaledVersionOf(buffer,preVert,len) )
526
        {
527
        float scale = preVert[0]!=0.0f ? buffer[0]/preVert[0] : buffer[1]/preVert[1];
528
        correctInfo(info,scale,sin,cos,oldSticker,inverted);
529
        return true;
530
        }
531
      }
532

    
533
    return false;
534
    }
535

    
536
///////////////////////////////////////////////////////////////////////////////////////////////////
537

    
538
  private boolean successfullyCollapsedStickers(final FaceInfo newInfo, final FaceInfo preInfo)
539
    {
540
    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

    
545
    if( len == newVert.length )
546
      {
547
      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
      }
555

    
556
    return false;
557
    }
558

    
559
///////////////////////////////////////////////////////////////////////////////////////////////////
560

    
561
  private float[][] constructVert(float[][] vertices, int[] index)
562
    {
563
    int len = index.length;
564
    float[][] ret = new float[len][4];
565

    
566
    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

    
574
    return ret;
575
    }
576

    
577
///////////////////////////////////////////////////////////////////////////////////////////////////
578

    
579
  private void prepareFaceInfo( final float[][] vertices, final int[][] indexes)
580
    {
581
    mFaceInfo.clear();
582
    mStickerInfo.clear();
583

    
584
    int numFaces = indexes.length;
585
    FaceInfo preInfo;
586

    
587
    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

    
594
      for(int previous=0; previous<face; previous++)
595
        {
596
        preInfo = mFaceInfo.get(previous);
597
        if( successfullyCollapsedStickers(newInfo,preInfo) ) break;
598
        }
599

    
600
      mFaceInfo.add(newInfo);
601
      }
602
    }
603

    
604
///////////////////////////////////////////////////////////////////////////////////////////////////
605

    
606
  private void prepareAndRoundCorners(MeshBase mesh, float[][] vertices, int[][] vertIndexes,
607
                                      float[][] corners, int[] cornerIndexes )
608
    {
609
    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

    
617
    for(int v=0; v<lenV; v++)
618
      {
619
      // prepare verts[]
620
      numNeig = 0;
621

    
622
      for (int[] vertIndex : vertIndexes)
623
        {
624
        lenFV = vertIndex.length;
625

    
626
        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
      {
670
      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
      }
679

    
680
    android.util.Log.e("D", "vertices= "+ver);
681
    }
682

    
683
///////////////////////////////////////////////////////////////////////////////////////////////////
684

    
685
  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
    {
697
    int EFFECTS_PER_FACE = 3;
698

    
699
    prepareFaceInfo(vertices,vertIndexes);
700

    
701
    int numFaces = vertIndexes.length;
702
    float[] band, bandsComputed;
703
    MeshBase[] meshes = new MeshBase[numFaces];
704
    FaceInfo fInfo;
705
    StickerInfo sInfo;
706

    
707
    //printStickerInfo();
708

    
709
    for(int face=0; face<numFaces; face++)
710
      {
711
      fInfo = mFaceInfo.get(face);
712
      sInfo = mStickerInfo.get(fInfo.sticker);
713

    
714
      //printFaceInfo(fInfo);
715

    
716
      band = bands[bandIndexes[face]];
717
      bandsComputed = computeBands( band[0], (int)band[1], band[2], band[3], (int)band[4]);
718
      meshes[face] = new MeshPolygon(sInfo.vertices,bandsComputed,(int)band[5],(int)band[6]);
719
      meshes[face].setEffectAssociation(0,(1<<face),0);
720
      }
721

    
722
    MeshBase mesh = new MeshJoined(meshes);
723
    MatrixEffect[] effects = new MatrixEffect[EFFECTS_PER_FACE*numFaces];
724
    Static3D center = new Static3D(0,0,0);
725

    
726
    for(int face=0; face<numFaces; face++)
727
      {
728
      int assoc = (1<<face);
729
      fInfo = mFaceInfo.get(face);
730

    
731
      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

    
735
      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

    
739
      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
      }
743

    
744
    prepareAndRoundCorners(mesh, vertices, vertIndexes, corners, cornerIndexes);
745

    
746
    return mesh;
747
    }
748
  }
(1-1/5)