Project

General

Profile

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

library / src / main / java / org / distorted / library / mesh / MeshPolygon.java @ e529379e

1 808ef3aa Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2 c4d06f90 Leszek Koltunski
// Copyright 2020 Leszek Koltunski  leszek@koltunski.pl                                          //
3 808ef3aa Leszek Koltunski
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6 c4d06f90 Leszek Koltunski
// This library is free software; you can redistribute it and/or                                 //
7
// modify it under the terms of the GNU Lesser General Public                                    //
8
// License as published by the Free Software Foundation; either                                  //
9
// version 2.1 of the License, or (at your option) any later version.                            //
10 808ef3aa Leszek Koltunski
//                                                                                               //
11 c4d06f90 Leszek Koltunski
// This library is distributed in the hope that it will be useful,                               //
12 808ef3aa Leszek Koltunski
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13 c4d06f90 Leszek Koltunski
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                             //
14
// Lesser General Public License for more details.                                               //
15 808ef3aa Leszek Koltunski
//                                                                                               //
16 c4d06f90 Leszek Koltunski
// You should have received a copy of the GNU Lesser General Public                              //
17
// License along with this library; if not, write to the Free Software                           //
18
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA                //
19 808ef3aa Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
20
21
package org.distorted.library.mesh;
22
23 8c57d77b Leszek Koltunski
import org.distorted.library.main.DistortedLibrary;
24
25 e529379e leszek
///////////////////////////////////////////////////////////////////////////////////////////////////
26 808ef3aa Leszek Koltunski
/**
27
 * Create a polygon of any shape and varying elevations from the edges towards the center.
28
 * <p>
29
 * Specify a list of vertices. Any two adjacent vertices + the center (0,0,0) form a triangle. The
30 2d732361 Leszek Koltunski
 * polygon is going to be split into such triangles, and each triangle is split into adjustable number
31 808ef3aa Leszek Koltunski
 * of 'bands' form the outer edge towards the center. Edges of each band can can at any elevation.
32
 */
33
public class MeshPolygon extends MeshBase
34
  {
35 d3287c14 Leszek Koltunski
  private static final int NUM_CACHE = 20;
36 b2913a86 Leszek Koltunski
37 808ef3aa Leszek Koltunski
  private float[] mPolygonVertices;
38
  private int mNumPolygonVertices;
39
  private float[] mPolygonBands;
40
  private int mNumPolygonBands;
41
42
  private int remainingVert;
43
  private int numVertices;
44 e529379e leszek
  private int extraBand, extraVertices;
45 808ef3aa Leszek Koltunski
46 d3287c14 Leszek Koltunski
  private float[] mCurveCache;
47 eeb5d115 Leszek Koltunski
48 808ef3aa Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
49
// polygonVertices>=3 , polygonBands>=2
50
51 d456b075 Leszek Koltunski
  private void computeNumberOfVertices()
52 808ef3aa Leszek Koltunski
     {
53 e529379e leszek
     if( mNumPolygonBands==2 && extraBand>0 )
54 fa640198 Leszek Koltunski
       {
55 e529379e leszek
       numVertices = 1 + 2*mNumPolygonVertices*(1+extraBand+2*extraVertices);
56 fa640198 Leszek Koltunski
       }
57
     else
58
       {
59
       numVertices = (mNumPolygonVertices*mNumPolygonBands+2)*(mNumPolygonBands-1) - 1;
60 e529379e leszek
       numVertices+= 2*mNumPolygonVertices*(2*extraBand*extraVertices);
61 fa640198 Leszek Koltunski
       }
62 d456b075 Leszek Koltunski
63 ac6a08e7 Leszek Koltunski
     remainingVert = numVertices;
64 808ef3aa Leszek Koltunski
     }
65 724f67ee Leszek Koltunski
66 808ef3aa Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
67
68 eeb5d115 Leszek Koltunski
  private void computeCache()
69 808ef3aa Leszek Koltunski
    {
70 d3287c14 Leszek Koltunski
    mCurveCache = new float[NUM_CACHE];
71
    float[] tmpD = new float[mNumPolygonBands+1];
72
    float[] tmpX = new float[mNumPolygonBands+1];
73 ac6a08e7 Leszek Koltunski
74 d3287c14 Leszek Koltunski
    for(int i=1; i<mNumPolygonBands; i++)
75
      {
76
      tmpD[i] = (mPolygonBands[2*i-1]-mPolygonBands[2*i+1]) / (mPolygonBands[2*i]-mPolygonBands[2*i-2]);
77
      tmpX[i] = 1.0f - (mPolygonBands[2*i]+mPolygonBands[2*i-2])/2;
78
      }
79
80
    tmpD[0] = tmpD[1];
81
    tmpD[mNumPolygonBands] = tmpD[mNumPolygonBands-1];
82
    tmpX[0] = 0.0f;
83
    tmpX[mNumPolygonBands] = 1.0f;
84 ac6a08e7 Leszek Koltunski
85 d3287c14 Leszek Koltunski
    int prev = 0;
86
    int next = 0;
87
88
    for(int i=0; i<NUM_CACHE-1; i++)
89 eeb5d115 Leszek Koltunski
      {
90 d3287c14 Leszek Koltunski
      float x = i/(NUM_CACHE-1.0f);
91 ac6a08e7 Leszek Koltunski
92 d3287c14 Leszek Koltunski
      if( x>=tmpX[next] )
93
        {
94
        prev = next;
95
        while( next<=mNumPolygonBands && x>=tmpX[next] ) next++;
96
        }
97
98
      if( next>prev )
99
        {
100
        float t = (x-tmpX[prev]) / (tmpX[next]-tmpX[prev]);
101
        mCurveCache[i] = t*(tmpD[next]-tmpD[prev]) + tmpD[prev];
102
        }
103
      else
104
        {
105
        mCurveCache[i] = tmpD[next];
106
        }
107 eeb5d115 Leszek Koltunski
      }
108 d3287c14 Leszek Koltunski
109
    mCurveCache[NUM_CACHE-1] = tmpD[mNumPolygonBands];
110 eeb5d115 Leszek Koltunski
    }
111 724f67ee Leszek Koltunski
112 fa640198 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
113
114
  private float getSpecialQuot(int index)
115
    {
116 e529379e leszek
    int num = 1 + extraBand + 2*extraVertices;
117 fa640198 Leszek Koltunski
    int change1 = extraVertices+1;
118
    int change2 = num-change1;
119 e529379e leszek
    float quot = 1.0f/(extraBand+1);
120 fa640198 Leszek Koltunski
121
    if( index<change1 )      return index*quot/change1;
122
    else if( index>change2 ) return 1-quot + (index-change2)*quot/change1;
123
    else                     return (index-change1+1)*quot;
124
    }
125
126 eeb5d115 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
127 808ef3aa Leszek Koltunski
128 d456b075 Leszek Koltunski
  private float getQuot(int index, int band, boolean isExtra)
129 eeb5d115 Leszek Koltunski
    {
130 d456b075 Leszek Koltunski
    int num = mNumPolygonBands-1-band;
131 808ef3aa Leszek Koltunski
132 d456b075 Leszek Koltunski
    if( num>0 )
133
      {
134
      if( isExtra )
135
        {
136 e529379e leszek
        int extra = extraBand-band+extraVertices;
137 d456b075 Leszek Koltunski
138
        if( index < extra )
139
          {
140 e529379e leszek
          float quot = ((float)extraBand-band)/(extra*num);
141 d456b075 Leszek Koltunski
          return index*quot;
142
          }
143
        else if( index > num+2*extraVertices-extra )
144
          {
145 e529379e leszek
          float quot = ((float)extraBand-band)/(extra*num);
146
          return (1.0f-((float)extraBand-band)/num) + (index-num-2*extraVertices+extra)*quot;
147 d456b075 Leszek Koltunski
          }
148
        else
149
          {
150
          return ((float)(index-extraVertices))/num;
151
          }
152
        }
153 808ef3aa Leszek Koltunski
154 d456b075 Leszek Koltunski
      return (float)index/num;
155
      }
156 808ef3aa Leszek Koltunski
157 d456b075 Leszek Koltunski
    return 1.0f;
158
    }
159
160 d3287c14 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
161
162
  private float derivative(float x)
163
    {
164
    if( x>=1.0f )
165
      {
166 fd527acd Leszek Koltunski
      return 0.0f;
167 d3287c14 Leszek Koltunski
      }
168
    else
169
      {
170
      float tmp = x*(NUM_CACHE-1);
171
      int i1 = (int)tmp;
172
      int i2 = i1+1;
173 1b5358fb Leszek Koltunski
174
      // why 0.5? Arbitrarily; this way the cubit faces of Twisty Puzzles
175
      // [the main and only user of this class] look better.
176 1bea4e18 Leszek Koltunski
      return 0.5f*((tmp-i1)*(mCurveCache[i2]-mCurveCache[i1]) + mCurveCache[i1]);
177 d3287c14 Leszek Koltunski
      }
178
    }
179
180 b2913a86 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
181
182
  private int addVertex(int vertex, int polyBand, int polyVertex, int polyEndVer, float quot,
183 fd527acd Leszek Koltunski
                        float[] attribs1, float[] attribs2)
184 d456b075 Leszek Koltunski
    {
185
    remainingVert--;
186
187 eeb5d115 Leszek Koltunski
    float Xfirst= mPolygonVertices[2*polyVertex  ];
188
    float Yfirst= mPolygonVertices[2*polyVertex+1];
189
    float Xlast = mPolygonVertices[2*polyEndVer  ];
190
    float Ylast = mPolygonVertices[2*polyEndVer+1];
191 808ef3aa Leszek Koltunski
192 eeb5d115 Leszek Koltunski
    float xEdge = Xfirst + quot*(Xlast-Xfirst);
193
    float yEdge = Yfirst + quot*(Ylast-Yfirst);
194 808ef3aa Leszek Koltunski
195 d3287c14 Leszek Koltunski
    float q = mPolygonBands[2*polyBand];
196 b2913a86 Leszek Koltunski
    float x = q*xEdge;
197
    float y = q*yEdge;
198 e529379e leszek
    float z = mPolygonBands[2*polyBand+1];
199 ac6a08e7 Leszek Koltunski
200 eeb5d115 Leszek Koltunski
    attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB  ] = x;
201
    attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB+1] = y;
202 b2913a86 Leszek Koltunski
    attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB+2] = z;
203 eeb5d115 Leszek Koltunski
204 e529379e leszek
    float d = derivative(1-mPolygonBands[2*polyBand]);
205 fd527acd Leszek Koltunski
206 e529379e leszek
    float vx = d*xEdge;
207
    float vy = d*yEdge;
208
    float vz = xEdge*xEdge + yEdge*yEdge;
209 fd527acd Leszek Koltunski
    float len = (float)Math.sqrt(vx*vx + vy*vy + vz*vz);
210
211 724f67ee Leszek Koltunski
    int index = VERT1_ATTRIBS*vertex + NOR_ATTRIB;
212 fd527acd Leszek Koltunski
    attribs1[index  ] = vx/len;
213
    attribs1[index+1] = vy/len;
214
    attribs1[index+2] = vz/len;
215 724f67ee Leszek Koltunski
216 eeb5d115 Leszek Koltunski
    attribs2[VERT2_ATTRIBS*vertex + TEX_ATTRIB  ] = x+0.5f;
217
    attribs2[VERT2_ATTRIBS*vertex + TEX_ATTRIB+1] = y+0.5f;
218 808ef3aa Leszek Koltunski
219
    return vertex+1;
220
    }
221
222 b2913a86 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
223
224 fd527acd Leszek Koltunski
  private int createBandStrip(int vertex, int polyBand, int polyVertex, float[] attribs1, float[] attribs2)
225 808ef3aa Leszek Koltunski
    {
226
    if( polyVertex==0 )
227
      {
228 fd527acd Leszek Koltunski
      vertex = addVertex(vertex,polyBand,0,1,0,attribs1,attribs2);
229
      if( polyBand>0 ) vertex = addVertex(vertex,polyBand,0,1,0,attribs1,attribs2);
230 808ef3aa Leszek Koltunski
      }
231
232 e529379e leszek
    boolean specialCase = mNumPolygonBands==2 && polyBand==0 && extraBand>0;
233
    boolean isExtra = polyBand<extraBand;
234
    int numPairs = specialCase ? extraBand+1 : mNumPolygonBands-1-polyBand;
235 fa640198 Leszek Koltunski
    if( isExtra ) numPairs += 2*extraVertices;
236 d456b075 Leszek Koltunski
237 eeb5d115 Leszek Koltunski
    int polyEndVer = polyVertex==mNumPolygonVertices-1 ? 0 : polyVertex+1;
238 d456b075 Leszek Koltunski
    float quot1, quot2;
239 808ef3aa Leszek Koltunski
240 eeb5d115 Leszek Koltunski
    for(int index=0; index<numPairs; index++)
241 808ef3aa Leszek Koltunski
      {
242 fa640198 Leszek Koltunski
      if( specialCase )
243
        {
244
        quot1 = 1.0f;
245
        quot2 = getSpecialQuot(index+1);
246
        }
247
      else
248
        {
249
        quot1 = getQuot(index  ,polyBand+1, isExtra);
250
        quot2 = getQuot(index+1,polyBand  , isExtra);
251
        }
252 d456b075 Leszek Koltunski
253 fd527acd Leszek Koltunski
      vertex = addVertex(vertex,polyBand+1,polyVertex,polyEndVer,quot1,attribs1,attribs2);
254
      vertex = addVertex(vertex,polyBand  ,polyVertex,polyEndVer,quot2,attribs1,attribs2);
255 b2913a86 Leszek Koltunski
      }
256
257 808ef3aa Leszek Koltunski
    return vertex;
258
    }
259
260
///////////////////////////////////////////////////////////////////////////////////////////////////
261
262
  private void buildGrid(float[] attribs1, float[] attribs2)
263
    {
264
    int vertex=0;
265
266 ac6a08e7 Leszek Koltunski
    for(int polyBand=0; polyBand<mNumPolygonBands-1; polyBand++)
267 808ef3aa Leszek Koltunski
      for(int polyVertex=0; polyVertex<mNumPolygonVertices; polyVertex++)
268 fd527acd Leszek Koltunski
        vertex = createBandStrip(vertex,polyBand,polyVertex,attribs1,attribs2);
269 808ef3aa Leszek Koltunski
    }
270
271
///////////////////////////////////////////////////////////////////////////////////////////////////
272
// PUBLIC API
273
///////////////////////////////////////////////////////////////////////////////////////////////////
274
/**
275
 * Create a polygon of any shape and varying elevations from the edges towards the center.
276 d456b075 Leszek Koltunski
 * Optionally make it more dense at the vertices.
277 808ef3aa Leszek Koltunski
 *
278
 * @param verticesXY 2N floats - packed description of polygon vertices. N pairs (x,y).
279 8b082b9f Leszek Koltunski
 *                   Vertices HAVE TO be specified in a COUNTERCLOCKWISE order (starting from any).
280 808ef3aa Leszek Koltunski
 * @param bands      2K floats; K pairs of two floats each describing a single band.
281
 *                   From (1.0,Z[0]) (outer edge, its Z elevation) to (0.0,Z[K]) (the center,
282
 *                   its elevation). The polygon is split into such concentric bands.
283 ac6a08e7 Leszek Koltunski
 *                   Must be band[2*i] > band[2*(i+1)] !
284 e529379e leszek
 * @param exBand     This and the next parameter describe how to make the mesh denser at the
285 d456b075 Leszek Koltunski
 *                   polyVertices. If e.g. exIndex=3 and exVertices=2, then 3 triangles of the
286 f4a2d97e Leszek Koltunski
 *                   outermost band (and 2 triangles of the next band, and 1 triangle of the third
287 d456b075 Leszek Koltunski
 *                   band) get denser - the 3 triangles become 3+2 = 5.
288
 * @param exVertices See above.
289 0b732630 Leszek Koltunski
 * @param centerX    the X coordinate of the 'center' of the Polygon, i.e. point of the mesh
290
 *                   all bands go to.
291
 * @param centerY    Y coordinate of the center.
292 808ef3aa Leszek Koltunski
 */
293 e529379e leszek
  public MeshPolygon(float[] verticesXY, float[] bands, int exBand, int exVertices, float centerX, float centerY)
294 808ef3aa Leszek Koltunski
    {
295
    super();
296
297 d456b075 Leszek Koltunski
    mPolygonVertices   = verticesXY;
298
    mPolygonBands      = bands;
299
    mNumPolygonVertices= mPolygonVertices.length /2;
300
    mNumPolygonBands   = mPolygonBands.length /2;
301 e529379e leszek
    extraBand          = exBand;
302 d456b075 Leszek Koltunski
    extraVertices      = exVertices;
303 808ef3aa Leszek Koltunski
304 0b732630 Leszek Koltunski
    if( centerX!=0.0f || centerY!=0.0f )
305
      {
306
      for(int v=0; v<mNumPolygonVertices; v++)
307
        {
308
        mPolygonVertices[2*v  ] -= centerX;
309
        mPolygonVertices[2*v+1] -= centerY;
310
        }
311
      }
312
313 d456b075 Leszek Koltunski
    computeNumberOfVertices();
314 724f67ee Leszek Koltunski
    computeCache();
315 808ef3aa Leszek Koltunski
316
    float[] attribs1= new float[VERT1_ATTRIBS*numVertices];
317
    float[] attribs2= new float[VERT2_ATTRIBS*numVertices];
318
319
    buildGrid(attribs1,attribs2);
320
321
    if( remainingVert!=0 )
322 8c57d77b Leszek Koltunski
      DistortedLibrary.logMessage("MeshPolygon: remainingVert " +remainingVert );
323 808ef3aa Leszek Koltunski
324 0b732630 Leszek Koltunski
    if( centerX!=0.0f || centerY!=0.0f )
325
      {
326
      for(int v=0; v<numVertices; v++)
327
        {
328
        attribs1[VERT1_ATTRIBS*v + POS_ATTRIB  ] += centerX;
329
        attribs1[VERT1_ATTRIBS*v + POS_ATTRIB+1] += centerY;
330
        attribs2[VERT2_ATTRIBS*v + TEX_ATTRIB  ] += centerX;
331
        attribs2[VERT2_ATTRIBS*v + TEX_ATTRIB+1] += centerY;
332
        }
333
      }
334
335 808ef3aa Leszek Koltunski
    setAttribs(attribs1,attribs2);
336
    }
337
338 0b732630 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
339
340
  public MeshPolygon(float[] verticesXY, float[] bands, int exIndex, int exVertices)
341
    {
342 e529379e leszek
    this(verticesXY,bands,exIndex,exVertices,0.0f,0.0f);
343 0b732630 Leszek Koltunski
    }
344
345 d456b075 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
346
/**
347
 * Create a polygon of any shape and varying elevations from the edges towards the center.
348
 * Equivalent of the previous with exIndex=0 or exVertices=0.
349
 */
350
  public MeshPolygon(float[] verticesXY, float[] bands)
351
    {
352 e529379e leszek
    this(verticesXY,bands,0,0,0.0f,0.0f);
353 d456b075 Leszek Koltunski
    }
354
355 808ef3aa Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
356
/**
357
 * Copy constructor.
358
 */
359
  public MeshPolygon(MeshPolygon mesh, boolean deep)
360
    {
361
    super(mesh,deep);
362
    }
363
364
///////////////////////////////////////////////////////////////////////////////////////////////////
365
/**
366
 * Copy the Mesh.
367
 *
368
 * @param deep If to be a deep or shallow copy of mVertAttribs1, i.e. the array holding vertices,
369
 *             normals and inflates (the rest, in particular the mVertAttribs2 containing texture
370
 *             coordinates and effect associations, is always deep copied)
371
 */
372
  public MeshPolygon copy(boolean deep)
373
    {
374
    return new MeshPolygon(this,deep);
375
    }
376
 }